1d08b213a77643e6fe5662c7d801bc55fbc36ec3
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / c6a8149 / InterruptEve.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  *  ======== InterruptEve.c ========
34  *  EVE 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/InterruptEve.xdc.h"
49 /* Register access method. */
50 #define REG16(A)   (*(volatile UInt16 *) (A))
51 #define REG32(A)   (*(volatile UInt32 *) (A))
53 /* Assigned eve mailbox users */
54 #define EVE_TO_HOST     0
55 #define EVE_TO_DSP      1
56 #define EVE_TO_VIDEO    2
57 #define HOST_TO_EVE     3
58 #define DSP_TO_EVE      4
59 #define VIDEO_TO_EVE    5
61 #define MAILBOX_REG_VAL(M)   (0x1 << (2 * M))
63 #define MAILBOX_MESSAGE(M) (InterruptEve_mailboxEveBaseAddr + 0x040 + (0x4 * M))
64 #define MAILBOX_STATUS(M)  (InterruptEve_mailboxEveBaseAddr + 0x0C0 + (0x4 * M))
66 #define MAILBOX_IRQSTATUS_CLR_EVE  (InterruptEve_mailboxEveBaseAddr + 0x104)
67 #define MAILBOX_IRQENABLE_SET_EVE  (InterruptEve_mailboxEveBaseAddr + 0x108)
68 #define MAILBOX_IRQENABLE_CLR_EVE  (InterruptEve_mailboxEveBaseAddr + 0x10C)
69 #define MAILBOX_EOI_REG            (InterruptEve_mailboxEveBaseAddr + 0x140)
71 #define MAILBOX_EVEINT      29
73 /*
74  *************************************************************************
75  *                      Module functions
76  *************************************************************************
77  */
79 /*
80  *  ======== InterruptEve_intEnable ========
81  *  Enable remote processor interrupt
82  */
83 Void InterruptEve_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
84 {
85     if (remoteProcId == InterruptEve_hostProcId) {
86         REG32(MAILBOX_IRQENABLE_SET_EVE) = MAILBOX_REG_VAL(HOST_TO_EVE);
87     }
88     else if (remoteProcId == InterruptEve_videoProcId) {
89         REG32(MAILBOX_IRQENABLE_SET_EVE) = MAILBOX_REG_VAL(VIDEO_TO_EVE);
90     }
91     else if (remoteProcId == InterruptEve_dspProcId) {
92         REG32(MAILBOX_IRQENABLE_SET_EVE) = MAILBOX_REG_VAL(DSP_TO_EVE);
93     }
94     else {
95         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
96     }
97 }
99 /*
100  *  ======== InterruptEve_intDisable ========
101  *  Disables remote processor interrupt
102  */
103 Void InterruptEve_intDisable(UInt16 remoteProcId,
104                                 IInterrupt_IntInfo *intInfo)
106     if (remoteProcId == InterruptEve_hostProcId) {
107         REG32(MAILBOX_IRQENABLE_CLR_EVE) = MAILBOX_REG_VAL(HOST_TO_EVE);
108     }
109     else if (remoteProcId == InterruptEve_videoProcId) {
110         REG32(MAILBOX_IRQENABLE_CLR_EVE) = MAILBOX_REG_VAL(VIDEO_TO_EVE);
111     }
112     else if (remoteProcId == InterruptEve_dspProcId) {
113         REG32(MAILBOX_IRQENABLE_CLR_EVE) = MAILBOX_REG_VAL(DSP_TO_EVE);
114     }
115     else {
116         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
117     }
120 /*
121  *  ======== InterruptEve_intRegister ========
122  */
123 Void InterruptEve_intRegister(UInt16 remoteProcId,
124                               IInterrupt_IntInfo *intInfo,
125                               Fxn func, UArg arg)
127     UInt        key;
128     Int         index;
129     Hwi_Params  hwiAttrs;
130     Error_Block eb;
131     InterruptEve_FxnTable *table;
133     Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
134             ti_sdo_ipc_Ipc_A_internal);
136     /* Assert that our MultiProc id is set correctly */
137     Assert_isTrue((InterruptEve_eveProcId == MultiProc_self()),
138                    ti_sdo_ipc_Ipc_A_internal);
140     /* init error block */
141     Error_init(&eb);
143     if (remoteProcId == InterruptEve_hostProcId) {
144         index = 0;
145     }
146     else if (remoteProcId == InterruptEve_videoProcId) {
147         index = 1;
148     }
149     else if (remoteProcId == InterruptEve_dspProcId) {
150         index = 2;
151     }
152     else {
153         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
154     }
156     /* Disable global interrupts */
157     key = Hwi_disable();
159     table = &(InterruptEve_module->fxnTable[index]);
160     table->func = func;
161     table->arg  = arg;
163     InterruptEve_intClear(remoteProcId, intInfo);
165     /* Make sure the interrupt only gets plugged once */
166     InterruptEve_module->numPlugged++;
167     if (InterruptEve_module->numPlugged == 1) {
168         /* Register interrupt to remote processor */
169         Hwi_Params_init(&hwiAttrs);
170         hwiAttrs.arg = arg;
171         hwiAttrs.vectorNum = intInfo->intVectorId;
173         Hwi_create(MAILBOX_EVEINT,
174                   (Hwi_FuncPtr)InterruptEve_intShmStub,
175                    &hwiAttrs,
176                    &eb);
178         Hwi_enableInterrupt(MAILBOX_EVEINT);
179     }
181     /* enable the mailbox and Hwi */
182     InterruptEve_intEnable(remoteProcId, intInfo);
184     /* Restore global interrupts */
185     Hwi_restore(key);
188 /*
189  *  ======== InterruptEve_intUnregister ========
190  */
191 Void InterruptEve_intUnregister(UInt16 remoteProcId,
192                                 IInterrupt_IntInfo *intInfo)
194     Hwi_Handle  hwiHandle;
195     Int         index;
196     InterruptEve_FxnTable *table;
198     if (remoteProcId == InterruptEve_hostProcId) {
199         index = 0;
200     }
201     else if (remoteProcId == InterruptEve_videoProcId) {
202         index = 1;
203     }
204     else if (remoteProcId == InterruptEve_dspProcId) {
205         index = 2;
206     }
207     else {
208         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
209     }
211     /* Disable the mailbox interrupt source */
212     InterruptEve_intDisable(remoteProcId, intInfo);
214     InterruptEve_module->numPlugged--;
215     if (InterruptEve_module->numPlugged == 0) {
216         /* Delete the Hwi */
217         hwiHandle = Hwi_getHandle(intInfo->intVectorId);
218         Hwi_delete(&hwiHandle);
219     }
221     /* Clear the FxnTable entry for the remote processor */
222     table = &(InterruptEve_module->fxnTable[index]);
223     table->func = NULL;
224     table->arg  = 0;
228 /*
229  *  ======== InterruptEve_intSend ========
230  *  Send interrupt to the remote processor
231  */
232 Void InterruptEve_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
233                           UArg arg)
235     UInt key;
237     if (remoteProcId == InterruptEve_hostProcId) {
238         /* disable interrupts */
239         key = Hwi_disable();
241         if (REG32(MAILBOX_STATUS(EVE_TO_HOST)) == 0) {
242             /* write the mailbox message to host */
243             REG32(MAILBOX_MESSAGE(EVE_TO_HOST)) = arg;
244         }
246         /* restore interrupts */
247         Hwi_restore(key);
248     }
249     else if (remoteProcId == InterruptEve_videoProcId) {
250         /* disable interrupts */
251         key = Hwi_disable();
253         if (REG32(MAILBOX_STATUS(EVE_TO_VIDEO)) == 0) {
254             /* write the mailbox message to video-m3 */
255             REG32(MAILBOX_MESSAGE(EVE_TO_VIDEO)) = arg;
256         }
258         /* restore interrupts */
259         Hwi_restore(key);
260     }
261     else {
262         /* disable interrupts */
263         key = Hwi_disable();
265         if (REG32(MAILBOX_STATUS(EVE_TO_DSP)) == 0) {
266             /* write the mailbox message to dsp */
267             REG32(MAILBOX_MESSAGE(EVE_TO_DSP)) = arg;
268         }
270         /* restore interrupts */
271         key = Hwi_disable();
272     }
275 /*
276  *  ======== InterruptEve_intPost ========
277  *  Simulate an interrupt from a remote processor
278  */
279 Void InterruptEve_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
280                             UArg arg)
282     UInt key;
284     if (srcProcId == InterruptEve_hostProcId) {
285         /* disable interrupts */
286         key = Hwi_disable();
288         if (REG32(MAILBOX_STATUS(HOST_TO_EVE)) == 0) {
289             /* write the mailbox message to arp32 */
290             REG32(MAILBOX_MESSAGE(HOST_TO_EVE)) = arg;
291         }
293         /* restore interrupts */
294         Hwi_restore(key);
295     }
296     else if (srcProcId == InterruptEve_videoProcId) {
297         /* disable interrupts */
298         key = Hwi_disable();
300         if (REG32(MAILBOX_STATUS(VIDEO_TO_EVE)) == 0) {
301             /* write the mailbox message to arp32 */
302             REG32(MAILBOX_MESSAGE(VIDEO_TO_EVE)) = arg;
303         }
305         /* restore interrupts */
306         Hwi_restore(key);
307     }
308     else {
309         /* disable interrupts */
310         key = Hwi_disable();
312         if (REG32(MAILBOX_STATUS(DSP_TO_EVE)) == 0) {
313             /* write the mailbox message to arp32 */
314             REG32(MAILBOX_MESSAGE(DSP_TO_EVE)) = arg;
315         }
317         /* restore interrupts */
318         Hwi_restore(key);
319     }
323 /*
324  *  ======== InterruptEve_intClear ========
325  *  Clear interrupt
326  */
327 UInt InterruptEve_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
329     UInt arg;
331     if (remoteProcId == InterruptEve_hostProcId) { /* HOST */
332         arg = REG32(MAILBOX_MESSAGE(HOST_TO_EVE));
333         REG32(MAILBOX_IRQSTATUS_CLR_EVE) = MAILBOX_REG_VAL(HOST_TO_EVE);
334     }
335     else if (remoteProcId == InterruptEve_videoProcId) { /* VIDEO-M3 */
336         arg = REG32(MAILBOX_MESSAGE(VIDEO_TO_EVE));
337         REG32(MAILBOX_IRQSTATUS_CLR_EVE) = MAILBOX_REG_VAL(VIDEO_TO_EVE);
338     }
339     else { /* DSP */
340         arg = REG32(MAILBOX_MESSAGE(DSP_TO_EVE));
341         REG32(MAILBOX_IRQSTATUS_CLR_EVE) = MAILBOX_REG_VAL(DSP_TO_EVE);
342     }
344     /* Write to EOI (End Of Interrupt) register */
345     REG32(MAILBOX_EOI_REG) = 0x1;
347     return (arg);
350 /*
351  *************************************************************************
352  *                      Internals functions
353  *************************************************************************
354  */
356 /*
357  *  ======== InterruptEve_intShmStub ========
358  */
359 Void InterruptEve_intShmStub(UArg arg)
361     InterruptEve_FxnTable *table;
363     /* Process messages from the HOST */
364     if ((REG32(MAILBOX_IRQENABLE_SET_EVE) & MAILBOX_REG_VAL(HOST_TO_EVE))
365         && REG32(MAILBOX_STATUS(HOST_TO_EVE)) != 0) {
366         table = &(InterruptEve_module->fxnTable[0]);
367         (table->func)(table->arg);
368     }
370     /* Process messages from VIDEO  */
371     if ((REG32(MAILBOX_IRQENABLE_SET_EVE) & MAILBOX_REG_VAL(VIDEO_TO_EVE))
372         && REG32(MAILBOX_STATUS(VIDEO_TO_EVE)) != 0) {
373         table = &(InterruptEve_module->fxnTable[1]);
374         (table->func)(table->arg);
375     }
377     /* Process messages from DSP  */
378     if ((REG32(MAILBOX_IRQENABLE_SET_EVE) & MAILBOX_REG_VAL(DSP_TO_EVE))
379         && REG32(MAILBOX_STATUS(DSP_TO_EVE)) != 0) {
380         table = &(InterruptEve_module->fxnTable[2]);
381         (table->func)(table->arg);
382     }