Add config to allow VPSS-M3 to EVE communication
[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         (remoteProcId == InterruptEve_vpssProcId)) {
90         REG32(MAILBOX_IRQENABLE_SET_EVE) = MAILBOX_REG_VAL(VIDEO_TO_EVE);
91     }
92     else if (remoteProcId == InterruptEve_dspProcId) {
93         REG32(MAILBOX_IRQENABLE_SET_EVE) = MAILBOX_REG_VAL(DSP_TO_EVE);
94     }
95     else {
96         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
97     }
98 }
100 /*
101  *  ======== InterruptEve_intDisable ========
102  *  Disables remote processor interrupt
103  */
104 Void InterruptEve_intDisable(UInt16 remoteProcId,
105                                 IInterrupt_IntInfo *intInfo)
107     if (remoteProcId == InterruptEve_hostProcId) {
108         REG32(MAILBOX_IRQENABLE_CLR_EVE) = MAILBOX_REG_VAL(HOST_TO_EVE);
109     }
110     else if ((remoteProcId == InterruptEve_videoProcId) ||
111         (remoteProcId == InterruptEve_vpssProcId)) {
112         REG32(MAILBOX_IRQENABLE_CLR_EVE) = MAILBOX_REG_VAL(VIDEO_TO_EVE);
113     }
114     else if (remoteProcId == InterruptEve_dspProcId) {
115         REG32(MAILBOX_IRQENABLE_CLR_EVE) = MAILBOX_REG_VAL(DSP_TO_EVE);
116     }
117     else {
118         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
119     }
122 /*
123  *  ======== InterruptEve_intRegister ========
124  */
125 Void InterruptEve_intRegister(UInt16 remoteProcId,
126                               IInterrupt_IntInfo *intInfo,
127                               Fxn func, UArg arg)
129     UInt        key;
130     Int         index;
131     Hwi_Params  hwiAttrs;
132     Error_Block eb;
133     InterruptEve_FxnTable *table;
135     Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
136             ti_sdo_ipc_Ipc_A_internal);
138     /* Assert that our MultiProc id is set correctly */
139     Assert_isTrue((InterruptEve_eveProcId == MultiProc_self()),
140                    ti_sdo_ipc_Ipc_A_internal);
142     /* init error block */
143     Error_init(&eb);
145     if (remoteProcId == InterruptEve_hostProcId) {
146         index = 0;
147     }
148     else if ((remoteProcId == InterruptEve_videoProcId) ||
149         (remoteProcId == InterruptEve_vpssProcId)) {
150         index = 1;
151     }
152     else if (remoteProcId == InterruptEve_dspProcId) {
153         index = 2;
154     }
155     else {
156         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
157     }
159     /* Disable global interrupts */
160     key = Hwi_disable();
162     table = &(InterruptEve_module->fxnTable[index]);
163     table->func = func;
164     table->arg  = arg;
166     InterruptEve_intClear(remoteProcId, intInfo);
168     /* Make sure the interrupt only gets plugged once */
169     InterruptEve_module->numPlugged++;
170     if (InterruptEve_module->numPlugged == 1) {
171         /* Register interrupt to remote processor */
172         Hwi_Params_init(&hwiAttrs);
173         hwiAttrs.arg = arg;
174         hwiAttrs.vectorNum = intInfo->intVectorId;
176         Hwi_create(MAILBOX_EVEINT,
177                   (Hwi_FuncPtr)InterruptEve_intShmStub,
178                    &hwiAttrs,
179                    &eb);
181         Hwi_enableInterrupt(MAILBOX_EVEINT);
182     }
184     /* enable the mailbox and Hwi */
185     InterruptEve_intEnable(remoteProcId, intInfo);
187     /* Restore global interrupts */
188     Hwi_restore(key);
191 /*
192  *  ======== InterruptEve_intUnregister ========
193  */
194 Void InterruptEve_intUnregister(UInt16 remoteProcId,
195                                 IInterrupt_IntInfo *intInfo)
197     Hwi_Handle  hwiHandle;
198     Int         index;
199     InterruptEve_FxnTable *table;
201     if (remoteProcId == InterruptEve_hostProcId) {
202         index = 0;
203     }
204     else if ((remoteProcId == InterruptEve_videoProcId) ||
205         (remoteProcId == InterruptEve_vpssProcId)) {
206         index = 1;
207     }
208     else if (remoteProcId == InterruptEve_dspProcId) {
209         index = 2;
210     }
211     else {
212         Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal);
213     }
215     /* Disable the mailbox interrupt source */
216     InterruptEve_intDisable(remoteProcId, intInfo);
218     InterruptEve_module->numPlugged--;
219     if (InterruptEve_module->numPlugged == 0) {
220         /* Delete the Hwi */
221         hwiHandle = Hwi_getHandle(intInfo->intVectorId);
222         Hwi_delete(&hwiHandle);
223     }
225     /* Clear the FxnTable entry for the remote processor */
226     table = &(InterruptEve_module->fxnTable[index]);
227     table->func = NULL;
228     table->arg  = 0;
232 /*
233  *  ======== InterruptEve_intSend ========
234  *  Send interrupt to the remote processor
235  */
236 Void InterruptEve_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
237                           UArg arg)
239     UInt key;
241     if (remoteProcId == InterruptEve_hostProcId) {
242         /* disable interrupts */
243         key = Hwi_disable();
245         if (REG32(MAILBOX_STATUS(EVE_TO_HOST)) == 0) {
246             /* write the mailbox message to host */
247             REG32(MAILBOX_MESSAGE(EVE_TO_HOST)) = arg;
248         }
250         /* restore interrupts */
251         Hwi_restore(key);
252     }
253     else if ((remoteProcId == InterruptEve_videoProcId) ||
254         (remoteProcId == InterruptEve_vpssProcId)) {
255         /* disable interrupts */
256         key = Hwi_disable();
258         if (REG32(MAILBOX_STATUS(EVE_TO_VIDEO)) == 0) {
259             /* write the mailbox message to video-m3 */
260             REG32(MAILBOX_MESSAGE(EVE_TO_VIDEO)) = arg;
261         }
263         /* restore interrupts */
264         Hwi_restore(key);
265     }
266     else {
267         /* disable interrupts */
268         key = Hwi_disable();
270         if (REG32(MAILBOX_STATUS(EVE_TO_DSP)) == 0) {
271             /* write the mailbox message to dsp */
272             REG32(MAILBOX_MESSAGE(EVE_TO_DSP)) = arg;
273         }
275         /* restore interrupts */
276         key = Hwi_disable();
277     }
280 /*
281  *  ======== InterruptEve_intPost ========
282  *  Simulate an interrupt from a remote processor
283  */
284 Void InterruptEve_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
285                             UArg arg)
287     UInt key;
289     if (srcProcId == InterruptEve_hostProcId) {
290         /* disable interrupts */
291         key = Hwi_disable();
293         if (REG32(MAILBOX_STATUS(HOST_TO_EVE)) == 0) {
294             /* write the mailbox message to arp32 */
295             REG32(MAILBOX_MESSAGE(HOST_TO_EVE)) = arg;
296         }
298         /* restore interrupts */
299         Hwi_restore(key);
300     }
301     else if ((srcProcId == InterruptEve_videoProcId) ||
302         (srcProcId == InterruptEve_vpssProcId)) {
303         /* disable interrupts */
304         key = Hwi_disable();
306         if (REG32(MAILBOX_STATUS(VIDEO_TO_EVE)) == 0) {
307             /* write the mailbox message to arp32 */
308             REG32(MAILBOX_MESSAGE(VIDEO_TO_EVE)) = arg;
309         }
311         /* restore interrupts */
312         Hwi_restore(key);
313     }
314     else {
315         /* disable interrupts */
316         key = Hwi_disable();
318         if (REG32(MAILBOX_STATUS(DSP_TO_EVE)) == 0) {
319             /* write the mailbox message to arp32 */
320             REG32(MAILBOX_MESSAGE(DSP_TO_EVE)) = arg;
321         }
323         /* restore interrupts */
324         Hwi_restore(key);
325     }
329 /*
330  *  ======== InterruptEve_intClear ========
331  *  Clear interrupt
332  */
333 UInt InterruptEve_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
335     UInt arg;
337     if (remoteProcId == InterruptEve_hostProcId) { /* HOST */
338         arg = REG32(MAILBOX_MESSAGE(HOST_TO_EVE));
339         REG32(MAILBOX_IRQSTATUS_CLR_EVE) = MAILBOX_REG_VAL(HOST_TO_EVE);
340     }
341     else if ((remoteProcId == InterruptEve_videoProcId) || /* VIDEO-M3 */
342         (remoteProcId == InterruptEve_vpssProcId)) {
343         arg = REG32(MAILBOX_MESSAGE(VIDEO_TO_EVE));
344         REG32(MAILBOX_IRQSTATUS_CLR_EVE) = MAILBOX_REG_VAL(VIDEO_TO_EVE);
345     }
346     else { /* DSP */
347         arg = REG32(MAILBOX_MESSAGE(DSP_TO_EVE));
348         REG32(MAILBOX_IRQSTATUS_CLR_EVE) = MAILBOX_REG_VAL(DSP_TO_EVE);
349     }
351     /* Write to EOI (End Of Interrupt) register */
352     REG32(MAILBOX_EOI_REG) = 0x1;
354     return (arg);
357 /*
358  *************************************************************************
359  *                      Internals functions
360  *************************************************************************
361  */
363 /*
364  *  ======== InterruptEve_intShmStub ========
365  */
366 Void InterruptEve_intShmStub(UArg arg)
368     InterruptEve_FxnTable *table;
370     /* Process messages from the HOST */
371     if ((REG32(MAILBOX_IRQENABLE_SET_EVE) & MAILBOX_REG_VAL(HOST_TO_EVE))
372         && REG32(MAILBOX_STATUS(HOST_TO_EVE)) != 0) {
373         table = &(InterruptEve_module->fxnTable[0]);
374         (table->func)(table->arg);
375     }
377     /* Process messages from VIDEO OR VPSS */
378     if ((REG32(MAILBOX_IRQENABLE_SET_EVE) & MAILBOX_REG_VAL(VIDEO_TO_EVE))
379         && REG32(MAILBOX_STATUS(VIDEO_TO_EVE)) != 0) {
380         table = &(InterruptEve_module->fxnTable[1]);
381         (table->func)(table->arg);
382     }
384     /* Process messages from DSP  */
385     if ((REG32(MAILBOX_IRQENABLE_SET_EVE) & MAILBOX_REG_VAL(DSP_TO_EVE))
386         && REG32(MAILBOX_STATUS(DSP_TO_EVE)) != 0) {
387         table = &(InterruptEve_module->fxnTable[2]);
388         (table->func)(table->arg);
389     }