1 #ifndef _HIL_H_
2 #define _HIL_H_
4 /*
5 * Copyright (c) 2014, Mentor Graphics Corporation
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
33 /**************************************************************************
34 * FILE NAME
35 *
36 * hil.h
37 *
38 * DESCRIPTION
39 *
40 * This file defines interface layer to access hardware features. This
41 * interface is used by both RPMSG and remoteproc components.
42 *
43 ***************************************************************************/
45 #include "openamp/virtio.h"
46 #include "openamp/firmware.h"
47 #include "metal/list.h"
48 #include "metal/io.h"
49 #include "metal/device.h"
50 #include "metal/mutex.h"
52 /* Configurable parameters */
53 #define HIL_MAX_CORES 2
54 #define HIL_MAX_NUM_VRINGS 2
55 #define HIL_MAX_NUM_CHANNELS 1
56 /* Reserved CPU id */
57 #define HIL_RSVD_CPU_ID 0xffffffff
59 struct hil_proc;
61 typedef void (*hil_proc_vdev_rst_cb_t)(struct hil_proc *proc, int id);
63 /**
64 * struct proc_shm
65 *
66 * This structure is maintained by hardware interface layer for
67 * shared memory information. The shared memory provides buffers
68 * for use by the vring to exchange messages between the cores.
69 *
70 */
71 struct proc_shm {
72 /* Start address of shared memory used for buffers. */
73 void *start_addr;
74 /* Start physical address of shared memory used for buffers. */
75 metal_phys_addr_t start_paddr;
76 /* sharmed memory I/O region */
77 struct metal_io_region *io;
78 /* sharmed memory metal device */
79 struct metal_device *dev;
80 /* Size of shared memory. */
81 unsigned long size;
82 /* Attributes for shared memory - cached or uncached. */
83 unsigned long flags;
84 };
86 /**
87 * struct proc_intr
88 *
89 * This structure is maintained by hardware interface layer for
90 * notification(interrupts) mechanism. The most common notification mechanism
91 * is Inter-Processor Interrupt(IPI). There can be other mechanism depending
92 * on SoC architecture.
93 *
94 */
95 struct proc_intr {
96 /* Interrupt number for vring - use for IPI */
97 unsigned int vect_id;
98 /* Interrupt priority */
99 unsigned int priority;
100 /* Interrupt trigger type */
101 unsigned int trigger_type;
102 /* IPI metal device */
103 struct metal_device *dev;
104 /* IPI device I/O */
105 struct metal_io_region *io;
106 /* Private data */
107 void *data;
108 };
110 /**
111 * struct proc_vring
112 *
113 * This structure is maintained by hardware interface layer to keep
114 * vring physical memory and notification info.
115 *
116 */
117 struct proc_vring {
118 /* Pointer to virtqueue encapsulating the vring */
119 struct virtqueue *vq;
120 /* Vring logical address */
121 void *vaddr;
122 /* Vring metal device */
123 struct metal_device *dev;
124 /* Vring I/O region */
125 struct metal_io_region *io;
126 /* Number of vring descriptors */
127 unsigned short num_descs;
128 /* Vring alignment */
129 unsigned long align;
130 /* Vring interrupt control block */
131 struct proc_intr intr_info;
132 };
134 /**
135 * struct proc_vdev
136 *
137 * This structure represents a virtio HW device for remote processor.
138 * Currently only one virtio device per processor is supported.
139 *
140 */
141 struct proc_vdev {
142 /* Address for the vdev info */
143 void *vdev_info;
144 /* Vdev interrupt control block */
145 struct proc_intr intr_info;
146 /* Vdev reset callback */
147 hil_proc_vdev_rst_cb_t rst_cb;
148 /* Number of vrings */
149 unsigned int num_vrings;
150 /* Virtio device features */
151 unsigned int dfeatures;
152 /* Virtio gen features */
153 unsigned int gfeatures;
154 /* Vring info control blocks */
155 struct proc_vring vring_info[HIL_MAX_NUM_VRINGS];
156 };
158 /**
159 * struct proc_chnl
160 *
161 * This structure represents channel IDs that would be used by
162 * the remote in the name service message. This will be extended
163 * further to support static channel creation.
164 *
165 */
166 struct proc_chnl {
167 /* Channel ID */
168 char name[32];
169 };
171 /**
172 * struct hil_proc
173 *
174 * This structure represents a remote processor and encapsulates shared
175 * memory and notification info required for IPC.
176 *
177 */
178 struct hil_proc {
179 /* HIL CPU ID */
180 unsigned long cpu_id;
181 /* HIL platform ops table */
182 struct hil_platform_ops *ops;
183 /* Shared memory info */
184 struct proc_shm sh_buff;
185 /* Virtio device hardware info */
186 struct proc_vdev vdev;
187 /* Number of RPMSG channels */
188 unsigned long num_chnls;
189 /* RPMsg channels array */
190 struct proc_chnl chnls[HIL_MAX_NUM_CHANNELS];
191 /* Initialized status */
192 int is_initialized;
193 /* hil_proc lock */
194 metal_mutex_t lock;
195 /* private data */
196 void *pdata;
197 /* List node */
198 struct metal_list node;
199 };
201 /**
202 * hil_create_proc
203 *
204 * This function creates a HIL proc instance
205 *
206 * @param ops - hil proc platform operations
207 * @param cpu_id - remote CPU ID.
208 * E.g. the CPU ID of the remote processor in its
209 * cluster.
210 * @param pdata - private data
211 * @return - pointer to proc instance
212 *
213 */
214 struct hil_proc *hil_create_proc(struct hil_platform_ops *ops,
215 unsigned long cpu_id, void *pdata);
217 /**
218 * hil_delete_proc
219 *
220 * This function deletes the given proc instance and frees the
221 * associated resources.
222 *
223 * @param proc - pointer to HIL proc instance
224 *
225 */
226 void hil_delete_proc(struct hil_proc *proc);
228 /**
229 * hil_init_proc
230 *
231 * This function initialize a HIL proc instance with the given platform data
232 * @param proc - pointer to the hil_proc to initialize
233 *
234 * @return - 0 succeeded, non-0 for failure
235 *
236 */
237 int hil_init_proc(struct hil_proc *proc);
239 /**
240 * hil_notified()
241 *
242 * This function is called when notification is received.
243 * This function gets the corresponding virtqueue and generates
244 * call back for it.
245 *
246 * @param proc - pointer to hil_proc
247 * @param notifyid - notifyid
248 *
249 */
250 void hil_notified(struct hil_proc *proc, uint32_t notifyid);
252 /**
253 * hil_get_vdev_info
254 *
255 * This function return virtio device for remote core.
256 *
257 * @param proc - pointer to remote proc
258 *
259 * @return - pointer to virtio HW device.
260 *
261 */
262 struct proc_vdev *hil_get_vdev_info(struct hil_proc *proc);
264 /**
265 * hil_get_chnl_info
266 *
267 * This function returns channels info for given proc.
268 *
269 * @param proc - pointer to proc info struct
270 * @param num_chnls - pointer to integer variable to hold
271 * number of available channels
272 *
273 * @return - pointer to channel info control block
274 *
275 */
276 struct proc_chnl *hil_get_chnl_info(struct hil_proc *proc, int *num_chnls);
278 /**
279 * hil_get_vring_info
280 *
281 * This function returns vring_info_table. The caller will use
282 * this table to get the vring HW info which will be subsequently
283 * used to create virtqueues.
284 *
285 * @param vdev - pointer to virtio HW device
286 * @param num_vrings - pointer to hold number of vrings
287 *
288 * @return - pointer to vring hardware info table
289 */
290 struct proc_vring *hil_get_vring_info(struct proc_vdev *vdev, int *num_vrings);
292 /**
293 * hil_get_shm_info
294 *
295 * This function returns shared memory info control block. The caller
296 * will use this information to create and manage memory buffers for
297 * vring descriptor table.
298 *
299 * @param proc - pointer to proc instance
300 *
301 * @return - pointer to shared memory region used for buffers
302 *
303 */
304 struct proc_shm *hil_get_shm_info(struct hil_proc *proc);
306 /**
307 * hil_free_virtqueues
308 *
309 * This function remove virt queues of the vdev.
311 * @param vdev - pointer to the vdev which needs to remove vqs
312 */
313 void hil_free_vqs(struct virtio_device *vdev);
315 /**
316 * hil_enable_vdev_notification()
317 *
318 * This function enable handler for vdev notification.
319 *
320 * @param proc - pointer to hil_proc
321 * @param id - vdev index
322 *
323 * @return - execution status
324 */
325 int hil_enable_vdev_notification(struct hil_proc *proc, int id);
327 /**
328 * hil_enable_vring_notifications()
329 *
330 * This function is called after successful creation of virtqueues.
331 * This function saves queue handle in the vring_info_table which
332 * will be used during interrupt handling .This function setups
333 * interrupt handlers.
334 *
335 * @param vring_index - index to vring HW table
336 * @param vq - pointer to virtqueue to save in vring HW table
337 *
338 * @return - execution status
339 */
340 int hil_enable_vring_notifications(int vring_index, struct virtqueue *vq);
342 /**
343 * hil_vdev_notify()
344 *
345 * This function generates IPI to let the other side know that there is
346 * change to virtio device configs.
347 *
348 * @param vdev - pointer to virtio device
349 *
350 */
351 void hil_vdev_notify(struct virtio_device *vdev);
353 /**
354 * hil_vring_notify()
355 *
356 * This function generates IPI to let the other side know that there is
357 * job available for it. The required information to achieve this, like interrupt
358 * vector, CPU id etc is be obtained from the proc_vring table.
359 *
360 * @param vq - pointer to virtqueue
361 *
362 */
363 void hil_vring_notify(struct virtqueue *vq);
365 /**
366 * hil_get_status
367 *
368 * This function is used to check if the given core is up and running.
369 * This call will return after it is confirmed that remote core has
370 * started.
371 *
372 * @param proc - pointer to proc instance
373 *
374 * @return - execution status
375 */
376 int hil_get_status(struct hil_proc *proc);
378 /**
379 * hil_set_status
380 *
381 * This function is used to update the status
382 * of the given core i.e it is ready for IPC.
383 *
384 * @param proc - pointer to remote proc
385 *
386 * @return - execution status
387 */
389 int hil_set_status(struct hil_proc *proc);
391 /**
392 * hil_boot_cpu
393 *
394 * This function starts remote processor at given address.
395 *
396 * @param proc - pointer to remote proc
397 * @param load_addr - load address of remote firmware
398 *
399 * @return - execution status
400 */
401 int hil_boot_cpu(struct hil_proc *proc, unsigned int load_addr);
403 /**
404 * hil_shutdown_cpu
405 *
406 * This function shutdowns the remote processor
407 *
408 * @param proc - pointer to remote proc
409 *
410 */
411 void hil_shutdown_cpu(struct hil_proc *proc);
413 /**
414 * hil_get_firmware
415 *
416 * This function returns address and size of given firmware name passed as
417 * parameter.
418 *
419 * @param fw_name - name of the firmware
420 * @param start_addr - pointer t hold start address of firmware
421 * @param size - pointer to hold size of firmware
422 *
423 * returns - status of function execution
424 *
425 */
426 int hil_get_firmware(char *fw_name, uintptr_t *start_addr,
427 unsigned int *size);
429 /**
430 * hil_poll
431 *
432 * This function polls the remote processor.
433 * If it is blocking mode, it will not return until the remoteproc
434 * is signaled. If it is non-blocking mode, it will return 0
435 * if the remoteproc has pending signals, it will return non 0
436 * otherwise.
437 *
438 * @param proc - hil_proc to poll
439 * @param nonblock - 0 for blocking, non-0 for non-blocking.
440 *
441 * @return - 0 for no errors, non-0 for errors.
442 */
443 int hil_poll (struct hil_proc *proc, int nonblock);
445 /**
446 * hil_set_shm
447 *
448 * This function set HIL proc shared memory
449 *
450 * @param proc - hil_proc to set
451 * @param bus_name - bus name of the shared memory device
452 * @param name - name of the shared memory, or platform device
453 * mandatory for Linux system.
454 * @param paddr - physical address of the memory for baremetal/RTOS only
455 * @param size - size of the shared memory
456 *
457 * If name argument exists, it will open the specified libmetal
458 * shared memory or the specified libmetal device if bus_name
459 * is specified to get the I/O region of the shared memory. Otherwise, it
460 * will use a generic normal I/O region for the shared memory.
461 * paddr argument is for baremetal/RTOS system only. Linux system
462 * will not take this paddr, for Linux system, you have to specify
463 * the name, otherwise, you will get segfault later.
464 *
465 * @return - 0 for no errors, non-0 for errors.
466 */
467 int hil_set_shm (struct hil_proc *proc,
468 const char *bus_name, const char *name,
469 metal_phys_addr_t paddr, size_t size);
471 /**
472 * hil_set_vring
473 *
474 * This function set HIL proc vring
475 *
476 * @param proc - hil_proc to set
477 * @param index - vring index
478 * @param bus_name - bus name of the vring device
479 * @param name - name of the shared memory, or platform device
480 * mandatory for Linux system.
481 *
482 * If name argument exists, it will open the specified libmetal
483 * shared memory or the specified device if bus name is specified
484 * to get the I/O region of the vring.
485 *
486 * @return - 0 for no errors, non-0 for errors.
487 */
488 int hil_set_vring (struct hil_proc *proc, int index,
489 const char *bus_name, const char *name);
491 /**
492 * hil_set_vdev_ipi
493 *
494 * This function set HIL proc vdev IPI
495 *
496 * @param proc - hil_proc to set
497 * @param index - vring index for the IPI
498 * @param irq - IPI irq vector ID
499 * @param data - IPI data
500 *
501 * @return - 0 for no errors, non-0 for errors.
502 */
503 int hil_set_vdev_ipi (struct hil_proc *proc, int index,
504 unsigned int irq, void *data);
506 /**
507 * hil_set_vring_ipi
508 *
509 * This function set HIL proc vring IPI
510 *
511 * @param proc - hil_proc to set
512 * @param index - vring index for the IPI
513 * @param irq - IPI irq vector ID
514 * @param data - IPI data
515 *
516 * @return - 0 for no errors, non-0 for errors.
517 */
518 int hil_set_vring_ipi (struct hil_proc *proc, int index,
519 unsigned int irq, void *data);
521 /**
522 * hil_set_rpmsg_channel
523 *
524 * This function set HIL proc rpmsg_channel
525 *
526 * @param proc - hil_proc to set
527 * @param index - vring index for the rpmsg_channel
528 * @param name - RPMsg channel name
529 *
530 * @return - 0 for no errors, non-0 for errors.
531 */
532 int hil_set_rpmsg_channel (struct hil_proc *proc, int index,
533 char *name);
535 /**
536 * hil_set_vdev_rst_cb
537 *
538 * This function set HIL proc vdev reset callback
539 *
540 * @param proc - hil_proc to set
541 * @param index - vdev index
542 * @param cb - reset callback
543 *
544 * @return - 0 for no errors, non-0 for errors.
545 */
546 int hil_set_vdev_rst_cb (struct hil_proc *proc, int index,
547 hil_proc_vdev_rst_cb_t cb);
549 /**
550 *
551 * This structure is an interface between HIL and platform porting
552 * component. It is required for the user to provide definitions of
553 * these functions when framework is ported to new hardware platform.
554 *
555 */
556 struct hil_platform_ops {
557 /**
558 * enable_interrupt()
559 *
560 * This function enables interrupt(IPI)
561 *
562 * @param intr - pointer to intr information
563 *
564 * @return - execution status
565 */
566 int (*enable_interrupt) (struct proc_intr *intr);
568 /**
569 * notify()
570 *
571 * This function generates IPI to let the other side know that there is
572 * job available for it.
573 *
574 * @param proc - pointer to the hil_proc
575 * @param intr_info - pointer to interrupt info control block
576 */
577 void (*notify) (struct hil_proc *proc, struct proc_intr * intr_info);
579 /**
580 * boot_cpu
581 *
582 * This unction boots the remote processor.
583 *
584 * @param proc - pointer to the hil_proc
585 * @param start_addr - start address of remote cpu
586 *
587 * @return - execution status
588 */
589 int (*boot_cpu) (struct hil_proc *proc, unsigned int start_addr);
591 /**
592 * shutdown_cpu
593 *
594 * This function shutdowns the remote processor.
595 *
596 * @param proc - pointer to the hil_proc
597 *
598 */
599 void (*shutdown_cpu) (struct hil_proc *proc);
601 /**
602 * poll
603 *
604 * This function polls the remote processor.
605 *
606 * @param proc - hil_proc to poll
607 * @param nonblock - 0 for blocking, non-0 for non-blocking.
608 *
609 * @return - 0 for no errors, non-0 for errors.
610 */
611 int (*poll) (struct hil_proc *proc, int nonblock);
613 /**
614 * initialize
615 *
616 * This function initialize remote processor with platform data.
617 *
618 * @param proc - hil_proc to poll
619 *
620 * @return NULL on failure, hil_proc pointer otherwise
621 *
622 */
623 int (*initialize) (struct hil_proc *proc);
625 /**
626 * release
627 *
628 * This function is to release remote processor resource
629 *
630 * @param[in] proc - pointer to the remote processor
631 *
632 */
633 void (*release) (struct hil_proc *proc);
634 };
636 /* Utility macros for register read/write */
637 #define HIL_MEM_READ8(addr) *(volatile unsigned char *)(addr)
638 #define HIL_MEM_READ16(addr) *(volatile unsigned short *)(addr)
639 #define HIL_MEM_READ32(addr) *(volatile unsigned long *)(addr)
640 #define HIL_MEM_WRITE8(addr,data) *(volatile unsigned char *)(addr) = (unsigned char)(data)
641 #define HIL_MEM_WRITE16(addr,data) *(volatile unsigned short *)(addr) = (unsigned short)(data)
642 #define HIL_MEM_WRITE32(addr,data) *(volatile unsigned long *)(addr) = (unsigned long)(data)
644 #endif /* _HIL_H_ */