//------------------------------------------------------------------------------ // // Function: OEMSetAlarmTime // // This function is called by the kernel to set the real-time clock alarm. // BOOL OEMSetAlarmTime( SYSTEMTIME *pSystemTime ) { BOOL rc = FALSE; OALMSG(OAL_TIMER && OAL_FUNC, (L"+OEMSetAlarmTime(%s)\r\n", SystemTimeToString(pSystemTime))); if (s_rtc.initialized) { // Save time to global structure EnterCriticalSection(&s_rtc.cs); if (g_ResumeRTC) { OALIoCtlHalRtcTime(0, NULL, 0, NULL, 0, NULL); g_ResumeRTC = FALSE; } // Round to seconds pSystemTime->wMilliseconds = 0; // Convert to filetime if (NKSystemTimeToFileTime(pSystemTime, (FILETIME*)&s_rtc.alarmFiletime)) { UCHAR status; UCHAR bcdTime[6]; // Adjust alarm time by secure offset s_rtc.alarmFiletime = s_rtc.alarmFiletime - s_rtc.baseOffset; // Convert to BCD time format FiletimeToHWTime( s_rtc.alarmFiletime, bcdTime ); // Write alarm registers TWLWriteByteReg(s_rtc.hTWL, TWL_ALARM_YEARS_REG, bcdTime[5]); TWLWriteByteReg(s_rtc.hTWL, TWL_ALARM_MONTHS_REG, bcdTime[4]); TWLWriteByteReg(s_rtc.hTWL, TWL_ALARM_DAYS_REG, bcdTime[3]); TWLWriteByteReg(s_rtc.hTWL, TWL_ALARM_HOURS_REG, bcdTime[2]); TWLWriteByteReg(s_rtc.hTWL, TWL_ALARM_MINUTES_REG, bcdTime[1]); TWLWriteByteReg(s_rtc.hTWL, TWL_ALARM_SECONDS_REG, bcdTime[0]); // Set toggle bit to latch alarm registers TWLReadByteReg(s_rtc.hTWL, TWL_RTC_CTRL_REG, &status); status |= TWL_RTC_CTRL_RUN | TWL_RTC_CTRL_GET_TIME; TWLWriteByteReg(s_rtc.hTWL, TWL_RTC_CTRL_REG, status); // Done rc = TRUE; } LeaveCriticalSection(&s_rtc.cs); } return rc; }
//------------------------------------------------------------------------------ // // Function: OEMSetRealTime // // This function is called by the kernel to set the real-time clock. A secure // timer requirement means that the time change is noted in baseOffset and // used to compute the time delta from the non-alterable RTC in T2 // BOOL OEMSetRealTime( SYSTEMTIME *pSystemTime ) { BOOL rc = FALSE; ULONGLONG fileTime; DWORD tickDelta; OALMSG(OAL_TIMER && OAL_FUNC, (L"+OEMSetRealTime(%s)\r\n", SystemTimeToString(pSystemTime))); if (s_rtc.initialized) { // Save time to global structure EnterCriticalSection(&s_rtc.cs); if (g_ResumeRTC) { OALIoCtlHalRtcTime(0, NULL, 0, NULL, 0, NULL); g_ResumeRTC = FALSE; } // Round to seconds pSystemTime->wMilliseconds = 0; // Convert to filetime if (NKSystemTimeToFileTime(pSystemTime, (FILETIME*)&fileTime)) { // Compute the tick delta (indicates the time in the RTC) tickDelta = OEMGetTickCount() - s_rtc.baseTickCount; // Update all the parameters s_rtc.baseFiletime = s_rtc.baseFiletime + ((ULONGLONG)tickDelta)*10000; s_rtc.baseOffset = fileTime - s_rtc.baseFiletime; s_rtc.baseTickCount = OEMGetTickCount(); // Save off base offset to the backup regs WriteBaseOffset( &s_rtc.baseOffset ); // Done rc = TRUE; } LeaveCriticalSection(&s_rtc.cs); } OALMSG(OAL_TIMER && OAL_FUNC, (L"-OEMSetRealTime\r\n")); return rc; }
//------------------------------------------------------------------------------ // // Function: OEMGetRealTime // // This function is called by the kernel to retrieve the time from // the real-time clock. // BOOL OEMGetRealTime( SYSTEMTIME *pSystemTime ) { DWORD delta; ULONGLONG time; OALMSG(OAL_TIMER && OAL_FUNC, (L"+OEMGetRealTime()\r\n")); if (!s_rtc.initialized) { // Return default time if RTC isn't initialized pSystemTime->wYear = RTC_BASE_YEAR_MIN; pSystemTime->wMonth = 1; pSystemTime->wDay = 1; pSystemTime->wHour = 0; pSystemTime->wMinute = 0; pSystemTime->wSecond = 0; pSystemTime->wDayOfWeek = 0; pSystemTime->wMilliseconds = 0; } else { EnterCriticalSection(&s_rtc.cs); if (g_ResumeRTC) { // suspend/resume occured, sync RTC OALIoCtlHalRtcTime(0, NULL, 0, NULL, 0, NULL); g_ResumeRTC = FALSE; } delta = OEMGetTickCount() - s_rtc.baseTickCount; time = s_rtc.baseFiletime + s_rtc.baseOffset + ((ULONGLONG)delta) * 10000; NKFileTimeToSystemTime((FILETIME*)&time, pSystemTime); pSystemTime->wMilliseconds = 0; LeaveCriticalSection(&s_rtc.cs); } OALMSG(OAL_TIMER && OAL_FUNC, (L"-OEMGetRealTime() = %s\r\n", SystemTimeToString(pSystemTime))); 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); }