2f7710af638c7d005166f7f504a2398c346b9d4e
1 /*
2 * Copyright (c) 2012-2014 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 * ======== NotifySetup.c ========
35 */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Assert.h>
38 #include <xdc/runtime/Error.h>
39 #include <xdc/runtime/Startup.h>
41 #include <ti/sdo/ipc/_Notify.h>
42 #include <ti/sdo/ipc/Ipc.h>
43 #include <ti/sdo/ipc/family/vayu/NotifyDriverMbx.h>
44 #include <ti/sdo/ipc/notifyDrivers/NotifyDriverShm.h>
45 #include <ti/sdo/utils/_MultiProc.h>
47 #include <ti/sysbios/family/c64p/EventCombiner.h>
48 #include <ti/sysbios/family/c64p/Hwi.h>
49 #include <ti/sysbios/family/shared/vayu/IntXbar.h>
51 #include "package/internal/NotifySetup.xdc.h"
54 #define EVENT_GROUP_SIZE 32
56 /* register access methods */
57 #define REG16(A) (*(volatile UInt16 *)(A))
58 #define REG32(A) (*(volatile UInt32 *)(A))
60 /* ipc helper macros */
61 #define MAILBOX_REG_VAL(m) (0x1 << (2 * (m)))
63 #define VIRTID(procId) (NotifySetup_procIdTable[(procId)])
65 #define MBX_BASEADDR_IDX(idx) ((NotifySetup_mailboxTable[(idx)] >> 16) & 0xFFFF)
67 #define MBX_USER_IDX(idx) ((NotifySetup_mailboxTable[(idx)] >> 8) & 0xFF)
69 #define SUBMBX_IDX(idx) (NotifySetup_mailboxTable[(idx)] & 0xFF)
71 #define MAILBOX_ADDR(idx) \
72 (NotifySetup_mailboxBaseAddr[MBX_BASEADDR_IDX(idx)])
74 #define MAILBOX_STATUS(idx) \
75 (MAILBOX_ADDR((idx)) + 0xC0 + (0x4 * SUBMBX_IDX((idx))))
77 #define MAILBOX_IRQENABLE_SET(idx) \
78 (MAILBOX_ADDR((idx)) + 0x108 + (0x10 * MBX_USER_IDX((idx))))
80 #define MBOX_IRQ_ENABLE(idx) \
81 ((REG32(MAILBOX_IRQENABLE_SET((idx))) & \
82 MAILBOX_REG_VAL(SUBMBX_IDX((idx)))) != 0)
84 #define MBOX_MSG_COUNT(idx) (REG32(MAILBOX_STATUS((idx))))
87 /*
88 *************************************************************************
89 * Module functions
90 *************************************************************************
91 */
93 /*
94 * ======== NotifySetup_Module_startup ========
95 */
96 Int NotifySetup_Module_startup(Int phase)
97 {
98 #if defined(xdc_target__isa_66)
100 extern cregister volatile UInt DNUM;
102 if (IntXbar_Module_startupDone()) {
103 if (DNUM == 0) { /* DSP1 */
104 NotifySetup_module->interruptTable[6] = 57; // IPU1-0
105 NotifySetup_module->interruptTable[9] = 57; // IPU1-1
107 /* plug eve3 and eve4 mbxs only if eve3 and eve4 exists */
108 if ((MultiProc_getId("EVE3") != MultiProc_INVALIDID) ||
109 (MultiProc_getId("EVE4") != MultiProc_INVALIDID)) {
110 }
112 /* plug mbx7 only if DSP2 or IPU2 exists */
113 if ((MultiProc_getId("DSP2") != MultiProc_INVALIDID) ||
114 (MultiProc_getId("IPU2") != MultiProc_INVALIDID) ||
115 (MultiProc_getId("IPU2-0") != MultiProc_INVALIDID)) {
116 NotifySetup_module->interruptTable[7] = 60; // IPU2-0
117 }
119 /* plug mbx8 only if IPU2-1 exists */
120 if (MultiProc_getId("IPU2-1") != MultiProc_INVALIDID) {
121 NotifySetup_module->interruptTable[10] = 61; // IPU2-1
122 }
123 }
124 else if (DNUM == 1) { /* DSP2 */
125 NotifySetup_module->interruptTable[7] = 57; // IPU2-0
126 NotifySetup_module->interruptTable[10] = 57; // IPU2-1
128 /* plug eve3 and eve4 mbxs only if eve3 and eve4 exists */
129 if ((MultiProc_getId("EVE3") != MultiProc_INVALIDID) ||
130 (MultiProc_getId("EVE4") != MultiProc_INVALIDID)) {
131 }
133 /* plug mbx7 only if DSP1 or IPU1 exists */
134 if ((MultiProc_getId("DSP1") != MultiProc_INVALIDID) ||
135 (MultiProc_getId("IPU1") != MultiProc_INVALIDID) ||
136 (MultiProc_getId("IPU1-0") != MultiProc_INVALIDID)) {
137 NotifySetup_module->interruptTable[6] = 60; // IPU1-0
138 }
140 /* plug mbx8 only if IPU1-1 exists */
141 if (MultiProc_getId("IPU1-1") != MultiProc_INVALIDID) {
142 NotifySetup_module->interruptTable[9] = 61; // IPU1-1
143 }
144 }
145 return (Startup_DONE);
146 }
148 return (Startup_NOTDONE);
150 #elif defined(xdc_target__isa_arp32)
152 /* TODO */
153 return (Startup_DONE);
155 #elif defined(xdc_target__isa_v7M4)
157 /* TODO */
158 return (Startup_DONE);
160 #elif defined(xdc_target__isa_v7A15)
162 /* TODO */
163 return (Startup_DONE);
165 #else
166 #error Invalid target
167 #endif
168 }
170 /*!
171 * ======== NotifySetup_attach ========
172 * Create driver instance specified at config time.
173 *
174 * This functions is generated by the NotifySetup.xdt template.
175 */
177 /*!
178 * ======== NotifySetup_sharedMemReq ========
179 * Compute how much shared memory is required by the driver.
180 *
181 * This functions is generated by the NotifySetup.xdt template.
182 */
184 /*!
185 * ======== NotifySetup_numIntLines ========
186 * Return number of available interrupt lines to the current processor.
187 */
188 UInt16 NotifySetup_numIntLines(UInt16 remoteProcId)
189 {
190 return (1);
191 }
193 /*
194 * ======== NotifySetup_driverType ========
195 * Find driver type for given connection.
196 *
197 * Search the connection array for the given remote processor. If
198 * found, return the requested notify driver type.
199 */
200 NotifySetup_Driver NotifySetup_driverType(UInt16 remoteProcId)
201 {
202 Int i;
203 NotifySetup_Driver driver = NotifySetup_Driver_SHAREDMEMORY;
205 /* look for remote processor in connection array */
206 for (i = 0; i < NotifySetup_module->connAry.length; i++) {
207 if (remoteProcId == NotifySetup_module->connAry.elem[i].procId) {
208 driver = NotifySetup_module->connAry.elem[i].driver;
209 break;
210 }
211 }
213 return(driver);
214 }
216 /*
217 * ======== NotifySetup_plugHwi ========
218 */
219 Void NotifySetup_plugHwi(UInt16 remoteProcId, Int cpuIntrNum,
220 NotifySetup_DriverIsr isr)
221 {
222 UInt key;
223 Hwi_Params hwiParams;
224 UInt16 virtId;
225 Int eventId;
226 UInt combinedEventId;
228 /* disable global interrupts (TODO: should be a gated module) */
229 key = Hwi_disable();
231 /* map processor id to virtual id */
232 virtId = VIRTID(remoteProcId);
234 /* save driver isr in dispatch table */
235 NotifySetup_module->isrDispatchTable[virtId] = isr;
237 /* program the event dispatcher */
238 eventId = NotifySetup_module->interruptTable[virtId];
239 EventCombiner_dispatchPlug(eventId, NotifySetup_dispatchIsr, eventId, TRUE);
241 /* make sure the interrupt is plugged only once */
242 NotifySetup_module->numPlugged++;
244 if (NotifySetup_module->numPlugged == 1) {
245 combinedEventId = eventId / EVENT_GROUP_SIZE;
247 Hwi_Params_init(&hwiParams);
248 hwiParams.eventId = combinedEventId;
249 hwiParams.arg = combinedEventId;
250 hwiParams.enableInt = TRUE;
252 Hwi_create(cpuIntrNum,
253 &ti_sysbios_family_c64p_EventCombiner_dispatch,
254 &hwiParams, NULL);
256 Hwi_enableInterrupt(cpuIntrNum);
257 }
259 /* restore global interrupts */
260 Hwi_restore(key);
261 }
263 /*
264 * ======== NotifySetup_unplugHwi ========
265 */
266 Void NotifySetup_unplugHwi(UInt16 remoteProcId, Int cpuIntrNum)
267 {
268 UInt key;
269 Hwi_Handle hwi;
270 UInt16 virtId;
271 Int eventId;
273 /* disable global interrupts (TODO: should be a gated module) */
274 key = Hwi_disable();
276 /* unplug interrupt if last user */
277 NotifySetup_module->numPlugged--;
279 if (NotifySetup_module->numPlugged == 0) {
280 hwi= Hwi_getHandle(cpuIntrNum);
281 Hwi_delete(&hwi);
282 }
284 /* unprogram the event dispatcher */
285 virtId = VIRTID(remoteProcId);
286 eventId = NotifySetup_module->interruptTable[virtId];
287 EventCombiner_disableEvent(eventId);
289 /* restore global interrupts */
290 Hwi_restore(key);
291 }
293 /*
294 * ======== NotifySetup_Shm_attach ========
295 */
296 Int NotifySetup_Shm_attach(UInt16 remoteProcId, Ptr sharedAddr)
297 {
298 NotifyDriverShm_Params notifyShmParams;
299 NotifyDriverShm_Handle shmDrvHandle;
300 ti_sdo_ipc_Notify_Handle notifyHandle;
301 Int status = Notify_S_SUCCESS;
302 Error_Block eb;
304 Error_init(&eb);
306 NotifyDriverShm_Params_init(¬ifyShmParams);
307 notifyShmParams.sharedAddr = sharedAddr;
308 notifyShmParams.remoteProcId = remoteProcId;
310 /* Set the intVectorId if on the DSP */
311 if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
312 (MultiProc_self() == NotifySetup_dsp2ProcId)) {
313 notifyShmParams.intVectorId = NotifySetup_dspIntVectId;
314 }
316 /* Set the intVectorId if on the EVE */
317 if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
318 (MultiProc_self() == NotifySetup_eve2ProcId) ||
319 (MultiProc_self() == NotifySetup_eve3ProcId) ||
320 (MultiProc_self() == NotifySetup_eve4ProcId)) {
322 if (VIRTID(remoteProcId) < 4) {
323 notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC1;
324 }
325 else {
326 notifyShmParams.intVectorId = NotifySetup_eveIntVectId_INTC0;
327 }
328 }
330 /* create the notify driver instance */
331 shmDrvHandle = NotifyDriverShm_create(¬ifyShmParams, &eb);
333 if (shmDrvHandle == NULL) {
334 return (Notify_E_FAIL);
335 }
337 /* create the front-end notify instance */
338 notifyHandle = ti_sdo_ipc_Notify_create(
339 NotifyDriverShm_Handle_upCast(shmDrvHandle), remoteProcId, 0,
340 NULL, &eb);
342 if (notifyHandle == NULL) {
343 NotifyDriverShm_delete(&shmDrvHandle);
344 status = Notify_E_FAIL;
345 }
347 return (status);
348 }
350 /*!
351 * ======== NotifySetup_Shm_sharedMemReq ========
352 */
353 SizeT NotifySetup_Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
354 {
355 SizeT memReq;
356 NotifyDriverShm_Params notifyShmParams;
358 NotifyDriverShm_Params_init(¬ifyShmParams);
359 notifyShmParams.sharedAddr = sharedAddr;
361 memReq = NotifyDriverShm_sharedMemReq(¬ifyShmParams);
363 return (memReq);
364 }
366 /*
367 * ======== NotifySetup_Mbx_attach ========
368 */
369 Int NotifySetup_Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr)
370 {
371 Int status = Notify_S_SUCCESS;
372 NotifyDriverMbx_Params params;
373 NotifyDriverMbx_Handle driver;
374 ti_sdo_ipc_Notify_Handle notify;
375 Error_Block eb;
377 Error_init(&eb);
379 NotifyDriverMbx_Params_init(¶ms);
380 params.remoteProcId = remoteProcId;
382 /* set the intVectorId if on the DSP */
383 if ((MultiProc_self() == NotifySetup_dsp1ProcId) ||
384 (MultiProc_self() == NotifySetup_dsp2ProcId)) {
385 params.intVectorId = NotifySetup_dspIntVectId;
386 }
388 /* set the intVectorId if on the EVE */
389 if ((MultiProc_self() == NotifySetup_eve1ProcId) ||
390 (MultiProc_self() == NotifySetup_eve2ProcId) ||
391 (MultiProc_self() == NotifySetup_eve3ProcId) ||
392 (MultiProc_self() == NotifySetup_eve4ProcId)) {
394 if (VIRTID(remoteProcId) < 4) {
395 params.intVectorId = NotifySetup_eveIntVectId_INTC1;
396 }
397 else {
398 params.intVectorId = NotifySetup_eveIntVectId_INTC0;
399 }
400 }
402 /* create the notify driver instance */
403 driver = NotifyDriverMbx_create(¶ms, &eb);
405 if (driver == NULL) {
406 return(Notify_E_FAIL);
407 }
409 /* create the front-end notify instance */
410 notify = ti_sdo_ipc_Notify_create(NotifyDriverMbx_Handle_upCast(driver),
411 remoteProcId, 0, NULL, &eb);
413 if (notify == NULL) {
414 NotifyDriverMbx_delete(&driver);
415 status = Notify_E_FAIL;
416 }
418 return(status);
419 }
421 /*!
422 * ======== NotifySetup_Mbx_sharedMemReq ========
423 */
424 SizeT NotifySetup_Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr)
425 {
426 SizeT memReq = 0;
428 return (memReq);
429 }
431 /*
432 *************************************************************************
433 * Internal functions
434 *************************************************************************
435 */
437 /*
438 * ======== NotifySetup_dispatchIsr ========
439 * arg = eventId
440 */
441 Void NotifySetup_dispatchIsr(UArg arg)
442 {
443 Int numProcessed;
444 UInt16 idx;
445 UInt16 srcVirtId;
446 UInt16 dstVirtId = VIRTID(MultiProc_self());
447 NotifySetup_DriverIsr driver;
449 do {
450 numProcessed = 0;
452 for (srcVirtId = 0; srcVirtId < NotifySetup_NUM_CORES; srcVirtId++) {
454 /* should not receive interrupts from myself */
455 if (srcVirtId == dstVirtId) {
456 continue;
457 }
459 /* check if processor would raise the given hardware eventId */
460 if (arg == NotifySetup_module->interruptTable[srcVirtId]) {
462 /* compute table index for given source and destination */
463 idx = (srcVirtId * NotifySetup_NUM_CORES) + dstVirtId;
465 /* check if submailbox has a message and irq is enabled */
466 if ((MBOX_MSG_COUNT(idx) != 0) && MBOX_IRQ_ENABLE(idx)) {
468 /* invoke driver isr to deliver the event */
469 driver = NotifySetup_module->isrDispatchTable[srcVirtId];
470 (*driver)(idx);
472 /* event has been delivered */
473 numProcessed++;
474 }
475 }
476 }
477 } while (numProcessed != 0);
478 }