//------------------------------------------------------------------------------ // // Function: OEMInterruptEnable // // This function enables the IRQ given its corresponding SysIntr value. // Function returns true if SysIntr is valid, else false. // BOOL OEMInterruptEnable(DWORD sysIntr, LPVOID pvData, DWORD cbData) { BOOL rc = FALSE; const UINT32 *pIrqs; UINT32 count; UNREFERENCED_PARAMETER(pvData); UNREFERENCED_PARAMETER(cbData); OALMSG(OAL_INTR&&OAL_VERBOSE,(L"+OEMInterruptEnable(%d, 0x%x, %d)\r\n", sysIntr, pvData, cbData)); // SYSINTR_VMINI & SYSINTR_TIMING are special cases if (sysIntr == SYSINTR_VMINI || sysIntr == SYSINTR_TIMING) { rc = TRUE; goto cleanUp; } // Obtain the SYSINTR's underlying IRQ number if (!OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs)) { // Indicate invalid SysIntr OALMSG(OAL_ERROR, ( L"ERROR: OEMInterruptEnable: IRQs are undefined for SysIntr %d\r\n", sysIntr )); goto cleanUp; } // Enable the interrupt rc = OALIntrEnableIrqs(count, pIrqs); cleanUp: OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptEnable(rc = 1)\r\n")); return rc; }
//------------------------------------------------------------------------------ // // Function: OEMInterruptMask // // This function masks the IRQ given its corresponding SysIntr value. // // VOID OEMInterruptMask(DWORD SysIntr, BOOL mask) { OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OEMInterruptMask(%d, %d)\r\n", SysIntr, mask)); // Based on mask enable or disable if (mask) { OALIntrDisableIrqs(1, &g_oalSysIntr2Irq[SysIntr]); } else { OALIntrEnableIrqs(1, &g_oalSysIntr2Irq[SysIntr]); } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptMask\r\n")); }
//------------------------------------------------------------------------------ // // Function: OEMInterruptEnable // // This function enables the IRQ given its corresponding SysIntr value. // Function returns true if SysIntr is valid, else false. // BOOL OEMInterruptEnable(DWORD SysIntr, VOID* pData, DWORD dataSize) { BOOL rc = FALSE; OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OEMInterruptEnable(%d, 0x%x, %d)\r\n", SysIntr, pData, dataSize)); // SYSINTR_VMINI & SYSINTR_TIMING are special cases if ((SysIntr == SYSINTR_VMINI) || (SysIntr == SYSINTR_TIMING)) { rc = TRUE; goto cleanUp; } // Enable interrupts rc = OALIntrEnableIrqs(1, &g_oalSysIntr2Irq[SysIntr]); cleanUp: OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptEnable(rc = 1)\r\n")); return rc; }
//------------------------------------------------------------------------------ // // Function: BSPIntrInit // // This function is called from OALIntrInit to initialize secondary interrupt // controller. // BOOL BSPIntrInit() { UINT8 *pPIC1Edge, *pPIC2Edge; UINT32 irq; OALMSG(OAL_INTR&&OAL_FUNC, (L"+BSPIntrInit\r\n")); // Add static mapping for on chip devices... OALIntrStaticTranslate(SYSINTR_FIRMWARE + 0, IRQ_UART1); // UART1 // Add GPIO static mapping for RTC alarm OALIntrStaticTranslate(SYSINTR_RTC_ALARM, IRQ_GPIO); // And enable it (it will not occur until it is set in OEMSetAlarmTime) irq = IRQ_GPIO; OALIntrEnableIrqs(1, &irq); // Get and save uncached virtual addresses for VRC5477 and PIC1/PIC2 g_pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); g_pPIC1Regs = OALPAtoUA(BSP_REG_PA_M1535_PIC1); g_pPIC2Regs = OALPAtoUA(BSP_REG_PA_M1535_PIC2); // M1535+ INTR uses positive logic (active on high), set VRC5477 CLRPORT32(&g_pVRC5477Regs->INTPPES0, 1 << 4); // We have to enable PCI interrupts irq = IRQ_INTA; OALIntrEnableIrqs(1, &irq); irq = IRQ_INTB; OALIntrEnableIrqs(1, &irq); irq = IRQ_INTC; OALIntrEnableIrqs(1, &irq); irq = IRQ_INTD; OALIntrEnableIrqs(1, &irq); // PIC1/PIC2 edge registers are needed only for initialization pPIC1Edge = OALPAtoUA(BSP_REG_PA_M1535_EDGE1); pPIC2Edge = OALPAtoUA(BSP_REG_PA_M1535_EDGE2); // Initialize the 8259 PIC1 OUTREG8(&g_pPIC1Regs->ctrl, 0x11); // ICW1, cascade & ICW4 OUTREG8(&g_pPIC1Regs->mask, IRQ_PIC_0); // ICW2, vector to 32 OUTREG8(&g_pPIC1Regs->mask, 0x04); // ICW3, slave on IRQ 2 OUTREG8(&g_pPIC1Regs->mask, 0x01); // ICW4, normal EOI OUTREG8(&g_pPIC1Regs->ctrl, 0x0B); // OCW2, read IS register OUTREG8(&g_pPIC1Regs->mask, 0xFF); // OCW1, all disabled // Now initialize the 8259 PIC2 OUTREG8(&g_pPIC2Regs->ctrl, 0x11); // ICW1, cascade & ICW4 OUTREG8(&g_pPIC2Regs->mask, IRQ_PIC_8); // ICW2, vector to 40 OUTREG8(&g_pPIC2Regs->mask, 0x02); // ICW3, we are IRQ 2 OUTREG8(&g_pPIC2Regs->mask, 0x01); // ICW4, normal EOI OUTREG8(&g_pPIC2Regs->ctrl, 0x0B); // OCW2, read IS register OUTREG8(&g_pPIC2Regs->mask, 0xFF); // OCW1, all disabled // IRQ0-IRQ7 Edge sensitive(IRQ2 cannot be set to level sensitive) OUTREG8(pPIC1Edge, 0x00); // IRQ9&IRQ11 level (USB host, PCI INTC), other edge sensitive OUTREG8(pPIC2Edge, 0x0A); // Enable interrupt from PIC2 on PIC1 CLRREG8(&g_pPIC1Regs->mask, 1 << 2); // Set static interrupt mappings for legacy devices OALIntrStaticTranslate(SYSINTR_FIRMWARE + 8, IRQ_PIC_1); // keyboard OALIntrStaticTranslate(SYSINTR_FIRMWARE + 9, IRQ_PIC_12); // mouse // We are done OALMSG(OAL_INTR&&OAL_FUNC, (L"-BSPIntrInit(rc = 1)\r\n")); return TRUE; }
//------------------------------------------------------------------------------ // // Function: OEMPowerOff // // Called when the system is to transition to it's lowest power mode (off) // VOID OEMPowerOff( ) { DWORD i; UINT32 sysIntr; UINT intr[3]; BOOL bPowerOn; BOOL bPrevIntrState; UINT irq = 0; UINT32 mask = 0; // disable interrupts (note: this should not be needed) bPrevIntrState = INTERRUPTS_ENABLE(FALSE); // UNDONE: verify if this is still necessary // Disable hardware watchdog OALWatchdogEnable(FALSE); // Make sure that KITL is powered off bPowerOn = FALSE; KITLIoctl(IOCTL_KITL_POWER_CALL, &bPowerOn, sizeof(bPowerOn), NULL, 0, NULL); //Save Perf Timer OALContextSavePerfTimer(); // Disable GPTimer2 (used for high perf/monte carlo profiling) EnableDeviceClocks(BSPGetGPTPerfDevice(), FALSE); // Give chance to do board specific stuff BSPPowerOff(); //---------------------------------------------- // capture all enabled interrupts and disable interrupts intr[0] = INREG32(&g_pIntr->pICLRegs->INTC_MIR0); intr[1] = INREG32(&g_pIntr->pICLRegs->INTC_MIR1); intr[2] = INREG32(&g_pIntr->pICLRegs->INTC_MIR2); OUTREG32(&g_pIntr->pICLRegs->INTC_MIR_SET0, OMAP_MPUIC_MASKALL); OUTREG32(&g_pIntr->pICLRegs->INTC_MIR_SET1, OMAP_MPUIC_MASKALL); OUTREG32(&g_pIntr->pICLRegs->INTC_MIR_SET2, OMAP_MPUIC_MASKALL); //---------------------------------------------- // Context Save/Restore // Save state then mask all GPIO interrupts for (i=0; i<g_pIntr->nbGpioBank; i++) { INTR_GPIO_CTXT* pCurrGpioCtxt = &g_pIntr->pGpioCtxt[i]; // Save current state pCurrGpioCtxt->restoreCtxt.IRQENABLE1 = INREG32(&pCurrGpioCtxt->pRegs->IRQENABLE1); pCurrGpioCtxt->restoreCtxt.WAKEUPENABLE = INREG32(&pCurrGpioCtxt->pRegs->WAKEUPENABLE); // Disable all GPIO interrupts in the bank OUTREG32(&pCurrGpioCtxt->pRegs->IRQENABLE1, 0); OUTREG32(&pCurrGpioCtxt->pRegs->WAKEUPENABLE, 0); OALIntrEnableIrqs(1,&pCurrGpioCtxt->bank_irq); } //---------------------------------------------- // Clear all enabled IO PAD wakeups for GPIOs for (i = 0; i < g_pIntr->nbGpioBank; ++i) { INTR_GPIO_CTXT* pCurrGpioCtxt = &g_pIntr->pGpioCtxt[i]; irq = BSPGetGpioIrq(0) + (i * 32); mask = pCurrGpioCtxt->restoreCtxt.WAKEUPENABLE; while (mask != 0) { // If a GPIO was wakeup enabled, then clear the wakeup if (mask & 0x1) { OEMEnableIOPadWakeup((irq - BSPGetGpioIrq(0)), FALSE); } irq++; mask >>= 1; } } //---------------------------------------------- // Enable wake sources interrupts for (sysIntr = SYSINTR_DEVICES; sysIntr < SYSINTR_MAXIMUM; sysIntr++) { // Skip if sysIntr isn't allowed as wake source if (!OALPowerWakeSource(sysIntr)) continue; // Enable it as interrupt OEMInterruptEnable(sysIntr, NULL, 0); } // enter full retention PrcmSuspend(); //---------------------------------------------- // Find wakeup source for (sysIntr = SYSINTR_DEVICES; sysIntr < SYSINTR_MAXIMUM; sysIntr++) { // Skip if sysIntr isn't allowed as wake source if (!OALPowerWakeSource(sysIntr)) continue; // When this sysIntr is pending we find wake source if (OEMInterruptPending(sysIntr)) { g_oalWakeSource = sysIntr; break; } } //---------------------------------------------- // Context Save/Restore // Put GPIO interrupt state back to the way it was before suspend for (i=0; i<g_pIntr->nbGpioBank; i++) { INTR_GPIO_CTXT* pCurrGpioCtxt = &g_pIntr->pGpioCtxt[i]; // Write registers with the previously saved values OUTREG32(&pCurrGpioCtxt->pRegs->IRQENABLE1, pCurrGpioCtxt->restoreCtxt.IRQENABLE1); OUTREG32(&pCurrGpioCtxt->pRegs->WAKEUPENABLE, pCurrGpioCtxt->restoreCtxt.WAKEUPENABLE); } //------------------------------------------------------- // Enable all previously enabled IO PAD wakeups for GPIOs for (i = 0; i < g_pIntr->nbGpioBank; ++i) { INTR_GPIO_CTXT* pCurrGpioCtxt = &g_pIntr->pGpioCtxt[i]; irq = BSPGetGpioIrq(0) + (i * 32); mask = pCurrGpioCtxt->restoreCtxt.WAKEUPENABLE; while (mask != 0) { // If a GPIO was wakeup enabled, then clear the wakeup if (mask & 0x1) { OEMEnableIOPadWakeup((irq - BSPGetGpioIrq(0)), TRUE); } irq++; mask >>= 1; } } //---------------------------------------------- // Re-enable interrupts OUTREG32(&g_pIntr->pICLRegs->INTC_MIR_CLEAR0, ~intr[0]); OUTREG32(&g_pIntr->pICLRegs->INTC_MIR_CLEAR1, ~intr[1]); OUTREG32(&g_pIntr->pICLRegs->INTC_MIR_CLEAR2, ~intr[2]); //---------------------------------------------- // Do board specific stuff BSPPowerOn(); //Sync to Hardware RTC after suspend\resume OALIoCtlHalRtcTime( 0, NULL, 0, NULL, 0, NULL); // Enable GPTimer (used for high perf/monte carlo profiling) EnableDeviceClocks(BSPGetGPTPerfDevice(), TRUE); //Restore Perf Timer OALContextRestorePerfTimer(); // Reinitialize KITL bPowerOn = TRUE; KITLIoctl(IOCTL_KITL_POWER_CALL, &bPowerOn, sizeof(bPowerOn), NULL, 0, NULL); // Enable hardware watchdog OALWatchdogEnable(TRUE); #ifndef SHIP_BUILD if (g_PrcmDebugSuspendResume) { OALMSG(1, (L"Enabled wake sources:\r\n")); for (sysIntr = SYSINTR_FIRMWARE; sysIntr < SYSINTR_MAXIMUM; sysIntr++) { if (OALPowerWakeSource(sysIntr)) OALMSG(1, (L" SYSINTR %d\r\n", sysIntr)); } OALMSG(1, (L"\r\nWake due to SYSINTR %d\r\n", g_oalWakeSource)); OALWakeupLatency_DumpSnapshot(); PrcmDumpSavedRefCounts(); DumpPrcmRegsSnapshot(); } #endif // restore interrupts INTERRUPTS_ENABLE(bPrevIntrState); }