[processor-sdk/performance-audio-sr.git] / ipc_3_43_00_00_eng / packages / ti / ipc / family / omap54xx / InterruptIpu.c
1 /*
2 * Copyright (c) 2011-2014, 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 * ======== InterruptIpu.c ========
34 * IPU Interrupt Manger
35 */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Log.h>
40 #include <xdc/runtime/Diags.h>
42 #include <ti/sysbios/hal/Hwi.h>
43 #include <ti/ipc/MultiProc.h>
45 #include "InterruptIpu.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 /* Assigned mailboxes */
57 #define HOST_TO_SYSM3_MBX 0 /* Rx on SysM3 from Host */
58 #define M3_TO_HOST_MBX 1 /* Tx to Host from M3 */
59 #define DSP_TO_HOST_MBX 2 /* Tx to Host from DSP */
60 #define HOST_TO_DSP_MBX 3 /* Rx on DSP from Host */
62 #define MAILBOX_BASEADDR (0xAA0F4000)
64 #define MAILBOX_MESSAGE(M) (MAILBOX_BASEADDR + 0x040 + (0x4 * M))
65 #define MAILBOX_FIFOSTATUS(M) (MAILBOX_BASEADDR + 0x080 + (0x4 * M))
66 #define MAILBOX_STATUS(M) (MAILBOX_BASEADDR + 0x0C0 + (0x4 * M))
67 #define MAILBOX_REG_VAL(M) (0x1 << (2 * M))
69 #define MAILBOX_IRQSTATUS_CLR_M3 (MAILBOX_BASEADDR + 0x124)
70 #define MAILBOX_IRQENABLE_SET_M3 (MAILBOX_BASEADDR + 0x128)
71 #define MAILBOX_IRQENABLE_CLR_M3 (MAILBOX_BASEADDR + 0x12C)
73 Hwi_FuncPtr userFxn = NULL;
75 Void InterruptIpu_isr(UArg arg);
78 /*
79 *************************************************************************
80 * Module functions
81 *************************************************************************
82 */
84 /*!
85 * ======== InterruptIpu_intEnable ========
86 * Enable remote processor interrupt
87 */
88 Void InterruptIpu_intEnable()
89 {
90 /* Enable the Mailbox IRQ */
91 REG32(MAILBOX_IRQENABLE_SET_M3) = MAILBOX_REG_VAL(HOST_TO_SYSM3_MBX);
92 }
94 /*!
95 * ======== InterruptIpu_intDisable ========
96 * Disables remote processor interrupt
97 */
98 Void InterruptIpu_intDisable()
99 {
100 /* Disable the Mailbox IRQ */
101 REG32(MAILBOX_IRQENABLE_CLR_M3) = MAILBOX_REG_VAL(HOST_TO_SYSM3_MBX);
102 }
104 /*!
105 * ======== InterruptIpu_intRegister ========
106 */
107 Void InterruptIpu_intRegister(Hwi_FuncPtr fxn)
108 {
109 Hwi_Params hwiAttrs;
110 UInt key;
112 /* Disable global interrupts */
113 key = Hwi_disable();
115 userFxn = fxn;
116 Hwi_Params_init(&hwiAttrs);
117 hwiAttrs.maskSetting = Hwi_MaskingOption_LOWER;
119 Hwi_create(M3INT_MBX, (Hwi_FuncPtr)InterruptIpu_isr, &hwiAttrs, NULL);
121 /* InterruptIpu_intEnable won't enable the Hwi */
122 Hwi_enableInterrupt(M3INT_MBX);
124 /* Enable the mailbox interrupt to the M3 core */
125 InterruptIpu_intEnable();
127 /* Restore global interrupts */
128 Hwi_restore(key);
129 }
131 /*!
132 * ======== InterruptIpu_intSend ========
133 * Send interrupt to the remote processor
134 */
135 Void InterruptIpu_intSend(UInt16 remoteProcId, UArg arg)
136 {
137 static Bool configured = FALSE;
138 static UInt16 hostProcId = MultiProc_INVALIDID;
139 static UInt16 dspProcId = MultiProc_INVALIDID;
141 Log_print2(Diags_USER1,
142 "InterruptIpu_intSend: Sending interrupt with payload 0x%x to proc #%d",
143 (IArg)arg, (IArg)remoteProcId);
145 if (!configured) {
146 hostProcId = MultiProc_getId("HOST");
147 dspProcId = MultiProc_getId("DSP");
148 configured = TRUE;
149 }
151 if (remoteProcId == dspProcId) {
152 while(REG32(MAILBOX_FIFOSTATUS(HOST_TO_DSP_MBX)));
153 REG32(MAILBOX_MESSAGE(HOST_TO_DSP_MBX)) = arg;
154 }
155 else if (remoteProcId == hostProcId) {
156 while(REG32(MAILBOX_FIFOSTATUS(M3_TO_HOST_MBX)));
157 REG32(MAILBOX_MESSAGE(M3_TO_HOST_MBX)) = arg;
158 }
159 else {
160 /* Should never get here */
161 Assert_isTrue(FALSE, NULL);
162 }
163 }
165 /*!
166 * ======== InterruptIpu_intClear ========
167 * Clear interrupt and return payload
168 */
169 UInt InterruptIpu_intClear()
170 {
171 UInt arg = INVALIDPAYLOAD;
173 /* First check whether incoming mailbox has a message */
174 /* If FIFO is empty, return INVALIDPAYLOAD */
175 if (REG32(MAILBOX_STATUS(HOST_TO_SYSM3_MBX)) == 0) {
176 return (arg);
177 }
178 else {
179 /* If there is a message, return the argument to the caller */
180 arg = REG32(MAILBOX_MESSAGE(HOST_TO_SYSM3_MBX));
181 REG32(MAILBOX_IRQSTATUS_CLR_M3) = MAILBOX_REG_VAL(HOST_TO_SYSM3_MBX);
182 }
184 return (arg);
185 }
187 /*!
188 * ======== InterruptIpu_isr ========
189 * Calls the function supplied by the user in intRegister
190 */
191 Void InterruptIpu_isr(UArg arg)
192 {
193 UArg payload;
195 payload = InterruptIpu_intClear();
196 if (payload != INVALIDPAYLOAD) {
197 Log_print1(Diags_USER1,
198 "InterruptIpu_isr: Interrupt received, payload = 0x%x\n",
199 (IArg)payload);
200 userFxn(payload);
201 }
202 }