📄 power.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// File: power.c
//
#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <au1.h>
//------------------------------------------------------------------------------
//
// Function: OEMPowerOff
//
// Called when the system is to transition to it's lowest power mode (off).
//
void OEMPowerOff(void)
{
AU1_IC_REGS *pIC0Regs = OALPAtoUA(AU1_IC0_REGS_PA);
AU1_IC_REGS *pIC1Regs = OALPAtoUA(AU1_IC1_REGS_PA);
AU1_SYS_REGS *pSysRegs = OALPAtoUA(AU1_SYS_REGS_PA);
UINT32 ic0cfg0, ic0cfg1, ic0cfg2, ic0mask, ic0assign;
UINT32 ic1cfg0, ic1cfg1, ic1cfg2, ic1mask, ic1assign;
UINT32 sysIntr, irq;
UINT32 wakemsk, wakesrc, mask;
UINT32 *pIrqs, i, count;
// Save actual interrupt masks for IC0
ic0cfg0 = INREG32(&pIC0Regs->CFG0RD);
ic0cfg1 = INREG32(&pIC0Regs->CFG1RD);
ic0cfg2 = INREG32(&pIC0Regs->CFG2RD);
ic0mask = INREG32(&pIC0Regs->MASKRD);
ic0assign = INREG32(&pIC0Regs->ASSIGNRD);
// Save actual interrupt masks for IC1
ic1cfg0 = INREG32(&pIC1Regs->CFG0RD);
ic1cfg1 = INREG32(&pIC1Regs->CFG1RD);
ic1cfg2 = INREG32(&pIC1Regs->CFG2RD);
ic1mask = INREG32(&pIC1Regs->MASKRD);
ic1assign = INREG32(&pIC1Regs->ASSIGNRD);
// Find actual wake mask
wakemsk = 0;
for (sysIntr = SYSINTR_DEVICES; sysIntr < SYSINTR_MAXIMUM; sysIntr++) {
// Skip if sysIntr isn't allowed as wake source
if (!OALPowerWakeSource(sysIntr)) continue;
// Get IRQs
if (!OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs)) continue;
// Hardware support only restricted number of sources
for (i = 0; i < count; i++) {
if (pIrqs[i] == IRQ_TOYMATCH2) {
wakemsk |= SYS_WAKEMSG_M20;
} else if (pIrqs[i] >= 32 && pIrqs[i] <= 39) {
// GPIO0 to GPIO7
wakemsk |= 1 << (pIrqs[i] - 32);
}
}
}
// Set mask to hardware
OUTREG32(&pSysRegs->WAKEMSK, wakemsk);
// Clear wake source
OUTREG32(&pSysRegs->WAKESRC, 0);
// Power off KITL
OALKitlPowerOff();
// Let BSP do board specific stuff
BSPPowerOff();
// Save restore address to scratch register
OUTREG32(&pSysRegs->SCRATCH0, OALCPUPowerOn);
// Finally power off CPU
OALCPUPowerOff();
// Find wakeup source
wakesrc = INREG32(&pSysRegs->WAKESRC);
mask = SYS_WAKESRC_GP0;
irq = 32;
while (irq <= 41) {
if ((wakesrc & mask) != 0) break;
mask <<= 1;
irq++;
};
// When we find wakup source set global variable
if (irq <= 41) {
if (irq == 41) irq = IRQ_TOYMATCH2;
g_oalWakeSource = OALIntrTranslateIrq(irq);
}
// Clear wakeup source register
OUTREG32(&pSysRegs->WAKESRC, wakesrc);
// Set restore address to zero
OUTREG32(&pSysRegs->SCRATCH0, 0);
// Then let BSP do board specific stuff
BSPPowerOn();
// Restore KITL
OALKitlPowerOn();
// Restore interrupt masks for IC0
OUTREG32(&pIC0Regs->CFG0CLR, 0xFFFFFFFF);
OUTREG32(&pIC0Regs->CFG0SET, ic0cfg0);
OUTREG32(&pIC0Regs->CFG1CLR, 0xFFFFFFFF);
OUTREG32(&pIC0Regs->CFG1SET, ic0cfg1);
OUTREG32(&pIC0Regs->CFG2CLR, 0xFFFFFFFF);
OUTREG32(&pIC0Regs->CFG2SET, ic0cfg2);
OUTREG32(&pIC0Regs->MASKCLR, 0xFFFFFFFF);
OUTREG32(&pIC0Regs->MASKSET, ic0mask);
OUTREG32(&pIC0Regs->ASSIGNCLR, 0xFFFFFFFF);
OUTREG32(&pIC0Regs->ASSIGNSET, ic0assign);
// Restore interrupt masks for IC1
OUTREG32(&pIC1Regs->CFG0CLR, 0xFFFFFFFF);
OUTREG32(&pIC1Regs->CFG0SET, ic1cfg0);
OUTREG32(&pIC1Regs->CFG1CLR, 0xFFFFFFFF);
OUTREG32(&pIC1Regs->CFG1SET, ic1cfg1);
OUTREG32(&pIC1Regs->CFG2CLR, 0xFFFFFFFF);
OUTREG32(&pIC1Regs->CFG2SET, ic1cfg2);
OUTREG32(&pIC1Regs->MASKCLR, 0xFFFFFFFF);
OUTREG32(&pIC1Regs->MASKSET, ic1mask);
OUTREG32(&pIC1Regs->ASSIGNCLR, 0xFFFFFFFF);
OUTREG32(&pIC1Regs->ASSIGNSET, ic1assign);
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -