5d60ed752cdc7e483c2e0e00d58801838d6a8790
1 /*
2 * Copyright (c) 2014, Mentor Graphics Corporation
3 * All rights reserved.
4 * Copyright (c) 2015 Xilinx, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of Mentor Graphics Corporation nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
31 /**************************************************************************
32 * FILE NAME
33 *
34 * zynqmp_remoteproc_r5.c
35 *
36 * DESCRIPTION
37 *
38 * This file is the Implementation of IPC hardware layer interface
39 * for Xilinx Zynq UltraScale+ MPSoC system.
40 *
41 **************************************************************************/
43 #include <errno.h>
44 #include <string.h>
45 #include <stdio.h>
46 #include "metal/io.h"
47 #include "metal/device.h"
48 #include "metal/utilities.h"
49 #include "metal/atomic.h"
50 #include "metal/irq.h"
51 #include "metal/cpu.h"
52 #include "metal/alloc.h"
53 #include "openamp/hil.h"
54 #include "openamp/remoteproc_plat.h"
55 #include "openamp/virtqueue.h"
57 /* IPI REGs OFFSET */
58 #define IPI_TRIG_OFFSET 0x00000000 /** IPI trigger register offset */
59 #define IPI_OBS_OFFSET 0x00000004 /** IPI observation register offset */
60 #define IPI_ISR_OFFSET 0x00000010 /* IPI interrupt status register offset */
61 #define IPI_IMR_OFFSET 0x00000014 /* IPI interrupt mask register offset */
62 #define IPI_IER_OFFSET 0x00000018 /* IPI interrupt enable register offset */
63 #define IPI_IDR_OFFSET 0x0000001C /* IPI interrupt disable register offset */
65 #define _rproc_wait() metal_cpu_yield()
67 #define DEBUG 1
69 /* -- FIX ME: ipi info is to be defined -- */
70 struct ipi_info {
71 uint32_t ipi_chn_mask;
72 int need_reg;
73 atomic_int sync;
74 };
76 /*--------------------------- Declare Functions ------------------------ */
77 static int _enable_interrupt(struct proc_vring *vring_hw);
78 static void _notify(int cpu_id, struct proc_intr *intr_info);
79 static int _boot_cpu(int cpu_id, unsigned int load_addr);
80 static void _shutdown_cpu(int cpu_id);
81 static int _poll(struct hil_proc *proc, int nonblock);
82 static struct hil_proc *_initialize(void *pdata, int cpu_id);
83 static void _release(struct hil_proc *proc);
85 /*--------------------------- Globals ---------------------------------- */
86 struct hil_platform_ops zynqmp_a53_r5_proc_ops = {
87 .enable_interrupt = _enable_interrupt,
88 .notify = _notify,
89 .boot_cpu = _boot_cpu,
90 .shutdown_cpu = _shutdown_cpu,
91 .poll = _poll,
92 .initialize = _initialize,
93 .release = _release,
94 };
96 static int _enable_interrupt(struct proc_vring *vring_hw)
97 {
98 (void)vring_hw;
99 return 0;
100 }
102 static void _notify(int cpu_id, struct proc_intr *intr_info)
103 {
105 (void)cpu_id;
106 struct ipi_info *ipi = (struct ipi_info *)(intr_info->data);
107 if (ipi == NULL)
108 return;
110 /* Trigger IPI */
111 metal_io_write32(intr_info->io, IPI_TRIG_OFFSET, ipi->ipi_chn_mask);
112 }
114 static int _boot_cpu(int cpu_id, unsigned int load_addr)
115 {
116 (void)cpu_id;
117 (void)load_addr;
118 return -1;
119 }
121 static void _shutdown_cpu(int cpu_id)
122 {
123 (void)cpu_id;
124 return;
125 }
127 static int _poll(struct hil_proc *proc, int nonblock)
128 {
129 struct proc_vring *vring;
130 struct ipi_info *ipi;
131 struct metal_io_region *io;
133 vring = &proc->vdev.vring_info[0];
134 ipi = (struct ipi_info *)(vring->intr_info.data);
135 io = vring->intr_info.io;
136 while(1) {
137 unsigned int ipi_intr_status =
138 (unsigned int)metal_io_read32(io, IPI_ISR_OFFSET);
139 if (ipi_intr_status & ipi->ipi_chn_mask) {
140 metal_io_write32(io, IPI_ISR_OFFSET,
141 ipi->ipi_chn_mask);
142 virtqueue_notification(vring->vq);
143 return 0;
144 } else if (nonblock) {
145 return -EAGAIN;
146 }
147 _rproc_wait();
148 }
149 }
151 static struct hil_proc * _initialize(void *pdata, int cpu_id)
152 {
153 (void) cpu_id;
155 struct hil_proc *proc;
156 int ret;
157 struct metal_io_region *io;
158 struct proc_intr *intr_info;
159 struct ipi_info *ipi;
160 unsigned int ipi_intr_status;
162 /* Allocate memory for proc instance */
163 proc = metal_allocate_memory(sizeof(struct hil_proc));
164 if (!proc) {
165 openamp_dbg("failed to allocate hil_proc mem\n");
166 return NULL;
167 }
168 memset(proc, 0, sizeof(struct hil_proc));
170 ret = rproc_init_plat_data(pdata, proc);
171 if (ret) {
172 openamp_dbg("failed to allocate hil_proc mem\n");
173 goto error;
174 }
175 intr_info = &(proc->vdev.vring_info[0].intr_info);
176 io = intr_info->io;
177 ipi = (struct ipi_info *)(intr_info->data);
178 ipi_intr_status =
179 (unsigned int)metal_io_read32(io, IPI_ISR_OFFSET);
180 if (ipi_intr_status & ipi->ipi_chn_mask) {
181 metal_io_write32(io, IPI_ISR_OFFSET, ipi->ipi_chn_mask);
182 }
183 metal_io_write32(io, IPI_IDR_OFFSET, ipi->ipi_chn_mask);
184 atomic_store(&ipi->sync, 1);
185 return proc;
186 error:
187 if (proc) {
188 rproc_close_plat(proc);
189 metal_free_memory(proc);
190 }
191 return NULL;
192 }
194 static void _release(struct hil_proc *proc)
195 {
196 if (proc) {
197 rproc_close_plat(proc);
198 metal_free_memory(proc);
199 }
200 }