📄 idle.c
字号:
/*
** INTEL CONFIDENTIAL
** Copyright 2000-2003 Intel Corporation All Rights Reserved.
**
** The source code contained or described herein and all documents
** related to the source code (Material) are owned by Intel Corporation
** or its suppliers or licensors. Title to the Material remains with
** Intel Corporation or its suppliers and licensors. The Material contains
** trade secrets and proprietary and confidential information of Intel
** or its suppliers and licensors. The Material is protected by worldwide
** copyright and trade secret laws and treaty provisions. No part of the
** Material may be used, copied, reproduced, modified, published, uploaded,
** posted, transmitted, distributed, or disclosed in any way without Intel抯
** prior express written permission.
** No license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise. Any license under such intellectual property rights
** must be express and approved by Intel in writing.
*/
#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <bsp.h>
#include <types.h>
#include <bulverde.h>
#include "xllp_dvm.h"
#include "xllp_lcd.h"
#include "xllp_ost.h"
#include "xllp_intc.h"
#include "xllp_rtc.h"
#include "ipm_dvfm.h"
#include "bulverde_keypad.h"
#include "xllp_dmac.h"
#include "bsp_cfg.h"
#include "bulverde_base_regs.h"
#include "bulverde_ost.h"
#include "mainstoneii.h"
#define CKEN16_LCD (0x1<<16)
#define CCCR_CPDIS_BIT_ON (0x1<<31)
#define CCCR_PPDIS_BIT_ON (0x1<<30)
#define CCCR_LCD_26_BIT_ON (0x1<<27)
#define CCCR_PLL_EARLY_EN_BIT_ON (0x1<<26)
extern void XllpCpuIdle();
extern void XllpCpuStandby();
extern BOOL ComboChange(COMBO_PARAM );
static void IPM_Enter_13M(void);
static void IPM_Exit_13M( );
static void IPMWait(unsigned Microscont);
static void IPMmsWait(unsigned msVal);
static void IPMusWait(unsigned msVal);
static void BulverdeEnterStandby(void);
static void USecWait(UINT32 usec);
#define SENSE_PCD_CHG_EN (1 << 25)
#define SENSE_MD_PCD(x) ((x) << 17)
extern volatile XLLP_PWRMGR_T *v_pPwrReg;
extern volatile XLLP_OST_T *v_pOSTReg;
extern volatile I2C_REG *v_pI2CReg;
extern volatile XLLP_CLKMGR_T *v_pClkReg;
extern volatile LCDRegs *v_pLCDRegs;
extern volatile XLLP_DMAC_T *v_pDMARegs;
extern XLLP_GPIO_T *v_pGPIOReg;
BOOL deep_idle_enabled = 0;
unsigned int clkcfg_save = 0;
int g_13MEnable = FALSE;
int g_SkipEnable = FALSE;
//------------------------------------------------------------------------------
//
// Function: IPMCPUIdle
//
// This Idle function implements a cpu idle.
// it enters 13M idle if BSP_NODEEPIDLE defined
// and g_13MEnable is true.
//
extern UINT32 idle_msec;
// James Lai suggest to stay in deep idle for at least 40 msec to avoid
// LCD flicker.
// But we conservatively select 5 msec
#define IDLE_MSEC_MIN 5
void IPMCPUIdle()
{
#ifndef BSP_NOIPM
#ifndef BSP_NODEEPIDLE
if( (deep_idle_enabled ==1) && (idle_msec >= IDLE_MSEC_MIN))
IPM_Enter_13M();
#endif
#endif
XllpCpuIdle();
#ifndef BSP_NOIPM
#ifndef BSP_NODEEPIDLE
if( (deep_idle_enabled ==1) && (idle_msec >= IDLE_MSEC_MIN))
IPM_Exit_13M();
#endif
#endif
}
#ifdef BSP_STANDBY_AS_IDLE
extern UINT32 OALTimerIntrHandler();
// setup ost4 and enter standby, return the duration of standby
UINT32 Standby(UINT32 idleMSec)
{
UINT32 time_before;
UINT32 time_match;
extern void ost4_set_compare(UINT32);
/* setup ost4 */
time_before = v_pOSTReg->oscr4;
time_match = v_pOSTReg->oscr4 + idleMSec;
ost4_set_compare(time_match);
BulverdeEnterStandby();
/* ost4 or something else get the cpu out of standby */
TIMER_M4_INT_CLR(v_pOSTReg->ossr);
TIMER_M4_INT_DIS(v_pOSTReg->oier);
return v_pOSTReg->oscr4 - time_before;
}
void BulverdeEnterStandby()
{
unsigned long SavedFDADR0;
unsigned int KeySnoop=0;
BOOL DMABusy = FALSE;
UINT32 i = 100000;
// Setup the Wakeup enable registers for all the wakeup sources
v_pPwrReg->PWER = 0xC0000003u;
v_pPwrReg->PRER = 3u;
v_pPwrReg->PFER = 3u;
// Clear the PEDR Edge Detects register
v_pPwrReg->PEDR = 0xCE00FE1B;
// Setup the keypad wakeups ( platform dependant )
v_pPwrReg->PKWR = 0x000FD000;
// Setting the OPDE bit so 13 Mhz OSC will still be powered.
v_pPwrReg->PCFR = ((0x1 << 6) | (0x1u << 14) | (0x1u << 15) | 0x1);
v_pPwrReg->PSTR = 0xF08;
v_pPwrReg->PSSR = 0x10;
// Clear the keypad status register.
v_pPwrReg->PKSR = 0x000FFFFF;
// FIXME: Check to see if any DMA Activity is in Progress.
// (takes care of Audio and MMC since they are DMA clients)
for(i=0; i<32; i++) {
if(v_pDMARegs->DCSR[i] & (0x1u << 31)) {
DMABusy = TRUE;
break;
}
}
// Check to see if any key press is in progress.
// FIXME: temply disabled to check this keypad events.
KeySnoop = XllpKpKeypressIsInProgress(v_pGPIOReg);
// if(KeySnoop || (v_pDriverGlobals->ipm.SkipLowPower) || (DMABusy)) {
if( DMABusy || g_SkipEnable || KeySnoop) {
XllpCpuIdle();
} else {
SavedFDADR0 = v_pLCDRegs->FDADR0;
v_pLCDRegs->LCSR0 = 1;
while(v_pLCDRegs->LCSR0 & 1);
v_pLCDRegs->LCCR0 = ((v_pLCDRegs->LCCR0 & 0x07FFFFFF) | 0x448);
while(!(v_pLCDRegs->LCSR0 & 1));
XllpCpuStandby(); // Beam me up Scotty !!
// set ENB to restart the LCD again
v_pLCDRegs->FDADR0 = SavedFDADR0;
v_pLCDRegs->LCCR0 = ((v_pLCDRegs->LCCR0 & 0x07FFFBFF) | 0x1);
}
v_pPwrReg->PSSR = 0x10;
// NKDbgPrintfW(TEXT("Leaving Standby from kernel\r\n"));
}
#endif
BOOL OALIoCtlSetFreqVolt(UINT32 code, VOID *pInpBuffer,
UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
COMBO_PARAM *combo_param;
combo_param = (COMBO_PARAM *)pInpBuffer;
//NKDbgPrintfW(TEXT("FV\r\n"));
ComboChange(*combo_param);
return TRUE;
}
BOOL OALIoCtlEnable13MIDLE(UINT32 code, VOID *pInpBuffer,
UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
deep_idle_enabled = 1;
return TRUE;
}
BOOL OALIoCtlDisable13MIDLE(UINT32 code, VOID *pInpBuffer,
UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
deep_idle_enabled = 0;
return TRUE;
}
#define CLKCFG_DEFAULT 0
// return the clkcfg value before entering 13M mode
static void IPM_Enter_13M(void)
{
int cccr;
int clkcfg;
int tmp;
//NKDbgPrintfW(TEXT("13M Enab\r\n"));
if( v_pClkReg->cccr & (1<<31) )
return;
/* LCD senses 13M mode and sets PCD to SENSE_MD_PCD automatically */
v_pLCDRegs->LCCR4 |= SENSE_PCD_CHG_EN | SENSE_MD_PCD(0);
clkcfg_save = clkcfg = XllpXSC1ReadCLKCFG() & XLLP_CLKCFG_MODE_MASK;
cccr = v_pClkReg->cccr;
cccr |= CCCR_CPDIS_BIT_ON;
cccr &= ~CCCR_PPDIS_BIT_ON;
// cccr |= CCCR_LCD_26_BIT_ON;
v_pClkReg->cccr = cccr;
cccr = v_pClkReg->cccr;
// Using one-step write to clkcfg to resolve the LCD flicker
clkcfg &= ~(XLLP_CLKCFG_T | XLLP_CLKCFG_HT);
clkcfg |= XLLP_CLKCFG_F;
XllpXSC1WriteCLKCFG(clkcfg);
tmp = v_pClkReg->cccr;
while (XllpXSC1ReadCLKCFG() != clkcfg);
//NKDbgPrintfW(TEXT("Done 13M En\r\n"));
}
#ifndef BSP_NODEEPIDLE
static void IPM_Exit_13M(void)
{
int cccr, ccsr;
int tmp;
// NKDbgPrintfW(TEXT("13M disab\r\n"));
cccr = v_pClkReg->cccr;
cccr |= (CCCR_CPDIS_BIT_ON | CCCR_PLL_EARLY_EN_BIT_ON);
v_pClkReg->cccr = cccr;
cccr = v_pClkReg->cccr;
if ((cccr & 0x84000000) != 0x84000000) { /* CPDIS, pll_early_en */
NKDbgPrintfW(TEXT("Warning: CPDIS or PLL_EARLY_EN not on.\r\n"));
}
IPMusWait(120);
// USecWait(100);
{
long volatile int i=0;
for (i=0; i<999999 /* arbitrary big value to prevent
looping forever */; i++) {
ccsr = v_pClkReg->ccsr;
if ((ccsr & 0x30000000) == 0x30000000) {
break;
}
}
}
cccr &= ~(CCCR_CPDIS_BIT_ON | CCCR_PPDIS_BIT_ON); /* Not ON */
//cccr |= CCCR_PLL_EARLY_EN_BIT_ON;
v_pClkReg->cccr = cccr;
tmp = v_pClkReg->cccr;
// restore the previous saved B, HT, T bits of clkcfg
// according to the spec, we can't do this in 13M mode
clkcfg_save = (XLLP_CLKCFG_F |XLLP_CLKCFG_B |XLLP_CLKCFG_T);
// Using one-step write to clkcfg to reslove the LCD flicker
XllpXSC1WriteCLKCFG(clkcfg_save);
// as required in the spec, read cccr,
// read clkcfg and compare to the written value until matched
// tmp = v_pClkReg->cccr;
while (XllpXSC1ReadCLKCFG() != clkcfg_save);
// NKDbgPrintfW(TEXT("Done 13M disab\r\n"));
return;
}
#endif
#define OSCR_OFFSET 0x10
static void IPMWait(unsigned Microscont)
{
volatile unsigned *lTimerOSCRAddress;
unsigned lValue,Time;
lTimerOSCRAddress = (unsigned *)((char*)v_pOSTReg + OSCR_OFFSET);
Time=*lTimerOSCRAddress;
lValue = Time + (Microscont*4);
if (lValue < Time)
{ // test for wrap
while (Time < *lTimerOSCRAddress);
}
while(*lTimerOSCRAddress <= lValue);
}
static void IPMmsWait(unsigned msVal)
{
IPMWait(msVal*1000);
}
static void IPMusWait(unsigned msVal)
{
IPMWait(msVal);
}
//------------------------------------------------------------------------------
int g_StandbyEnable = FALSE;
BOOL OALIoCtlStandbyIdleGetStatus(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
// Validate caller's arguments.
//
if (!pOutBuffer || (outSize < sizeof(g_StandbyEnable)))
{
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
return(FALSE);
}
// Copy the cache information into the caller's buffer.
//
memcpy(pOutBuffer, &g_StandbyEnable, sizeof(g_StandbyEnable));
if (pOutSize)
*pOutSize = sizeof(g_StandbyEnable);
return(TRUE);
}
BOOL OALIoCtlStandbyIdleSetStatus(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
int input;
// Validate caller's arguments.
//
if (!pInpBuffer || (inpSize < sizeof(g_StandbyEnable)))
{
NKSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
input = *(int*)pInpBuffer;
if (input != TRUE && input != FALSE)
{
NKSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
g_StandbyEnable = input;
// NKDbgPrintfW(TEXT("Standby -- is %d\r\n"), g_StandbyEnable);
return(TRUE);
}
static void USecWait(UINT32 usec)
{
UINT32 countBegin = v_pOSTReg->oscr0;
UINT32 countEnd;
/* replace 3.25 with 4 for no float in kernel mode,
* optimize it when necessary.
*/
countEnd = countBegin + usec * 4;
if (countEnd < v_pOSTReg->oscr0)
while (countEnd < v_pOSTReg->oscr0);
while(v_pOSTReg->oscr0 <= countEnd);
}
BOOL OALIoCtlSkipLowPowerSetStatus(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
int input;
// Validate caller's arguments.
//
if (!pInpBuffer || (inpSize < sizeof(g_SkipEnable)))
{
NKSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
input = *(int*)pInpBuffer;
if (input != TRUE && input != FALSE)
{
NKSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
g_SkipEnable = input;
// NKDbgPrintfW(TEXT("skip enable is %d\r\n"), g_SkipEnable);
return(TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -