]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/vayu/InterruptDsp.c
SDOCM00106584 Notify mailbox driver support on DRA7xx (IPU, HOST) - Part 1
[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_intEnable ========
93  *  Enable remote processor interrupt
94  */
95 Void InterruptDsp_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
96 {
97     UInt16 index;
99     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
100             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
102     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
104     REG32(MAILBOX_IRQENABLE_SET_DSP(index))=MAILBOX_REG_VAL(SUBMBX_IDX(index));
107 /*
108  *  ======== InterruptDsp_intDisable ========
109  *  Disables remote processor interrupt
110  */
111 Void InterruptDsp_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
113     UInt16 index;
115     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
116             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
118     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
120     REG32(MAILBOX_IRQENABLE_CLR_DSP(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
123 /*
124  *  ======== InterruptDsp_intRegister ========
125  */
126 Void InterruptDsp_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
127         Fxn func, UArg arg)
129     UInt        key;
130     Int         index;
131     InterruptDsp_FxnTable *table;
133     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
134             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
136     index = PROCID(remoteProcId);
138     /* Disable global interrupts */
139     key = Hwi_disable();
141     table = &(InterruptDsp_module->fxnTable[index]);
142     table->func = func;
143     table->arg  = arg;
145     InterruptDsp_intClear(remoteProcId, intInfo);
147     /* plug the cpu interrupt */
148     NotifySetup_plugHwi(remoteProcId, intInfo->intVectorId,
149             InterruptDsp_intShmStub);
151     /* Enable the mailbox interrupt to the DSP */
152     InterruptDsp_intEnable(remoteProcId, intInfo);
154     /* Restore global interrupts */
155     Hwi_restore(key);
158 /*
159  *  ======== InterruptDsp_intUnregister ========
160  */
161 Void InterruptDsp_intUnregister(UInt16 remoteProcId,
162                                 IInterrupt_IntInfo *intInfo)
164     Int index;
165     InterruptDsp_FxnTable *table;
167     Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) &&
168             (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal);
170     index = PROCID(remoteProcId);
172     /* disable the mailbox interrupt source */
173     InterruptDsp_intDisable(remoteProcId, intInfo);
175     /* unplug isr and unprogram the event dispatcher */
176     NotifySetup_unplugHwi(remoteProcId, intInfo->intVectorId);
178     table = &(InterruptDsp_module->fxnTable[index]);
179     table->func = NULL;
180     table->arg  = 0;
183 /*
184  *  ======== InterruptDsp_intSend ========
185  *  Send interrupt to the remote processor
186  */
187 Void InterruptDsp_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
188                           UArg arg)
190     UInt key;
191     UInt16 index;
193     index = MBX_TABLE_IDX(MultiProc_self(), remoteProcId);
195     /*
196      *  Before writing to a mailbox, check whether it already contains a
197      *  message. If so, wait for the message to be read since we want one
198      *  and only one message per interrupt. Disable interrupts between reading
199      *  the MSGSTATUS_X register and writing to the mailbox to protect from
200      *  another thread doing an intSend at the same time.
201      */
202     key = Hwi_disable();
203     while (REG32(MAILBOX_STATUS(index)) != 0) {
204         Hwi_restore(key);
205         key = Hwi_disable();
206     }
207     REG32(MAILBOX_MESSAGE(index)) = arg;
208     Hwi_restore(key);
211 /*
212  *  ======== InterruptDsp_intPost ========
213  */
214 Void InterruptDsp_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
215                           UArg arg)
217     UInt key;
218     UInt16 index;
220     index = MBX_TABLE_IDX(srcProcId, MultiProc_self());
222     key = Hwi_disable();
223     if (REG32(MAILBOX_STATUS(index)) == 0) {
224         REG32(MAILBOX_MESSAGE(index)) = arg;
225     }
226     Hwi_restore(key);
229 /*
230  *  ======== InterruptDsp_intClear ========
231  *  Clear interrupt
232  */
233 UInt InterruptDsp_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
235     UInt arg;
236     UInt16 index;
238     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
240     arg = REG32(MAILBOX_MESSAGE(index));
241     REG32(MAILBOX_IRQSTATUS_CLR_DSP(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
243     /* Write to EOI (End Of Interrupt) register */
244     REG32(MAILBOX_EOI_REG(index)) = 0x1;
246     return (arg);
249 /*
250  *************************************************************************
251  *                      Internals functions
252  *************************************************************************
253  */
255 /*
256  *  ======== InterruptDsp_intShmStub ========
257  */
258 Void InterruptDsp_intShmStub(UInt16 idx)
260     UInt16 srcVirtId;
261     InterruptDsp_FxnTable *table;
263     srcVirtId = idx / InterruptDsp_NUM_CORES;
264     table = &(InterruptDsp_module->fxnTable[srcVirtId]);
265     (table->func)(table->arg);