📄 hal_power.c
字号:
/**************************************************************************
; HAL_POWER.c
; Control the power and clock of LCDC
;
; Copyright (c) 2002 Epson Research and Development, Inc.
; All Rights Reserved.
;
;**************************************************************************/
#include "sysLCDC.h"
/****************************************************************************
; Function: Power Save Mode on/off
; Input :
; Output :
; Format : unsigned short PowerSaveMode(unsigned short enable)
;****************************************************************************/
unsigned short PowerSaveMode(unsigned short enable)
{
unsigned short reg0012, reg0014, val16;
unsigned long i;
long idx;
unsigned long index;
long FoundReg0012;
reg0014 = halReadReg16(REG0014_POWER_SAVE_CONFIG);
if (enable) // Enable Power Save Mode
{
for (i = 0; i < TIMEOUT_POWERSAVE; ++i) // timeout in case memory status never changes
{
reg0014 = halReadReg16(REG0014_POWER_SAVE_CONFIG);
if (reg0014 & 0x0040) // check the Memory Power Save Status
break;
}
if (i == TIMEOUT_POWERSAVE) // if timeout ,return error
return FALSE;
reg0014 |= POWER_SAVE_MODE_ENABLE; // set Power Save mode enable
halWriteReg16(REG0014_POWER_SAVE_CONFIG, reg0014);
reg0012 = (unsigned short) (halReadReg16(REG0012_PLL_SETTING2) | PLL_DISABLE); // disable the PLL
halWriteReg16(REG0012_PLL_SETTING2, reg0012);
return TRUE;
}
else // Disable Power Save mode
{
FoundReg0012 = FALSE; // Set PLL bypass to CFG Settings
val16 = 0x0001; // default to PLL bypass
for (idx = 0; idx < NUM_REGS; idx++) // Find the last reference to REG[0012h] and find the power up delay
{
index = HalInfo.Regs[idx].Index;
if (index == REG0012_PLL_SETTING2)
{
FoundReg0012 = TRUE;
val16 = HalInfo.Regs[idx].Value;
}
}
reg0012 = (unsigned short) (halReadReg16(REG0012_PLL_SETTING2) & PLL_ENABLE); // Setting PLL Bypass based on CFG settings
reg0012 |= (val16 & 0x0001);
halWriteReg16(REG0012_PLL_SETTING2, reg0012);
//halDelayUS(HalInfo.wLcdPowerupTime * 1000L); // Delay
reg0014 = (unsigned short) (halReadReg16(REG0014_POWER_SAVE_CONFIG) & POWER_SAVE_MODE_DISABLE);// disable the POWER Save mode
halWriteReg16(REG0014_POWER_SAVE_CONFIG, reg0014);
return TRUE;
}
}
/****************************************************************************
; Function: Set PLL
; Input :
; Output :
; Format : Boolean SetPll( unsigned short WhichPll, unsigned long freq )
;****************************************************************************/
BOOL SetPll( unsigned short WhichPll, unsigned long freq )
{
unsigned long ClosestN, ClosestL, ClosestPll, ClosestDiff;
unsigned long n, l, pll, diff;
unsigned long ClosestVbits, v, vBits, factor;
unsigned long Kv;
BOOL PllProgrammed = TRUE;
if (WhichPll != 0)
WhichPll = 0;
// Find the closest PLL frequency based on N and L
ClosestN = 0;
ClosestL = 0;
ClosestPll = (ClosestN + 1) * (ClosestL + 1) * HalInfo.dwClkI;
ClosestDiff = abs32(freq, ClosestPll);
Kv = 0;
n = 16;
while (n--) // n must loop from 15 to 0
{
for (l = 0; l <= 1023; ++l)
{
pll = (n + 1) * (l + 1) * HalInfo.dwClkI;
diff = abs32(freq, pll);
if (diff < ClosestDiff)
{
ClosestN = n;
ClosestL = l;
ClosestPll = (ClosestN + 1) * (ClosestL + 1) * HalInfo.dwClkI;
ClosestDiff = abs32(freq, ClosestPll);
}
}
}
// Determine V based on PLL frequency
// 100 MHz <= PLL * V <= 410 MHz
// if V==2, V divider bits=1
// if V==4, V divider bits=2
// if V==8, V divider bits=3
//
ClosestVbits = 0;
// If the duty cycle is not important, lower power consumption can be achieved
// by setting the V-divider bits and VCO Kv Set bits to 0.
if (!(HalInfo.dwFlags & fPLL_LOWPOWER))
{
for (vBits = 1; vBits <= 3; ++vBits)
{
v = 1 << vBits;
factor = ClosestPll * v;
if ((100 * MHZ <= factor) && (factor <= 410 * MHZ))
{
// Determine if V satisfies the next criteria for Kv
// Determine Kv
// if (100 MHz <= PLL * V <= 200 MHz) then Kv=2
// if (200 MHz < PLL * V <= 300 MHz) then Kv=5
// if (300 MHz < PLL * V <= 410 MHz) then Kv=7
factor = ClosestPll * v;
Kv = 0;
if ((100 * MHZ <= factor) && (factor <= 200 * MHZ))
Kv = 2;
else if ((200 * MHZ < factor) && (factor <= 300 * MHZ))
Kv = 5;
else if ((300 * MHZ < factor) && (factor <= 410 * MHZ))
Kv = 7;
if (Kv != 0)
{
ClosestVbits = vBits;
break;
}
}
}
if ((ClosestVbits == 0) || (Kv == 0))
{
PllProgrammed = FALSE;
// Force valid values
ClosestVbits = 3;
Kv = 2;
}
}
ClosestN &= 0x0f;
ClosestL &= 0x3ff;
ClosestVbits &= 0x03;
PowerSaveMode(TRUE); // Go into power save before writing to PLL registers
halWriteReg16(REG000E_PLL_SETTING0, (unsigned short) ((ClosestN << 12) | (ClosestL << 2) | ClosestVbits));
halWriteReg16(REG0010_PLL_SETTING1, (unsigned short) (Kv << 12));
halWriteReg16(REG0012_PLL_SETTING2, 0);
// Restore original setting
// halDelayUS(100);
PowerSaveMode(FALSE);
return PllProgrammed;
}
/****************************************************************************
; Function: Get PLL
; Input :
; Output :
; Format : unsigned long GetPll( unsigned short WhichPll, long *error )
;****************************************************************************/
unsigned long GetPll( unsigned short WhichPll, long *error )
{
unsigned long N, L, V, pll;
unsigned long Kv;
unsigned short reg;
unsigned long factor;
long tmp;
if (error == NULL) // The error would be set to NULL if the caller doesn't want to get the error
error = &tmp;
*error = FALSE;
if (WhichPll != 0)
{
*error = TRUE;
return 0;
}
reg = halReadReg16(REG000E_PLL_SETTING0);
N = reg >> 12;
L = (reg >> 2) & 0x3ff;
pll = (N + 1) * (L + 1) * HalInfo.dwClkI;
// If the duty cycle is not important, lower power consumption can be achieved
// by setting the V-divider bits and VCO Kv Set bits to 0.
// Don't check these bits if PLL Low Power mode has been configured.
if (!(HalInfo.dwFlags & fPLL_LOWPOWER))
{
// Verify if PLL registers programmed correctly
V = 1 << (reg & 0x03);
Kv = halReadReg16(REG0010_PLL_SETTING1) >> 12;
factor = pll * V;
if ((100 * MHZ <= factor) && (factor <= 410 * MHZ))
{
if ((100 * MHZ <= factor) && (factor <= 200 * MHZ))
{
if (Kv != 2)
*error = TRUE;
}
else if ((200 * MHZ < factor) && (factor <= 300 * MHZ))
{
if (Kv != 5)
*error = TRUE;
}
else if ((300 * MHZ < factor) && (factor <= 410 * MHZ))
{
if (Kv != 7)
*error = TRUE;
}
}
else
*error = TRUE;
}
return pll;
}
/****************************************************************************
; Function: Get Pll Power Down
; Input :
; Output :
; Format : unsigned short GetPllPowerDown(void)
;****************************************************************************/
unsigned short GetPllPowerDown(void)
{
return (halReadReg16(REG0012_PLL_SETTING2) & 0x0001) ? TRUE : FALSE;
}
/****************************************************************************
; Function: Get System CLK Divide
; Input :
; Output :
; Format : unsigned short GetSystemClkDivide(void)
;****************************************************************************/
unsigned short GetSystemClkDivide(void)
{
return (halReadReg16(REG0018_SYSTEM_CLOCK_SETTING) & 0x03) + 1;
}
/****************************************************************************
; Function: Get System Clock
; Input :
; Output :
; Format : unsigned long GetSystemClock(unsigned long *UsingClkI)
;****************************************************************************/
unsigned long GetSystemClock(unsigned long *UsingClkI)
{
if (GetPllPowerDown())
{
if (UsingClkI != NULL)
*UsingClkI= TRUE;
return HalInfo.dwClkI / GetSystemClkDivide();
}
else
{
if (UsingClkI != NULL)
*UsingClkI = FALSE;
return GetPll(0, NULL) / GetSystemClkDivide();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -