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

📄 hal_power.c

📁 一款SmartPhone的驱动代码
💻 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 + -