⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 power.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -