/*! * ======== InterruptBenelli_intShmMbxStub ======== */ Void InterruptBenelli_intShmMbxStub(UArg arg) { UInt16 index; UInt16 selfIdx; UInt16 loopIdx; InterruptBenelli_FxnTable *table; selfIdx = MultiProc_self(); for (loopIdx = 0; loopIdx < MultiProc_getNumProcsInCluster(); loopIdx++) { if (loopIdx == selfIdx) { continue; } index = MBX_TABLE_IDX(loopIdx, selfIdx); if (((REG32(MAILBOX_STATUS(index)) != 0) && (REG32(MAILBOX_IRQENABLE_SET(index)) & MAILBOX_REG_VAL(SUBMBX_IDX(index))))) { table = &(InterruptBenelli_module->fxnTable[PROCID(loopIdx)]); (table->func)(table->arg); } } }
/*! * ======== InterruptDsp_intShmStub ======== */ Void InterruptDsp_intShmStub(UArg arg) { UInt16 index; UInt16 selfIdx; UInt16 loopIdx; InterruptDsp_FxnTable *table; selfIdx = MultiProc_self(); /* * Loop through each Sub-mailbox to determine which one generated * interrupt. */ for (loopIdx = 0; loopIdx < MultiProc_getNumProcsInCluster(); loopIdx++) { if (loopIdx == selfIdx) { continue; } index = MBX_TABLE_IDX(loopIdx, selfIdx); if ((REG32(MAILBOX_STATUS(index)) != 0) && (REG32(MAILBOX_IRQENABLE_SET_DSP(index)) & MAILBOX_REG_VAL(SUBMBX_IDX(index)))) { table = &(InterruptDsp_module->fxnTable[PROCID(loopIdx)]); (table->func)(table->arg); } } }
/*! * ======== InterruptBenelli_intUnregister ======== */ Void InterruptBenelli_intUnregister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo) { UInt mbxIdx; Int index; InterruptBenelli_FxnTable *table; Hwi_Handle hwiHandle; mbxIdx = MBX_BASEADDR_IDX(MBX_TABLE_IDX(remoteProcId, MultiProc_self())); index = PROCID(remoteProcId); /* Disable the mailbox interrupt source */ InterruptBenelli_intDisable(remoteProcId, intInfo); /* Disable the interrupt itself */ InterruptBenelli_module->numPlugged[mbxIdx]--; if (InterruptBenelli_module->numPlugged[mbxIdx] == 0) { hwiHandle = Hwi_getHandle(intInfo->localIntId); Hwi_delete(&hwiHandle); } /* Clear the FxnTable entry for the remote processor */ table = &(InterruptBenelli_module->fxnTable[index]); table->func = NULL; table->arg = 0; }
/*! * ======== InterruptDsp_intSend ======== * Send interrupt to the remote processor */ Void InterruptDsp_intSend(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo, UArg arg) { UInt key; UInt16 index; index = MBX_TABLE_IDX(MultiProc_self(), remoteProcId); /* * Before writing to a mailbox, check whehter it already contains a message * If so, then don't write to the mailbox since we want one and only one * message per interrupt. Disable interrupts between reading * the MSGSTATUS_X register and writing to the mailbox to protect from * another thread doing an intSend at the same time * * Note regarding possible race condition between local 'intSend' and * remote 'intClear': * It is possible that we we read the MAILBOX_MSGSTATUS_X register during * the remote side's intClear. Therefore, we might choose _not_ to send * write to the mailbox even though the mailbox is about to be cleared a * few cycles later. In this case, the interrupt will be lost. * This is OK, however. intClear should always be called by the Notify * driver _before_ shared memory is read, so the event will be picked up * anyway by the previous interrupt that caused intClear to be called. */ key = Hwi_disable(); if (REG32(MAILBOX_STATUS(index)) == 0) { REG32(MAILBOX_MESSAGE(index)) = arg; } Hwi_restore(key); }
/*! * ======== InterruptArp32_intEnable ======== * Enable remote processor interrupt */ Void InterruptArp32_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo) { UInt16 index; index = MBX_TABLE_IDX(remoteProcId, MultiProc_self()); REG32(MAILBOX_IRQENABLE_SET(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index)); }
/*! * ======== InterruptBenelli_intClear ======== * Clear interrupt */ UInt InterruptBenelli_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo) { UInt arg; UInt16 index; index = MBX_TABLE_IDX(remoteProcId, MultiProc_self()); arg = REG32(MAILBOX_MESSAGE(index)); REG32(MAILBOX_IRQSTATUS_CLR(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index)); return (arg); }
/*! * ======== InterruptDsp_intDisable ======== * Disables remote processor interrupt */ Void InterruptDsp_intDisable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo) { UInt16 index; Assert_isTrue(((remoteProcId < MultiProc_getNumProcsInCluster()) && (remoteProcId != MultiProc_self())), ti_sdo_ipc_Ipc_A_internal); index = MBX_TABLE_IDX(remoteProcId, MultiProc_self()); REG32(MAILBOX_IRQENABLE_CLR_DSP(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index)); }
/*! * ======== InterruptBenelli_intEnable ======== * Enable remote processor interrupt */ Void InterruptBenelli_intEnable(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo) { UInt16 index; index = MBX_TABLE_IDX(remoteProcId, MultiProc_self()); /* * If the remote processor communicates via mailboxes, we should enable * the Mailbox IRQ instead of enabling the Hwi because multiple mailboxes * share the same Hwi */ REG32(MAILBOX_IRQENABLE_SET(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index)); }
/*! * ======== InterruptBenelli_intRegister ======== */ Void InterruptBenelli_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo, Fxn func, UArg arg) { Hwi_Params hwiAttrs; UInt key; UInt mbxIdx; Int index; InterruptBenelli_FxnTable *table; Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors, ti_sdo_ipc_Ipc_A_internal); /* Assert that our MultiProc id is set correctly */ Assert_isTrue((InterruptBenelli_benelliProcId == MultiProc_self()), ti_sdo_ipc_Ipc_A_internal); mbxIdx = MBX_BASEADDR_IDX(MBX_TABLE_IDX(remoteProcId, MultiProc_self())); index = PROCID(remoteProcId); intInfo->localIntId = InterruptBenelli_benelliInterruptTable[index]; /* Disable global interrupts */ key = Hwi_disable(); table = &(InterruptBenelli_module->fxnTable[index]); table->func = func; table->arg = arg; InterruptBenelli_intClear(remoteProcId, intInfo); Hwi_Params_init(&hwiAttrs); hwiAttrs.maskSetting = Hwi_MaskingOption_LOWER; /* Make sure the interrupt only gets plugged once */ InterruptBenelli_module->numPlugged[mbxIdx]++; if (InterruptBenelli_module->numPlugged[mbxIdx] == 1) { Hwi_create(intInfo->localIntId, (Hwi_FuncPtr)InterruptBenelli_intShmMbxStub, &hwiAttrs, NULL); /* Interrupt_intEnable won't enable the Hwi */ Hwi_enableInterrupt(intInfo->localIntId); } InterruptBenelli_intEnable(remoteProcId, intInfo); /* Restore global interrupts */ Hwi_restore(key); }
/*! * ======== InterruptBenelli_intPost ======== * Simulate an interrupt from a remote processor */ Void InterruptBenelli_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo, UArg arg) { UInt key; UInt16 index; index = MBX_TABLE_IDX(srcProcId, MultiProc_self()); key = Hwi_disable(); if (REG32(MAILBOX_STATUS(index)) == 0) { REG32(MAILBOX_MESSAGE(index)) = arg; } Hwi_restore(key); }
/*! * ======== InterruptDsp_intClear ======== * Clear interrupt */ UInt InterruptDsp_intClear(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo) { UInt arg; UInt16 index; index = MBX_TABLE_IDX(remoteProcId, MultiProc_self()); arg = REG32(MAILBOX_MESSAGE(index)); REG32(MAILBOX_IRQSTATUS_CLR_DSP(index)) = MAILBOX_REG_VAL(SUBMBX_IDX(index)); /* Write to EOI (End Of Interrupt) register */ REG32(MAILBOX_EOI_REG(index)) = 0x1; return (arg); }
/*! * ======== InterruptArp32_intPost ======== * Simulate an interrupt from a remote processor */ Void InterruptArp32_intPost(UInt16 srcProcId, IInterrupt_IntInfo *intInfo, UArg arg) { UInt key; UInt16 index; index = MBX_TABLE_IDX(srcProcId, MultiProc_self()); /* disable interrupts */ key = Hwi_disable(); if (REG32(MAILBOX_STATUS(index)) == 0) { /* write the mailbox message to arp32 */ REG32(MAILBOX_MESSAGE(index)) = arg; } /* restore interrupts */ Hwi_restore(key); }