8a18e9deab9901764b4215040a85b10b6c5453de
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / vayu / NotifySetup.c
1 /*
2  * Copyright (c) 2012-2014 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/Ipc.h>
42 #include <ti/sdo/ipc/_Notify.h>
43 #include <ti/sdo/ipc/family/vayu/NotifyDriverMbx.h>
44 #include <ti/sdo/ipc/notifyDrivers/NotifyDriverShm.h>
45 #include <ti/sdo/utils/_MultiProc.h>
47 #if defined(xdc_target__isaCompatible_64P)
49 #include <ti/sysbios/family/c64p/EventCombiner.h>
50 #include <ti/sysbios/family/c64p/Hwi.h>
51 #include <ti/sysbios/family/shared/vayu/IntXbar.h>
53 #elif defined(xdc_target__isaCompatible_arp32)
55 #include <ti/sysbios/family/arp32/Hwi.h>
57 #elif defined(xdc_target__isaCompatible_v7M)
59 #include <ti/sysbios/family/arm/m3/Hwi.h>
61 #elif defined(xdc_target__isaCompatible_v7A)
63 #include <ti/sysbios/family/arm/gic/Hwi.h>
65 #else
66 #error Invalid target
67 #endif
69 #include "package/internal/NotifySetup.xdc.h"
72 #define EVENT_GROUP_SIZE 32
74 /* register access methods */
75 #define REG16(A)        (*(volatile UInt16 *)(A))
76 #define REG32(A)        (*(volatile UInt32 *)(A))
78 /* ipc helper macros */
79 #define MAILBOX_REG_VAL(m) (0x1 << (2 * (m)))
81 #define VIRTID(procId) (NotifySetup_procIdTable[(procId)])
83 #define MBX_BASEADDR_IDX(idx) ((NotifySetup_mailboxTable[(idx)] >> 16) & 0xFFFF)
85 #define MBX_USER_IDX(idx) ((NotifySetup_mailboxTable[(idx)] >> 8) & 0xFF)
87 #define SUBMBX_IDX(idx) (NotifySetup_mailboxTable[(idx)] & 0xFF)
89 #define MAILBOX_ADDR(idx) \
90         (NotifySetup_mailboxBaseAddr[MBX_BASEADDR_IDX(idx)])
92 #define MAILBOX_STATUS(idx) \
93         (MAILBOX_ADDR((idx)) + 0xC0 + (0x4 * SUBMBX_IDX((idx))))
95 #define MAILBOX_IRQENABLE_SET(idx) \
96         (MAILBOX_ADDR((idx)) + 0x108 + (0x10 * MBX_USER_IDX((idx))))
98 #define MBOX_IRQ_ENABLE(idx) \
99     ((REG32(MAILBOX_IRQENABLE_SET((idx))) & \
100     MAILBOX_REG_VAL(SUBMBX_IDX((idx)))) != 0)
102 #define MBOX_MSG_COUNT(idx) (REG32(MAILBOX_STATUS((idx))))
105 /*
106  *************************************************************************
107  *                      Module functions
108  *************************************************************************
109  */
111 /*
112  *  ======== NotifySetup_Module_startup ========
113  */
114 Int NotifySetup_Module_startup(Int phase)
116 #if defined(xdc_target__isaCompatible_64P)
118     extern cregister volatile UInt DNUM;
120     if (IntXbar_Module_startupDone()) {
121         if (DNUM == 0) {               /* DSP1 */
122             NotifySetup_module->interruptTable[6] = 57; // IPU1-0
123             NotifySetup_module->interruptTable[9] = 57; // IPU1-1
125             /* plug eve3 and eve4 mbxs only if eve3 and eve4 exists */
126             if ((MultiProc_getId("EVE3") != MultiProc_INVALIDID) ||
127                 (MultiProc_getId("EVE4") != MultiProc_INVALIDID)) {
128             }
130             /* plug mbx7 only if DSP2 or IPU2 exists */
131             if ((MultiProc_getId("DSP2") != MultiProc_INVALIDID) ||
132                 (MultiProc_getId("IPU2") != MultiProc_INVALIDID) ||
133                 (MultiProc_getId("IPU2-0") != MultiProc_INVALIDID)) {
134                 NotifySetup_module->interruptTable[7] = 60; // IPU2-0
135             }
137             /* plug mbx8 only if IPU2-1 exists */
138             if (MultiProc_getId("IPU2-1") != MultiProc_INVALIDID) {
139                 NotifySetup_module->interruptTable[10] = 61; // IPU2-1
140             }
141         }
142         else if (DNUM == 1) {          /* DSP2 */
143             NotifySetup_module->interruptTable[7] = 57; // IPU2-0
144             NotifySetup_module->interruptTable[10] = 57; // IPU2-1
146             /* plug eve3 and eve4 mbxs only if eve3 and eve4 exists */
147             if ((MultiProc_getId("EVE3") != MultiProc_INVALIDID) ||
148                 (MultiProc_getId("EVE4") != MultiProc_INVALIDID)) {
149             }
151             /* plug mbx7 only if DSP1 or IPU1 exists */
152             if ((MultiProc_getId("DSP1") != MultiProc_INVALIDID) ||
153                 (MultiProc_getId("IPU1") != MultiProc_INVALIDID) ||
154                 (MultiProc_getId("IPU1-0") != MultiProc_INVALIDID)) {
155                 NotifySetup_module->interruptTable[6] = 60; // IPU1-0
156             }
158             /* plug mbx8 only if IPU1-1 exists */
159             if (MultiProc_getId("IPU1-1") != MultiProc_INVALIDID) {
160                 NotifySetup_module->interruptTable[9] = 61; // IPU1-1
161             }
162         }
163         return (Startup_DONE);
164     }
166     return (Startup_NOTDONE);
168 #elif defined(xdc_target__isaCompatible_arp32)
170     /* nothing to do on this processor */
171     return (Startup_DONE);
173 #elif defined(xdc_target__isaCompatible_v7M)
175     /* TODO */
176     return (Startup_DONE);
178 #elif defined(xdc_target__isaCompatible_v7A)
180     /* TODO */
181     return (Startup_DONE);
183 #else
184 #error Invalid target
185 #endif
188 /*!
189  *  ======== NotifySetup_attach ========
190  *  Create driver instance specified at config time.
191  *
192  *  This functions is generated by the NotifySetup.xdt template.
193  */
195 /*!
196  *  ======== NotifySetup_sharedMemReq ========
197  *  Compute how much shared memory is required by the driver.
198  *
199  *  This functions is generated by the NotifySetup.xdt template.
200  */
202 /*!
203  * ======== NotifySetup_numIntLines ========
204  * Return number of available interrupt lines to the current processor.
205  */
206 UInt16 NotifySetup_numIntLines(UInt16 remoteProcId)
208     return (1);
211 /*
212  *  ======== NotifySetup_driverType ========
213  *  Find driver type for given connection.
214  *
215  *  Search the connection array for the given remote processor. If
216  *  found, return the requested notify driver type.
217  */
218 NotifySetup_Driver NotifySetup_driverType(UInt16 remoteProcId)
220     Int i;
221     NotifySetup_Driver driver = NotifySetup_Driver_SHAREDMEMORY;
223     /* look for remote processor in connection array */
224     for (i = 0; i < NotifySetup_module->connAry.length; i++) {
225         if (remoteProcId == NotifySetup_module->connAry.elem[i].procId) {
226             driver = NotifySetup_module->connAry.elem[i].driver;
227             break;
228         }
229     }
231     return(driver);
234 /*
235  *  ======== NotifySetup_plugHwi ========
236  */
237 Void NotifySetup_plugHwi(UInt16 remoteProcId, Int cpuIntrNum,
238         NotifySetup_DriverIsr isr)
240     Error_Block eb;
241     UInt        key;
242     Hwi_Params  hwiParams;
243     UInt16      virtId;
244     Int         eventId;
245 #if defined(xdc_target__isaCompatible_64P)
246     UInt        combinedEventId;
247 #elif defined(xdc_target__isaCompatible_arp32)
248     UInt        mbxIdx;
249 #endif
251     Error_init(&eb);
253     /* disable global interrupts (TODO: should be a gated module) */
254     key = Hwi_disable();
256     /* map processor id to virtual id */
257     virtId = VIRTID(remoteProcId);
259     /* save driver isr in dispatch table */
260     NotifySetup_module->isrDispatchTable[virtId] = isr;
262 #if defined(xdc_target__isaCompatible_64P)
264     /* program the event dispatcher */
265     eventId = NotifySetup_module->interruptTable[virtId];
266     EventCombiner_dispatchPlug(eventId, NotifySetup_dispatchIsr, eventId, TRUE);
268     /* make sure the interrupt is plugged only once */
269     NotifySetup_module->numPlugged[0]++;
271     if (NotifySetup_module->numPlugged[0] == 1) {
272         combinedEventId = eventId / EVENT_GROUP_SIZE;
274         Hwi_Params_init(&hwiParams);
275         hwiParams.eventId = combinedEventId;
276         hwiParams.arg = combinedEventId;
277         hwiParams.enableInt = TRUE;
279         Hwi_create(cpuIntrNum,
280                 &ti_sysbios_family_c64p_EventCombiner_dispatch,
281                 &hwiParams, &eb);
282         /* TODO: add error handling */
284         Hwi_enableInterrupt(cpuIntrNum);
285     }
287 #elif defined(xdc_target__isaCompatible_arp32)
289     if ((remoteProcId == NotifySetup_dsp1ProcId) ||
290         (remoteProcId == NotifySetup_ipu1_0ProcId) ||
291         (remoteProcId == NotifySetup_hostProcId)) {
293         mbxIdx = 0;
294     }
295     else if ((remoteProcId == NotifySetup_dsp2ProcId) ||
296         (remoteProcId == NotifySetup_ipu2_0ProcId) ||
297         (remoteProcId == NotifySetup_ipu1_1ProcId) ||
298         (remoteProcId == NotifySetup_ipu2_1ProcId)) {
300         mbxIdx = 1;
301     }
302     else {
303         mbxIdx = 2; /* remote processor must be EVEx */
304     }
306     /* make sure the interrupt is plugged only once */
307     NotifySetup_module->numPlugged[mbxIdx]++;
309     if (NotifySetup_module->numPlugged[mbxIdx] == 1) {
310         eventId = NotifySetup_module->interruptTable[virtId];
312         Hwi_Params_init(&hwiParams);
313         hwiParams.arg = eventId;
314         hwiParams.vectorNum = cpuIntrNum;
316         Hwi_create(eventId, NotifySetup_dispatchIsr, &hwiParams, &eb);
317         /* TODO: add error handling */
319         Hwi_enableInterrupt(NotifySetup_module->interruptTable[virtId]);
320     }
322 #elif defined(xdc_target__isaCompatible_v7M)
324     /* TODO */
326 #elif defined(xdc_target__isaCompatible_v7A)
328     /* TODO */
330 #else
331 #error Invalid target
332 #endif
334     /* restore global interrupts */
335     Hwi_restore(key);
338 /*
339  *  ======== NotifySetup_unplugHwi ========
340  */
341 Void NotifySetup_unplugHwi(UInt16 remoteProcId, Int cpuIntrNum)
343     UInt        key;
344     Hwi_Handle  hwi;
345 #if defined(xdc_target__isaCompatible_64P)
346     UInt16      virtId;
347     Int         eventId;
348 #elif defined(xdc_target__isaCompatible_arp32)
349     UInt        mbxIdx;
350 #endif
352     /* disable global interrupts (TODO: should be a gated module) */
353     key = Hwi_disable();
355 #if defined(xdc_target__isaCompatible_64P)
357     /* unplug interrupt if last user */
358     NotifySetup_module->numPlugged[0]--;
360     if (NotifySetup_module->numPlugged[0] == 0) {
361         hwi = Hwi_getHandle(cpuIntrNum);
362         Hwi_delete(&hwi);
363     }
365     /* unprogram the event dispatcher */
366     virtId = VIRTID(remoteProcId);
367     eventId = NotifySetup_module->interruptTable[virtId];
368     EventCombiner_disableEvent(eventId);
370 #elif defined(xdc_target__isaCompatible_arp32)
372     if ((remoteProcId == NotifySetup_dsp1ProcId) ||
373         (remoteProcId == NotifySetup_ipu1_0ProcId) ||
374         (remoteProcId == NotifySetup_hostProcId)) {
376         mbxIdx = 0;
377     }
378     else if ((remoteProcId == NotifySetup_dsp2ProcId) ||
379         (remoteProcId == NotifySetup_ipu2_0ProcId) ||
380         (remoteProcId == NotifySetup_ipu1_1ProcId) ||
381         (remoteProcId == NotifySetup_ipu2_1ProcId)) {
383         mbxIdx = 1;
384     }
385     else {
386         mbxIdx = 2; /* remote processor must be EVEx */
387     }
389     /* unplug interrupt if last user */
390     NotifySetup_module->numPlugged[mbxIdx]--;
392     if (NotifySetup_module->numPlugged[0] == 0) {
393         hwi = Hwi_getHandle(cpuIntrNum);
394         Hwi_delete(&hwi);
395     }
397 #elif defined(xdc_target__isaCompatible_v7M)
399     /* TODO */
401 #elif defined(xdc_target__isaCompatible_v7A)
403     /* TODO */
405 #else
406 #error Invalid target
407 #endif
409     /* restore global interrupts */
410     Hwi_restore(key);
413 /*
414  *  ======== NotifySetup_Shm_attach ========
415  */
416 Int NotifySetup_Shm_attach(UInt16 remoteProcId, Ptr sharedAddr)
418     NotifyDriverShm_Params notifyShmParams;
419     NotifyDriverShm_Handle shmDrvHandle;
420     ti_sdo_ipc_Notify_Handle notifyHandle;
421     Int status = Notify_S_SUCCESS;
422     Error_Block eb;
424     Error_init(&eb);
426     NotifyDriverShm_Params_init(&notifyShmParams);
427     notifyShmParams.sharedAddr = sharedAddr;
428     notifyShmParams.remoteProcId  = remoteProcId;
430     /* Set the intVectorId if on the DSP */
431     if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
432         (MultiProc_self() == NotifySetup_dsp2ProcId)) {
433             notifyShmParams.intVectorId = NotifySetup_dspIntVectId;
434     }
436     /* Set the intVectorId if on the EVE */
437     if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
438         (MultiProc_self() == NotifySetup_eve2ProcId) ||
439         (MultiProc_self() == NotifySetup_eve3ProcId) ||
440         (MultiProc_self() == NotifySetup_eve4ProcId)) {
442         if (VIRTID(remoteProcId) < 4) {
443             notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC1;
444         }
445         else {
446             notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC0;
447         }
448     }
450     /* create the notify driver instance */
451     shmDrvHandle = NotifyDriverShm_create(&notifyShmParams, &eb);
453     if (shmDrvHandle == NULL) {
454         return (Notify_E_FAIL);
455     }
457     /* create the front-end notify instance */
458     notifyHandle = ti_sdo_ipc_Notify_create(
459             NotifyDriverShm_Handle_upCast(shmDrvHandle), remoteProcId, 0,
460             NULL, &eb);
462     if (notifyHandle == NULL) {
463         NotifyDriverShm_delete(&shmDrvHandle);
464         status = Notify_E_FAIL;
465     }
467     return (status);
470 /*!
471  *  ======== NotifySetup_Shm_sharedMemReq ========
472  */
473 SizeT NotifySetup_Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
475     SizeT memReq;
476     NotifyDriverShm_Params notifyShmParams;
478     NotifyDriverShm_Params_init(&notifyShmParams);
479     notifyShmParams.sharedAddr = sharedAddr;
481     memReq = NotifyDriverShm_sharedMemReq(&notifyShmParams);
483     return (memReq);
486 /*
487  *  ======== NotifySetup_Mbx_attach ========
488  */
489 Int NotifySetup_Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr)
491     Int status = Notify_S_SUCCESS;
492     NotifyDriverMbx_Params params;
493     NotifyDriverMbx_Handle driver;
494     ti_sdo_ipc_Notify_Handle notify;
495     Error_Block eb;
497     Error_init(&eb);
499     NotifyDriverMbx_Params_init(&params);
500     params.remoteProcId = remoteProcId;
502     /* set the intVectorId if on the DSP */
503     if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
504         (MultiProc_self() == NotifySetup_dsp2ProcId)) {
505         params.intVectorId = NotifySetup_dspIntVectId;
506     }
508     /* set the intVectorId if on the EVE */
509     if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
510         (MultiProc_self() == NotifySetup_eve2ProcId) ||
511         (MultiProc_self() == NotifySetup_eve3ProcId) ||
512         (MultiProc_self() == NotifySetup_eve4ProcId)) {
514         if (VIRTID(remoteProcId) < 4) {
515             params.intVectorId = NotifySetup_eveIntVectId_INTC1;
516         }
517         else {
518             params.intVectorId = NotifySetup_eveIntVectId_INTC0;
519         }
520     }
522     /* create the notify driver instance */
523     driver = NotifyDriverMbx_create(&params, &eb);
525     if (driver == NULL) {
526         return(Notify_E_FAIL);
527     }
529     /* create the front-end notify instance */
530     notify = ti_sdo_ipc_Notify_create(NotifyDriverMbx_Handle_upCast(driver),
531             remoteProcId, 0, NULL, &eb);
533     if (notify == NULL) {
534         NotifyDriverMbx_delete(&driver);
535         status = Notify_E_FAIL;
536     }
538     return(status);
541 /*!
542  *  ======== NotifySetup_Mbx_sharedMemReq ========
543  */
544 SizeT NotifySetup_Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
546     SizeT memReq = 0;
548     return (memReq);
551 /*
552  *************************************************************************
553  *                       Internal functions
554  *************************************************************************
555  */
557 /*
558  *  ======== NotifySetup_dispatchIsr ========
559  *  arg = eventId
560  */
561 Void NotifySetup_dispatchIsr(UArg arg)
563     Int numProcessed;
564     UInt16 idx;
565     UInt16 srcVirtId;
566     UInt16 dstVirtId = VIRTID(MultiProc_self());
567     NotifySetup_DriverIsr driver;
569     do {
570         numProcessed = 0;
572         for (srcVirtId = 0; srcVirtId < NotifySetup_NUM_CORES; srcVirtId++) {
574             /* should not receive interrupts from myself */
575             if (srcVirtId == dstVirtId) {
576                 continue;
577             }
579             /* check if processor would raise the given hardware eventId */
580             if (arg == NotifySetup_module->interruptTable[srcVirtId]) {
582                 /* compute table index for given source and destination */
583                 idx = (srcVirtId * NotifySetup_NUM_CORES) + dstVirtId;
585                 /* check if submailbox has a message and irq is enabled */
586                 if ((MBOX_MSG_COUNT(idx) != 0) && MBOX_IRQ_ENABLE(idx)) {
588                     /* invoke driver isr to deliver the event */
589                     driver = NotifySetup_module->isrDispatchTable[srcVirtId];
590                     (*driver)(idx);
592                     /* event has been delivered */
593                     numProcessed++;
594                 }
595             }
596         }
597     } while (numProcessed != 0);