408ebbdf1d434f4a8bdb74ab7c7bcc66a216fa96
[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     Bits16      mask;
250 #endif
252     Error_init(&eb);
254     /* disable interrupts */
255     key = Hwi_disable();
257     /* map processor id to virtual id */
258     virtId = VIRTID(remoteProcId);
260     /* save driver isr in dispatch table */
261     NotifySetup_module->isrDispatchTable[virtId] = isr;
263 #if defined(xdc_target__isaCompatible_64P)
265     /* program the event dispatcher */
266     eventId = NotifySetup_module->interruptTable[virtId];
267     EventCombiner_dispatchPlug(eventId, NotifySetup_dispatchIsr, eventId, TRUE);
269     /* make sure the interrupt is plugged only once */
270     NotifySetup_module->numPlugged[0]++;
272     if (NotifySetup_module->numPlugged[0] == 1) {
273         combinedEventId = eventId / EVENT_GROUP_SIZE;
275         Hwi_Params_init(&hwiParams);
276         hwiParams.eventId = combinedEventId;
277         hwiParams.arg = combinedEventId;
278         hwiParams.enableInt = TRUE;
280         Hwi_create(cpuIntrNum,
281                 &ti_sysbios_family_c64p_EventCombiner_dispatch,
282                 &hwiParams, &eb);
283         /* TODO: add error handling */
285         Hwi_enableInterrupt(cpuIntrNum);
286     }
288 #elif defined(xdc_target__isaCompatible_arp32)
290     if ((remoteProcId == NotifySetup_dsp1ProcId) ||
291         (remoteProcId == NotifySetup_ipu1_0ProcId) ||
292         (remoteProcId == NotifySetup_hostProcId)) {
294         mbxIdx = 0;
295     }
296     else if ((remoteProcId == NotifySetup_dsp2ProcId) ||
297         (remoteProcId == NotifySetup_ipu2_0ProcId) ||
298         (remoteProcId == NotifySetup_ipu1_1ProcId) ||
299         (remoteProcId == NotifySetup_ipu2_1ProcId)) {
301         mbxIdx = 1;
302     }
303     else {
304         mbxIdx = 2; /* remote processor must be EVEx */
305     }
307     /* make sure the interrupt is plugged only once */
308     NotifySetup_module->numPlugged[mbxIdx]++;
310     if (NotifySetup_module->numPlugged[mbxIdx] == 1) {
311         eventId = NotifySetup_module->interruptTable[virtId];
313         /* compute the hwi mask */
314         mask = (1 << NotifySetup_eveIntVectId_INTC0)
315                 | (1 << NotifySetup_eveIntVectId_INTC1);
317         Hwi_Params_init(&hwiParams);
318         hwiParams.arg = eventId;
319         hwiParams.vectorNum = cpuIntrNum;
320         hwiParams.maskSetting = Hwi_MaskingOption_BITMASK;
321         hwiParams.disableIerMask = mask;
322         hwiParams.restoreIerMask = mask;
324         Hwi_create(eventId, NotifySetup_dispatchIsr, &hwiParams, &eb);
325         /* TODO: add error handling */
327         Hwi_enableInterrupt(NotifySetup_module->interruptTable[virtId]);
328     }
330 #elif defined(xdc_target__isaCompatible_v7M)
332     /* TODO */
334 #elif defined(xdc_target__isaCompatible_v7A)
336     /* TODO */
338 #else
339 #error Invalid target
340 #endif
342     /* restore interrupts */
343     Hwi_restore(key);
346 /*
347  *  ======== NotifySetup_unplugHwi ========
348  */
349 Void NotifySetup_unplugHwi(UInt16 remoteProcId, Int cpuIntrNum)
351     UInt        key;
352     Hwi_Handle  hwi;
353 #if defined(xdc_target__isaCompatible_64P)
354     UInt16      virtId;
355     Int         eventId;
356 #elif defined(xdc_target__isaCompatible_arp32)
357     UInt        mbxIdx;
358 #endif
360     /* disable global interrupts (TODO: should be a gated module) */
361     key = Hwi_disable();
363 #if defined(xdc_target__isaCompatible_64P)
365     /* unplug interrupt if last user */
366     NotifySetup_module->numPlugged[0]--;
368     if (NotifySetup_module->numPlugged[0] == 0) {
369         hwi = Hwi_getHandle(cpuIntrNum);
370         Hwi_delete(&hwi);
371     }
373     /* unprogram the event dispatcher */
374     virtId = VIRTID(remoteProcId);
375     eventId = NotifySetup_module->interruptTable[virtId];
376     EventCombiner_disableEvent(eventId);
378 #elif defined(xdc_target__isaCompatible_arp32)
380     if ((remoteProcId == NotifySetup_dsp1ProcId) ||
381         (remoteProcId == NotifySetup_ipu1_0ProcId) ||
382         (remoteProcId == NotifySetup_hostProcId)) {
384         mbxIdx = 0;
385     }
386     else if ((remoteProcId == NotifySetup_dsp2ProcId) ||
387         (remoteProcId == NotifySetup_ipu2_0ProcId) ||
388         (remoteProcId == NotifySetup_ipu1_1ProcId) ||
389         (remoteProcId == NotifySetup_ipu2_1ProcId)) {
391         mbxIdx = 1;
392     }
393     else {
394         mbxIdx = 2; /* remote processor must be EVEx */
395     }
397     /* unplug interrupt if last user */
398     NotifySetup_module->numPlugged[mbxIdx]--;
400     if (NotifySetup_module->numPlugged[0] == 0) {
401         hwi = Hwi_getHandle(cpuIntrNum);
402         Hwi_delete(&hwi);
403     }
405 #elif defined(xdc_target__isaCompatible_v7M)
407     /* TODO */
409 #elif defined(xdc_target__isaCompatible_v7A)
411     /* TODO */
413 #else
414 #error Invalid target
415 #endif
417     /* restore global interrupts */
418     Hwi_restore(key);
421 /*
422  *  ======== NotifySetup_Shm_attach ========
423  */
424 Int NotifySetup_Shm_attach(UInt16 remoteProcId, Ptr sharedAddr)
426     NotifyDriverShm_Params notifyShmParams;
427     NotifyDriverShm_Handle shmDrvHandle;
428     ti_sdo_ipc_Notify_Handle notifyHandle;
429     Int status = Notify_S_SUCCESS;
430     Error_Block eb;
432     Error_init(&eb);
434     NotifyDriverShm_Params_init(&notifyShmParams);
435     notifyShmParams.sharedAddr = sharedAddr;
436     notifyShmParams.remoteProcId  = remoteProcId;
438     /* Set the intVectorId if on the DSP */
439     if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
440         (MultiProc_self() == NotifySetup_dsp2ProcId)) {
441             notifyShmParams.intVectorId = NotifySetup_dspIntVectId;
442     }
444     /* Set the intVectorId if on the EVE */
445     if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
446         (MultiProc_self() == NotifySetup_eve2ProcId) ||
447         (MultiProc_self() == NotifySetup_eve3ProcId) ||
448         (MultiProc_self() == NotifySetup_eve4ProcId)) {
450         if (VIRTID(remoteProcId) < 4) {
451             notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC1;
452         }
453         else {
454             notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC0;
455         }
456     }
458     /* create the notify driver instance */
459     shmDrvHandle = NotifyDriverShm_create(&notifyShmParams, &eb);
461     if (shmDrvHandle == NULL) {
462         return (Notify_E_FAIL);
463     }
465     /* create the front-end notify instance */
466     notifyHandle = ti_sdo_ipc_Notify_create(
467             NotifyDriverShm_Handle_upCast(shmDrvHandle), remoteProcId, 0,
468             NULL, &eb);
470     if (notifyHandle == NULL) {
471         NotifyDriverShm_delete(&shmDrvHandle);
472         status = Notify_E_FAIL;
473     }
475     return (status);
478 /*!
479  *  ======== NotifySetup_Shm_sharedMemReq ========
480  */
481 SizeT NotifySetup_Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
483     SizeT memReq;
484     NotifyDriverShm_Params notifyShmParams;
486     NotifyDriverShm_Params_init(&notifyShmParams);
487     notifyShmParams.sharedAddr = sharedAddr;
489     memReq = NotifyDriverShm_sharedMemReq(&notifyShmParams);
491     return (memReq);
494 /*
495  *  ======== NotifySetup_Mbx_attach ========
496  */
497 Int NotifySetup_Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr)
499     Int status = Notify_S_SUCCESS;
500     NotifyDriverMbx_Params params;
501     NotifyDriverMbx_Handle driver;
502     ti_sdo_ipc_Notify_Handle notify;
503     Error_Block eb;
505     Error_init(&eb);
507     NotifyDriverMbx_Params_init(&params);
508     params.remoteProcId = remoteProcId;
510     /* set the intVectorId if on the DSP */
511     if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
512         (MultiProc_self() == NotifySetup_dsp2ProcId)) {
513         params.intVectorId = NotifySetup_dspIntVectId;
514     }
516     /* set the intVectorId if on the EVE */
517     if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
518         (MultiProc_self() == NotifySetup_eve2ProcId) ||
519         (MultiProc_self() == NotifySetup_eve3ProcId) ||
520         (MultiProc_self() == NotifySetup_eve4ProcId)) {
522         if (VIRTID(remoteProcId) < 4) {
523             params.intVectorId = NotifySetup_eveIntVectId_INTC1;
524         }
525         else {
526             params.intVectorId = NotifySetup_eveIntVectId_INTC0;
527         }
528     }
530     /* create the notify driver instance */
531     driver = NotifyDriverMbx_create(&params, &eb);
533     if (driver == NULL) {
534         return(Notify_E_FAIL);
535     }
537     /* create the front-end notify instance */
538     notify = ti_sdo_ipc_Notify_create(NotifyDriverMbx_Handle_upCast(driver),
539             remoteProcId, 0, NULL, &eb);
541     if (notify == NULL) {
542         NotifyDriverMbx_delete(&driver);
543         status = Notify_E_FAIL;
544     }
546     return(status);
549 /*!
550  *  ======== NotifySetup_Mbx_sharedMemReq ========
551  */
552 SizeT NotifySetup_Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
554     SizeT memReq = 0;
556     return (memReq);
559 /*
560  *************************************************************************
561  *                       Internal functions
562  *************************************************************************
563  */
565 /*
566  *  ======== NotifySetup_dispatchIsr ========
567  *  arg = eventId
568  */
569 Void NotifySetup_dispatchIsr(UArg arg)
571     Int numProcessed;
572     UInt16 idx;
573     UInt16 srcVirtId;
574     UInt16 dstVirtId = VIRTID(MultiProc_self());
575     NotifySetup_DriverIsr driver;
577     do {
578         numProcessed = 0;
580         for (srcVirtId = 0; srcVirtId < NotifySetup_NUM_CORES; srcVirtId++) {
582             /* skip null drivers, processor not in system or self */
583             driver = NotifySetup_module->isrDispatchTable[srcVirtId];
585             if (driver == NULL) {
586                 continue;
587             }
589             /* check if processor would raise the given hardware eventId */
590             if (arg == NotifySetup_module->interruptTable[srcVirtId]) {
592                 /* compute table index for given source and destination */
593                 idx = (srcVirtId * NotifySetup_NUM_CORES) + dstVirtId;
595                 /* check if submailbox has a message and irq is enabled */
596                 if ((MBOX_MSG_COUNT(idx) != 0) && MBOX_IRQ_ENABLE(idx)) {
598                     /* invoke driver isr to deliver the event */
599                     (*driver)(idx);
601                     /* event has been delivered */
602                     numProcessed++;
603                 }
604             }
605         }
606     } while (numProcessed != 0);