]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/omap4430/InterruptDsp.c
Rename: git mv src packages to complete application of ipc-j patches to ipcdev.
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / omap4430 / InterruptDsp.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  *  ======== InterruptDsp.c ========
34  *  Mailbox based interrupt manager
35  */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Assert.h>
39 #include <ti/sysbios/family/c64p/Hwi.h>
40 #include <ti/sysbios/family/c64p/tesla/Wugen.h>
42 #include <ti/sdo/utils/_MultiProc.h>
43 #include <ti/sdo/ipc/_Ipc.h>
45 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
47 #include "package/internal/InterruptDsp.xdc.h"
49 /* Register access method. */
50 #define REG16(A)   (*(volatile UInt16 *) (A))
51 #define REG32(A)   (*(volatile UInt32 *) (A))
53 #define MPUINT                 26
54 #define DSPINT                 55
55 #define M3INT_MBX              50
57 /* Assigned mailboxes */
58 #define DSP_TO_MPU             0
59 #define DSP_TO_M3              1
60 #define M3_TO_DSP              2
61 #define MPU_TO_DSP             3
62 #define MPU_TO_M3              4
63 #define M3_TO_MPU              5
65 #define MAILBOX_MESSAGE(M) \
66     InterruptDsp_mailboxBaseAddr + 0x040 + (0x4 * M)
67 #define MAILBOX_STATUS(M) \
68     InterruptDsp_mailboxBaseAddr + 0x0C0 + (0x4 * M)
70 #define MAILBOX_IRQSTATUS_CLR_DSP   InterruptDsp_mailboxBaseAddr + 0x114
71 #define MAILBOX_IRQENABLE_SET_DSP   InterruptDsp_mailboxBaseAddr + 0x118
72 #define MAILBOX_IRQENABLE_CLR_DSP   InterruptDsp_mailboxBaseAddr + 0x11C
74 /*
75  *************************************************************************
76  *                      Module functions
77  *************************************************************************
78  */
80 /*!
81  *  ======== InterruptDsp_intEnable ========
82  *  Enable remote processor interrupt
83  */
84 Void InterruptDsp_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
85 {
86     if (remoteProcId == InterruptDsp_hostProcId) {
87         REG32(MAILBOX_IRQENABLE_SET_DSP) = 0x40;
88     }
89     else if (remoteProcId == InterruptDsp_core0ProcId) {
90         REG32(MAILBOX_IRQENABLE_SET_DSP) = 0x10;
91     }
92     else {
93         /* DSP cannot talk to CORE1 */
94         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
95     }
96 }
98 /*!
99  *  ======== InterruptDsp_intDisable ========
100  *  Disables remote processor interrupt
101  */
102 Void InterruptDsp_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
104     if (remoteProcId == InterruptDsp_hostProcId) {
105         REG32(MAILBOX_IRQENABLE_CLR_DSP) = 0x40;
106     }
107     else if (remoteProcId == InterruptDsp_core0ProcId) {
108         REG32(MAILBOX_IRQENABLE_CLR_DSP) = 0x10;
109     }
110     else {
111         /* DSP cannot talk to CORE1 */
112         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
113     }
116 /*!
117  *  ======== InterruptDsp_intRegister ========
118  */
119 Void InterruptDsp_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
120                               Fxn func, UArg arg)
122     UInt        key;
123     Int         index;
124     InterruptDsp_FxnTable *table;
125     Hwi_Params  hwiParams;
127     /* Ensure that our ID is set correctly */
128     Assert_isTrue(InterruptDsp_dspProcId == MultiProc_self(),
129             ti_sdo_ipc_Ipc_A_internal);
131     /* Ensure that remoteProcId is valid */
132     Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
133             ti_sdo_ipc_Ipc_A_invArgument);
135     /* Ensure that proper intVectorId has been supplied */
136     Assert_isTrue(intInfo->intVectorId <= 15, ti_sdo_ipc_Ipc_A_internal);
138     if (remoteProcId == InterruptDsp_hostProcId) {
139         index = 0;
140     }
141     else if (remoteProcId == InterruptDsp_core0ProcId) {
142         index = 1;
143     }
144     else {
145         /* DSP cannot talk to CORE1 */
146         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
147     }
149     /* Disable global interrupts */
150     key = Hwi_disable();
152     table = &(InterruptDsp_module->fxnTable[index]);
153     table->func = func;
154     table->arg  = arg;
156     InterruptDsp_intClear(remoteProcId, intInfo);
158     /* Make sure the interrupt only gets plugged once */
159     InterruptDsp_module->numPlugged++;
160     if (InterruptDsp_module->numPlugged == 1) {
161         Hwi_Params_init(&hwiParams);
162         hwiParams.eventId = DSPINT;
163         Hwi_create(intInfo->intVectorId,
164                    (Hwi_FuncPtr)InterruptDsp_intShmStub,
165                    &hwiParams,
166                    NULL);
168         /* Enable the interrupt */
169         Wugen_enableEvent(DSPINT);
170         Hwi_enableInterrupt(intInfo->intVectorId);
171     }
173     /* Enable the mailbox interrupt to the DSP */
174     InterruptDsp_intEnable(remoteProcId, intInfo);
176     /* Restore global interrupts */
177     Hwi_restore(key);
180 /*!
181  *  ======== InterruptDsp_intUnregister ========
182  */
183 Void InterruptDsp_intUnregister(UInt16 remoteProcId,
184                                 IInterrupt_IntInfo *intInfo)
186     Hwi_Handle  hwiHandle;
187     Int         index;
188     InterruptDsp_FxnTable *table;
190     if (remoteProcId == InterruptDsp_hostProcId) {
191         index = 0;
192     }
193     else if (remoteProcId == InterruptDsp_core0ProcId) {
194         index = 1;
195     }
196     else {
197         /* DSP cannot talk to CORE1 */
198         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
199     }
202     /* Disable the mailbox interrupt source */
203     InterruptDsp_intDisable(remoteProcId, intInfo);
205     InterruptDsp_module->numPlugged--;
206     if (InterruptDsp_module->numPlugged == 0) {
207         /* Delete the Hwi */
208         hwiHandle = Hwi_getHandle(intInfo->intVectorId);
209         Hwi_delete(&hwiHandle);
210     }
212     table = &(InterruptDsp_module->fxnTable[index]);
213     table->func = NULL;
214     table->arg  = NULL;
217 /*!
218  *  ======== InterruptDsp_intSend ========
219  *  Send interrupt to the remote processor
220  */
221 Void InterruptDsp_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
222                           UArg arg)
224     UInt key;
226     /*
227      *  Before writing to a mailbox, check whehter it already contains a message
228      *  If so, then don't write to the mailbox since we want one and only one
229      *  message per interrupt.  Disable interrupts between reading
230      *  the MSGSTATUS_X register and writing to the mailbox to protect from
231      *  another thread doing an intSend at the same time
232      */
233     if (remoteProcId == InterruptDsp_hostProcId) {
234         /* Using mailbox 0 */
235         key = Hwi_disable();
236         if (REG32(MAILBOX_STATUS(DSP_TO_MPU)) == 0) {
237             REG32(MAILBOX_MESSAGE(DSP_TO_MPU)) = arg;
238         }
239         Hwi_restore(key);
240     }
241     else if (remoteProcId == InterruptDsp_core0ProcId) {
242         /* Using mailbox 1 */
243         key = Hwi_disable();
244         if (REG32(MAILBOX_STATUS(DSP_TO_M3)) == 0) {
245             REG32(MAILBOX_MESSAGE(DSP_TO_M3)) = arg;
246         }
247         Hwi_restore(key);
248     }
249     else {
250         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
251     }
254 /*!
255  *  ======== InterruptDsp_intPost ========
256  *  Send interrupt to the remote processor
257  */
258 Void InterruptDsp_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
259                           UArg arg)
261     UInt key;
263     if (srcProcId == InterruptDsp_hostProcId) {
264         key = Hwi_disable();
265         if (REG32(MAILBOX_STATUS(MPU_TO_DSP)) == 0) {
266             REG32(MAILBOX_MESSAGE(MPU_TO_DSP)) = arg;
267         }
268         Hwi_restore(key);
269     }
270     else if (srcProcId == InterruptDsp_core0ProcId) {
271         key = Hwi_disable();
272         if (REG32(MAILBOX_STATUS(M3_TO_DSP)) == 0) {
273             REG32(MAILBOX_MESSAGE(M3_TO_DSP)) = arg;
274         }
275         Hwi_restore(key);
276     }
277     else {
278         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
279     }
282 /*!
283  *  ======== InterruptDsp_intClear ========
284  *  Clear interrupt
285  */
286 UInt InterruptDsp_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
288     UInt arg;
290     if (remoteProcId == InterruptDsp_hostProcId) {
291         /* Mailbox 3 */
292         arg = REG32(MAILBOX_MESSAGE(MPU_TO_DSP));
293         REG32(MAILBOX_IRQSTATUS_CLR_DSP) = 0x40;
294     }
295     else if (remoteProcId == InterruptDsp_core0ProcId) {
296         /* Mailbox 2 */
297         arg = REG32(MAILBOX_MESSAGE(M3_TO_DSP));
298         REG32(MAILBOX_IRQSTATUS_CLR_DSP) = 0x10;
299     }
300     else {
301         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
302     }
304     return (arg);
307 /*
308  *************************************************************************
309  *                      Internals functions
310  *************************************************************************
311  */
313 /*!
314  *  ======== InterruptDsp_intShmStub ========
315  */
316 Void InterruptDsp_intShmStub(UArg arg)
318     InterruptDsp_FxnTable *table;
320     /* Process messages from  HOST */
321     if ((REG32(MAILBOX_IRQENABLE_SET_DSP) & 0x40) &&
322         REG32(MAILBOX_STATUS(MPU_TO_DSP)) != 0) {
323         table = &(InterruptDsp_module->fxnTable[0]);
324         (table->func)(table->arg);
325     }
327     /* Process messages from CORE0 */
328     if ((REG32(MAILBOX_IRQENABLE_SET_DSP) & 0x10) &&
329         REG32(MAILBOX_STATUS(M3_TO_DSP)) != 0) {
330         table = &(InterruptDsp_module->fxnTable[1]);
331         (table->func)(table->arg);
332     }