📄 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.
//
//------------------------------------------------------------------------------
//
// File: power.c
//
// Power BSP callback functions implementation.
//
#include <bsp.h>
#include <intr_fpga.h>
//Local functions
//
void BSPSetWakeSrc(PBULVERDE_PWER_REGBITS pPwer, int irq);
BOOL BSPGetWakeSrc(PBULVERDE_PEDR_REGBITS pPedr, UINT32* pSrcIrq);
//Module level vars
//
static volatile UINT32 g_BLRegs_intmskena_savedval = 0;
static volatile UINT32 g_BLRegs_intsetclr_savedval = 0;
static volatile MAINSTONEII_BLR_REGS *g_pBLRegs = NULL;
static volatile BULVERDE_GPIO_REG *g_pGPIORegs = NULL;
//------------------------------------------------------------------------------
//
// Function: BSPPowerOffInit
//
// Description: This function is called during OEMInit to set registers for suspend/resume functionality.
//
VOID BSPPowerOffInit()
{
PBULVERDE_PWRRST_REG pPwrRst_reg = (PBULVERDE_PWRRST_REG) OALPAtoUA(BULVERDE_BASE_REG_PA_PWR);
UINT32 dummyRead;
UINT32 rtcSysIntr = SYSINTR_RTC_ALARM;
g_pBLRegs = (volatile MAINSTONEII_BLR_REGS *) OALPAtoVA(MAINSTONEII_BASE_REG_PA_FPGA, FALSE);
g_pGPIORegs = (volatile BULVERDE_GPIO_REG*) OALPAtoUA(BULVERDE_BASE_REG_PA_GPIO);
// set wake up sources keybd control register (PKWR)
//
//disable all
OUTREG32(&pPwrRst_reg->pkwr, 0x0);
dummyRead = INREG32(&pPwrRst_reg->pkwr); //read to make sure values are latched
// enable rising edge and/or falling edge GPIO detects
// otherwise GPIO edge detects will not resume the device
// (GPIO1 is tied to SW21 on Mainstone II board. This switch is
// used as the suspend/resume power button (see pwrbutton driver))
// enable all rising edge detects, disable GPIO1 (pwrbutton) rising edge detect
OUTREG32(&pPwrRst_reg->prer, (~(PRER_REG_RSVD_BITS) & ~0x00000002));
dummyRead = INREG32(&pPwrRst_reg->prer);
// disable all falling edge detects, enable GPIO1 (pwrbutton) falling edge detect
OUTREG32(&pPwrRst_reg->pfer, (~(PFER_REG_RSVD_BITS) & 0x00000002));
dummyRead = INREG32(&pPwrRst_reg->pfer);
// enable wake up from RTC alarm on sleep/suspend
OALIoCtlHalEnableWake(IOCTL_HAL_ENABLE_WAKE, &rtcSysIntr, sizeof(rtcSysIntr), NULL, 0, NULL);
}
//------------------------------------------------------------------------------
//
// 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;
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;
// Save off FPGA interrupt controller mask and clear it.
// BSPSetWakeSrc will set it up with wake up source mask.
//
g_BLRegs_intmskena_savedval = (INREG32((PULONG)&g_pBLRegs->int_msk_en)) & ~INTMSK_RESERVED_BITS;
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, 0);
// Save off pending FPGA interrupts and clear the reg.
//
g_BLRegs_intsetclr_savedval = (INREG32((PULONG)&g_pBLRegs->int_set_clr)) & ~INTSETCLR_RESERVED_BITS;
OUTREG32((PULONG)&g_pBLRegs->int_set_clr, 0);
// 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 (!OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs))
continue; // Get IRQs
for (i = 0; i < count; i++) { // Hardware supports only restricted number of sources
BSPSetWakeSrc(pwerBits, pIrqs[i]);
}
}
// set wake up sources register (PWER)
OUTREG32(&pPwrRst_reg->pwer, pwerVal);
dummyRead = INREG32(&pPwrRst_reg->pwer);
}
//------------------------------------------------------------------------------
VOID BSPPowerOn()
{
UINT32 wakesrc, srcIrq;
PBULVERDE_PWRRST_REG pPwrRst_reg = (PBULVERDE_PWRRST_REG) OALPAtoUA(BULVERDE_BASE_REG_PA_PWR);
// find wake up source
//
wakesrc = INREG32(&pPwrRst_reg->pedr);
wakesrc &= ~PEDR_REG_RSVD_BITS;
if (BSPGetWakeSrc((PBULVERDE_PEDR_REGBITS)&wakesrc, &srcIrq))
g_oalWakeSource = OALIntrTranslateIrq(srcIrq);
// clear wake up source status register (PEDR)
OUTREG32(&pPwrRst_reg->pedr, wakesrc );
// Restore the FPGA interrupt controller.
//
// 1. Disable all FPGA interrupts (disable FPGA GPIO0 assertion to Bulverde).
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, 0);
// 2. Clear the Bulverde GPIO0 edge detection.
OUTREG32((PULONG)&g_pGPIORegs->GEDR0, XLLP_GPIO_BIT_0);
// 3. Wait...
OALStall(1);
// 4. Restore FPGA pending interrupts from before device was suspended.
// Note: this adds pending interrupts from pre-suspend state to any
// other interrupts that might have been fired during suspend state.
OUTREG32((PULONG)&g_pBLRegs->int_set_clr,
((INREG32((PULONG)&g_pBLRegs->int_set_clr)) & ~INTSETCLR_RESERVED_BITS) | g_BLRegs_intsetclr_savedval);
// 5. Restore the FPGA mask (this will cause any pending interrupts to assert
// to the Bulverde).
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, g_BLRegs_intmskena_savedval);
}
//------------------------------------------------------------------------------
//
// Function: BSPSetWakeSrc
//
// Description: called to set wake-up sources.
//
void BSPSetWakeSrc(PBULVERDE_PWER_REGBITS pPwer, int irq)
{
//ignore undefined IRQ
if (irq == OAL_INTR_IRQ_UNDEFINED)
return;
switch(irq) {
case IRQ_RTCALARM:
pPwer->rtc_alarm = 1;
break;
case IRQ_GPIO1:
pPwer->gpio1 = 1;
break;
case IRQ_GPIO0:
pPwer->gpio0 = 1;
break;
default:
// Handle FPGA interrupts
//
if (irq >= IRQ_MAINSTONEII_GPIO0_MIN && irq <= IRQ_MAINSTONEII_GPIO0_MAX)
{
// Unmask the corresponding FPGA interrupt bit
UINT32 TempVal = (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, (TempVal | FPGA_INT_BIT(irq)));
//Enable GPIO0 interrupt as all FPGA interrupts appear at GPIO0
pPwer->gpio0 = 1;
break;
}
OALMSG(OAL_WARN, (
L"BSPSetWakeSrc: IRQ %d not supported as wake up source\r\n", irq
));
}
}
//------------------------------------------------------------------------------
//
// Function: BSPGetWakeSrc
//
// Description: called to get the wake-up source.
//
BOOL BSPGetWakeSrc(PBULVERDE_PEDR_REGBITS pPedr, UINT32* pSrcIrq)
{
if (pPedr->rtc_alarm)
*pSrcIrq = IRQ_RTCALARM;
else if (pPedr->gpio1)
*pSrcIrq = IRQ_GPIO1;
else if (pPedr->gpio0)
{
// Handle FPGA interrupts.
// Bulverde says GPIO0 caused wake-up. Since all
// FPGA interrupts are tied to GPIO0 determine
// which FPGA interrupt caused the wake-up.
//
UINT8 nInt;
UINT32 TempVal;
// Read the pending FPGA interrupts and ignore masked/reserved interrupts.
TempVal = INREG32((PULONG)&g_pBLRegs->int_set_clr);
TempVal &= (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
// Scan through the pending interrupts and look for a match.
for (nInt = IRQ_MAINSTONEII_GPIO0_MIN ; nInt <= IRQ_MAINSTONEII_GPIO0_MAX ; nInt++)
{
if (TempVal & FPGA_INT_BIT(nInt))
{
*pSrcIrq = nInt;
break;
}
}
}
else
return 0; //no match found
return 1; // match found
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -