📄 hw_pmu.c
字号:
/*********************************************************************************
* Copyright (C),2004-2005, Fuzhou Rockchip Co.,Ltd.
* All Rights Reserved
* V1.00
* FileName : Hw_pmu.c
* Author : lzy
* Description:
* History :
* <author> <time> <version> <desc>
* lzy 07/6/29 1.0 ORG
*
*********************************************************************************/
#include "include.h"
#include "hw_include.h"
#include "hw_scu.h"
#include "hw_pll.h"
#define PMU
#define ARM_IDLE_FREQ 24
extern UINT16 gSysState;
const PMU_TABLE_t Pmu_Tabel_Entry[PMU_MODULE_MAX] =
{
{PMU_DUMMY, 0, 0},
{PMU_IDLE, ARM_IDLE_FREQ, 0},
{PMU_INIT, 192, 0 },
{PMU_MEDIALIBUPDATE, 192, 0 },
{PMU_MAINMENU, 12, 0},
{PMU_BROWER, 40, 0},
{PMU_MP3, 54, 0},
{PMU_MP3H, 58, 0},
{PMU_WMA, 80, 0},
{PMU_WAV, 24, 0},
{PMU_APE, Max_ARM_Freq, 0},
{PMU_FLAC, 64, 0},
{PMU_RA, 60, 0},
{PMU_AAC, 80, 0},
{PMU_OGG, 80, 0},
{PMU_EQ, 70, 0},
{PMU_RECORDADPCM, 96, 0},
{PMU_RECORDMP3, 48, 0},
{PMU_VIDEOLOWLL, 10, 70}, //chang 031421
{PMU_VIDEOLOWL, 20, 80},
{PMU_VIDEOLOW, 120, 0}, // {PMU_VIDEOLOW, 120, 100}, // text
{PMU_VIDEOMEDLOW, 120, 100},// {PMU_VIDEOMEDLOW, 120, 120},
{PMU_VIDEOMED, 120, 140}, // {PMU_VIDEOMED, 120, 140},
{PMU_VIDEOMEDHIGH, 132, 140}, // {PMU_VIDEOMEDHIGH, 132, 140},
{PMU_VIDEOHIGH, 140, 176}, //{PMU_VIDEOHIGH, 140, 176},
{PMU_VIDEOTVOUT, Max_ARM_Freq, 0},
{PMU_RVLOW, 100, 80},
{PMU_RVMED, 120, 120},
{PMU_RVHIGH, 200, 0},
{PMU_BMP, 100, 0},
{PMU_JPEG, 100, 150},
{PMU_GIF, 100, 0},
{PMU_TXT, 24, 0},
{PMU_FM, 0, 0},
{PMU_STOPWATCH, 40, 0},
#if ROCK_CAMERA
{PMU_CAMLOW, 140, 120}, //camera
{PMU_CAMHIGH, 200, 176},
#endif
{PMU_GAME, 60, 0},
{PMU_USB, 96, 0},
#ifdef RGB_PANEL
{PMU_BLON, 90, 0}, //根据屏大小再做调节
#else
{PMU_BLON, 60, 0},
#endif
{PMU_LCD_UPDATE, 20, 0}
};
/**************************************************************************
* 函数名称: PMU_SDFreqSatisfy
* 函数描述: 为满足sd卡的clock不小于15mHz,需要保证pclk在30--50mHz或60mHz以上
* 入口参数:
* 出口参数: 无
* 返回值: 无
* 注释: 将arm主频分为一下几个区间:
Freq<30: 系统基本在idle状态或无读卡动作,不需调整
30<Freq<50: 强制Pdiv = 1,Hdiv = 1
50<Freq<60: Freq = 60
60<Freq<100: if(Pdiv==Hdiv==2)Pdiv=1
100<Freq<120: Freq = 120
120<Freq<240: 频率设置函数会限制Pdiv==Hdiv==2,Pclk>30
***************************************************************************/
#define PMU_SDFREQ_MINLIMIT 20
#define PMU_APBFREQ_MINLIMIT (PMU_SDFREQ_MINLIMIT<<1)
void PMU_SDFreqSatisfy(UINT32* ArmFreq, UINT32* Hdiv, UINT32* Pdiv)
{
#if 0
if ((*ArmFreq > PMU_APBFREQ_MINLIMIT) && (*ArmFreq < 60))
*ArmFreq = 60;
if ((*ArmFreq > (PMU_APBFREQ_MINLIMIT << 1)) && (*ArmFreq < 120))
*ArmFreq = 120;
if ((*ArmFreq > 30) && (*ArmFreq < PMU_APBFREQ_MINLIMIT))
{
*Hdiv = HCLK_DIV1;
*Pdiv = PCLK_DIV1;
}
if ((*ArmFreq > 60) && (*ArmFreq < (PMU_APBFREQ_MINLIMIT << 1)))
{
if ((*Hdiv == HCLK_DIV2) && (*Pdiv == PCLK_DIV2))
*Pdiv = PCLK_DIV1;
}
#endif
}
ALIGN(8) static INT64U Module_list = 0;
/**************************************************************************
* 函数名称: PMU_ChangeFreq
* 函数描述: 设置各个模块使用的时钟
* 入口参数: armfreq:
dspfreq:
hclk_div:
pclk_div:
* 出口参数: 无
* 返回值: 无
* 注释:
***************************************************************************/
static UINT32 PMU_SetFreq(INT64U module_list)
{
UINT32 armfreq = 0, dspfreq = 0;
UINT32 hclk_div, pclk_div;
UINT32 hclk, pclk, i, j;
if (!module_list)
module_list = PMU_IDLE;
for (i = 0; i < 64; i++)
{
if (module_list &((INT64U)((INT64U)1 << i)))
{
armfreq += Pmu_Tabel_Entry[i].ARM_FREQ;
dspfreq += Pmu_Tabel_Entry[i].DSP_FREQ;
}
}
PMU_SDFreqSatisfy(&armfreq, &hclk_div, &pclk_div);
if (module_list & ((INT64U)1 << PMU_BLON))
{
hclk_div = HCLK_DIV1;
pclk_div = PCLK_DIV2;
}
else
{
hclk_div = HCLK_DIV2;
pclk_div = PCLK_DIV2;
}
armfreq -= ARM_IDLE_FREQ;
#ifndef DRIVER_ONLY
FlashTimingCfg(100);
Screen_SetMcuIFWaitTime(100);
#endif
if ((armfreq > 133) && (armfreq <= 160))//主频需求高一般总线不能过低,ahb在133mhz时会有一个波谷,故,人为调高一些
armfreq = 160; //功耗会相应的高一些
Pll_SetARMFreq(armfreq, hclk_div, pclk_div);
hclk = Pll_get_ahb_freq();
#ifndef DRIVER_ONLY
FlashTimingCfg(hclk);
Screen_SetMcuIFWaitTime(hclk);
#endif
SDRAM_SetFreq(hclk);
pclk = Pll_get_apb_freq();
PWM_UpdateAllApbFreq(pclk);
ADC_SetFreq(pclk);
Timer_SetFreq(pclk);
WDT_SetFreq(pclk);
if (dspfreq)
{
if (Pll_get_dsp_freq())
{
#if 0
//如已有软件在DSP 中运行
Scu_ClockDisable(DSP_CLOCK);
Pll_SetDSPFreq(dspfreq);
Scu_ClockEnable(DSP_CLOCK);
#endif
}
else
{
// 原DSP 不运行
Scu_ClockEnable(DWDMA_CLOCK);
Scu_ClockDisable(DSP_CLOCK);
Scu_ModuleReset(DSP_C_RESET, TRUE);
Scu_ModuleReset(DSP_P_RESET, TRUE);
USDELAY(10);
Pll_SetDSPFreq(dspfreq);
USDELAY(10);
Scu_ClockEnable(DSP_CLOCK);
USDELAY(10);
Scu_ModuleReset(DSP_P_RESET, FALSE);
}
}
else
{
// 关闭DSP
Scu_ModuleReset(DSP_C_RESET, TRUE);
// Scu_ModuleReset(DSP_P_RESET, TRUE);
USDELAY(10);
Scu_ClockDisable(DSP_CLOCK);
Pll_PowerDown(PLL_DSP);
}
return module_list;
}
void Pmu_SetBit64(INT64U* module_list, UINT16 BitCnt)
{
UINT32 * P2MList = (UINT32*)module_list;
if (BitCnt > 32)
{
BitCnt -= 32;
*P2MList |= BitCnt;
}
else
*(++P2MList) |= BitCnt;
}
void Pmu_ClrBit64(INT64U* module_list, UINT16 BitCnt)
{
UINT32 * P2MList = (UINT32*)module_list;
if (BitCnt > 32)
{
BitCnt -= 32;
*P2MList &= ~BitCnt;
}
else
*(++P2MList) &= ~BitCnt;
}
/**************************************************************************
* 函数名称: PMU_EnterModule
* 函数描述: 根据系统模块设置系统时钟
* 入口参数: PMU_MODULE_t 模块名称
* 出口参数: 无
* 返回值: 无
* 注释:
***************************************************************************/
UINT32 PMU_EnterModule(PMU_MODULE_t modulename)
{
#ifdef PMU
unsigned int pmuid;
unsigned int i = modulename;
pmuid = Pmu_Tabel_Entry[modulename].PMU_ID;
if (modulename != pmuid)
{
for (i = 0; i < PMU_MODULE_MAX; i++)
{
pmuid = Pmu_Tabel_Entry[i].PMU_ID;
if (pmuid == modulename)
{
break;
}
}
}
if (PMU_MODULE_MAX == i)
return FALSE;
//if already enter this module, no switch PMU again then return
if (Module_list & (INT64U)((INT64U)1 << i))
return Module_list;
//to prevent enter function again, lock OS schedule
#ifndef DRIVER_ONLY
OSSchedLock();
#endif
Module_list |= (INT64U)((INT64U)1 << i);
//Pmu_SetBit64(&Module_list,i);
PMU_SetFreq(Module_list);
#ifndef DRIVER_ONLY
OSSchedUnlock();
#endif
return Module_list;
#endif
}
/**************************************************************************
* 函数名称: PMU_ExitModule
* 函数描述: 根据系统模块设置系统时钟
* 入口参数:
* 出口参数: 无
* 返回值: 无
* 注释:
***************************************************************************/
UINT32 PMU_ExitModule(PMU_MODULE_t modulename)
{
#ifdef PMU
unsigned int pmuid;
unsigned int i = modulename;
pmuid = Pmu_Tabel_Entry[modulename].PMU_ID;
if (modulename != pmuid)
{
for (i = 0; i < PMU_MODULE_MAX; i++)
{
pmuid = Pmu_Tabel_Entry[i].PMU_ID;
if (pmuid == modulename)
{
break;
}
}
}
if (PMU_MODULE_MAX == i)
return FALSE;
//if already exit this module, no switch PMU again then return
if (Module_list & (INT64U)((INT64U)1 << i))
{
//to prevent enter function again, lock OS schedule
#ifndef DRIVER_ONLY
OSSchedLock();
#endif
Module_list &= ~(INT64U)((INT64U)1 << i);
//Pmu_ClrBit64(&Module_list,i);
PMU_SetFreq(Module_list);
#ifndef DRIVER_ONLY
OSSchedUnlock();
#endif
}
return Module_list;
#endif
}
/**************************************************************************
* 函数名称: PMU_PoweOnInit
* 函数描述: 初始化PMU 模块,关闭不需要的模块时钟
* 入口参数:
* 出口参数: 无
* 返回值: 无
* 注释: 由于关闭部分时钟,此函数必须先调用
***************************************************************************/
void PMU_PowerOnInit(void)
{
#ifdef PMU
UINT32 config = 0;
config = OTP_CLK_DIS
| DSP_CLK_DIS
| UHC_CLK_DIS
| VIP_HCLK_DIS
| VIP_CLK_DIS
| SPI_CLK_DIS
| HSADC_CLK_DIS
| HSADC_HCLK_DIS
| RTC_CLK_DIS
#ifndef _DEBUG_
| UART0_CLK_DIS
| UART1_CLK_DIS
#endif
;
// |SDMMC_CLK_DIS
pSCUReg->SCU_CLKCFG = config;
Module_list = 1 << PMU_IDLE;
PMU_EnterModule(PMU_INIT);
Pll_PowerDown(PLL_AUX);
#endif
}
/**************************************************************************
* 函数名称: PMU_GetState
* 函数描述: 获取当前PMU 的模块状况
* 入口参数:
* 出口参数: 无
* 返回值: Module_list 模块列表
* 注释:
***************************************************************************/
INT64U PMU_GetState(void)
{
return Module_list;
}
/**************************************************************************
* 函数名称: PMU_SDEnable
* 函数描述: 开启SD/MMC 时钟
* 入口参数:
* 出口参数: 无
* 返回值: 无
* 注释:
***************************************************************************/
void PMU_SDEnable(void)
{
Scu_ClockEnable(SDMMC_CLOCK);
}
/**************************************************************************
* 函数名称: PMU_SDDisable
* 函数描述: 关闭SD/MMC 时钟
* 入口参数:
* 出口参数: 无
* 返回值: 无
* 注释:
***************************************************************************/
void PMU_SDDisable(void)
{
Scu_ClockDisable(SDMMC_CLOCK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -