]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/family/c647x/Interrupt.c
Added linux-side executable, libraries and object files to the .gitignore list
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / c647x / Interrupt.c
1 /*
2  * Copyright (c) 2012-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  *  C647x based interrupt manager.
35  */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Startup.h>
41 #include <ti/sysbios/family/c64p/Hwi.h>
43 #include <ti/sdo/ipc/_Ipc.h>
44 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
45 #include <ti/sdo/utils/_MultiProc.h>
46 #include <ti/sdo/ipc/_SharedRegion.h>
48 #include <ti/sdo/ipc/family/c647x/MultiProcSetup.h>
50 #include "package/internal/Interrupt.xdc.h"
53 /*
54  *************************************************************************
55  *                      Module functions
56  *************************************************************************
57  */
59 /*
60  *  ======== Interrupt_Module_startup ========
61  */
62 Int Interrupt_Module_startup(Int phase)
63 {
64     volatile UInt32 *kick0 = (volatile UInt32 *)Interrupt_KICK0;
65     volatile UInt32 *kick1 = (volatile UInt32 *)Interrupt_KICK1;
66     SharedRegion_Entry entry;
67     UInt16 procId = MultiProc_self();
69     /*
70      *  Wait for Startup to be done (if MultiProc id not yet set) because a
71      *  user fxn should set it
72      */
73     if (!Startup_Module_startupDone() && procId == MultiProc_INVALIDID) {
74         return (Startup_NOTDONE);
75     }
77     if (!Interrupt_enableKick) {
78         /* Do not unlock the kick registers */
79         return (Startup_DONE);
80     }
82     SharedRegion_getEntry(0, &entry);
84     /*
85      * Only write to the KICK registers if:
86      * - This core is the SR0 owner
87      * - There is no SR0 and this core has procId '0'
88      */
89     if ((entry.isValid && procId == entry.ownerProcId) ||
90         (!entry.isValid && procId == 0)) {
91         if (Interrupt_KICK0 && Interrupt_KICK1){
92             /* unlock the KICK mechanism in the Bootcfg MMRs if defined */
93             kick0[0] = 0x83e70b13;      /* must be written with this value */
94             kick1[0] = 0x95a4f1e0;      /* must be written with this value */
95         }
96     }
98     return (Startup_DONE);
99 }
101 /*
102  *  ======== Interrupt_intEnable ========
103  *  Enable interrupt
104  */
105 Void Interrupt_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
107     Hwi_enableInterrupt(intInfo->intVectorId);
110 /*
111  *  ======== Interrupt_intDisable ========
112  *  Disables interrupts
113  */
114 Void Interrupt_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
116     Hwi_disableInterrupt(intInfo->intVectorId);
119 /*
120  *  ======== Interrupt_intRegister ========
121  *  Register ISR for remote processor interrupt
122  */
123 Void Interrupt_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
124                            Fxn func, UArg arg)
126     UInt key, i;
127     Hwi_Params hwiAttrs;
129     /* Disable global interrupts */
130     key = Hwi_disable();
132     /* setup the function table using the same Hwi int */
133     Interrupt_module->args[remoteProcId] = arg;
135     /* Make sure the interrupt only gets plugged once */
136     Interrupt_module->numPlugged++;
137     if (Interrupt_module->numPlugged == 1) {
138         Interrupt_module->func = func;
140         /* Clear any pending interrupt */
141         for (i = 0; i < ti_sdo_utils_MultiProc_numProcessors; i++) {
142             Interrupt_intClear(i, NULL);
143         }
145         /* Register interrupt to remote processor */
146         Hwi_Params_init(&hwiAttrs);
147         hwiAttrs.maskSetting = Hwi_MaskingOption_SELF;
148         hwiAttrs.arg         = arg;
149         hwiAttrs.eventId     = Interrupt_INTERDSPINT;
151         Hwi_create(intInfo->intVectorId,
152             (Hwi_FuncPtr)Interrupt_intShmStub, &hwiAttrs, NULL);
154         Hwi_enableInterrupt(intInfo->intVectorId);
155     }
157     /* Restore global interrupts */
158     Hwi_restore(key);
161 /*
162  *  ======== Interrupt_intUnregister ========
163  */
164 Void Interrupt_intUnregister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
166     Hwi_Handle hwiHandle;
168     Interrupt_module->numPlugged--;
169     if (Interrupt_module->numPlugged == 0) {
170         /* No need to disable interrupt: Hwi_delete takes care of this */
171         hwiHandle = Hwi_getHandle(intInfo->intVectorId);
172         Hwi_delete(&hwiHandle);
174         /* unset the function */
175         Interrupt_module->func = NULL;
176     }
178     /* Unset the function table */
179     Interrupt_module->args[remoteProcId] = 0;
182 /*
183  *  ======== Interrupt_intSend ========
184  *  Send interrupt to the remote processor
185  */
186 Void Interrupt_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
187                        UArg arg)
189     UInt32 val;
190     extern volatile cregister Uns DNUM;
191     volatile UInt32 *ipcgr = (volatile UInt32 *)Interrupt_IPCGR0;
193     /*
194      *  bit 0 is set to generate interrupt.
195      *  bits 4-7 is set to specify the interrupt generation source.
196      *  The convention is that bit 4 (SRCS0) is used for core 0,
197      *  bit 5 (SRCS1) for core 1, etc... .
198      */
199     val = (1 << (DNUM + Interrupt_SRCSx_SHIFT)) | 1;
201     ipcgr[MultiProcSetup_procMap[remoteProcId]] =  val;
204 /*
205  *  ======== Interrupt_intPost ========
206  *  Send interrupt to the remote processor
207  */
208 Void Interrupt_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
209                        UArg arg)
211     UInt32 val;
212     extern volatile cregister Uns DNUM;
213     volatile UInt32 *ipcgr = (volatile UInt32 *)Interrupt_IPCGR0;
215     /*
216      *  bit 0 is set to generate interrupt.
217      *  bits 4-7 is set to specify the interrupt generation source.
218      *  The convention is that bit 4 (SRCS0) is used for core 0,
219      *  bit 5 (SRCS1) for core 1, etc... .
220      */
221     val = (1 << (MultiProcSetup_procMap[srcProcId] + Interrupt_SRCSx_SHIFT)) | 1;
223     ipcgr[DNUM] =  val;
226 /*
227  *  ======== Interrupt_intClear ========
228  *  Acknowledge interrupt by clearing the corresponding source bit.
229  *  Does not clear the IFR bit by way of ICR write because that should
230  *  only be done during init time.
231  */
232 UInt Interrupt_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
234     extern volatile cregister Uns DNUM;
235     volatile UInt32 *ipcar = (volatile UInt32 *)Interrupt_IPCAR0;
237     ipcar[DNUM] =  (1 << (MultiProcSetup_procMap[remoteProcId] +
238             Interrupt_SRCSx_SHIFT));
240     return (0);
243 /*
244  *************************************************************************
245  *                      Internals functions
246  *************************************************************************
247  */
249 /*
250  *  ======== Interrupt_intShmStub ========
251  */
252 Void Interrupt_intShmStub(UArg arg)
254     Int i;
255     extern volatile cregister Uns DNUM;
256     volatile UInt32 *ipcar = (volatile UInt32 *)Interrupt_IPCAR0;
257     UInt32 ipcarVal = ipcar[DNUM];
259     for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++) {
260         if ((ipcarVal) & (1 << (MultiProcSetup_procMap[i +
261             MultiProc_getBaseIdOfCluster()]
262             + Interrupt_SRCSx_SHIFT))) {
263             Interrupt_module->func(Interrupt_module->args[i +
264                 MultiProc_getBaseIdOfCluster()]);
265         }
266     }