7a6ffb504b5bb466d8ef7925ee992e4e344cc39b
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / am65xx / InterruptR5f.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  */
32 /*
33  *  ======== InterruptR5f.c ========
34  *  AM65XX R5F based interupt manager
35  */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
40 #include <ti/sysbios/BIOS.h>
41 #include <ti/sysbios/family/arm/v7r/keystone3/Core.h>
42 #include <ti/sysbios/family/arm/v7r/keystone3/Hwi.h>
44 #include <ti/sdo/ipc/family/am65xx/NotifySetup.h>
46 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
47 #include <ti/sdo/utils/_MultiProc.h>
49 #include "package/internal/InterruptR5f.xdc.h"
51 /* Register access method. */
52 #define REG16(A)   (*(volatile UInt16 *) (A))
53 #define REG32(A)   (*(volatile UInt32 *) (A))
55 #define PROCID(IDX)               (InterruptR5f_procIdTable[(IDX)])
56 #define MBX_TABLE_IDX(SRC, DST)   ((PROCID(SRC) * InterruptR5f_NUM_CORES) + \
57                                     PROCID(DST))
58 #define SUBMBX_IDX(IDX)           (InterruptR5f_mailboxTable[(IDX)] & 0xFF)
59 #define MBX_USER_IDX(IDX)         ((InterruptR5f_mailboxTable[(IDX)] >> 8) \
60                                     & 0xFF)
61 #define MBX_BASEADDR_IDX(IDX)    ((InterruptR5f_mailboxTable[(IDX)] >> 16) \
62                                     & 0xFFFF)
64 #define MAILBOX_REG_VAL(M)        (0x1 << (2 * M))
66 #define MAILBOX_MESSAGE(IDX)      (InterruptR5f_mailboxBaseAddr[  \
67                                     MBX_BASEADDR_IDX(IDX)] + 0x40 +   \
68                                     (0x4 * SUBMBX_IDX(IDX)))
69 #define MAILBOX_STATUS(IDX)       (InterruptR5f_mailboxBaseAddr[  \
70                                     MBX_BASEADDR_IDX(IDX)] + 0xC0 +   \
71                                     (0x4 * SUBMBX_IDX(IDX)))
73 #define MAILBOX_IRQSTATUS_CLR(IDX)   (InterruptR5f_mailboxBaseAddr[  \
74                                         MBX_BASEADDR_IDX(IDX)] + (0x10 * \
75                                         MBX_USER_IDX(IDX)) + 0x104)
76 #define MAILBOX_IRQENABLE_SET(IDX)   (InterruptR5f_mailboxBaseAddr[  \
77                                         MBX_BASEADDR_IDX(IDX)] + (0x10 * \
78                                         MBX_USER_IDX(IDX)) + 0x108)
79 #define MAILBOX_IRQENABLE_CLR(IDX)   (InterruptR5f_mailboxBaseAddr[  \
80                                         MBX_BASEADDR_IDX(IDX)] + (0x10 * \
81                                         MBX_USER_IDX(IDX)) + 0x10C)
82 #define MAILBOX_EOI_REG(IDX)         (InterruptR5f_mailboxBaseAddr[  \
83                                         MBX_BASEADDR_IDX(IDX)] + 0x140)
85 #define WUGENIPU        19
87 /*
88  *************************************************************************
89  *                      Module functions
90  *************************************************************************
91  */
93 /*
94  *  ======== InterruptR5f_intEnable ========
95  *  Enable remote processor interrupt
96  */
97 Void InterruptR5f_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
98 {
99     UInt16 index;
100     Bool useMailbox = TRUE;
101     UInt subMbxIdx;
103     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
105     if ((remoteProcId == InterruptR5f_r5f_0ProcId) ||
106             (remoteProcId == InterruptR5f_r5f_1ProcId)) {
107             Hwi_enableInterrupt(WUGENIPU);
108             useMailbox = FALSE;
109     }
111     /*  If the remote processor communicates via mailboxes, we should enable
112      *  the Mailbox IRQ instead of enabling the Hwi because multiple mailboxes
113      *  share the same Hwi
114      */
115     if (useMailbox) {
116         subMbxIdx = SUBMBX_IDX(index);
117         REG32(MAILBOX_IRQENABLE_SET(index)) = MAILBOX_REG_VAL(subMbxIdx);
118     }
121 /*
122  *  ======== InterruptR5f_intDisable ========
123  *  Disables remote processor interrupt
124  */
125 Void InterruptR5f_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
127     UInt16 index;
128     Bool useMailbox = TRUE;
129     UInt subMbxIdx;
131     if ((remoteProcId == InterruptR5f_r5f_0ProcId) ||
132             (remoteProcId == InterruptR5f_r5f_1ProcId)) {
133             Hwi_disableInterrupt(WUGENIPU);
134             useMailbox = FALSE;
135     }
137     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
139     /*  If the remote processor communicates via mailboxes, we should disable
140      *  the Mailbox IRQ instead of disabling the Hwi because multiple mailboxes
141      *  share the same Hwi
142      */
143     if (useMailbox) {
144         subMbxIdx = SUBMBX_IDX(index);
145         REG32(MAILBOX_IRQENABLE_CLR(index)) = MAILBOX_REG_VAL(subMbxIdx);
146     }
149 /*
150  *  ======== InterruptR5f_intRegister ========
151  */
152 Void InterruptR5f_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
153         Fxn func, UArg arg)
155     Hwi_Params  hwiAttrs;
156     UInt        key;
157     Int         index;
158     InterruptR5f_FxnTable *table;
160     Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
161             ti_sdo_utils_MultiProc_A_invalidMultiProcId);
163     /* index is the virtual id (invariant) */
164     index = PROCID(remoteProcId);
166     intInfo->localIntId = NotifySetup_interruptTable(index);
168     /* Disable global interrupts */
169     key = Hwi_disable();
171     /* store callback function by virtual id */
172     table = &(InterruptR5f_module->fxnTable[index]);
173     table->func = func;
174     table->arg  = arg;
176     InterruptR5f_intClear(remoteProcId, intInfo);
178     Hwi_Params_init(&hwiAttrs);
179     hwiAttrs.maskSetting = Hwi_MaskingOption_LOWER;
181     /* plug the cpu interrupt with notify setup dispatch isr */
182     NotifySetup_plugHwi(remoteProcId, intInfo->localIntId,
183         InterruptR5f_intShmMbxStub);
185     InterruptR5f_intEnable(remoteProcId, intInfo);
187     /* Restore global interrupts */
188     Hwi_restore(key);
191 /*
192  *  ======== InterruptR5f_intUnregister ========
193  */
194 Void InterruptR5f_intUnregister(UInt16 remoteProcId,
195         IInterrupt_IntInfo *intInfo)
197     Int index;
198     Hwi_Handle hwiHandle;
199     InterruptR5f_FxnTable *table;
201     /* Disable the mailbox interrupt source */
202     InterruptR5f_intDisable(remoteProcId, intInfo);
204     if ((remoteProcId == InterruptR5f_r5f_0ProcId) ||
205         (remoteProcId == InterruptR5f_r5f_1ProcId)) {
206         hwiHandle = Hwi_getHandle(WUGENIPU);
207         Hwi_delete(&hwiHandle);
208     }
209     else {
210         NotifySetup_unplugHwi(remoteProcId, intInfo->localIntId);
211     }
213     /* index is the virtual id (invariant) */
214     index = PROCID(remoteProcId);
216     /* Clear the FxnTable entry for the remote processor */
217     table = &(InterruptR5f_module->fxnTable[index]);
218     table->func = NULL;
219     table->arg  = 0;
223 /*
224  *  ======== InterruptR5f_intSend ========
225  *  Send interrupt to the remote processor
226  */
227 Void InterruptR5f_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
228         UArg arg)
230     UInt key;
231     UInt16 index;
233     index = MBX_TABLE_IDX(MultiProc_self(), remoteProcId);
234     key = Hwi_disable();
235     while (REG32(MAILBOX_STATUS(index)) != 0) {
236         Hwi_restore(key);
237         key = Hwi_disable();
238     }
239     REG32(MAILBOX_MESSAGE(index)) = arg;
240     Hwi_restore(key);
245 /*
246  *  ======== InterruptR5f_intPost ========
247  *  Simulate an interrupt from a remote processor
248  */
249 Void InterruptR5f_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
250                              UArg arg)
252     UInt key;
253     UInt16 index;
255     index = MBX_TABLE_IDX(srcProcId, MultiProc_self());
256     key = Hwi_disable();
257     if (REG32(MAILBOX_STATUS(index)) == 0) {
258         REG32(MAILBOX_MESSAGE(index)) = arg;
259     }
260     Hwi_restore(key);
264 /*
265  *  ======== InterruptR5f_intClear ========
266  *  Clear interrupt
267  */
268 UInt InterruptR5f_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
270     UInt arg;
271     UInt16 index;
273     index = MBX_TABLE_IDX(remoteProcId, MultiProc_self());
274     arg = REG32(MAILBOX_MESSAGE(index));
275     REG32(MAILBOX_IRQSTATUS_CLR(index)) =
276         MAILBOX_REG_VAL(SUBMBX_IDX(index));
278     return (arg);
281 /*
282  *************************************************************************
283  *                      Internals functions
284  *************************************************************************
285  */
287 /*
288  *  ======== InterruptR5f_intShmMbxStub ========
289  */
290 Void InterruptR5f_intShmMbxStub(UInt16 idx)
292     UInt16 srcVirtId;
293     InterruptR5f_FxnTable *table;
295     srcVirtId = idx / InterruptR5f_NUM_CORES;
296     table = &(InterruptR5f_module->fxnTable[srcVirtId]);
297     (table->func)(table->arg);