1 /*
2 * Copyright (c) 2011-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 * ======== Interrupt.c ========
34 * OMAP4430/Ducati Interrupt Manger
35 */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
40 #include <ti/sysbios/hal/Hwi.h>
41 #include <ti/sysbios/family/c64p/tesla/Wugen.h>
43 #include <ti/ipc/MultiProc.h>
45 #include "InterruptDsp.h"
47 /* Register access method. */
48 #define REG16(A) (*(volatile UInt16 *) (A))
49 #define REG32(A) (*(volatile UInt32 *) (A))
51 #define HOSTINT 26
52 #define DSPINT 55
53 #define M3INT_MBX 50
54 #define M3INT 19
56 #define DSPEVENTID 5
58 /* Assigned mailboxes */
59 #define HOST_TO_SYSM3_MBX 0 /* Rx on SysM3 from Host */
60 #define M3_TO_HOST_MBX 1 /* Tx to Host from M3 */
61 #define DSP_TO_HOST_MBX 2 /* Tx to Host from DSP */
62 #define HOST_TO_DSP_MBX 3 /* Rx on DSP from Host */
63 #define SYSM3_TO_APPM3_MBX 4 /* Rx on AppM3 from Host/SysM3 */
65 #define MAILBOX_BASEADDR (0x4A0F4000)
67 #define MAILBOX_MESSAGE(M) (MAILBOX_BASEADDR + 0x040 + (0x4 * M))
68 #define MAILBOX_STATUS(M) (MAILBOX_BASEADDR + 0x0C0 + (0x4 * M))
69 #define MAILBOX_REG_VAL(M) (0x1 << (2 * M))
71 #define MAILBOX_IRQSTATUS_CLR_DSP (MAILBOX_BASEADDR + 0x114)
72 #define MAILBOX_IRQENABLE_SET_DSP (MAILBOX_BASEADDR + 0x118)
73 #define MAILBOX_IRQENABLE_CLR_DSP (MAILBOX_BASEADDR + 0x11C)
75 Hwi_FuncPtr userFxn = NULL;
77 Void InterruptDsp_isr(UArg arg);
79 /*
80 *************************************************************************
81 * Module functions
82 *************************************************************************
83 */
85 /*!
86 * ======== InterruptDsp_intEnable ========
87 * Enable remote processor interrupt
88 */
89 Void InterruptDsp_intEnable()
90 {
91 REG32(MAILBOX_IRQENABLE_SET_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
92 }
94 /*!
95 * ======== InterruptDsp_intDisable ========
96 * Disables remote processor interrupt
97 */
98 Void InterruptDsp_intDisable()
99 {
100 REG32(MAILBOX_IRQENABLE_CLR_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
101 }
103 /*!
104 * ======== InterruptDsp_intRegister ========
105 */
106 Void InterruptDsp_intRegister(Hwi_FuncPtr fxn)
107 {
108 Hwi_Params hwiAttrs;
109 UInt key;
111 userFxn = fxn;
113 /* Disable global interrupts */
114 key = Hwi_disable();
116 /*
117 * DSP interrupts are edge-triggered, so clear the interrupt status to
118 * regenerate an interrupt if there are some messages sent prior to
119 * booting the DSP.
120 */
121 REG32(MAILBOX_IRQSTATUS_CLR_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
123 Hwi_Params_init(&hwiAttrs);
125 hwiAttrs.eventId = DSPINT;
126 Hwi_create(DSPEVENTID,
127 (Hwi_FuncPtr)InterruptDsp_isr,
128 &hwiAttrs,
129 NULL);
131 /* Enable the interrupt */
132 Wugen_enableEvent(DSPINT);
133 Hwi_enableInterrupt(DSPEVENTID);
135 /* Enable the mailbox interrupt to the M3 core */
136 InterruptDsp_intEnable();
138 /* Restore global interrupts */
139 Hwi_restore(key);
140 }
142 /*!
143 * ======== InterruptDsp_intSend ========
144 * Send interrupt to the remote processor
145 */
146 Void InterruptDsp_intSend(UInt16 remoteProcId, UArg arg)
147 {
148 static Bool configured = FALSE;
149 static UInt16 sysm3ProcId = MultiProc_INVALIDID;
150 static UInt16 appm3ProcId = MultiProc_INVALIDID;
151 static UInt16 hostProcId = MultiProc_INVALIDID;
152 static UInt16 dspProcId = MultiProc_INVALIDID;
154 if (!configured) {
155 hostProcId = MultiProc_getId("HOST");
156 dspProcId = MultiProc_getId("DSP");
157 sysm3ProcId = MultiProc_getId("CORE0");
158 appm3ProcId = MultiProc_getId("CORE1");
159 configured = TRUE;
160 }
162 if (remoteProcId == sysm3ProcId) {
163 REG32(MAILBOX_MESSAGE(HOST_TO_SYSM3_MBX)) = arg;
164 }
165 else if (remoteProcId == appm3ProcId) {
166 REG32(MAILBOX_MESSAGE(SYSM3_TO_APPM3_MBX)) = arg;
167 }
168 else if (remoteProcId == hostProcId) {
169 REG32(MAILBOX_MESSAGE(DSP_TO_HOST_MBX)) = arg;
170 }
171 else if (remoteProcId == dspProcId) {
172 REG32(MAILBOX_MESSAGE(HOST_TO_DSP_MBX)) = arg;
173 }
174 else {
175 /* Should never get here */
176 Assert_isTrue(FALSE, NULL);
177 }
178 }
180 /*!
181 * ======== InterruptDsp_intClear ========
182 * Clear interrupt and return payload
183 */
184 UInt InterruptDsp_intClear()
185 {
186 UInt arg = INVALIDPAYLOAD;
188 if (REG32(MAILBOX_STATUS(HOST_TO_DSP_MBX)) != 0) {
189 /* If there is a message, return the argument to the caller */
190 arg = REG32(MAILBOX_MESSAGE(HOST_TO_DSP_MBX));
191 REG32(MAILBOX_IRQSTATUS_CLR_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
192 }
194 return (arg);
195 }
197 /*!
198 * ======== InterruptDsp_isr ========
199 */
200 Void InterruptDsp_isr(UArg arg)
201 {
202 UArg payload;
204 payload = InterruptDsp_intClear();
205 if (payload != (UInt)INVALIDPAYLOAD) {
206 userFxn(payload);
207 }
208 }