8c75141fcc1f08cdb9f1b7a7c702117abeb6713f
1 /*
2 * Copyright (c) 2017-2018 Texas Instruments Incorporated - http://www.ti.com
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 */
33 /*
34 * ======== InterruptHost.c ========
35 * Ducati/A8 based interupt manager
36 */
38 #include <xdc/std.h>
39 #include <xdc/runtime/Assert.h>
41 #include <ti/sysbios/family/arm/gicv3/Hwi.h>
43 #include <ti/sdo/ipc/family/am65xx/NotifySetup.h>
44 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
45 #include <ti/sdo/ipc/_Ipc.h>
46 #include <ti/sdo/utils/_MultiProc.h>
48 #include "package/internal/InterruptHost.xdc.h"
50 /* Register access method. */
51 #define REG16(A) (*(volatile UInt16 *) (A))
52 #define REG32(A) (*(volatile UInt32 *) (A))
54 #define PROCID(IDX) (InterruptHost_procIdTable[(IDX)])
55 #define MBX_TABLE_IDX(SRC, DST) ((PROCID(SRC) * InterruptHost_NUM_CORES) + \
56 PROCID(DST))
57 #define SUBMBX_IDX(IDX) (InterruptHost_mailboxTable[(IDX)] & 0xFF)
58 #define MBX_USER_IDX(IDX) ((InterruptHost_mailboxTable[(IDX)] >> 8) \
59 & 0xFF)
60 #define MBX_BASEADDR_IDX(IDX) ((InterruptHost_mailboxTable[(IDX)] >> 16) \
61 & 0xFFFF)
63 #define MAILBOX_REG_VAL(M) (0x1 << (2 * M))
65 #define MAILBOX_MESSAGE(IDX) (InterruptHost_mailboxBaseAddr[ \
66 MBX_BASEADDR_IDX(IDX)] + 0x40 + \
67 (0x4 * SUBMBX_IDX(IDX)))
68 #define MAILBOX_STATUS(IDX) (InterruptHost_mailboxBaseAddr[ \
69 MBX_BASEADDR_IDX(IDX)] + 0xC0 + \
70 (0x4 * SUBMBX_IDX(IDX)))
72 #define MAILBOX_IRQSTATUS_CLR(IDX) (InterruptHost_mailboxBaseAddr[ \
73 MBX_BASEADDR_IDX(IDX)] + (0x10 * \
74 MBX_USER_IDX(IDX)) + 0x104)
75 #define MAILBOX_IRQENABLE_SET(IDX) (InterruptHost_mailboxBaseAddr[ \
76 MBX_BASEADDR_IDX(IDX)] + (0x10 * \
77 MBX_USER_IDX(IDX)) + 0x108)
78 #define MAILBOX_IRQENABLE_CLR(IDX) (InterruptHost_mailboxBaseAddr[ \
79 MBX_BASEADDR_IDX(IDX)] + (0x10 * \
80 MBX_USER_IDX(IDX)) + 0x10C)
81 #define MAILBOX_EOI_REG(IDX) (InterruptHost_mailboxBaseAddr[ \
82 MBX_BASEADDR_IDX(IDX)] + 0x140)
84 /*
85 *************************************************************************
86 * Module functions
87 *************************************************************************
88 */
90 /*
91 * ======== InterruptHost_intEnable ========
92 * Enable remote processor interrupt
93 */
94 Void InterruptHost_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
95 {
96 UInt16 index;
97 UInt subMbxIdx;
99 index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
101 /* If the remote processor communicates via mailboxes, we should enable
102 * the Mailbox IRQ instead of enabling the Hwi because multiple mailboxes
103 * share the same Hwi
104 */
105 subMbxIdx = SUBMBX_IDX(index);
106 REG32(MAILBOX_IRQENABLE_SET(index)) = MAILBOX_REG_VAL(subMbxIdx);
107 }
109 /*
110 * ======== InterruptHost_intDisable ========
111 * Disables remote processor interrupt
112 */
113 Void InterruptHost_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
114 {
115 UInt16 index;
116 UInt subMbxIdx;
118 index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
120 /* If the remote processor communicates via mailboxes, we should disable
121 * the Mailbox IRQ instead of disabling the Hwi because multiple mailboxes
122 * share the same Hwi
123 */
124 subMbxIdx = SUBMBX_IDX(index);
125 REG32(MAILBOX_IRQENABLE_CLR(index)) = MAILBOX_REG_VAL(subMbxIdx);
126 }
128 /*
129 * ======== InterruptHost_intRegister ========
130 */
131 Void InterruptHost_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
132 Fxn func, UArg arg)
133 {
134 UInt key;
135 Int index;
136 InterruptHost_FxnTable *table;
138 Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
139 ti_sdo_ipc_Ipc_A_internal);
141 /* Assert that our MultiProc id is set correctly */
142 Assert_isTrue((InterruptHost_hostProcId == MultiProc_self()),
143 ti_sdo_ipc_Ipc_A_internal);
145 /* index is the virtual id (invariant) */
146 index = PROCID(remoteProcId);
148 intInfo->localIntId = NotifySetup_interruptTable(index);
150 /* Disable global interrupts */
151 key = Hwi_disable();
153 /* store callback function by virtual id */
154 table = &(InterruptHost_module->fxnTable[index]);
155 table->func = func;
156 table->arg = arg;
158 InterruptHost_intClear(remoteProcId, intInfo);
160 /* plug the cpu interrupt with notify setup dispatch isr */
161 NotifySetup_plugHwi(remoteProcId, intInfo->localIntId,
162 InterruptHost_intShmStub);
164 InterruptHost_intEnable(remoteProcId, intInfo);
166 /* Restore global interrupts */
167 Hwi_restore(key);
168 }
170 /*
171 * ======== InterruptHost_intUnregister ========
172 */
173 Void InterruptHost_intUnregister(UInt16 remoteProcId,
174 IInterrupt_IntInfo *intInfo)
175 {
176 Int index;
177 InterruptHost_FxnTable *table;
179 /* Disable the mailbox interrupt source */
180 InterruptHost_intDisable(remoteProcId, intInfo);
182 NotifySetup_unplugHwi(remoteProcId, intInfo->localIntId);
184 /* index is the virtual id (invariant) */
185 index = PROCID(remoteProcId);
187 /* Clear the FxnTable entry for the remote processor */
188 table = &(InterruptHost_module->fxnTable[index]);
189 table->func = NULL;
190 table->arg = 0;
191 }
193 /*
194 * ======== InterruptHost_intSend ========
195 * Send interrupt to the remote processor
196 */
197 Void InterruptHost_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
198 UArg arg)
199 {
200 UInt key;
201 UInt16 index;
203 index = MBX_TABLE_IDX(MultiProc_self(), remoteProcId);
204 key = Hwi_disable();
205 if (REG32(MAILBOX_STATUS(index)) == 0) {
206 REG32(MAILBOX_MESSAGE(index)) = arg;
207 }
208 Hwi_restore(key);
209 }
211 /*
212 * ======== InterruptHost_intPost ========
213 * Simulate an interrupt from a remote processor
214 */
215 Void InterruptHost_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
216 UArg arg)
217 {
218 UInt key;
219 UInt16 index;
221 index = MBX_TABLE_IDX(srcProcId, MultiProc_self());
222 key = Hwi_disable();
223 if (REG32(MAILBOX_STATUS(index)) == 0) {
224 REG32(MAILBOX_MESSAGE(index)) = arg;
225 }
226 Hwi_restore(key);
227 }
229 /*
230 * ======== InterruptHost_intClear ========
231 * Clear interrupt
232 */
233 UInt InterruptHost_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
234 {
235 UInt arg;
236 UInt16 index;
238 index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
239 arg = REG32(MAILBOX_MESSAGE(index));
240 REG32(MAILBOX_IRQSTATUS_CLR(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index));
242 return (arg);
243 }
245 /*
246 *************************************************************************
247 * Internals functions
248 *************************************************************************
249 */
251 /*
252 * ======== InterruptHost_intShmMbxStub ========
253 */
254 Void InterruptHost_intShmStub(UInt16 idx)
255 {
256 UInt16 srcVirtId;
257 InterruptHost_FxnTable *table;
259 srcVirtId = idx / InterruptHost_NUM_CORES;
260 table = &(InterruptHost_module->fxnTable[srcVirtId]);
261 (table->func)(table->arg);
262 }