Revert "SDOCM00106428 Add notify mailbox driver support on DRA7xx (Part 3)"
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / vayu / InterruptArp32.c
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
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  */
32 /*
33  *  ======== InterruptArp32.c ========
34  *  ARP32 mailbox based interrupt manager
35  */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Error.h>
41 #include <ti/sysbios/family/arp32/Hwi.h>
43 #include <ti/sdo/utils/_MultiProc.h>
44 #include <ti/sdo/ipc/_Ipc.h>
45 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
47 #include "package/internal/InterruptArp32.xdc.h"
49 /* Register access method. */
50 #define REG16(A)   (*(volatile UInt16 *) (A))
51 #define REG32(A)   (*(volatile UInt32 *) (A))
53 #define PROCID(IDX)               (InterruptArp32_procIdTable[IDX])
54 #define MBX_TABLE_IDX(SRC, DST)   ((PROCID(SRC) * InterruptArp32_NUM_CORES) + \
55                                     PROCID(DST))
56 #define SUBMBX_IDX(IDX)           (InterruptArp32_mailboxTable[IDX] & 0xFF)
57 #define MBX_USER_IDX(IDX)         ((InterruptArp32_mailboxTable[IDX] >> 8) \
58                                     & 0xFF)
59 #define MBX_BASEADDR_IDX(IDX)     ((InterruptArp32_mailboxTable[IDX] >> 16) \
60                                     & 0xFFFF)
62 #define MAILBOX_REG_VAL(M)   (0x1 << (2 * M))
64 #define MAILBOX_MESSAGE(IDX) (InterruptArp32_mailboxBaseAddr[  \
65                                 MBX_BASEADDR_IDX(IDX)] + 0x040 \
66                                 + (0x4 * SUBMBX_IDX(IDX)))
67 #define MAILBOX_STATUS(IDX)  (InterruptArp32_mailboxBaseAddr[  \
68                                 MBX_BASEADDR_IDX(IDX)] + 0x0C0 \
69                                 + (0x4 * SUBMBX_IDX(IDX)))
71 #define MAILBOX_IRQSTATUS_CLR(IDX)  (InterruptArp32_mailboxBaseAddr[   \
72                                         MBX_BASEADDR_IDX(IDX)] + 0x104 \
73                                         + (MBX_USER_IDX(IDX) * 0x10))
74 #define MAILBOX_IRQENABLE_SET(IDX)  (InterruptArp32_mailboxBaseAddr[   \
75                                         MBX_BASEADDR_IDX(IDX)] + 0x108 \
76                                         + (MBX_USER_IDX(IDX) * 0x10))
77 #define MAILBOX_IRQENABLE_CLR(IDX)  (InterruptArp32_mailboxBaseAddr[   \
78                                         MBX_BASEADDR_IDX(IDX)] + 0x10C \
79                                         + (MBX_USER_IDX(IDX) * 0x10))
81 #define MAILBOX_EOI_REG(IDX)        (InterruptArp32_mailboxBaseAddr[   \
82                                         MBX_BASEADDR_IDX(IDX)] + 0x140)
84 /* This needs to match the virtual id from the TableInit.xs */
85 #define DSP1_ID     4
86 #define DSP2_ID     5
87 #define IPU1_ID     6
88 #define IPU2_ID     7
89 #define HOST_ID     8
90 #define IPU1_1_ID   9
91 #define IPU2_1_ID   10
93 /*
94  *************************************************************************
95  *                      Module functions
96  *************************************************************************
97  */
99 /*
100  *  ======== InterruptArp32_intEnable ========
101  *  Enable remote processor interrupt
102  */
103 Void InterruptArp32_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
105     UInt16 index;
107     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
109     REG32(MAILBOX_IRQENABLE_SET(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
112 /*
113  *  ======== InterruptArp32_intDisable ========
114  *  Disables remote processor interrupt
115  */
116 Void InterruptArp32_intDisable(UInt16 remoteProcId,
117                                 IInterrupt_IntInfo *intInfo)
119     UInt16 index;
121     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
123     REG32(MAILBOX_IRQENABLE_CLR(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
126 /*
127  *  ======== InterruptArp32_intRegister ========
128  */
129 Void InterruptArp32_intRegister(UInt16 remoteProcId,
130                                  IInterrupt_IntInfo *intInfo,
131                                  Fxn func, UArg arg)
133     UInt        key;
134     UInt16      index;
135     UInt        mbxIdx;
136     Hwi_Params  hwiAttrs;
137     Error_Block eb;
138     InterruptArp32_FxnTable *table;
140     Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
141            ti_sdo_ipc_Ipc_A_internal);
143     /* Assert that our MultiProc id is set correctly */
144     Assert_isTrue((InterruptArp32_eve1ProcId == MultiProc_self()) ||
145                   (InterruptArp32_eve2ProcId == MultiProc_self()) ||
146                   (InterruptArp32_eve3ProcId == MultiProc_self()) ||
147                   (InterruptArp32_eve4ProcId == MultiProc_self()),
148                    ti_sdo_ipc_Ipc_A_internal);
150     /* init error block */
151     Error_init(&eb);
153     index = PROCID(remoteProcId);
155     /* Disable global interrupts */
156     key = Hwi_disable();
158     table = &(InterruptArp32_module->fxnTable[index]);
159     table->func = func;
160     table->arg  = arg;
162     InterruptArp32_intClear(remoteProcId, intInfo);
164     if ((index == DSP1_ID) || (index == IPU1_ID) || (index == HOST_ID)) {
165         mbxIdx = 0;
166     }
167     else if ((index == DSP2_ID) || (index == IPU2_ID) ||
168              (index == IPU1_1_ID) || (index == IPU2_1_ID)) {
169         mbxIdx = 1;
170     }
171     else if (index < InterruptArp32_NUM_EVES) {
172         mbxIdx = 2;
173     }
175     /* Make sure the interrupt only gets plugged once */
176     InterruptArp32_module->numPlugged[mbxIdx]++;
177     if (InterruptArp32_module->numPlugged[mbxIdx] == 1) {
178         /* Register interrupt to remote processor */
179         Hwi_Params_init(&hwiAttrs);
180         hwiAttrs.arg = arg;
181         hwiAttrs.vectorNum = intInfo->intVectorId;
183         Hwi_create(InterruptArp32_eveInterruptTable[index],
184                   (Hwi_FuncPtr)InterruptArp32_intShmStub,
185                    &hwiAttrs,
186                    &eb);
187         Hwi_enableInterrupt(InterruptArp32_eveInterruptTable[index]);
188     }
190     /* enable the mailbox and Hwi */
191     InterruptArp32_intEnable(remoteProcId, intInfo);
193     /* Restore global interrupts */
194     Hwi_restore(key);
197 /*
198  *  ======== InterruptArp32_intUnregister ========
199  */
200 Void InterruptArp32_intUnregister(UInt16 remoteProcId,
201                                    IInterrupt_IntInfo *intInfo)
203     UInt16 index;
204     UInt   mbxIdx;
205     Hwi_Handle  hwiHandle;
206     InterruptArp32_FxnTable *table;
208     index = PROCID(remoteProcId);
210     if ((remoteProcId == DSP1_ID) || (remoteProcId == IPU1_ID) ||
211         (remoteProcId == HOST_ID)) {
212         mbxIdx = 0;
213     }
214     else if ((remoteProcId == DSP2_ID) || (remoteProcId == IPU2_ID) ||
215         (remoteProcId == IPU1_1_ID) || (remoteProcId == IPU2_1_ID)) {
216         mbxIdx = 1;
217     }
218     else if (remoteProcId < InterruptArp32_NUM_EVES) {
219         mbxIdx = 2;
220     }
222     /* Disable the mailbox interrupt source */
223     InterruptArp32_intDisable(remoteProcId, intInfo);
225     InterruptArp32_module->numPlugged[mbxIdx]--;
226     if (InterruptArp32_module->numPlugged[mbxIdx] == 0) {
227         /* Delete the Hwi */
228         hwiHandle = Hwi_getHandle(InterruptArp32_eveInterruptTable[index]);
229         Hwi_delete(&hwiHandle);
230     }
232     /* Clear the FxnTable entry for the remote processor */
233     table = &(InterruptArp32_module->fxnTable[index]);
234     table->func = NULL;
235     table->arg  = 0;
239 /*
240  *  ======== InterruptArp32_intSend ========
241  *  Send interrupt to the remote processor
242  */
243 Void InterruptArp32_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
244                              UArg arg)
246     UInt key;
247     UInt16 index;
249     index = MBX_TABLE_IDX(MultiProc_self(), remoteProcId);
251     /* disable interrupts */
252     key = Hwi_disable();
254     if (REG32(MAILBOX_STATUS(index)) == 0) {
255         /* write the mailbox message to remote proc */
256         REG32(MAILBOX_MESSAGE(index)) = arg;
257     }
259     /* restore interrupts */
260     Hwi_restore(key);
264 /*
265  *  ======== InterruptArp32_intPost ========
266  *  Simulate an interrupt from a remote processor
267  */
268 Void InterruptArp32_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
269                              UArg arg)
271     UInt key;
272     UInt16 index;
274     index = MBX_TABLE_IDX(srcProcId, MultiProc_self());
276     /* disable interrupts */
277     key = Hwi_disable();
279     if (REG32(MAILBOX_STATUS(index)) == 0) {
280         /* write the mailbox message to arp32 */
281         REG32(MAILBOX_MESSAGE(index)) = arg;
282     }
284     /* restore interrupts */
285     Hwi_restore(key);
289 /*
290  *  ======== InterruptArp32_intClear ========
291  *  Clear interrupt
292  */
293 UInt InterruptArp32_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
295     UInt arg;
296     UInt16 index;
298     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
300     arg = REG32(MAILBOX_MESSAGE(index));
301     /* clear the dsp mailbox */
302     REG32(MAILBOX_IRQSTATUS_CLR(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
304     /* Write to EOI (End Of Interrupt) register */
305     REG32(MAILBOX_EOI_REG(index)) = 0x1;
307     return (arg);
310 /*
311  *************************************************************************
312  *                      Internals functions
313  *************************************************************************
314  */
316 /*
317  *  ======== InterruptArp32_intShmStub ========
318  */
319 Void InterruptArp32_intShmStub(UArg arg)
321     UInt16 index;
322     UInt16 selfIdx;
323     UInt16 loopIdx;
324     InterruptArp32_FxnTable *table;
326     selfIdx = MultiProc_self();
328     for (loopIdx = 0; loopIdx < MultiProc_getNumProcsInCluster(); loopIdx++) {
330         if (loopIdx == selfIdx) {
331             continue;
332         }
334         index = MBX_TABLE_IDX(loopIdx, selfIdx);
336         if ((REG32(MAILBOX_STATUS(index)) != 0) &&
337             (REG32(MAILBOX_IRQENABLE_SET(index)) &
338              MAILBOX_REG_VAL(SUBMBX_IDX(index)))) {
339             /* call function with arg */
340             table = &(InterruptArp32_module->fxnTable[PROCID(loopIdx)]);
341             (table->func)(table->arg);
342         }
343     }