//------------------------------------------------------------------------------ // // Function: OEMPowerOff // // Description: Called when the system is to transition to it's lowest power mode (off) // // void OEMPowerOff() { volatile S3C6410_SYSCON_REG *pSysConReg; volatile S3C6410_GPIO_REG *pGPIOReg; volatile S3C6410_VIC_REG *pVIC0Reg; volatile S3C6410_VIC_REG *pVIC1Reg; volatile S3C6410_DMAC_REG *pDMAC0Reg; volatile S3C6410_DMAC_REG *pDMAC1Reg; volatile OTG_PHY_REG *pOtgPhyReg; OAL_KITL_ARGS *pArgs; BOOL PowerStateOn; int nIndex = 0; OALMSG(TRUE, (L"[OEM] ++OEMPowerOff()")); // Make sure that KITL is powered off pArgs = (OAL_KITL_ARGS*)OALArgsQuery(OAL_ARGS_QUERY_KITL); if (pArgs && ((pArgs->flags & OAL_KITL_FLAGS_ENABLED) != 0)) { PowerStateOn = FALSE; KITLIoctl (IOCTL_KITL_POWER_CALL, &PowerStateOn, sizeof(PowerStateOn), NULL, 0, NULL); OALMSG(OAL_VERBOSE, (L"OEMPowerOff: KITL Disabled\r\n")); } //----------------------------- // Prepare Specific Actions for Sleep //----------------------------- BSPPowerOff(); //------------------------------ // Prepare CPU Entering Sleep Mode //------------------------------ //---------------- // Map SFR Address //---------------- pSysConReg = (S3C6410_SYSCON_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_SYSCON, FALSE); pGPIOReg = (S3C6410_GPIO_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_GPIO, FALSE); pVIC0Reg = (S3C6410_VIC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_VIC0, FALSE); pVIC1Reg = (S3C6410_VIC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_VIC1, FALSE); pDMAC0Reg = (S3C6410_DMAC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_DMA0, FALSE); pDMAC1Reg = (S3C6410_DMAC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_DMA1, FALSE); pOtgPhyReg = (OTG_PHY_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_USBOTG_PHY, FALSE); //------------------ // Save VIC Registers //------------------ S3C6410_SaveState_VIC((void *)pVIC0Reg, (void *)pVIC1Reg, g_aSleepSave_VIC); // Disable All Interrupt pVIC0Reg->VICINTENCLEAR = 0xFFFFFFFF; pVIC1Reg->VICINTENCLEAR = 0xFFFFFFFF; pVIC0Reg->VICSOFTINTCLEAR = 0xFFFFFFFF; pVIC1Reg->VICSOFTINTCLEAR = 0xFFFFFFFF; //-------------------- // Save DMAC Registers //-------------------- S3C6410_SaveState_DMACon((void *)pDMAC0Reg, g_aSleepSave_DMACon0); S3C6410_SaveState_DMACon((void *)pDMAC1Reg, g_aSleepSave_DMACon1); //------------------ // Save GPIO Register //------------------ S3C6410_SaveState_GPIO((void *)pGPIOReg, g_aSleepSave_GPIO); //-------------------- // Save SysCon Register //-------------------- S3C6410_SaveState_SysCon((void *)pSysConReg, g_aSleepSave_SysCon); //--------------------------------------------------------------------------- // Unmask Clock Gating for All IPsand Block Power turn On for the IPs not going to sleep //--------------------------------------------------------------------------- // HCLK_IROM, HCLK_MEM1, HCLK_MEM0, HCLK_MFC Should be Always On for power Mode (Something coupled with BUS operation) //pSysConReg->HCLK_GATE |= ((1<<25)|(1<<22)|(1<<21)|(1<<0)); pSysConReg->HCLK_GATE = 0xFFFFFFFF; pSysConReg->PCLK_GATE = 0xFFFFFFFF; pSysConReg->SCLK_GATE = 0xFFFFFFFF; // Turn On All Block Block Power pSysConReg->NORMAL_CFG = 0xFFFFFF00; // Wait for Block Power Stable while((pSysConReg->BLK_PWR_STAT & 0x7E) != 0x7E); //---------------------------- // Wake Up Source Configuration //---------------------------- // S3C6410_WakeUpSource_Configure(); //------------------------------- // Extra work for Entering Sleep Mode //------------------------------- // USB Power Control pSysConReg->OTHERS &= ~(1<<16); // USB Signal Mask Clear pGPIOReg->SPCON |= (1<<3); // USB Tranceiver PAD to Suspend #ifdef _IROM_SDMMC_ // Sleep Mode Pad Configuration. HSJANG 070926. SLPEN must be 0 to change cpcon value for reading OM. #else // Sleep Mode Pad Configuration pGPIOReg->SLPEN = 0x2; // Controlled by SLPEN Bit (You Should Clear SLPEN Bit in Wake Up Process...) #endif //----------------------- // CPU Entering Sleep Mode //----------------------- OALCPUPowerOff(); // Now in Sleep //---------------------------- // CPU Wake Up from Sleep Mode //---------------------------- // Restore SysCon Register S3C6410_RestoreState_SysCon((void *)pSysConReg, g_aSleepSave_SysCon); // Restore GPIO Register S3C6410_RestoreState_GPIO((void *)pGPIOReg, g_aSleepSave_GPIO); #ifdef _IROM_SDMMC_ // Sleep Mode Pad Configuration. HSJANG 070926. SLPEN must be 0 to change cpcon value for reading OM. #else // Sleep Mode Pad Configuration pGPIOReg->SLPEN = 0x2; // Clear SLPEN Bit for Pad back to Normal Mode #endif //----------------------- // Restore DMAC Registers //----------------------- S3C6410_RestoreState_DMACon((void *)pDMAC0Reg, g_aSleepSave_DMACon0); S3C6410_RestoreState_DMACon((void *)pDMAC1Reg, g_aSleepSave_DMACon1); // Restore VIC Registers S3C6410_RestoreState_VIC((void *)pVIC0Reg, (void *)pVIC1Reg, g_aSleepSave_VIC); // UART Debug Port Initialize OEMInitDebugSerial(); // Disable Vectored Interrupt Mode on CP15 System_DisableVIC(); // Enable Branch Prediction on CP15 System_EnableBP(); // Enable IRQ Interrupt on CP15 System_EnableIRQ(); // Enable FIQ Interrupt on CP15 System_EnableFIQ(); // Initialize System Timer OEMInitializeSystemTimer(RESCHED_PERIOD, OEM_COUNT_1MS, 0); // USB Power Control InitializeOTGCLK(); // pll_powerdown, suspend mode pGPIOReg->SPCON &= ~(1<<3); // USB Tranceiver PAD to Normal //-------------------------------------- // Post Processing Specific Actions for Wake Up //-------------------------------------- BSPPowerOn(); // Reinitialize KITL if (pArgs && ((pArgs->flags & OAL_KITL_FLAGS_ENABLED) != 0)) { PowerStateOn = TRUE; KITLIoctl (IOCTL_KITL_POWER_CALL, &PowerStateOn, sizeof(PowerStateOn), NULL, 0, NULL); } OALMSG(TRUE, (L"[OEM] --OEMPowerOff()")); }
//------------------------------------------------------------------------------ // // Function: OEMPowerOff // // Description: Called when the system is to transition to it's lowest power mode (off) // // void OEMPowerOff() { volatile S3C6400_SYSCON_REG *pSysConReg; volatile S3C6400_GPIO_REG *pGPIOReg; volatile S3C6400_VIC_REG *pVIC0Reg; volatile S3C6400_VIC_REG *pVIC1Reg; volatile S3C6400_DMAC_REG *pDMAC0Reg; volatile S3C6400_DMAC_REG *pDMAC1Reg; int nIndex = 0; OALMSG(TRUE, (L"[OEM] ++OEMPowerOff()")); #if 0 // KITL can not support Sleep // Make sure that KITL is powered off pArgs = (OAL_KITL_ARGS*)OALArgsQuery(OAL_ARGS_QUERY_KITL); if ((pArgs->flags & OAL_KITL_FLAGS_ENABLED) != 0) { OALKitlPowerOff(); OALMSG(1, (L"OEMPowerOff: KITL Disabled\r\n")); } #endif //----------------------------- // Disable DVS and Set to Full Speed //----------------------------- #ifdef DVS_EN ChangeDVSLevel(SYS_L0); #endif //----------------------------- // Prepare Specific Actions for Sleep //----------------------------- BSPPowerOff(); //------------------------------ // Prepare CPU Entering Sleep Mode //------------------------------ //---------------- // Map SFR Address //---------------- pSysConReg = (S3C6400_SYSCON_REG *)OALPAtoVA(S3C6400_BASE_REG_PA_SYSCON, FALSE); pGPIOReg = (S3C6400_GPIO_REG *)OALPAtoVA(S3C6400_BASE_REG_PA_GPIO, FALSE); pVIC0Reg = (S3C6400_VIC_REG *)OALPAtoVA(S3C6400_BASE_REG_PA_VIC0, FALSE); pVIC1Reg = (S3C6400_VIC_REG *)OALPAtoVA(S3C6400_BASE_REG_PA_VIC1, FALSE); pDMAC0Reg = (S3C6400_DMAC_REG *)OALPAtoVA(S3C6400_BASE_REG_PA_DMA0, FALSE); pDMAC1Reg = (S3C6400_DMAC_REG *)OALPAtoVA(S3C6400_BASE_REG_PA_DMA1, FALSE); //------------------ // Save VIC Registers //------------------ S3C6400_SaveState_VIC((void *)pVIC0Reg, (void *)pVIC1Reg, g_aSleepSave_VIC); // Disable All Interrupt pVIC0Reg->VICINTENCLEAR = 0xFFFFFFFF; pVIC1Reg->VICINTENCLEAR = 0xFFFFFFFF; pVIC0Reg->VICSOFTINTCLEAR = 0xFFFFFFFF; pVIC1Reg->VICSOFTINTCLEAR = 0xFFFFFFFF; //-------------------- // Save DMAC Registers //-------------------- S3C6400_SaveState_DMACon((void *)pDMAC0Reg, g_aSleepSave_DMACon0); S3C6400_SaveState_DMACon((void *)pDMAC1Reg, g_aSleepSave_DMACon1); //------------------ // Save GPIO Register //------------------ S3C6400_SaveState_GPIO((void *)pGPIOReg, g_aSleepSave_GPIO); //-------------------- // Save SysCon Register //-------------------- S3C6400_SaveState_SysCon((void *)pSysConReg, g_aSleepSave_SysCon); //------------------------------------------------------- // Unmask Clock Gating and Block Power turn On (SW workaround) //------------------------------------------------------- // HCLK_IROM, HCLK_MEM1, HCLK_MEM0, HCLK_MFC Should be Always On for power Mode (Something coupled with BUS operation) //pSysConReg->HCLK_GATE |= ((1<<25)|(1<<22)|(1<<21)|(1<<0)); pSysConReg->HCLK_GATE = 0xFFFFFFFF; pSysConReg->PCLK_GATE = 0xFFFFFFFF; pSysConReg->SCLK_GATE = 0xFFFFFFFF; // Turn On All Block Block Power pSysConReg->NORMAL_CFG = 0xFFFFFF00; // Wait for Block Power Stable while((pSysConReg->BLK_PWR_STAT & 0x7E) != 0x7E); //---------------------------- // Wake Up Source Configuration //---------------------------- S3C6400_WakeUpSource_Configure(); //------------------------------- // Extra work for Entering Sleep Mode //------------------------------- // USB Power Control pSysConReg->OTHERS &= ~(1<<16); // USB Signal Mask Clear pGPIOReg->SPCON |= (1<<3); // USB Tranceiver PAD to Suspend // TODO: SPCONSLP ??? //pGPIOReg->SPCONSLP; // Use Default Valie //------------------------------- // GPIO Configuration for Sleep State //------------------------------- // TODO: Configure GPIO at Sleep //BSPConfigGPIOforPowerOff(); // Sleep Mode Pad Configuration pGPIOReg->SLPEN = 0x2; // Controlled by SLPEN Bit (You Should Clear SLPEN Bit in Wake Up Process...) //----------------------- // CPU Entering Sleep Mode //----------------------- OALCPUPowerOff(); // Now in Sleep //---------------------------- // CPU Wake Up from Sleep Mode //---------------------------- //---------------------------- // Wake Up Source Determine //---------------------------- S3C6400_WakeUpSource_Detect(); // USB Power Control pSysConReg->OTHERS |= (1<<16); // TODO: USB Signal Mask Set (Device must handle it...) pGPIOReg->SPCON &= ~(1<<3); // USB Tranceiver PAD to Normal // Restore SysCon Register S3C6400_RestoreState_SysCon((void *)pSysConReg, g_aSleepSave_SysCon); // Restore GPIO Register S3C6400_RestoreState_GPIO((void *)pGPIOReg, g_aSleepSave_GPIO); // Sleep Mode Pad Configuration pGPIOReg->SLPEN = 0x2; // Clear SLPEN Bit for Pad back to Normal Mode //----------------------- // Restore DMAC Registers //----------------------- S3C6400_RestoreState_DMACon((void *)pDMAC0Reg, g_aSleepSave_DMACon0); S3C6400_RestoreState_DMACon((void *)pDMAC1Reg, g_aSleepSave_DMACon1); // Restore VIC Registers S3C6400_RestoreState_VIC((void *)pVIC0Reg, (void *)pVIC1Reg, g_aSleepSave_VIC); //pVIC0Reg->VICADDRESS = 0x0; //pVIC1Reg->VICADDRESS = 0x0; // UART Debug Port Initialize OEMInitDebugSerial(); // Disable Vectored Interrupt Mode on CP15 System_DisableVIC(); // Enable Branch Prediction on CP15 System_EnableBP(); // Enable IRQ Interrupt on CP15 System_EnableIRQ(); // Enable FIQ Interrupt on CP15 System_EnableFIQ(); if (g_oalWakeSource == SYSWAKE_UNKNOWN) { OALMSG(TRUE, (L"[OEM:ERR] OEMPowerOff() : SYSWAKE_UNKNOWN , WAKEUP_STAT = 0x%08x", g_LastWakeupStatus)); } // Initialize System Timer OEMInitializeSystemTimer(RESCHED_PERIOD, OEM_COUNT_1MS, 0); #if 0 // KITL can not support Sleep // Reinitialize KITL if ((pArgs->flags & OAL_KITL_FLAGS_ENABLED) != 0) { OALKitlPowerOn(); } #endif //-------------------------------------- // Post Processing Specific Actions for Wake Up //-------------------------------------- BSPPowerOn(); OALMSG(TRUE, (L"[OEM] --OEMPowerOff()")); }
//------------------------------------------------------------------------------ // // 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); }