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 * ======== InterruptDucati.c ========
34 * Ducati/TI81xx 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/m3/Hwi.h>
42 #include <ti/sysbios/family/arm/ducati/Core.h>
43 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
44 #include <ti/sdo/ipc/_Ipc.h>
45 #include <ti/sdo/utils/_MultiProc.h>
47 #include "package/internal/InterruptDucati.xdc.h"
49 /* Register access method. */
50 #define REG16(A) (*(volatile UInt16 *) (A))
51 #define REG32(A) (*(volatile UInt32 *) (A))
53 /*
54 * Ducati control register that maintains inter-core interrupt bits.
55 *
56 * Using separate VIDEO and VPSS values to do 16-bit reads/writes
57 * because we do not want to overwrite the other cores value.
58 */
59 #define INTERRUPT_VIDEO (InterruptDucati_ducatiCtrlBaseAddr)
60 #define INTERRUPT_VPSS (InterruptDucati_ducatiCtrlBaseAddr + 2)
62 /* Assigned mailboxes */
63 #define DSP_TO_HOST 0
64 #define DSP_TO_VIDEO 1
65 #define DSP_TO_VPSS 2
66 #define HOST_TO_DSP 3
67 #define HOST_TO_VIDEO 4
68 #define HOST_TO_VPSS 5
69 #define VIDEO_TO_HOST 6
70 #define VIDEO_TO_DSP 7
71 #define VPSS_TO_HOST 8
72 #define VPSS_TO_DSP 9
74 #define MAILBOX_REG_VAL(M) (0x1 << (2 * M))
76 #define MAILBOX_MESSAGE(M) (InterruptDucati_mailboxBaseAddr + 0x040 + (0x4 * M))
77 #define MAILBOX_STATUS(M) (InterruptDucati_mailboxBaseAddr + 0x0C0 + (0x4 * M))
79 /* VIDEO registers */
80 #define MAILBOX_IRQSTATUS_CLR_VIDEO (InterruptDucati_mailboxBaseAddr + 0x124)
81 #define MAILBOX_IRQENABLE_SET_VIDEO (InterruptDucati_mailboxBaseAddr + 0x128)
82 #define MAILBOX_IRQENABLE_CLR_VIDEO (InterruptDucati_mailboxBaseAddr + 0x12C)
84 /* VPSS registers */
85 #define MAILBOX_IRQSTATUS_CLR_VPSS (InterruptDucati_mailboxBaseAddr + 0x134)
86 #define MAILBOX_IRQENABLE_SET_VPSS (InterruptDucati_mailboxBaseAddr + 0x138)
87 #define MAILBOX_IRQENABLE_CLR_VPSS (InterruptDucati_mailboxBaseAddr + 0x13C)
89 #define HOSTINT 77
90 #define M3VIDEOINT 53
91 #define M3DSSINT 54
92 #define DSPINT 56
93 #define M3INT 19
95 /*
96 *************************************************************************
97 * Module functions
98 *************************************************************************
99 */
101 /*!
102 * ======== InterruptDucati_intEnable ========
103 * Enable remote processor interrupt
104 */
105 Void InterruptDucati_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
106 {
107 /*
108 * If the remote processor communicates via mailboxes, we should enable
109 * the Mailbox IRQ instead of enabling the Hwi because multiple mailboxes
110 * share the same Hwi
111 */
112 if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
113 if (remoteProcId == InterruptDucati_hostProcId) {
114 REG32(MAILBOX_IRQENABLE_SET_VIDEO) = MAILBOX_REG_VAL(HOST_TO_VIDEO);
115 }
116 else if (remoteProcId == InterruptDucati_dspProcId) {
117 REG32(MAILBOX_IRQENABLE_SET_VIDEO) = MAILBOX_REG_VAL(DSP_TO_VIDEO);
118 }
119 else {
120 Hwi_enableInterrupt(M3INT);
121 }
122 }
123 else {
124 if (remoteProcId == InterruptDucati_hostProcId) {
125 REG32(MAILBOX_IRQENABLE_SET_VPSS) = MAILBOX_REG_VAL(HOST_TO_VPSS);
126 }
127 else if (remoteProcId == InterruptDucati_dspProcId) {
128 REG32(MAILBOX_IRQENABLE_SET_VPSS) = MAILBOX_REG_VAL(DSP_TO_VPSS);
129 }
130 else {
131 Hwi_enableInterrupt(M3INT);
132 }
133 }
134 }
136 /*!
137 * ======== InterruptDucati_intDisable ========
138 * Disables remote processor interrupt
139 */
140 Void InterruptDucati_intDisable(UInt16 remoteProcId,
141 IInterrupt_IntInfo *intInfo)
142 {
143 /*
144 * If the remote processor communicates via mailboxes, we should disable
145 * the Mailbox IRQ instead of disabling the Hwi because multiple mailboxes
146 * share the same Hwi
147 */
148 if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
149 if (remoteProcId == InterruptDucati_hostProcId) {
150 REG32(MAILBOX_IRQENABLE_CLR_VIDEO) = MAILBOX_REG_VAL(HOST_TO_VIDEO);
151 }
152 else if (remoteProcId == InterruptDucati_dspProcId) {
153 REG32(MAILBOX_IRQENABLE_CLR_VIDEO) = MAILBOX_REG_VAL(DSP_TO_VIDEO);
154 }
155 else {
156 Hwi_disableInterrupt(M3INT);
157 }
158 }
159 else {
160 if (remoteProcId == InterruptDucati_hostProcId) {
161 REG32(MAILBOX_IRQENABLE_CLR_VPSS) = MAILBOX_REG_VAL(HOST_TO_VPSS);
162 }
163 else if (remoteProcId == InterruptDucati_dspProcId) {
164 REG32(MAILBOX_IRQENABLE_CLR_VPSS) = MAILBOX_REG_VAL(DSP_TO_VPSS);
165 }
166 else {
167 Hwi_disableInterrupt(M3INT);
168 }
169 }
170 }
172 /*!
173 * ======== InterruptDucati_intRegister ========
174 */
175 Void InterruptDucati_intRegister(UInt16 remoteProcId,
176 IInterrupt_IntInfo *intInfo,
177 Fxn func, UArg arg)
178 {
179 Hwi_Params hwiAttrs;
180 UInt key;
181 Int index;
182 InterruptDucati_FxnTable *table;
184 Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors,
185 ti_sdo_ipc_Ipc_A_internal);
187 /* Assert that our MultiProc id is set correctly */
188 Assert_isTrue((InterruptDucati_videoProcId == MultiProc_self()) ||
189 (InterruptDucati_vpssProcId == MultiProc_self()),
190 ti_sdo_ipc_Ipc_A_internal);
192 /*
193 * VPSS-M3 & VIDEO-M3 each have a unique interrupt ID for receiving
194 * interrupts external to the Ducati subsystem. (M3DSSINT & M3VIDEOINT).
195 * However, they have a separate interrupt ID for receving interrupt from
196 * each other(M3INT).
197 *
198 * Store the interrupt id in the intInfo so it can be used during
199 * intUnregiseter.
200 */
201 if (remoteProcId == InterruptDucati_dspProcId) {
202 index = 0;
203 if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
204 intInfo->localIntId = M3VIDEOINT;
205 }
206 else {
207 intInfo->localIntId = M3DSSINT;
208 }
209 }
210 else if (remoteProcId == InterruptDucati_hostProcId) {
211 index = 1;
212 if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
213 intInfo->localIntId = M3VIDEOINT;
214 }
215 else {
216 intInfo->localIntId = M3DSSINT;
217 }
218 }
219 else {
220 /* Going to the other M3 */
221 index = 2;
222 intInfo->localIntId = M3INT;
223 }
225 /* Disable global interrupts */
226 key = Hwi_disable();
228 table = &(InterruptDucati_module->fxnTable[index]);
229 table->func = func;
230 table->arg = arg;
232 InterruptDucati_intClear(remoteProcId, intInfo);
234 Hwi_Params_init(&hwiAttrs);
235 hwiAttrs.maskSetting = Hwi_MaskingOption_LOWER;
237 /* Make sure the interrupt only gets plugged once */
238 if (remoteProcId == InterruptDucati_videoProcId ||
239 remoteProcId == InterruptDucati_vpssProcId) {
240 Hwi_create(intInfo->localIntId,
241 (Hwi_FuncPtr)InterruptDucati_intShmDucatiStub,
242 &hwiAttrs,
243 NULL);
244 }
245 else {
246 InterruptDucati_module->numPlugged++;
247 if (InterruptDucati_module->numPlugged == 1) {
248 Hwi_create(intInfo->localIntId,
249 (Hwi_FuncPtr)InterruptDucati_intShmMbxStub,
250 &hwiAttrs,
251 NULL);
253 /* Interrupt_intEnable won't enable the Hwi */
254 Hwi_enableInterrupt(intInfo->localIntId);
255 }
256 }
258 InterruptDucati_intEnable(remoteProcId, intInfo);
260 /* Restore global interrupts */
261 Hwi_restore(key);
262 }
264 /*!
265 * ======== InterruptDucati_intUnregister ========
266 */
267 Void InterruptDucati_intUnregister(UInt16 remoteProcId,
268 IInterrupt_IntInfo *intInfo)
269 {
270 Int index;
271 InterruptDucati_FxnTable *table;
272 Hwi_Handle hwiHandle;
274 if (remoteProcId == InterruptDucati_dspProcId) {
275 index = 0;
276 }
277 else if (remoteProcId == InterruptDucati_hostProcId) {
278 index = 1;
279 }
280 else {
281 /* Going to the other M3 */
282 index = 2;
283 }
285 /* Disable the mailbox interrupt source */
286 InterruptDucati_intDisable(remoteProcId, intInfo);
288 /* Disable the interrupt itself */
289 if (remoteProcId == InterruptDucati_videoProcId ||
290 remoteProcId == InterruptDucati_vpssProcId) {
291 hwiHandle = Hwi_getHandle(M3INT);
292 Hwi_delete(&hwiHandle);
293 }
294 else {
295 InterruptDucati_module->numPlugged--;
296 if (InterruptDucati_module->numPlugged == 0) {
297 hwiHandle = Hwi_getHandle(intInfo->localIntId);
298 Hwi_delete(&hwiHandle);
299 }
300 }
302 /* Clear the FxnTable entry for the remote processor */
303 table = &(InterruptDucati_module->fxnTable[index]);
304 table->func = NULL;
305 table->arg = 0;
306 }
309 /*!
310 * ======== InterruptDucati_intSend ========
311 * Send interrupt to the remote processor
312 */
313 Void InterruptDucati_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo,
314 UArg arg)
315 {
316 UInt key;
318 if (remoteProcId == InterruptDucati_videoProcId ||
319 remoteProcId == InterruptDucati_vpssProcId) {
320 if (!(BIOS_smpEnabled) && (Core_getId() == 1)) {
321 /* VPSS-M3 to VIDEO-M3 */
322 REG16(INTERRUPT_VIDEO) |= 0x1;
323 }
324 else {
325 /* VIDEO-M3 to VPSS-M3 */
326 REG16(INTERRUPT_VPSS) |= 0x1;
327 }
328 }
329 else if (remoteProcId == InterruptDucati_dspProcId) {
330 if (!(BIOS_smpEnabled) && (Core_getId() == 1)) {
331 /* VPSS-M3 to DSP */
332 key = Hwi_disable();
333 if (REG32(MAILBOX_STATUS(VPSS_TO_DSP)) == 0) {
334 REG32(MAILBOX_MESSAGE(VPSS_TO_DSP)) = arg;
335 }
336 Hwi_restore(key);
337 }
338 else {
339 /* VIDEO-M3 to DSP */
340 key = Hwi_disable();
341 if (REG32(MAILBOX_STATUS(VIDEO_TO_DSP)) == 0) {
342 REG32(MAILBOX_MESSAGE(VIDEO_TO_DSP)) = arg;
343 }
344 Hwi_restore(key);
345 }
346 }
347 else { /* HOSTINT */
348 if (!(BIOS_smpEnabled) && (Core_getId() == 1)) {
349 /* VPSS-M3 to HOST */
350 key = Hwi_disable();
351 if (REG32(MAILBOX_STATUS(VPSS_TO_HOST)) == 0) {
352 REG32(MAILBOX_MESSAGE(VPSS_TO_HOST)) = arg;
353 }
354 Hwi_restore(key);
355 }
356 else {
357 /* VIDEO-M3 to HOST */
358 key = Hwi_disable();
359 if (REG32(MAILBOX_STATUS(VIDEO_TO_HOST)) == 0) {
360 REG32(MAILBOX_MESSAGE(VIDEO_TO_HOST)) = arg;
361 }
362 Hwi_restore(key);
363 }
364 }
365 }
368 /*!
369 * ======== InterruptDucati_intPost ========
370 * Simulate an interrupt from a remote processor
371 */
372 Void InterruptDucati_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo,
373 UArg arg)
374 {
375 UInt key;
377 if (srcProcId == InterruptDucati_videoProcId ||
378 srcProcId == InterruptDucati_vpssProcId) {
379 if (!(BIOS_smpEnabled) && (Core_getId() == 1)) {
380 /* VIDEO-M3 to VPSS-M3 */
381 REG16(INTERRUPT_VPSS) |= 0x1;
382 }
383 else {
384 /* VPSS-M3 to VIDEO-M3 */
385 REG16(INTERRUPT_VIDEO) |= 0x1;
386 }
387 }
388 else if (srcProcId == InterruptDucati_dspProcId) {
389 if (!(BIOS_smpEnabled) && (Core_getId() == 1)) {
390 /* DSP to VPSS-M3 */
391 key = Hwi_disable();
392 if (REG32(MAILBOX_STATUS(DSP_TO_VPSS)) == 0) {
393 REG32(MAILBOX_MESSAGE(DSP_TO_VPSS)) = arg;
394 }
395 Hwi_restore(key);
396 }
397 else {
398 /* DSP to VIDEO-M3 */
399 key = Hwi_disable();
400 if (REG32(MAILBOX_STATUS(DSP_TO_VIDEO)) == 0) {
401 REG32(MAILBOX_MESSAGE(DSP_TO_VIDEO)) = arg;
402 }
403 Hwi_restore(key);
404 }
405 }
406 else { /* HOSTINT */
407 if (!(BIOS_smpEnabled) && (Core_getId() == 1)) {
408 /* HOST to VPSS-M3 */
409 key = Hwi_disable();
410 if (REG32(MAILBOX_STATUS(HOST_TO_VPSS)) == 0) {
411 REG32(MAILBOX_MESSAGE(HOST_TO_VPSS)) = arg;
412 }
413 Hwi_restore(key);
414 }
415 else {
416 /* HOST to VIDEO-M3 */
417 key = Hwi_disable();
418 if (REG32(MAILBOX_STATUS(HOST_TO_VIDEO)) == 0) {
419 REG32(MAILBOX_MESSAGE(HOST_TO_VIDEO)) = arg;
420 }
421 Hwi_restore(key);
422 }
423 }
424 }
427 /*!
428 * ======== InterruptDucati_intClear ========
429 * Clear interrupt
430 */
431 UInt InterruptDucati_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo)
432 {
433 UInt arg;
435 if (remoteProcId == InterruptDucati_videoProcId ||
436 remoteProcId == InterruptDucati_vpssProcId) {
437 arg = REG32(InterruptDucati_ducatiCtrlBaseAddr);
439 /* Look at BIOS's ducati Core id */
440 if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
441 if ((REG16(INTERRUPT_VIDEO) & 0x1) == 0x1) {
442 /* VPSS-M3 to VIDEO-M3 */
443 REG16(INTERRUPT_VIDEO) &= ~(0x1);
444 }
445 }
446 else {
447 if ((REG16(INTERRUPT_VPSS) & 0x1) == 0x1) {
448 /* VIDEO-M3 to VPSS-M3 */
449 REG16(INTERRUPT_VPSS) &= ~(0x1);
450 }
451 }
452 }
453 else if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
454 if (remoteProcId == InterruptDucati_hostProcId) {
455 /* HOST to VIDEO-M3 */
456 arg = REG32(MAILBOX_MESSAGE(HOST_TO_VIDEO));
457 REG32(MAILBOX_IRQSTATUS_CLR_VIDEO) = MAILBOX_REG_VAL(HOST_TO_VIDEO);
458 }
459 else {
460 /* DSP to VIDEO-M3 */
461 arg = REG32(MAILBOX_MESSAGE(DSP_TO_VIDEO));
462 REG32(MAILBOX_IRQSTATUS_CLR_VIDEO) = MAILBOX_REG_VAL(DSP_TO_VIDEO);
463 }
464 }
465 else { /* M3DSSINT */
466 if (remoteProcId == InterruptDucati_hostProcId) {
467 /* HOST to VPSS-M3 */
468 arg = REG32(MAILBOX_MESSAGE(HOST_TO_VPSS));
469 REG32(MAILBOX_IRQSTATUS_CLR_VPSS) = MAILBOX_REG_VAL(HOST_TO_VPSS);
470 }
471 else {
472 /* DSP to VPSS-M3 */
473 arg = REG32(MAILBOX_MESSAGE(DSP_TO_VPSS));
474 REG32(MAILBOX_IRQSTATUS_CLR_VPSS) = MAILBOX_REG_VAL(DSP_TO_VPSS);
475 }
476 }
478 return (arg);
479 }
481 /*
482 *************************************************************************
483 * Internals functions
484 *************************************************************************
485 */
487 /*!
488 * ======== InterruptDucati_intShmDucatiStub ========
489 */
490 Void InterruptDucati_intShmDucatiStub(UArg arg)
491 {
492 InterruptDucati_FxnTable *table;
494 table = &(InterruptDucati_module->fxnTable[2]);
495 (table->func)(table->arg);
496 }
498 /*!
499 * ======== InterruptDucati_intShmMbxStub ========
500 */
501 Void InterruptDucati_intShmMbxStub(UArg arg)
502 {
503 InterruptDucati_FxnTable *table;
505 if ((BIOS_smpEnabled) || (Core_getId() == 0)) {
506 if ((REG32(MAILBOX_IRQENABLE_SET_VIDEO) &
507 MAILBOX_REG_VAL(DSP_TO_VIDEO)) &&
508 REG32(MAILBOX_STATUS(DSP_TO_VIDEO)) != 0) { /* DSP to VIDEO-M3 */
509 table = &(InterruptDucati_module->fxnTable[0]);
510 (table->func)(table->arg);
511 }
512 if ((REG32(MAILBOX_IRQENABLE_SET_VIDEO) &
513 MAILBOX_REG_VAL(HOST_TO_VIDEO)) &&
514 REG32(MAILBOX_STATUS(HOST_TO_VIDEO)) != 0) { /* HOST to VIDEO-M3 */
515 table = &(InterruptDucati_module->fxnTable[1]);
516 (table->func)(table->arg);
517 }
518 }
519 else {
520 if ((REG32(MAILBOX_IRQENABLE_SET_VPSS) &
521 MAILBOX_REG_VAL(DSP_TO_VPSS)) &&
522 REG32(MAILBOX_STATUS(DSP_TO_VPSS)) != 0) { /* DSP to VPSS-M3 */
523 table = &(InterruptDucati_module->fxnTable[0]);
524 (table->func)(table->arg);
525 }
526 if ((REG32(MAILBOX_IRQENABLE_SET_VPSS) &
527 MAILBOX_REG_VAL(HOST_TO_VPSS)) &&
528 REG32(MAILBOX_STATUS(HOST_TO_VPSS)) != 0) { /* HOST to VPSS-M3 */
529 table = &(InterruptDucati_module->fxnTable[1]);
530 (table->func)(table->arg);
531 }
532 }
533 }