2fd11ef17cbc30ace594febfe5677204cbf9b3fb
[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;
323         Hwi_create(eventId, NotifySetup_dispatchIsr, &hwiParams, &eb);
324         /* TODO: add error handling */
326         Hwi_enableInterrupt(NotifySetup_module->interruptTable[virtId]);
327     }
329 #elif defined(xdc_target__isaCompatible_v7M)
331     /* TODO */
333 #elif defined(xdc_target__isaCompatible_v7A)
335     /* TODO */
337 #else
338 #error Invalid target
339 #endif
341     /* restore interrupts */
342     Hwi_restore(key);
345 /*
346  *  ======== NotifySetup_unplugHwi ========
347  */
348 Void NotifySetup_unplugHwi(UInt16 remoteProcId, Int cpuIntrNum)
350     UInt        key;
351     Hwi_Handle  hwi;
352 #if defined(xdc_target__isaCompatible_64P)
353     UInt16      virtId;
354     Int         eventId;
355 #elif defined(xdc_target__isaCompatible_arp32)
356     UInt        mbxIdx;
357 #endif
359     /* disable global interrupts (TODO: should be a gated module) */
360     key = Hwi_disable();
362 #if defined(xdc_target__isaCompatible_64P)
364     /* unplug interrupt if last user */
365     NotifySetup_module->numPlugged[0]--;
367     if (NotifySetup_module->numPlugged[0] == 0) {
368         hwi = Hwi_getHandle(cpuIntrNum);
369         Hwi_delete(&hwi);
370     }
372     /* unprogram the event dispatcher */
373     virtId = VIRTID(remoteProcId);
374     eventId = NotifySetup_module->interruptTable[virtId];
375     EventCombiner_disableEvent(eventId);
377 #elif defined(xdc_target__isaCompatible_arp32)
379     if ((remoteProcId == NotifySetup_dsp1ProcId) ||
380         (remoteProcId == NotifySetup_ipu1_0ProcId) ||
381         (remoteProcId == NotifySetup_hostProcId)) {
383         mbxIdx = 0;
384     }
385     else if ((remoteProcId == NotifySetup_dsp2ProcId) ||
386         (remoteProcId == NotifySetup_ipu2_0ProcId) ||
387         (remoteProcId == NotifySetup_ipu1_1ProcId) ||
388         (remoteProcId == NotifySetup_ipu2_1ProcId)) {
390         mbxIdx = 1;
391     }
392     else {
393         mbxIdx = 2; /* remote processor must be EVEx */
394     }
396     /* unplug interrupt if last user */
397     NotifySetup_module->numPlugged[mbxIdx]--;
399     if (NotifySetup_module->numPlugged[0] == 0) {
400         hwi = Hwi_getHandle(cpuIntrNum);
401         Hwi_delete(&hwi);
402     }
404 #elif defined(xdc_target__isaCompatible_v7M)
406     /* TODO */
408 #elif defined(xdc_target__isaCompatible_v7A)
410     /* TODO */
412 #else
413 #error Invalid target
414 #endif
416     /* restore global interrupts */
417     Hwi_restore(key);
420 /*
421  *  ======== NotifySetup_Shm_attach ========
422  */
423 Int NotifySetup_Shm_attach(UInt16 remoteProcId, Ptr sharedAddr)
425     NotifyDriverShm_Params notifyShmParams;
426     NotifyDriverShm_Handle shmDrvHandle;
427     ti_sdo_ipc_Notify_Handle notifyHandle;
428     Int status = Notify_S_SUCCESS;
429     Error_Block eb;
431     Error_init(&eb);
433     NotifyDriverShm_Params_init(&notifyShmParams);
434     notifyShmParams.sharedAddr = sharedAddr;
435     notifyShmParams.remoteProcId  = remoteProcId;
437     /* Set the intVectorId if on the DSP */
438     if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
439         (MultiProc_self() == NotifySetup_dsp2ProcId)) {
440             notifyShmParams.intVectorId = NotifySetup_dspIntVectId;
441     }
443     /* Set the intVectorId if on the EVE */
444     if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
445         (MultiProc_self() == NotifySetup_eve2ProcId) ||
446         (MultiProc_self() == NotifySetup_eve3ProcId) ||
447         (MultiProc_self() == NotifySetup_eve4ProcId)) {
449         if (VIRTID(remoteProcId) < 4) {
450             notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC1;
451         }
452         else {
453             notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC0;
454         }
455     }
457     /* create the notify driver instance */
458     shmDrvHandle = NotifyDriverShm_create(&notifyShmParams, &eb);
460     if (shmDrvHandle == NULL) {
461         return (Notify_E_FAIL);
462     }
464     /* create the front-end notify instance */
465     notifyHandle = ti_sdo_ipc_Notify_create(
466             NotifyDriverShm_Handle_upCast(shmDrvHandle), remoteProcId, 0,
467             NULL, &eb);
469     if (notifyHandle == NULL) {
470         NotifyDriverShm_delete(&shmDrvHandle);
471         status = Notify_E_FAIL;
472     }
474     return (status);
477 /*!
478  *  ======== NotifySetup_Shm_sharedMemReq ========
479  */
480 SizeT NotifySetup_Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
482     SizeT memReq;
483     NotifyDriverShm_Params notifyShmParams;
485     NotifyDriverShm_Params_init(&notifyShmParams);
486     notifyShmParams.sharedAddr = sharedAddr;
488     memReq = NotifyDriverShm_sharedMemReq(&notifyShmParams);
490     return (memReq);
493 /*
494  *  ======== NotifySetup_Mbx_attach ========
495  */
496 Int NotifySetup_Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr)
498     Int status = Notify_S_SUCCESS;
499     NotifyDriverMbx_Params params;
500     NotifyDriverMbx_Handle driver;
501     ti_sdo_ipc_Notify_Handle notify;
502     Error_Block eb;
504     Error_init(&eb);
506     NotifyDriverMbx_Params_init(&params);
507     params.remoteProcId = remoteProcId;
509     /* set the intVectorId if on the DSP */
510     if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
511         (MultiProc_self() == NotifySetup_dsp2ProcId)) {
512         params.intVectorId = NotifySetup_dspIntVectId;
513     }
515     /* set the intVectorId if on the EVE */
516     if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
517         (MultiProc_self() == NotifySetup_eve2ProcId) ||
518         (MultiProc_self() == NotifySetup_eve3ProcId) ||
519         (MultiProc_self() == NotifySetup_eve4ProcId)) {
521         if (VIRTID(remoteProcId) < 4) {
522             params.intVectorId = NotifySetup_eveIntVectId_INTC1;
523         }
524         else {
525             params.intVectorId = NotifySetup_eveIntVectId_INTC0;
526         }
527     }
529     /* create the notify driver instance */
530     driver = NotifyDriverMbx_create(&params, &eb);
532     if (driver == NULL) {
533         return(Notify_E_FAIL);
534     }
536     /* create the front-end notify instance */
537     notify = ti_sdo_ipc_Notify_create(NotifyDriverMbx_Handle_upCast(driver),
538             remoteProcId, 0, NULL, &eb);
540     if (notify == NULL) {
541         NotifyDriverMbx_delete(&driver);
542         status = Notify_E_FAIL;
543     }
545     return(status);
548 /*!
549  *  ======== NotifySetup_Mbx_sharedMemReq ========
550  */
551 SizeT NotifySetup_Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
553     SizeT memReq = 0;
555     return (memReq);
558 /*
559  *************************************************************************
560  *                       Internal functions
561  *************************************************************************
562  */
564 /*
565  *  ======== NotifySetup_dispatchIsr ========
566  *  arg = eventId
567  */
568 Void NotifySetup_dispatchIsr(UArg arg)
570     Int numProcessed;
571     UInt16 idx;
572     UInt16 srcVirtId;
573     UInt16 dstVirtId = VIRTID(MultiProc_self());
574     NotifySetup_DriverIsr driver;
576     do {
577         numProcessed = 0;
579         for (srcVirtId = 0; srcVirtId < NotifySetup_NUM_CORES; srcVirtId++) {
581             /* skip null drivers, processor not in system or self */
582             driver = NotifySetup_module->isrDispatchTable[srcVirtId];
584             if (driver == NULL) {
585                 continue;
586             }
588             /* check if processor would raise the given hardware eventId */
589             if (arg == NotifySetup_module->interruptTable[srcVirtId]) {
591                 /* compute table index for given source and destination */
592                 idx = (srcVirtId * NotifySetup_NUM_CORES) + dstVirtId;
594                 /* check if submailbox has a message and irq is enabled */
595                 if ((MBOX_MSG_COUNT(idx) != 0) && MBOX_IRQ_ENABLE(idx)) {
597                     /* invoke driver isr to deliver the event */
598                     (*driver)(idx);
600                     /* event has been delivered */
601                     numProcessed++;
602                 }
603             }
604         }
605     } while (numProcessed != 0);