]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/am65xx/InterruptHost.c
8c75141fcc1f08cdb9f1b7a7c702117abeb6713f
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / am65xx / InterruptHost.c
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);
109 /*
110  *  ======== InterruptHost_intDisable ========
111  *  Disables remote processor interrupt
112  */
113 Void InterruptHost_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
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);
128 /*
129  *  ======== InterruptHost_intRegister ========
130  */
131 Void InterruptHost_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
132         Fxn func, UArg arg)
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);
170 /*
171  *  ======== InterruptHost_intUnregister ========
172  */
173 Void InterruptHost_intUnregister(UInt16 remoteProcId,
174         IInterrupt_IntInfo *intInfo)
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;
193 /*
194  *  ======== InterruptHost_intSend ========
195  *  Send interrupt to the remote processor
196  */
197 Void InterruptHost_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
198         UArg arg)
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);
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)
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);
229 /*
230  *  ======== InterruptHost_intClear ========
231  *  Clear interrupt
232  */
233 UInt InterruptHost_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
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);
245 /*
246  *************************************************************************
247  *                      Internals functions
248  *************************************************************************
249  */
251 /*
252  *  ======== InterruptHost_intShmMbxStub ========
253  */
254 Void InterruptHost_intShmStub(UInt16 idx)
256     UInt16 srcVirtId;
257     InterruptHost_FxnTable *table;
259     srcVirtId = idx / InterruptHost_NUM_CORES;
260     table = &(InterruptHost_module->fxnTable[srcVirtId]);
261     (table->func)(table->arg);