724040686c76b87cdd2846c3184995d09facd8d4
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, *proc_data;
75 struct metal_list *node;
76 int status;
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 if (!pdata)
87 return NULL;
88 proc_data = (struct hil_proc *)pdata;
89 if (!proc_data->ops || !proc_data->ops->initialize)
90 return NULL;
92 /* Allocate memory for proc instance */
93 proc = env_allocate_memory(sizeof(struct hil_proc));
94 if (!proc) {
95 return NULL;
96 }
98 /* Get HW specfic info */
99 status = proc_data->ops->initialize(pdata,
100 proc, cpu_id);
101 if (status) {
102 env_free_memory(proc);
103 return NULL;
104 }
106 /* Enable mapping for the shared memory region */
107 env_map_memory((unsigned int)proc->sh_buff.start_addr,
108 (unsigned int)proc->sh_buff.start_addr,
109 proc->sh_buff.size, (SHARED_MEM | UNCACHED));
111 metal_list_add_tail(&procs, &proc->node);
113 return proc;
114 }
116 /**
117 * hil_delete_proc
118 *
119 * This function deletes the given proc instance and frees the
120 * associated resources.
121 *
122 * @param proc - pointer to hil remote_proc instance
123 *
124 */
125 void hil_delete_proc(struct hil_proc *proc)
126 {
127 struct metal_list *node;
128 metal_list_for_each(&procs, node) {
129 if (proc ==
130 metal_container_of(node, struct hil_proc, node)) {
131 metal_list_del(&proc->node);
132 proc->ops->release(proc);
133 return;
134 }
135 }
136 }
138 /**
139 * hil_isr()
140 *
141 * This function is called when interrupt is received for the vring.
142 * This function gets the corresponding virtqueue and generates
143 * call back for it.
144 *
145 * @param vring_hw - pointer to vring control block
146 *
147 */
148 void hil_isr(struct proc_vring *vring_hw)
149 {
150 virtqueue_notification(vring_hw->vq);
151 }
153 /**
154 * hil_get_proc
155 *
156 * This function finds the proc instance based on the given ID
157 * from the proc list and returns it to user.
158 *
159 * @param cpu_id - cpu id
160 *
161 * @return - pointer to hil proc instance
162 *
163 */
164 struct hil_proc *hil_get_proc(int cpu_id)
165 {
166 struct metal_list *node;
167 struct hil_proc *proc;
169 metal_list_for_each(&procs, node) {
170 proc = metal_container_of(node, struct hil_proc, node);
171 if (proc->cpu_id == (unsigned int)cpu_id) {
172 return proc;
173 }
174 }
176 return NULL;
177 }
179 /**
180 * hil_get_chnl_info
181 *
182 * This function returns channels info for given proc.
183 *
184 * @param proc - pointer to proc info struct
185 * @param num_chnls - pointer to integer variable to hold
186 * number of available channels
187 *
188 * @return - pointer to channel info control block
189 *
190 */
191 struct proc_chnl *hil_get_chnl_info(struct hil_proc *proc, int *num_chnls)
192 {
193 *num_chnls = proc->num_chnls;
194 return (proc->chnls);
195 }
197 /**
198 * hil_get_vdev_info
199 *
200 * This function return virtio device for remote core.
201 *
202 * @param proc - pointer to remote proc
203 *
204 * @return - pointer to virtio HW device.
205 *
206 */
208 struct proc_vdev *hil_get_vdev_info(struct hil_proc *proc)
209 {
210 return (&proc->vdev);
212 }
214 /**
215 * hil_get_vring_info
216 *
217 * This function returns vring_info_table. The caller will use
218 * this table to get the vring HW info which will be subsequently
219 * used to create virtqueues.
220 *
221 * @param vdev - pointer to virtio HW device
222 * @param num_vrings - pointer to hold number of vrings
223 *
224 * @return - pointer to vring hardware info table
225 */
226 struct proc_vring *hil_get_vring_info(struct proc_vdev *vdev, int *num_vrings)
227 {
229 *num_vrings = vdev->num_vrings;
230 return (vdev->vring_info);
232 }
234 /**
235 * hil_get_shm_info
236 *
237 * This function returns shared memory info control block. The caller
238 * will use this information to create and manage memory buffers for
239 * vring descriptor table.
240 *
241 * @param proc - pointer to proc instance
242 *
243 * @return - pointer to shared memory region used for buffers
244 *
245 */
246 struct proc_shm *hil_get_shm_info(struct hil_proc *proc)
247 {
248 return (&proc->sh_buff);
249 }
251 /**
252 * hil_enable_vring_notifications()
253 *
254 * This function is called after successful creation of virtqueues.
255 * This function saves queue handle in the vring_info_table which
256 * will be used during interrupt handling .This function setups
257 * interrupt handlers.
258 *
259 * @param vring_index - index to vring HW table
260 * @param vq - pointer to virtqueue to save in vring HW table
261 *
262 * @return - execution status
263 */
264 int hil_enable_vring_notifications(int vring_index, struct virtqueue *vq)
265 {
266 struct hil_proc *proc_hw = (struct hil_proc *)vq->vq_dev->device;
267 struct proc_vring *vring_hw = &proc_hw->vdev.vring_info[vring_index];
268 /* Save virtqueue pointer for later reference */
269 vring_hw->vq = vq;
271 if (proc_hw->ops->enable_interrupt) {
272 proc_hw->ops->enable_interrupt(vring_hw);
273 }
275 return 0;
276 }
278 /**
279 * hil_vring_notify()
280 *
281 * This function generates IPI to let the other side know that there is
282 * job available for it. The required information to achieve this, like interrupt
283 * vector, CPU id etc is be obtained from the proc_vring table.
284 *
285 * @param vq - pointer to virtqueue
286 *
287 */
288 void hil_vring_notify(struct virtqueue *vq)
289 {
290 struct hil_proc *proc_hw = (struct hil_proc *)vq->vq_dev->device;
291 struct proc_vring *vring_hw =
292 &proc_hw->vdev.vring_info[vq->vq_queue_index];
294 if (proc_hw->ops->notify) {
295 proc_hw->ops->notify(proc_hw->cpu_id, &vring_hw->intr_info);
296 }
297 }
299 /**
300 * hil_get_status
301 *
302 * This function is used to check if the given core is up and running.
303 * This call will return after it is confirmed that remote core has
304 * started.
305 *
306 * @param proc - pointer to proc instance
307 *
308 * @return - execution status
309 */
310 int hil_get_status(struct hil_proc *proc)
311 {
312 (void)proc;
314 /* For future use only. */
315 return 0;
316 }
318 /**
319 * hil_set_status
320 *
321 * This function is used to update the status
322 * of the given core i.e it is ready for IPC.
323 *
324 * @param proc - pointer to remote proc
325 *
326 * @return - execution status
327 */
328 int hil_set_status(struct hil_proc *proc)
329 {
330 (void)proc;
332 /* For future use only. */
333 return 0;
334 }
336 /**
337 * hil_boot_cpu
338 *
339 * This function boots the remote processor.
340 *
341 * @param proc - pointer to remote proc
342 * @param start_addr - start address of remote cpu
343 *
344 * @return - execution status
345 */
346 int hil_boot_cpu(struct hil_proc *proc, unsigned int start_addr)
347 {
349 if (proc->ops->boot_cpu) {
350 proc->ops->boot_cpu(proc->cpu_id, start_addr);
351 }
352 #if defined (OPENAMP_BENCHMARK_ENABLE)
353 boot_time_stamp = env_get_timestamp();
354 #endif
356 return 0;
357 }
359 /**
360 * hil_shutdown_cpu
361 *
362 * This function shutdowns the remote processor
363 *
364 * @param proc - pointer to remote proc
365 *
366 */
367 void hil_shutdown_cpu(struct hil_proc *proc)
368 {
369 if (proc->ops->shutdown_cpu) {
370 proc->ops->shutdown_cpu(proc->cpu_id);
371 }
372 #if defined (OPENAMP_BENCHMARK_ENABLE)
373 shutdown_time_stamp = env_get_timestamp();
374 #endif
375 }
377 /**
378 * hil_get_firmware
379 *
380 * This function returns address and size of given firmware name passed as
381 * parameter.
382 *
383 * @param fw_name - name of the firmware
384 * @param start_addr - pointer t hold start address of firmware
385 * @param size - pointer to hold size of firmware
386 *
387 * returns - status of function execution
388 *
389 */
390 int hil_get_firmware(char *fw_name, unsigned int *start_addr,
391 unsigned int *size)
392 {
393 return (config_get_firmware(fw_name, start_addr, size));
394 }