7bf1c727db5d12fb12185d708daed7138f851a10
[processor-sdk/open-amp.git] / lib / common / hil.c
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)
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         }
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)
127         virtqueue_notification(vring_hw->vq);
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)
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;
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)
170         *num_chnls = proc->num_chnls;
171         return (proc->chnls);
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)
187         return (&proc->vdev);
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)
206         *num_vrings = vdev->num_vrings;
207         return (vdev->vring_info);
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)
225         return (&proc->sh_buff);
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)
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;
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)
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         }
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)
289         (void)proc;
291         /* For future use only. */
292         return 0;
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)
307         (void)proc;
309         /* For future use only. */
310         return 0;
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)
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;
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)
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
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)
370         return (config_get_firmware(fw_name, start_addr, size));
373 int hil_poll (struct hil_proc *proc, int nonblock)
375         return proc->ops->poll(proc, nonblock);