📄 power.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <bsp.h>
#include <pcf50606.h>
#include <power_i2c.h>
#include <xllp_defs.h>
#include <xllp_pm_sleepcontext.h>
#include "off.h"
#define PKSR_REG_RSVD_BITS 0xFFF00000
BOOL g_fPlatformPowerOff;
//Local functions
//
void BSPSetWakeSrc(PBULVERDE_PWER_REGBITS pPwer, int irq);
BOOL BSPGetWakeSrc(PBULVERDE_PEDR_REGBITS pPedr, UINT32* pSrcIrq);
//Module level vars
//
static volatile BULVERDE_GPIO_REG *g_pGPIORegs = NULL;
struct OFF_SLEEP_DATA_S m_SleepData;
UINT32 ckenVal = 0;
#define CORE_VOLTAGE(x) (900 + x*25)
//------------------------------------------------------------------------------
//
// Function: BSPSetCoreVoltage
//
// Description: This function is called by BSPPowerInit to Initialize the core power supply voltage
//
VOID BSPSetCoreVoltage()
{
UCHAR regVal1 = 0;
UCHAR regVal2 = 0;
UCHAR regVal3 = 0;
UCHAR regVal4 = 0;
UCHAR voltBits = 0;
UCHAR targetvoltBits = 0;
BOOL regDefault = FALSE;
// Read the current Core voltage
regVal1 = ReadPI2CRegister(DCDC1);
regVal2 = ReadPI2CRegister(DCDC2);
regVal3 = ReadPI2CRegister(DCDC3);
regVal4 = ReadPI2CRegister(DCDC4);
if ((regVal3 & 0x7) == 0)
{
// core voltage is pointed to by DCDC1 register regardless of PWR_ENx state
voltBits = regVal1 & 0x1F;
regDefault = TRUE;
OALMSGS(1,(TEXT("BSPSetCoreVoltage: Current Core voltage = %d mV.\r\n"), CORE_VOLTAGE(voltBits)));
}
else if ((regVal3 & 0x7) == 0x7)
{
// core voltage is pointed to by DCDC2 register regardless of PWR_ENx state
voltBits = regVal2 & 0x1F;
regDefault = FALSE;
OALMSGS(1,(TEXT("BSPSetCoreVoltage: Current Core voltage = %d mV.\r\n"), CORE_VOLTAGE(voltBits)));
}
else
{
OALMSGS(1,(TEXT("BSPSetCoreVoltage: Cannot determine DVM state.\r\n")));
return;
}
//******************************************************************/
// Sample Core voltage settings
// Refer to the Bulverde EMTS and PCF50606 PMIC documentation for more info
// Set core voltage to 900mV
//targetvoltBits = 0; // corresponds to 900mV
//OALMSGS(1,(TEXT("BSPSetCoreVoltage: Setting Core voltage to 900 mV.\r\n")));
// Set core voltage to 1100mV
//targetvoltBits = 0x8; // corresponds to 1100mV
//OALMSGS(1,(TEXT("BSPSetCoreVoltage: Setting Core voltage to 1100 mV.\r\n")));
// TODO: This should really be made dependent on the CCCR and CLKCFG settings
// Set core voltage to 1150mV
targetvoltBits = 0xA; // corresponds to 1150mV
OALMSGS(1,(TEXT("BSPSetCoreVoltage: Setting Core voltage to 1150mV mV.\r\n")));
while (voltBits > targetvoltBits)
{
voltBits--;
if (regDefault)
{
WritePI2CRegister(DCDC2, 0xC0 | voltBits);
WritePI2CRegister(DCDC3, 0x0F);
regDefault = FALSE;
OALMSGS(1,(TEXT("BSPSetCoreVoltage: Iteration:: core = %d mV.\r\n"), CORE_VOLTAGE(voltBits)));
}
else
{
WritePI2CRegister(DCDC1, 0xC0 | voltBits);
WritePI2CRegister(DCDC3, 0x08);
regDefault = TRUE;
OALMSGS(1,(TEXT("BSPSetCoreVoltage: Iteration:: core = %d mV.\r\n"), CORE_VOLTAGE(voltBits)));
}
}
}
//------------------------------------------------------------------------------
//
// Function: BSPPowerOffInit
//
// Description: This function is called by BSPPowerInit to set registers for suspend/resume functionality.
//
VOID BSPPowerOffInit()
{
UINT32 dummyRead;
UINT32 pwerVal = 0;
UINT32 pslrVal = 0;
UINT32 sysIntrRTC = SYSINTR_RTC_ALARM;
UINT32 sysIntrPCF50606 = SYSINTR_PCF50606;
UINT32 sysIntrKEYPAD = SYSINTR_KEYPAD;
UINT32 sysIntrWIFI = SYSINTR_WIFIWAKEUP;
PBULVERDE_PWRRST_REG pPwrRst_reg = (PBULVERDE_PWRRST_REG) OALPAtoUA(BULVERDE_BASE_REG_PA_PWR);
PBULVERDE_PWER_REGBITS pwerBits = (PBULVERDE_PWER_REGBITS) &pwerVal;
g_pGPIORegs = (volatile BULVERDE_GPIO_REG*) OALPAtoUA(BULVERDE_BASE_REG_PA_GPIO);
// enable GPIO0 rising edge detect by default
// also enable GPIO14 wake up (WIFI Wakeup)
OUTREG32(&pPwrRst_reg->prer, 0x00000001);
dummyRead = INREG32(&pPwrRst_reg->prer);
OUTREG32(&pPwrRst_reg->pfer, 0x00004001);
dummyRead = INREG32(&pPwrRst_reg->pfer);
// set up the PSLR
pslrVal = INREG32(&pPwrRst_reg->pslr);
pslrVal &= 0xFFD00F0C; // zero off unused/reserved bits
// set ROD = 0, which assert nRESET_OUT (Disables the LCD and AEC chips)
// Also set SL_PI = off
pslrVal &= 0xFFE00F00;
OUTREG32(&pPwrRst_reg->pslr, pslrVal);
// set up the PCFR
OUTREG32(&pPwrRst_reg->pcfr, 0x00008000);
// reset the RCSR
OUTREG32(&pPwrRst_reg->rcsr, 0x0000000F);
// enable wake up from RTC alarm, keypad and the PMU (PCF50606) by default
OALIoCtlHalEnableWake(IOCTL_HAL_ENABLE_WAKE, &sysIntrRTC, sizeof(sysIntrRTC), NULL, 0, NULL);
OALIoCtlHalEnableWake(IOCTL_HAL_ENABLE_WAKE, &sysIntrPCF50606, sizeof(sysIntrPCF50606), NULL, 0, NULL);
OALIoCtlHalEnableWake(IOCTL_HAL_ENABLE_WAKE, &sysIntrKEYPAD, sizeof(sysIntrKEYPAD), NULL, 0, NULL);
OALIoCtlHalEnableWake(IOCTL_HAL_ENABLE_WAKE, &sysIntrWIFI, sizeof(sysIntrWIFI), NULL, 0, NULL);
// configure the GPIO pins to enable the wifi wakeup interrupt
g_pGPIORegs->GAFR0_L &= 0xCFFFFFFF; // configure GPIO 14 as a GPIO
g_pGPIORegs->GPDR0 &= ~(XLLP_BIT_14); // configure GPIO 14 as input
g_pGPIORegs->GFER0 |= XLLP_BIT_14; // Turn on falling edge detection
g_pGPIORegs->GRER0 |= XLLP_BIT_14; // Turn on rising edge detection
g_pGPIORegs->GEDR0 |= XLLP_BIT_14; // Clear pending edge interrupt
g_fPlatformPowerOff = FALSE;
}
//------------------------------------------------------------------------------
//
// Function: BSPPowerInit
//
// Description: This function is called during OEMInit to Initialize the power supply
// set the registers for suspend/resume functionality.
//
VOID BSPPowerInit()
{
UCHAR RTCRegs[7] = {0};
SYSTEMTIME st;
// Initialize Power I2C registers;
//
if (!PI2CInit())
{
OALMSGS(1, (TEXT("BSPPowerInit: Failed to initialize Pi2c communication. Returning.\r\n")));
return;
}
// Set the RTC time if we have persisted value from the PCF RTC
RTCRegs[6] = ReadPI2CRegister(RTCYR);
RTCRegs[5] = ReadPI2CRegister(RTCMT);
RTCRegs[4] = ReadPI2CRegister(RTCDT);
// RTC Defaults to 01 Jan 00. If we encounter this case, don't update the system RTC
if (!(RTCRegs[6] == 0 && RTCRegs[5] == 1 && RTCRegs[4] == 1))
{
// read the remaining PCF RTC regs and set the system RTC
RTCRegs[0] = ReadPI2CRegister(RTCSC);
RTCRegs[1] = ReadPI2CRegister(RTCMN);
RTCRegs[2] = ReadPI2CRegister(RTCHR);
RTCRegs[3] = ReadPI2CRegister(RTCWD);
st.wYear = BCDTODEC(RTCRegs[6]) + 2000;
st.wMonth = BCDTODEC(RTCRegs[5]);
st.wDay = BCDTODEC(RTCRegs[4]);
st.wDayOfWeek = BCDTODEC(RTCRegs[3]);
st.wHour = BCDTODEC(RTCRegs[2]);
st.wMinute = BCDTODEC(RTCRegs[1]);
st.wSecond = BCDTODEC(RTCRegs[0]);
OEMSetRealTime(&st);
OALMSGS(1, (TEXT("BSPPowerInit: System RTC set to %d / %d / %d - %d:%d:%d.\r\n"), st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond));
}
// set the core voltage to 900mV
BSPSetCoreVoltage();
// Initialize suspend/resume function
BSPPowerOffInit();
}
//------------------------------------------------------------------------------
//
// Function: BSPPowerOff
//
// Description: This function is called as the last function before calling the XLLP layer
// to save the context and put the CPU in low power mode.
//
VOID BSPPowerOff()
{
UINT32 *pIrqs, i, count, sysIntr;
UINT32 dummyRead;
UINT32 pwerVal = 0;
UINT32 pkwrVal = 0;
PBULVERDE_PWER_REGBITS pwerBits = (PBULVERDE_PWER_REGBITS) &pwerVal;
PBULVERDE_PWRRST_REG pPwrRst_reg = (PBULVERDE_PWRRST_REG) OALPAtoUA(BULVERDE_BASE_REG_PA_PWR);
// In low power mode (sleep/deep-sleep) drive same levels on GPIO outputs as current levels.
// Note: Need to set everytime as PGSRx registers are set to 0 on each reset.
//
pPwrRst_reg->pgsr0 = g_pGPIORegs->GPLR0 & ~PGSR0_REG_RSVD_BITS;
pPwrRst_reg->pgsr1 = g_pGPIORegs->GPLR1 & ~PGSR1_REG_RSVD_BITS;
pPwrRst_reg->pgsr2 = g_pGPIORegs->GPLR2 & ~PGSR2_REG_RSVD_BITS;
pPwrRst_reg->pgsr3 = g_pGPIORegs->GPLR3 & ~PGSR3_REG_RSVD_BITS;
// Set wake up sources
//
for (sysIntr = SYSINTR_DEVICES; sysIntr < SYSINTR_MAXIMUM; sysIntr++) {
if (!OALPowerWakeSource(sysIntr))
continue; // Skip if sysIntr isn't allowed as wake source
if (SYSINTR_KEYPAD == sysIntr)
{
// set wake up sources keybd control register (PKWR)
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -