]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/omap4430/InterruptDucati.c
b3c931ab42d27067b5e7c70de92e88bf2cc7ca15
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / omap4430 / InterruptDucati.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  *  ======== InterruptDucati.c ========
34  *  OMAP4430/Ducati Interrupt Manger
35  */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
40 #include <ti/sysbios/family/arm/m3/Hwi.h>
41 #include <ti/sysbios/family/arm/ducati/Core.h>
42 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
44 #include <ti/sdo/ipc/_Ipc.h>
45 #include <ti/sdo/utils/_MultiProc.h>
47 #include "package/internal/InterruptDucati.xdc.h"
49 /* Register access method. */
50 #define REG16(A)   (*(volatile UInt16 *) (A))
51 #define REG32(A)   (*(volatile UInt32 *) (A))
53 /* Register access method. */
54 #define REG16(A)   (*(volatile UInt16 *) (A))
55 #define REG32(A)   (*(volatile UInt32 *) (A))
57 #define HOSTINT                26
58 #define DSPINT                 55
59 #define M3INT_MBX              50
60 #define M3INT                  19
62 /* Assigned mailboxes */
63 #define DSP_TO_HOST            0
64 #define DSP_TO_M3              1
65 #define M3_TO_DSP              2
66 #define HOST_TO_DSP            3
67 #define HOST_TO_M3             4
68 #define M3_TO_HOST             5
70 #define MAILBOX_MESSAGE(M)   InterruptDucati_mailboxBaseAddr + 0x040 + (0x4 * M)
71 #define MAILBOX_STATUS(M)    InterruptDucati_mailboxBaseAddr + 0x0C0 + (0x4 * M)
73 #define MAILBOX_IRQSTATUS_CLR_M3    InterruptDucati_mailboxBaseAddr + 0x124
74 #define MAILBOX_IRQENABLE_SET_M3    InterruptDucati_mailboxBaseAddr + 0x128
75 #define MAILBOX_IRQENABLE_CLR_M3    InterruptDucati_mailboxBaseAddr + 0x12C
77 /*
78  *  Ducati control register that maintains inter-core interrupt bits.
79  *
80  *  Using separate core0 and core1 values to do 16-bit reads/writes
81  *  because we do not want to overwrite the other cores value.
82  */
83 #define INTERRUPT_CORE_0       (InterruptDucati_ducatiCtrlBaseAddr)
84 #define INTERRUPT_CORE_1       (InterruptDucati_ducatiCtrlBaseAddr + 2)
86 /*
87  *************************************************************************
88  *                      Module functions
89  *************************************************************************
90  */
92 /*!
93  *  ======== InterruptDucati_intEnable ========
94  *  Enable remote processor interrupt
95  */
96 Void InterruptDucati_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
97 {
98     /*
99      *  If the remote processor communicates via mailboxes, we should enable
100      *  the Mailbox IRQ instead of enabling the Hwi because multiple mailboxes
101      *  share the same Hwi
102      */
103     if (Core_getId() == 0) {
104         if (remoteProcId == InterruptDucati_hostProcId) {
105             REG32(MAILBOX_IRQENABLE_SET_M3) = 0x100;
106         }
107         else if (remoteProcId == InterruptDucati_dspProcId) {
108             REG32(MAILBOX_IRQENABLE_SET_M3) = 0x4;
109         }
110         else {
111             Hwi_enableInterrupt(M3INT);
112         }
113     }
114     else {
115         Hwi_enableInterrupt(M3INT);
116     }
119 /*!
120  *  ======== InterruptDucati_intDisable ========
121  *  Disables remote processor interrupt
122  */
123 Void InterruptDucati_intDisable(UInt16 remoteProcId,
124                                 IInterrupt_IntInfo *intInfo)
126     /*
127      *  If the remote processor communicates via mailboxes, we should disable
128      *  the Mailbox IRQ instead of disabling the Hwi because multiple mailboxes
129      *  share the same Hwi
130      */
131     if (Core_getId() == 0) {
132         if (remoteProcId == InterruptDucati_hostProcId) {
133             REG32(MAILBOX_IRQENABLE_CLR_M3) = 0x100;
134         }
135         else if (remoteProcId == InterruptDucati_dspProcId) {
136             REG32(MAILBOX_IRQENABLE_CLR_M3) = 0x4;
137         }
138         else {
139             Hwi_disableInterrupt(M3INT);
140         }
141     }
142     else {
143         Hwi_disableInterrupt(M3INT);
144     }
147 /*!
148  *  ======== InterruptDucati_intRegister ========
149  */
150 Void InterruptDucati_intRegister(UInt16 remoteProcId,
151                                  IInterrupt_IntInfo *intInfo,
152                                  Fxn func, UArg arg)
154     Hwi_Params  hwiAttrs;
155     UInt        key;
156     Int         index;
157     InterruptDucati_FxnTable *table;
159     /* Ensure that remoteProcId is valid */
160     Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
161             ti_sdo_ipc_Ipc_A_internal);
163     /* Ensure that our ID is set correctly */
164     Assert_isTrue((InterruptDucati_core0ProcId == MultiProc_self()) ||
165                   (InterruptDucati_core1ProcId == MultiProc_self()),
166                   ti_sdo_ipc_Ipc_A_internal);
168     /* Ensure that, if on CORE1, we're only talking to CORE0 */
169     Assert_isTrue(Core_getId() == 0 ||
170                   remoteProcId == InterruptDucati_core0ProcId,
171                   ti_sdo_ipc_Ipc_A_internal);
173     if (remoteProcId == InterruptDucati_dspProcId) {
174         index = 0;
175     }
176     else if (remoteProcId == InterruptDucati_hostProcId) {
177         index = 1;
178     }
179     else {
180         /* Going to the other M3 */
181         index = 2;
182     }
184     /* Disable global interrupts */
185     key = Hwi_disable();
187     table = &(InterruptDucati_module->fxnTable[index]);
188     table->func = func;
189     table->arg  = arg;
191     InterruptDucati_intClear(remoteProcId, intInfo);
193     Hwi_Params_init(&hwiAttrs);
194     hwiAttrs.maskSetting = Hwi_MaskingOption_LOWER;
196     /* Make sure the interrupt only gets plugged once */
197     if (remoteProcId == InterruptDucati_core0ProcId ||
198         remoteProcId == InterruptDucati_core1ProcId) {
199         Hwi_create(M3INT,
200                    (Hwi_FuncPtr) InterruptDucati_intShmDucatiStub,
201                    &hwiAttrs,
202                    NULL);
203     }
204     else {
205         InterruptDucati_module->numPlugged++;
206         if (InterruptDucati_module->numPlugged == 1) {
207             Hwi_create(M3INT_MBX,
208                        (Hwi_FuncPtr) InterruptDucati_intShmMbxStub,
209                        &hwiAttrs,
210                        NULL);
213             /* Interrupt_intEnable won't enable the Hwi */
214             Hwi_enableInterrupt(M3INT_MBX);
215         }
216     }
218     /* Enable the mailbox interrupt to the M3 core */
219     InterruptDucati_intEnable(remoteProcId, intInfo);
221     /* Restore global interrupts */
222     Hwi_restore(key);
226 /*!
227  *  ======== InterruptDucati_intUnregister ========
228  */
229 Void InterruptDucati_intUnregister(UInt16 remoteProcId,
230                                    IInterrupt_IntInfo *intInfo)
232     Hwi_Handle hwiHandle;
233     Int index;
234     InterruptDucati_FxnTable *table;
236     if (remoteProcId == InterruptDucati_dspProcId) {
237         index = 0;
238     }
239     else if (remoteProcId == InterruptDucati_hostProcId) {
240         index = 1;
241     }
242     else {
243         /* Going to the other M3 */
244         index = 2;
245     }
247     /* Disable the mailbox interrupt source */
248     InterruptDucati_intDisable(remoteProcId, intInfo);
250     /* Delete/disable the Hwi */
251     if (remoteProcId == InterruptDucati_core0ProcId ||
252         remoteProcId == InterruptDucati_core1ProcId) {
253         hwiHandle = Hwi_getHandle(M3INT);
254         Hwi_delete(&hwiHandle);
255     }
256     else {
257         InterruptDucati_module->numPlugged--;
258         if (InterruptDucati_module->numPlugged == 0) {
259             hwiHandle = Hwi_getHandle(M3INT_MBX);
260             Hwi_delete(&hwiHandle);
261         }
262     }
264     /* Clear the FxnTable entry for the remote processor */
265     table = &(InterruptDucati_module->fxnTable[index]);
266     table->func = NULL;
267     table->arg  = 0;
270 /*!
271  *  ======== InterruptDucati_intSend ========
272  *  Send interrupt to the remote processor
273  */
274 Void InterruptDucati_intSend(UInt16 remoteProcId,
275                              IInterrupt_IntInfo *intInfo,
276                              UArg arg)
278     UInt key;
280      /*
281      *  Before writing to a mailbox, check whehter it already contains a message
282      *  If so, then don't write to the mailbox since we want one and only one
283      *  message per interrupt.  Disable interrupts between reading
284      *  the MSGSTATUS_X register and writing to the mailbox to protect from
285      *  another thread doing an intSend at the same time
286      */
287     if (remoteProcId == InterruptDucati_core0ProcId ||
288         remoteProcId == InterruptDucati_core1ProcId) {
289         if (Core_getId() == 1) {
290             REG16(INTERRUPT_CORE_0) |= 0x1;
291         }
292         else {
293             REG16(INTERRUPT_CORE_1) |= 0x1;
294         }
295     }
296     else if (remoteProcId == InterruptDucati_dspProcId) {
297         key = Hwi_disable();
298         if (REG32(MAILBOX_STATUS(M3_TO_DSP)) == 0) {
299             REG32(MAILBOX_MESSAGE(M3_TO_DSP)) = arg;
300         }
301         Hwi_restore(key);
302     }
303     else { /* HOSTINT */
304         key = Hwi_disable();
305         if (REG32(MAILBOX_STATUS(M3_TO_HOST)) == 0) {
306             REG32(MAILBOX_MESSAGE(M3_TO_HOST)) = arg;
307         }
308         Hwi_restore(key);
309     }
312 /*!
313  *  ======== InterruptDucati_intPost ========
314  *  Simulate interrupt from remote processor
315  */
316 Void InterruptDucati_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
317                              UArg arg)
319     UInt key;
321     if (srcProcId == InterruptDucati_core0ProcId ||
322         srcProcId == InterruptDucati_core1ProcId) {
323         if (Core_getId() == 1) {
324             REG16(INTERRUPT_CORE_1) |= 0x1;
325         }
326         else {
327             REG16(INTERRUPT_CORE_0) |= 0x1;
328         }
329     }
330     else if (srcProcId == InterruptDucati_dspProcId) {
331         key = Hwi_disable();
332         if (REG32(MAILBOX_STATUS(DSP_TO_M3)) == 0) {
333             REG32(MAILBOX_MESSAGE(DSP_TO_M3)) = arg;
334         }
335         Hwi_restore(key);
336     }
337     else { /* HOSTINT */
338         key = Hwi_disable();
339         if (REG32(MAILBOX_STATUS(HOST_TO_M3)) == 0) {
340             REG32(MAILBOX_MESSAGE(HOST_TO_M3)) = arg;
341         }
342         Hwi_restore(key);
343     }
346 /*!
347  *  ======== InterruptDucati_intClear ========
348  *  Clear interrupt
349  */
350 UInt InterruptDucati_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
352     UInt arg;
354     if (remoteProcId == InterruptDucati_core0ProcId ||
355         remoteProcId == InterruptDucati_core1ProcId) {
356         arg = REG32(InterruptDucati_ducatiCtrlBaseAddr);
358         /* Look at BIOS's ducati Core id */
359         if (Core_getId() == 0) {
360             if ((REG16(INTERRUPT_CORE_0) & 0x1) == 0x1) {
361                 REG16(INTERRUPT_CORE_0) &= ~(0x1);
362             }
363         }
364         else {
365             if ((REG16(INTERRUPT_CORE_1) & 0x1) == 0x1) {
366                 REG16(INTERRUPT_CORE_1) &= ~(0x1);
367             }
368         }
369     }
370     else {
371         if (remoteProcId == InterruptDucati_hostProcId) {
372             arg = REG32(MAILBOX_MESSAGE(HOST_TO_M3));
373             REG32(MAILBOX_IRQSTATUS_CLR_M3) = 0x100; /* Mbx 4 */
374         }
375         else {
376             arg = REG32(MAILBOX_MESSAGE(DSP_TO_M3));
377             REG32(MAILBOX_IRQSTATUS_CLR_M3) = 0x4; /* Mbx 1 */
378         }
379     }
381     return (arg);
384 /*
385  *************************************************************************
386  *                      Internal functions
387  *************************************************************************
388  */
390 /*!
391  *  ======== InterruptDucati_intShmStub ========
392  */
393 Void InterruptDucati_intShmDucatiStub(UArg arg)
395     InterruptDucati_FxnTable *table;
397     table = &(InterruptDucati_module->fxnTable[2]);
398     (table->func)(table->arg);
401 /*!
402  *  ======== InterruptDucati_intShmMbxStub ========
403  */
404 Void InterruptDucati_intShmMbxStub(UArg arg)
406     InterruptDucati_FxnTable *table;
408     /* Process messages from the DSP  */
409     if ((REG32(MAILBOX_IRQENABLE_SET_M3) & 0x4) &&
410         REG32(MAILBOX_STATUS(DSP_TO_M3)) != 0) {
411         table = &(InterruptDucati_module->fxnTable[0]);
412         (table->func)(table->arg);
413     }
415     /* Process messages from the HOST  */
416     if ((REG32(MAILBOX_IRQENABLE_SET_M3) & 0x100) &&
417         REG32(MAILBOX_STATUS(HOST_TO_M3)) != 0) {
418         table = &(InterruptDucati_module->fxnTable[1]);
419         (table->func)(table->arg);
420     }