907f85c9d0f21376a23f9940579ef2bc30a86110
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / vayu / InterruptDsp.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  *  ======== InterruptDsp.c ========
35  *  Mailbox based interrupt manager
36  */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Startup.h>
41 #include <ti/sysbios/family/c64p/EventCombiner.h>
42 #include <ti/sysbios/family/c64p/Hwi.h>
43 #include <ti/sysbios/family/shared/vayu/IntXbar.h>
45 #include <ti/sdo/ipc/_Ipc.h>
46 #include <ti/sdo/ipc/family/vayu/NotifySetup.h>
47 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
48 #include <ti/sdo/utils/_MultiProc.h>
50 #include "package/internal/InterruptDsp.xdc.h"
52 /* Register access method. */
53 #define REG16(A)   (*(volatile UInt16 *) (A))
54 #define REG32(A)   (*(volatile UInt32 *) (A))
56 #define PROCID(IDX)               (InterruptDsp_procIdTable[IDX])
57 #define MBX_TABLE_IDX(SRC, DST)   ((PROCID(SRC) * InterruptDsp_NUM_CORES) + \
58                                     PROCID(DST))
59 #define SUBMBX_IDX(IDX)           (InterruptDsp_mailboxTable[IDX] & 0xFF)
60 #define MBX_USER_IDX(IDX)         ((InterruptDsp_mailboxTable[IDX] >> 8) & 0xFF)
61 #define MBX_BASEADDR_IDX(IDX)     ((InterruptDsp_mailboxTable[IDX] >> 16) & 0xFFFF)
63 #define MAILBOX_REG_VAL(M)        (0x1 << (2 * M))
65 #define MAILBOX_MESSAGE(IDX)      (InterruptDsp_mailboxBaseAddr[  \
66                                     MBX_BASEADDR_IDX(IDX)] + 0x40 \
67                                     + (0x4 * SUBMBX_IDX(IDX)))
68 #define MAILBOX_STATUS(IDX)       (InterruptDsp_mailboxBaseAddr[  \
69                                     MBX_BASEADDR_IDX(IDX)] + 0xC0 \
70                                     + (0x4 * SUBMBX_IDX(IDX)))
72 #define MAILBOX_IRQSTATUS_CLR_DSP(IDX)   (InterruptDsp_mailboxBaseAddr[ \
73                                            MBX_BASEADDR_IDX(IDX)] +     \
74                                            (0x10 * MBX_USER_IDX(IDX)) + 0x104)
75 #define MAILBOX_IRQENABLE_SET_DSP(IDX)   (InterruptDsp_mailboxBaseAddr[ \
76                                            MBX_BASEADDR_IDX(IDX)] +     \
77                                            (0x10 * MBX_USER_IDX(IDX)) + 0x108)
78 #define MAILBOX_IRQENABLE_CLR_DSP(IDX)   (InterruptDsp_mailboxBaseAddr[ \
79                                            MBX_BASEADDR_IDX(IDX)] +     \
80                                            (0x10 * MBX_USER_IDX(IDX)) + 0x10C)
81 #define MAILBOX_EOI_REG(IDX)             (InterruptDsp_mailboxBaseAddr[ \
82                                            MBX_BASEADDR_IDX(IDX)] + 0x140)
83 #define EVENT_GROUP_SIZE                 32
85 /*
86  *************************************************************************
87  *                      Module functions
88  *************************************************************************
89  */
91 /*
92  *  ======== InterruptDsp_Module_startup ========
93  */
94 Int InterruptDsp_Module_startup(Int phase)
95 {
96     extern cregister volatile UInt DNUM;
98     if (IntXbar_Module_startupDone()) {
99         /* connect mailbox interrupts at startup */
100         if (DNUM == 0) {               /* DSP1 */
101             IntXbar_connect(24, 284);  // eve1 mailbox 0 user 1
102             IntXbar_connect(25, 293);  // eve2 mailbox 0 user 1
103             IntXbar_connect(26, 249);  // system mailbox 5 user 0
105             InterruptDsp_module->interruptTable[6] = 57;    // IPU1-0
106             InterruptDsp_module->interruptTable[9] = 57;    // IPU1-1
108             /* plug eve3 and eve4 mbxs only if eve3 and eve4 exists */
109             if ((MultiProc_getId("EVE3") != MultiProc_INVALIDID) ||
110                 (MultiProc_getId("EVE4") != MultiProc_INVALIDID)) {
111                 IntXbar_connect(27, 302);  // eve3 mailbox 0 user 1
112                 IntXbar_connect(28, 311);  // eve4 mailbox 0 user 1
113             }
115             /* plug mbx7 only if DSP2 or IPU2 exists */
116             if ((MultiProc_getId("DSP2") != MultiProc_INVALIDID) ||
117                 (MultiProc_getId("IPU2") != MultiProc_INVALIDID) ||
118                 (MultiProc_getId("IPU2-0") != MultiProc_INVALIDID)) {
119                 IntXbar_connect(29, 257);  // system mailbox 7 user 0
120                 InterruptDsp_module->interruptTable[7] = 60;    // IPU2-0
121             }
123             /* plug mbx8 only if IPU2-1 exists */
124             if (MultiProc_getId("IPU2-1") != MultiProc_INVALIDID) {
125                 IntXbar_connect(30, 261);  // system mailbox 8 user 0
126                 InterruptDsp_module->interruptTable[10] = 61;    // IPU2-1
127             }
128         }
129         else if (DNUM == 1) {          /* DSP2 */
130             IntXbar_connect(24, 287);  // eve1 mailbox 1 user 1
131             IntXbar_connect(25, 296);  // eve2 mailbox 1 user 1
132             IntXbar_connect(26, 253);  // system mailbox 6 user 0
134             InterruptDsp_module->interruptTable[7] = 57;    // IPU2-0
135             InterruptDsp_module->interruptTable[10] = 57;   // IPU2-1
137             /* plug eve3 and eve4 mbxs only if eve3 and eve4 exists */
138             if ((MultiProc_getId("EVE3") != MultiProc_INVALIDID) ||
139                 (MultiProc_getId("EVE4") != MultiProc_INVALIDID)) {
140                 IntXbar_connect(27, 305);  // eve3 mailbox 1 user 1
141                 IntXbar_connect(28, 314);  // eve4 mailbox 1 user 1
142             }
144             /* plug mbx7 only if DSP1 or IPU1 exists */
145             if ((MultiProc_getId("DSP1") != MultiProc_INVALIDID) ||
146                 (MultiProc_getId("IPU1") != MultiProc_INVALIDID) ||
147                 (MultiProc_getId("IPU1-0") != MultiProc_INVALIDID)) {
148                 IntXbar_connect(29, 258);  // system mailbox 7 user 1
149                 InterruptDsp_module->interruptTable[6] = 60;    // IPU1-0
150             }
152             /* plug mbx8 only if IPU1-1 exists */
153             if (MultiProc_getId("IPU1-1") != MultiProc_INVALIDID) {
154                 IntXbar_connect(30, 262);  // system mailbox 8 user 1
155                 InterruptDsp_module->interruptTable[9] = 61;    // IPU1-1
156             }
157         }
158         return (Startup_DONE);
159     }
161     return (Startup_NOTDONE);
164 /*
165  *  ======== InterruptDsp_intEnable ========
166  *  Enable remote processor interrupt
167  */
168 Void InterruptDsp_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
170     UInt16 index;
172     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
173             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
175     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
177     REG32(MAILBOX_IRQENABLE_SET_DSP(index))=MAILBOX_REG_VAL(SUBMBX_IDX(index));
180 /*
181  *  ======== InterruptDsp_intDisable ========
182  *  Disables remote processor interrupt
183  */
184 Void InterruptDsp_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
186     UInt16 index;
188     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
189             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
191     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
193     REG32(MAILBOX_IRQENABLE_CLR_DSP(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
196 /*
197  *  ======== InterruptDsp_intRegister ========
198  */
199 Void InterruptDsp_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
200         Fxn func, UArg arg)
202     UInt        key;
203     Int         index;
204     InterruptDsp_FxnTable *table;
206     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
207             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
209     index = PROCID(remoteProcId);
211     /* Disable global interrupts */
212     key = Hwi_disable();
214     table = &(InterruptDsp_module->fxnTable[index]);
215     table->func = func;
216     table->arg  = arg;
218     InterruptDsp_intClear(remoteProcId, intInfo);
220     /* plug the cpu interrupt */
221     NotifySetup_plugHwi(remoteProcId, intInfo->intVectorId,
222             InterruptDsp_intShmStub);
224     /* Enable the mailbox interrupt to the DSP */
225     InterruptDsp_intEnable(remoteProcId, intInfo);
227     /* Restore global interrupts */
228     Hwi_restore(key);
231 /*
232  *  ======== InterruptDsp_intUnregister ========
233  */
234 Void InterruptDsp_intUnregister(UInt16 remoteProcId,
235                                 IInterrupt_IntInfo *intInfo)
237     Int index;
238     InterruptDsp_FxnTable *table;
240     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
241             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
243     index = PROCID(remoteProcId);
245     /* disable the mailbox interrupt source */
246     InterruptDsp_intDisable(remoteProcId, intInfo);
248     /* unplug isr and unprogram the event dispatcher */
249     NotifySetup_unplugHwi(remoteProcId, intInfo->intVectorId);
251     table = &(InterruptDsp_module->fxnTable[index]);
252     table->func = NULL;
253     table->arg  = 0;
256 /*
257  *  ======== InterruptDsp_intSend ========
258  *  Send interrupt to the remote processor
259  */
260 Void InterruptDsp_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
261                           UArg arg)
263     UInt key;
264     UInt16 index;
266     index = MBX_TABLE_IDX(MultiProc_self(), remoteProcId);
268     /*
269      *  Before writing to a mailbox, check whether it already contains a
270      *  message. If so, wait for the message to be read since we want one
271      *  and only one message per interrupt. Disable interrupts between reading
272      *  the MSGSTATUS_X register and writing to the mailbox to protect from
273      *  another thread doing an intSend at the same time.
274      */
275     key = Hwi_disable();
276     while (REG32(MAILBOX_STATUS(index)) != 0) {
277         Hwi_restore(key);
278         key = Hwi_disable();
279     }
280     REG32(MAILBOX_MESSAGE(index)) = arg;
281     Hwi_restore(key);
284 /*
285  *  ======== InterruptDsp_intPost ========
286  */
287 Void InterruptDsp_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
288                           UArg arg)
290     UInt key;
291     UInt16 index;
293     index = MBX_TABLE_IDX(srcProcId, MultiProc_self());
295     key = Hwi_disable();
296     if (REG32(MAILBOX_STATUS(index)) == 0) {
297         REG32(MAILBOX_MESSAGE(index)) = arg;
298     }
299     Hwi_restore(key);
302 /*
303  *  ======== InterruptDsp_intClear ========
304  *  Clear interrupt
305  */
306 UInt InterruptDsp_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
308     UInt arg;
309     UInt16 index;
311     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
313     arg = REG32(MAILBOX_MESSAGE(index));
314     REG32(MAILBOX_IRQSTATUS_CLR_DSP(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
316     /* Write to EOI (End Of Interrupt) register */
317     REG32(MAILBOX_EOI_REG(index)) = 0x1;
319     return (arg);
322 /*
323  *************************************************************************
324  *                      Internals functions
325  *************************************************************************
326  */
328 /*
329  *  ======== InterruptDsp_intShmStub ========
330  */
331 Void InterruptDsp_intShmStub(UInt16 idx)
333     UInt16 srcVirtId;
334     InterruptDsp_FxnTable *table;
336     srcVirtId = idx / InterruptDsp_NUM_CORES;
337     table = &(InterruptDsp_module->fxnTable[srcVirtId]);
338     (table->func)(table->arg);