7bf1c727db5d12fb12185d708daed7138f851a10
1 /*
2 * Copyright (c) 2014, Mentor Graphics Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. Neither the name of Mentor Graphics Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
30 /**************************************************************************
31 * FILE NAME
32 *
33 * hil.c
34 *
35 * COMPONENT
36 *
37 * OpenAMP Stack.
38 *
39 * DESCRIPTION
40 *
41 * This file is implementation of generic part of HIL.
42 *
43 *
44 *
45 **************************************************************************/
47 #include "openamp/hil.h"
48 #include "metal/utilities.h"
50 /*--------------------------- Globals ---------------------------------- */
51 static METAL_DECLARE_LIST (procs);
53 #if defined (OPENAMP_BENCHMARK_ENABLE)
55 unsigned long long boot_time_stamp;
56 unsigned long long shutdown_time_stamp;
58 #endif
60 /**
61 * hil_create_proc
62 *
63 * This function creates a HIL proc instance for given CPU id and populates
64 * it with platform info.
65 *
66 * @param pdata - platform data for the remote processor
67 * @param cpu_id - cpu id
68 *
69 * @return - pointer to proc instance
70 *
71 */
72 struct hil_proc *hil_create_proc(void *pdata, int cpu_id)
73 {
74 struct hil_proc *proc = 0;
75 struct proc_info_hdr *info_hdr = (struct proc_info_hdr *)pdata;
76 struct metal_list *node;
78 /* If proc already exists then return it */
79 metal_list_for_each(&procs, node) {
80 proc = metal_container_of(node, struct hil_proc, node);
81 if (proc->cpu_id == (unsigned int)cpu_id) {
82 return proc;
83 }
84 }
86 proc = info_hdr->ops->initialize(pdata, cpu_id);
87 if (proc)
88 metal_list_add_tail(&procs, &proc->node);
90 return proc;
91 }
93 /**
94 * hil_delete_proc
95 *
96 * This function deletes the given proc instance and frees the
97 * associated resources.
98 *
99 * @param proc - pointer to hil remote_proc instance
100 *
101 */
102 void hil_delete_proc(struct hil_proc *proc)
103 {
104 struct metal_list *node;
105 metal_list_for_each(&procs, node) {
106 if (proc ==
107 metal_container_of(node, struct hil_proc, node)) {
108 metal_list_del(&proc->node);
109 proc->ops->release(proc);
110 return;
111 }
112 }
113 }
115 /**
116 * hil_isr()
117 *
118 * This function is called when interrupt is received for the vring.
119 * This function gets the corresponding virtqueue and generates
120 * call back for it.
121 *
122 * @param vring_hw - pointer to vring control block
123 *
124 */
125 void hil_isr(struct proc_vring *vring_hw)
126 {
127 virtqueue_notification(vring_hw->vq);
128 }
130 /**
131 * hil_get_proc
132 *
133 * This function finds the proc instance based on the given ID
134 * from the proc list and returns it to user.
135 *
136 * @param cpu_id - cpu id
137 *
138 * @return - pointer to hil proc instance
139 *
140 */
141 struct hil_proc *hil_get_proc(int cpu_id)
142 {
143 struct metal_list *node;
144 struct hil_proc *proc;
146 metal_list_for_each(&procs, node) {
147 proc = metal_container_of(node, struct hil_proc, node);
148 if (proc->cpu_id == (unsigned int)cpu_id) {
149 return proc;
150 }
151 }
153 return NULL;
154 }
156 /**
157 * hil_get_chnl_info
158 *
159 * This function returns channels info for given proc.
160 *
161 * @param proc - pointer to proc info struct
162 * @param num_chnls - pointer to integer variable to hold
163 * number of available channels
164 *
165 * @return - pointer to channel info control block
166 *
167 */
168 struct proc_chnl *hil_get_chnl_info(struct hil_proc *proc, int *num_chnls)
169 {
170 *num_chnls = proc->num_chnls;
171 return (proc->chnls);
172 }
174 /**
175 * hil_get_vdev_info
176 *
177 * This function return virtio device for remote core.
178 *
179 * @param proc - pointer to remote proc
180 *
181 * @return - pointer to virtio HW device.
182 *
183 */
185 struct proc_vdev *hil_get_vdev_info(struct hil_proc *proc)
186 {
187 return (&proc->vdev);
189 }
191 /**
192 * hil_get_vring_info
193 *
194 * This function returns vring_info_table. The caller will use
195 * this table to get the vring HW info which will be subsequently
196 * used to create virtqueues.
197 *
198 * @param vdev - pointer to virtio HW device
199 * @param num_vrings - pointer to hold number of vrings
200 *
201 * @return - pointer to vring hardware info table
202 */
203 struct proc_vring *hil_get_vring_info(struct proc_vdev *vdev, int *num_vrings)
204 {
206 *num_vrings = vdev->num_vrings;
207 return (vdev->vring_info);
209 }
211 /**
212 * hil_get_shm_info
213 *
214 * This function returns shared memory info control block. The caller
215 * will use this information to create and manage memory buffers for
216 * vring descriptor table.
217 *
218 * @param proc - pointer to proc instance
219 *
220 * @return - pointer to shared memory region used for buffers
221 *
222 */
223 struct proc_shm *hil_get_shm_info(struct hil_proc *proc)
224 {
225 return (&proc->sh_buff);
226 }
228 /**
229 * hil_enable_vring_notifications()
230 *
231 * This function is called after successful creation of virtqueues.
232 * This function saves queue handle in the vring_info_table which
233 * will be used during interrupt handling .This function setups
234 * interrupt handlers.
235 *
236 * @param vring_index - index to vring HW table
237 * @param vq - pointer to virtqueue to save in vring HW table
238 *
239 * @return - execution status
240 */
241 int hil_enable_vring_notifications(int vring_index, struct virtqueue *vq)
242 {
243 struct hil_proc *proc_hw = (struct hil_proc *)vq->vq_dev->device;
244 struct proc_vring *vring_hw = &proc_hw->vdev.vring_info[vring_index];
245 /* Save virtqueue pointer for later reference */
246 vring_hw->vq = vq;
248 if (proc_hw->ops->enable_interrupt) {
249 proc_hw->ops->enable_interrupt(vring_hw);
250 }
252 return 0;
253 }
255 /**
256 * hil_vring_notify()
257 *
258 * This function generates IPI to let the other side know that there is
259 * job available for it. The required information to achieve this, like interrupt
260 * vector, CPU id etc is be obtained from the proc_vring table.
261 *
262 * @param vq - pointer to virtqueue
263 *
264 */
265 void hil_vring_notify(struct virtqueue *vq)
266 {
267 struct hil_proc *proc_hw = (struct hil_proc *)vq->vq_dev->device;
268 struct proc_vring *vring_hw =
269 &proc_hw->vdev.vring_info[vq->vq_queue_index];
271 if (proc_hw->ops->notify) {
272 proc_hw->ops->notify(proc_hw->cpu_id, &vring_hw->intr_info);
273 }
274 }
276 /**
277 * hil_get_status
278 *
279 * This function is used to check if the given core is up and running.
280 * This call will return after it is confirmed that remote core has
281 * started.
282 *
283 * @param proc - pointer to proc instance
284 *
285 * @return - execution status
286 */
287 int hil_get_status(struct hil_proc *proc)
288 {
289 (void)proc;
291 /* For future use only. */
292 return 0;
293 }
295 /**
296 * hil_set_status
297 *
298 * This function is used to update the status
299 * of the given core i.e it is ready for IPC.
300 *
301 * @param proc - pointer to remote proc
302 *
303 * @return - execution status
304 */
305 int hil_set_status(struct hil_proc *proc)
306 {
307 (void)proc;
309 /* For future use only. */
310 return 0;
311 }
313 /**
314 * hil_boot_cpu
315 *
316 * This function boots the remote processor.
317 *
318 * @param proc - pointer to remote proc
319 * @param start_addr - start address of remote cpu
320 *
321 * @return - execution status
322 */
323 int hil_boot_cpu(struct hil_proc *proc, unsigned int start_addr)
324 {
326 if (proc->ops->boot_cpu) {
327 proc->ops->boot_cpu(proc->cpu_id, start_addr);
328 }
329 #if defined (OPENAMP_BENCHMARK_ENABLE)
330 boot_time_stamp = env_get_timestamp();
331 #endif
333 return 0;
334 }
336 /**
337 * hil_shutdown_cpu
338 *
339 * This function shutdowns the remote processor
340 *
341 * @param proc - pointer to remote proc
342 *
343 */
344 void hil_shutdown_cpu(struct hil_proc *proc)
345 {
346 if (proc->ops->shutdown_cpu) {
347 proc->ops->shutdown_cpu(proc->cpu_id);
348 }
349 #if defined (OPENAMP_BENCHMARK_ENABLE)
350 shutdown_time_stamp = env_get_timestamp();
351 #endif
352 }
354 /**
355 * hil_get_firmware
356 *
357 * This function returns address and size of given firmware name passed as
358 * parameter.
359 *
360 * @param fw_name - name of the firmware
361 * @param start_addr - pointer t hold start address of firmware
362 * @param size - pointer to hold size of firmware
363 *
364 * returns - status of function execution
365 *
366 */
367 int hil_get_firmware(char *fw_name, uintptr_t *start_addr,
368 unsigned int *size)
369 {
370 return (config_get_firmware(fw_name, start_addr, size));
371 }
373 int hil_poll (struct hil_proc *proc, int nonblock)
374 {
375 return proc->ops->poll(proc, nonblock);
376 }