]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/am65xx/NotifySetup.c
K3: Add support for K3 AM65XX device
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / am65xx / NotifySetup.c
1 /*
2  * Copyright (c) 2017-2018 Texas Instruments Incorporated - http://www.ti.com
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
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software 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,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /*
34  *  ======== NotifySetup.c ========
35  */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Assert.h>
38 #include <xdc/runtime/Error.h>
39 #include <xdc/runtime/Startup.h>
41 #include <ti/sdo/ipc/_Notify.h>
42 #include <ti/sdo/ipc/family/am65xx/NotifyDriverMbx.h>
43 #include <ti/sdo/ipc/notifyDrivers/NotifyDriverShm.h>
44 #include <ti/sdo/utils/_MultiProc.h>
46 #if defined(xdc_target__isaCompatible_v7R)
48 #include <ti/sysbios/BIOS.h>
49 #include <ti/sysbios/family/arm/v7r/keystone3/Hwi.h>
50 #include <ti/sysbios/family/arm/v7r/keystone3/Core.h>
52 #elif defined(xdc_target__isaCompatible_v8A)
53 #include <ti/sysbios/family/arm/gicv3/Hwi.h>
54 #else
55 #error Invalid target
56 #endif
58 #include "package/internal/NotifySetup.xdc.h"
61 #define EVENT_GROUP_SIZE 32
63 /* register access methods */
64 #define REG16(A)        (*(volatile UInt16 *)(A))
65 #define REG32(A)        (*(volatile UInt32 *)(A))
67 /* ipc helper macros */
68 #define MAILBOX_REG_VAL(m) (0x1 << (2 * (m)))
70 #define VIRTID(procId) (NotifySetup_procIdTable[(procId)])
72 #define MBX_BASEADDR_IDX(idx) ((NotifySetup_mailboxTable[(idx)] >> 16) & 0xFFFF)
74 #define MBX_USER_IDX(idx) ((NotifySetup_mailboxTable[(idx)] >> 8) & 0xFF)
76 #define SUBMBX_IDX(idx) (NotifySetup_mailboxTable[(idx)] & 0xFF)
78 #define MAILBOX_ADDR(idx) \
79         (NotifySetup_mailboxBaseAddr[MBX_BASEADDR_IDX(idx)])
81 #define MAILBOX_STATUS(idx) \
82         (MAILBOX_ADDR((idx)) + 0xC0 + (0x4 * SUBMBX_IDX((idx))))
84 #define MAILBOX_IRQENABLE_SET(idx) \
85         (MAILBOX_ADDR((idx)) + 0x108 + (0x10 * MBX_USER_IDX((idx))))
87 #define MBOX_IRQ_ENABLE(idx) \
88     ((REG32(MAILBOX_IRQENABLE_SET((idx))) & \
89     MAILBOX_REG_VAL(SUBMBX_IDX((idx)))) != 0)
91 #define MBOX_MSG_COUNT(idx) (REG32(MAILBOX_STATUS((idx))))
93 #define M2M_LVL_INT_RTR_BASE 0x00A10000
94 #define M2M_LV_INT_ICR0_OFFSET 0x4
95 #define NAVSS_INT_RTR_BASE 0x310E0000
96 #define NAVSS_INT_ICR0_OFFSET 0x4
98 /* Corresponds to VIM: 160 */
99 #define M2M_LVL_INT_RTR_OUTPUT_R5F0_0 0
100 /* Corresponds to VIM: 161 */
101 #define M2M_LVL_INT_RTR_OUTPUT_R5F0_1 1
102 /* Corresponds to VIM: 162 */
103 #define M2M_LVL_INT_RTR_OUTPUT_R5F1_0 2
104 /* Corresponds to VIM: 163 */
105 #define M2M_LVL_INT_RTR_OUTPUT_R5F1_1 3
107 #define NAVSS_INT_RTR_INPUT_MAILBOX0_USER0 436
108 #define NAVSS_INT_RTR_INPUT_MAILBOX0_USER1 437
110 #define NAVSS_INT_RTR_INPUT_MAILBOX1_USER0 432
111 #define NAVSS_INT_RTR_INPUT_MAILBOX1_USER1 433
113 #define NAVSS_INT_RTR_INPUT_MAILBOX2_USER0 428
114 #define NAVSS_INT_RTR_INPUT_MAILBOX2_USER1 429
116 /* Corresponds to GIC: 496 */
117 #define NAVSS_INT_RTR_OUTPUT_A53_0    112
118 /* Corresponds to GIC: 497 */
119 #define NAVSS_INT_RTR_OUTPUT_A53_1    113
121 #define NAVSS_INT_RTR_OUTPUT_R5F0_0 120
122 #define NAVSS_INT_RTR_OUTPUT_R5F1_0 121
123 #define NAVSS_INT_RTR_OUTPUT_R5F0_1 122
124 #define NAVSS_INT_RTR_OUTPUT_R5F1_1 123
126 /* The following INPUT is connected to NAVSS OUTPUT 120 */
127 #define M2M_LVL_INT_RTR_INPUT_A53_PEND_120 184
128 /* The following INPUT is connected to NAVSS OUTPUT 121 */
129 #define M2M_LVL_INT_RTR_INPUT_A53_PEND_121 185
131 /* The following INPUT is connected to NAVSS OUTPUT 122 */
132 #define M2M_LVL_INT_RTR_INPUT_A53_PEND_122 186
133 /* The following INPUT is connected to NAVSS OUTPUT 123 */
134 #define M2M_LVL_INT_RTR_INPUT_A53_PEND_123 187
136 static inline void connect_m2m_lvl_int_rtr(UInt32 input_evt, UInt32 output_line)
138 #ifdef INTERRUPT_ROUTING_THROUGH_DMSC
139     /* TODO: Need to add code to configure routing through DMSC */
140 #else
141     /* TODO: Eventually the interrupt routing below cannot be done
142      * directly. Need to go through DMSC. Currently this is done
143      * directly to help Pre-silicon testing
144      */
145     *((UInt32 *)(M2M_LVL_INT_RTR_BASE + M2M_LV_INT_ICR0_OFFSET) + output_line) = input_evt;
146 #endif
149 static inline void connect_navss_int_rtr(UInt32 input_evt, UInt32 output_line)
151 #ifdef INTERRUPT_ROUTING_THROUGH_DMSC
152     /* TODO: Need to add code to configure routing through DMSC */
153 #else
154     /* TODO: Eventually the interrupt routing below cannot be done
155      * directly. Need to go through DMSC. Currently this is done
156      * directly to help Pre-silicon testing
157      */
158     *((UInt32 *)(NAVSS_INT_RTR_BASE + NAVSS_INT_ICR0_OFFSET) + output_line) = input_evt;
159 #endif
162 /*
163  *************************************************************************
164  *                      Module functions
165  *************************************************************************
166  */
168 /*
169  *  ======== NotifySetup_Module_startup ========
170  */
171 Int NotifySetup_Module_startup(Int phase)
173 #if defined(xdc_target__isaCompatible_v7R)
174     /* connect mailbox interrupts at startup */
175     if ((Core_getId() == 0)) {
176         /* R5F-0 */
177         /* Navss mailbox 0 User 1 */
178         /* Configure NAVSS interrupt router */
179         connect_navss_int_rtr(NAVSS_INT_RTR_INPUT_MAILBOX0_USER1,
180             NAVSS_INT_RTR_OUTPUT_R5F0_0);
181         /* Configure MCU level interrupt router */
182         connect_m2m_lvl_int_rtr(M2M_LVL_INT_RTR_INPUT_A53_PEND_120,
183             M2M_LVL_INT_RTR_OUTPUT_R5F0_0);
185         /* plug mbx2 only if R5F-1 exists */
186         if ((MultiProc_getId("R5F-1") != MultiProc_INVALIDID)) {
187             /* Navss mailbox 2 User 0 */
188             /* Configure NAVSS interrupt router */
189             connect_navss_int_rtr(NAVSS_INT_RTR_INPUT_MAILBOX2_USER0,
190                 NAVSS_INT_RTR_OUTPUT_R5F0_1);
191             /* Configure MCU level interrupt router */
192             connect_m2m_lvl_int_rtr(M2M_LVL_INT_RTR_INPUT_A53_PEND_121,
193                 M2M_LVL_INT_RTR_OUTPUT_R5F0_1);
194         }
195     }
196     else { /* R5F-1 */
197         /* Navss mailbox 1 User 1 */
198         /* Configure NAVSS interrupt router */
199         connect_navss_int_rtr(NAVSS_INT_RTR_INPUT_MAILBOX1_USER1,
200             NAVSS_INT_RTR_OUTPUT_R5F1_0);
201         /* Configure MCU level interrupt router */
202         connect_m2m_lvl_int_rtr(M2M_LVL_INT_RTR_INPUT_A53_PEND_122,
203             M2M_LVL_INT_RTR_OUTPUT_R5F1_1);
205         /* plug mbx2 only if R5F-0 exists */
206         if ((MultiProc_getId("R5F-0") != MultiProc_INVALIDID)) {
207             /* Navss mailbox 2 User 1 */
208             /* Configure NAVSS interrupt router */
209             connect_navss_int_rtr(NAVSS_INT_RTR_INPUT_MAILBOX2_USER1,
210                 NAVSS_INT_RTR_OUTPUT_R5F1_1);
211             /* Configure MCU level interrupt router */
212             connect_m2m_lvl_int_rtr(M2M_LVL_INT_RTR_INPUT_A53_PEND_123,
213                 M2M_LVL_INT_RTR_OUTPUT_R5F1_1);
214         }
215     }
216     return (Startup_DONE);
218 #elif defined(xdc_target__isaCompatible_v8A)
219     /* Navss mailbox 0 User 0 */
220     /* Configure NAVSS interrupt router */
221     connect_navss_int_rtr(NAVSS_INT_RTR_INPUT_MAILBOX0_USER0,
222         NAVSS_INT_RTR_OUTPUT_A53_0);
223     /* Navss mailbox 1 User 0 */
224     /* Configure NAVSS interrupt router */
225     connect_navss_int_rtr(NAVSS_INT_RTR_INPUT_MAILBOX1_USER0,
226         NAVSS_INT_RTR_OUTPUT_A53_1);
227     return (Startup_DONE);
229 #else
230 #error Invalid target
231 #endif
234 /*
235  *  ======== NotifySetup_interruptTable ========
236  */
237 UInt16 NotifySetup_interruptTable(Int srcVirtId)
239     return (NotifySetup_module->interruptTable[srcVirtId]);
242 /*
243  *  ======== NotifySetup_attach ========
244  *  Create driver instance specified at config time.
245  *
246  *  This functions is generated by the NotifySetup.xdt template.
247  */
249 /*
250  *  ======== NotifySetup_sharedMemReq ========
251  *  Compute how much shared memory is required by the driver.
252  *
253  *  This functions is generated by the NotifySetup.xdt template.
254  */
256 /*
257  * ======== NotifySetup_numIntLines ========
258  * Return number of available interrupt lines to the current processor.
259  */
260 UInt16 NotifySetup_numIntLines(UInt16 remoteProcId)
262     return (1);
265 /*
266  *  ======== NotifySetup_driverType ========
267  *  Find driver type for given connection.
268  *
269  *  Search the connection array for the given remote processor. If
270  *  found, return the requested notify driver type.
271  */
272 NotifySetup_Driver NotifySetup_driverType(UInt16 remoteProcId)
274     Int i;
275     NotifySetup_Driver driver = NotifySetup_Driver_SHAREDMEMORY;
277     /* look for remote processor in connection array */
278     for (i = 0; i < NotifySetup_module->connAry.length; i++) {
279         if (remoteProcId == NotifySetup_module->connAry.elem[i].procId) {
280             driver = NotifySetup_module->connAry.elem[i].driver;
281             break;
282         }
283     }
285     return (driver);
288 /*
289  *  ======== NotifySetup_plugHwi ========
290  */
291 Void NotifySetup_plugHwi(UInt16 remoteProcId, Int cpuIntrNum,
292         NotifySetup_DriverIsr isr)
294     Error_Block eb;
295     UInt        key;
296     Hwi_Params  hwiParams;
297     UInt16      srcVirtId;
298 #if defined(xdc_target__isaCompatible_v7R) \
299     || defined(xdc_target__isaCompatible_v8A)
300     UInt16      idx;
301     UInt        mbxIdx;
302 #endif
304     Error_init(&eb);
306     /* disable interrupts */
307     key = Hwi_disable();
309     /* map remote processor id to virtual id */
310     srcVirtId = VIRTID(remoteProcId);
312     /* save driver ISR in dispatch table */
313     NotifySetup_module->isrDispatchTable[srcVirtId] = isr;
315 #if defined(xdc_target__isaCompatible_v7R) \
316     || defined(xdc_target__isaCompatible_v8A)
318     /* compute table index for given source and destination */
319     idx = (srcVirtId * NotifySetup_NUM_CORES) + VIRTID(MultiProc_self());
321     /* compute mailbox index */
322     mbxIdx = MBX_BASEADDR_IDX(idx);
324     /* make sure the interrupt is plugged only once */
325     NotifySetup_module->numPlugged[mbxIdx]++;
327     if (NotifySetup_module->numPlugged[mbxIdx] == 1) {
329         Hwi_Params_init(&hwiParams);
330         hwiParams.maskSetting = Hwi_MaskingOption_LOWER;
331         hwiParams.arg = cpuIntrNum;
333         Hwi_create(cpuIntrNum, NotifySetup_dispatchIsr, &hwiParams, &eb);
334         /* TODO: add error handling */
336         Hwi_enableInterrupt(cpuIntrNum);
337     }
339 #else
340 #error Invalid target
341 #endif
343     /* restore interrupts */
344     Hwi_restore(key);
347 /*
348  *  ======== NotifySetup_unplugHwi ========
349  */
350 Void NotifySetup_unplugHwi(UInt16 remoteProcId, Int cpuIntrNum)
352     UInt        key;
353     Hwi_Handle  hwi;
354     UInt16      srcVirtId;
355 #if defined(xdc_target__isaCompatible_v7R) \
356     || defined(xdc_target__isaCompatible_v8A)
357     UInt16      idx;
358     UInt        mbxIdx;
359 #endif
361     /* disable global interrupts (TODO: should be a gated module) */
362     key = Hwi_disable();
364     /* map processor id to virtual id */
365     srcVirtId = VIRTID(remoteProcId);
367     /* remove driver isr from dispatch table */
368     NotifySetup_module->isrDispatchTable[srcVirtId] = NULL;
370 #if defined(xdc_target__isaCompatible_v7R) \
371     || defined(xdc_target__isaCompatible_v8A)
373     /* decrement plug count */
374     idx = (srcVirtId * NotifySetup_NUM_CORES) + VIRTID(MultiProc_self());
375     mbxIdx = MBX_BASEADDR_IDX(idx);
376     NotifySetup_module->numPlugged[mbxIdx]--;
378     /* unplug interrupt if last user */
379     if (NotifySetup_module->numPlugged[0] == 0) {
380         hwi = Hwi_getHandle(cpuIntrNum);
381         Hwi_delete(&hwi);
382     }
384 #else
385 #error Invalid target
386 #endif
388     /* restore global interrupts */
389     Hwi_restore(key);
392 /*
393  *  ======== NotifySetup_Shm_attach ========
394  */
395 Int NotifySetup_Shm_attach(UInt16 remoteProcId, Ptr sharedAddr)
397     NotifyDriverShm_Params notifyShmParams;
398     NotifyDriverShm_Handle shmDrvHandle;
399     ti_sdo_ipc_Notify_Handle notifyHandle;
400     Int status = Notify_S_SUCCESS;
401     Error_Block eb;
403     Error_init(&eb);
405     NotifyDriverShm_Params_init(&notifyShmParams);
406     notifyShmParams.sharedAddr = sharedAddr;
407     notifyShmParams.remoteProcId  = remoteProcId;
409     /* create the notify driver instance */
410     shmDrvHandle = NotifyDriverShm_create(&notifyShmParams, &eb);
412     if (shmDrvHandle == NULL) {
413         return (Notify_E_FAIL);
414     }
416     /* create the front-end notify instance */
417     notifyHandle = ti_sdo_ipc_Notify_create(
418             NotifyDriverShm_Handle_upCast(shmDrvHandle), remoteProcId, 0,
419             NULL, &eb);
421     if (notifyHandle == NULL) {
422         NotifyDriverShm_delete(&shmDrvHandle);
423         status = Notify_E_FAIL;
424     }
426     return (status);
429 /*!
430  *  ======== NotifySetup_Shm_sharedMemReq ========
431  */
432 SizeT NotifySetup_Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
434     SizeT memReq;
435     NotifyDriverShm_Params notifyShmParams;
437     NotifyDriverShm_Params_init(&notifyShmParams);
438     notifyShmParams.sharedAddr = sharedAddr;
440     memReq = NotifyDriverShm_sharedMemReq(&notifyShmParams);
442     return (memReq);
445 /*
446  *  ======== NotifySetup_Mbx_attach ========
447  */
448 Int NotifySetup_Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr)
450     Int status = Notify_S_SUCCESS;
451     NotifyDriverMbx_Params params;
452     NotifyDriverMbx_Handle driver;
453     ti_sdo_ipc_Notify_Handle notify;
454     UInt16 virtId;
455     Error_Block eb;
457     Error_init(&eb);
459     NotifyDriverMbx_Params_init(&params);
460     params.remoteProcId = remoteProcId;
462     /* set the intVectorId if on the R5F */
463     if ((MultiProc_self() == NotifySetup_r5f_0ProcId) ||
464         (MultiProc_self() == NotifySetup_r5f_1ProcId)) {
466         virtId = VIRTID(remoteProcId);
467         params.intVectorId = NotifySetup_module->interruptTable[virtId];
468     }
470     /* set the intVectorId if on the HOST */
471     if (MultiProc_self() == NotifySetup_hostProcId) {
472         virtId = VIRTID(remoteProcId);
473         params.intVectorId = NotifySetup_module->interruptTable[virtId];
474     }
476     /* create the notify driver instance */
477     driver = NotifyDriverMbx_create(&params, &eb);
479     if (driver == NULL) {
480         return (Notify_E_FAIL);
481     }
483     /* create the front-end notify instance */
484     notify = ti_sdo_ipc_Notify_create(NotifyDriverMbx_Handle_upCast(driver),
485             remoteProcId, 0, NULL, &eb);
487     if (notify == NULL) {
488         NotifyDriverMbx_delete(&driver);
489         status = Notify_E_FAIL;
490     }
492     return (status);
495 /*!
496  *  ======== NotifySetup_Mbx_sharedMemReq ========
497  */
498 SizeT NotifySetup_Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
500     SizeT memReq = 0;
502     return (memReq);
505 /*
506  *************************************************************************
507  *                       Internal functions
508  *************************************************************************
509  */
511 /*
512  *  ======== NotifySetup_dispatchIsr ========
513  *  Dispatch the current interrupt to the appropriate notify driver
514  *
515  *  The given interrupt may be shared by multiple notify drivers. This
516  *  ISR inspects the mailbox which raised the interrupt and looks for
517  *  all FIFOs which have data and raise the given interrupt. For each
518  *  one, the interrupt is dispatched to the registered driver for that
519  *  FIFO.
520  *
521  *  @param(arg) The eventId which raised the interrupt.
522  */
523 Void NotifySetup_dispatchIsr(UArg arg)
525     Int numProcessed;
526     UInt16 idx;
527     UInt16 srcVirtId;
528     UInt16 dstVirtId = VIRTID(MultiProc_self());
529     NotifySetup_DriverIsr driver;
531     do {
532         numProcessed = 0;
534         for (srcVirtId = 0; srcVirtId < NotifySetup_NUM_CORES; srcVirtId++) {
536             /* skip null drivers, processor not in system or self */
537             driver = NotifySetup_module->isrDispatchTable[srcVirtId];
539             if (driver == NULL) {
540                 continue;
541             }
543             /* check if processor would raise the given hardware eventId */
544             if (arg == NotifySetup_module->interruptTable[srcVirtId]) {
546                 /* compute table index for given source and destination */
547                 idx = (srcVirtId * NotifySetup_NUM_CORES) + dstVirtId;
549                 /* check if submailbox has a message and irq is enabled */
550                 if ((MBOX_MSG_COUNT(idx) != 0) && MBOX_IRQ_ENABLE(idx)) {
552                     /* invoke driver isr to deliver the event */
553                     (*driver)(idx);
555                     /* event has been delivered */
556                     numProcessed++;
557                 }
558             }
559         }
560     } while (numProcessed != 0);