继续MTK平台的研究
开始研究电源管理,因为PM永远是嵌入式的核心技术,所以静下来走一遍流程。
MTK启动的过程:
硬件板载的启动入口为
static __init int board_init(void)
{
mt6573_power_management_init();
mt6573_board_init();
return 0;
}
其中mt6573_board_init();的作用如下:
mt6573_board_init() is used for chip-dependent code.
* It is suggested to put driver code in this function to do:
* 1). Capability structure of platform devices.
* 2). Define platform devices with their resources.
* 3). Register MT65XX platform devices.
即注册各种devices 如:&pmem_multimedia_device,&mt6573_device_uart[i],&AudDrv_device,&mt6573_nand_dev,&kpd_pdev等等各种设备。
其中mt6573_power_management_init();初始化各种电源管理。下面是这个函数的源码:
void mt6573_power_management_init(void)
{
/* Check Chip Version */
gChipVer = DRV_Reg32(APHW_VER);
printk("[%s]: gChipVer = 0x%x\r\n",__FUNCTION__, gChipVer);
/* Load DVFS, DCM Setting from Spare*/
mt6573_load_spare_settings();
/* Clock Gating init, gated un-necessary power*/
mt6573_CG_init();
/* Set specific chip setting*/
mt6573_chip_dep_init();
/* Power mamagement log init*/
mt6573_log_init();
/* DCM init*/
mt6573_dcm_init();
/* Thermal protect Init*/
hwThermalProtectInit();
/* Sleep Controller init*/
slp_mod_init();
}
首先看mt6573_load_spare_settings();
void mt6573_load_spare_settings(void)
{
u16 spar0;
spar0 = 0;
if (spar0 & SPARE_SECRET_KEY)
{
if(spar0 & SPARE_E1_PATCH)
gChipVer = CHIP_VER_E2;
if(spar0 & SPARE_DVFS_EN)
bCanEnDVFS = TRUE;
else
bCanEnDVFS = FALSE;
if(spar0 & SPARE_VAPROC_ADJUST_EN)
bBUCK_ADJUST = TRUE;
else
bBUCK_ADJUST = FALSE;
if(spar0 & SPARE_DVFS_LOG)
bEnDVFSLog = TRUE;
else
bEnDVFSLog = FALSE;
}
}
从代码中看是加载备用设备,但spar0 = 0所以后面的代码应该不会执行了。这是我个人的观点,希望有提出意见的。抛开这个问题可以看出主要是读标志位来给設的变量赋TURE or FALSE.
再看:mt6573_CG_init();
void mt6573_CG_init(void)
{
UINT32 u4Val;
struct cust_mt65xx_led *cust_led_list = get_cust_led_list(); //设置各种Led背光
set_clock_listen(TRUE);
DRV_SetReg32(APMCU_CG_CLR0, 0xffffffff);
... ...
后面设置一些设备模块的时钟
}
mt6573_chip_dep_init(); 设置芯片寄存器
。。。
重点看看sleep 控制器的初始化。
void slp_mod_init(void)
{
slp_pmu_init();
ost_mod_init();
suspend_set_ops(&slp_suspend_ops);
proc_create_data("slp_md_sta", 0444, NULL, &slp_md_sta_fops, NULL);
}
先看slp_pmu_init();
static void slp_pmu_init(void)
{
u16 con1;
#ifdef VCORE_1_1_V_IN_SLEEP
/* Vcore = 1.1V in sleep mode */
con1 = (slp_read16(VCORE_CON1) & 0xfe0f) | (28 << 4);
slp_write16(VCORE_CON1, con1);
#else
/* Vcore = 0.9V in sleep mode */
con1 = (slp_read16(VCORE_CON1) & 0xfe0f) | (20 << 4);
slp_write16(VCORE_CON1, con1);
#endif
/* Vaproc = 0.9V in sleep mode */
con1 = (slp_read16(VAPROC_CON1) & 0xfe0f) | (20 << 4);
slp_write16(VAPROC_CON1, con1);
/* clear CCI_SRCLKEN to enable HW sleep-mode control */
con1 = slp_read16(VA28_CON1) & ~(1U << 8);
slp_write16(VA28_CON1, con1);
slp_write_sync();
}
从代码上看,当睡眠有两种电压模式,一种是1.1V,还有一种是0.9V。依据芯片具体用哪种电压模式,然后写入寄存器。
再看:suspend_set_ops(&slp_suspend_ops);
void suspend_set_ops(struct platform_suspend_ops *ops)
{
mutex_lock(&pm_mutex);
suspend_ops = ops;
mutex_unlock(&pm_mutex);
}
所以就是给slp_suspend_ops赋值就可以拉:
static struct platform_suspend_ops slp_suspend_ops = {
.valid = slp_suspend_ops_valid,
.begin = slp_suspend_ops_begin,
.prepare = slp_suspend_ops_prepare,
.enter = slp_suspend_ops_enter,
.finish = slp_suspend_ops_finish,
.end = slp_suspend_ops_end,
};
即初始化这个数据结构里的成员函数
其中重要的函数是
static int slp_suspend_ops_enter(suspend_state_t state)
{
/* legacy log */
printk("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printk("_Chip_pm_enter @@@@@@@@@@@@@@@@@@@@@@\n");
printk(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
if (slp_dump_gpio)
gpio_dump_regs();
if (get_chip_eco_ver() == CHIP_E1) {
/* disable DCM to workaround EMI auto-refresh issue */
MT6573_DISABLE_HW_DCM_AP();
} else {
MT6573_ENABLE_HW_DCM_AP();
}
if (slp_dump_regs)
slp_dump_pm_regs();
rtc_disable_writeif();
slp_wake_reason = ost_go_to_sleep();
rtc_enable_writeif();
MT6573_DISABLE_HW_DCM_AP();
return 0;
}
wake_reason_t ost_go_to_sleep(void)
{
int i;
unsigned long flags;
struct mtk_irq_mask mask;
wake_reason_t wr;
spin_lock_irqsave(&ost_lock, flags);
for (i = 0; i < NUM_WAKE_SRC; i++) {
if (ost_wake_src & (1U << i))
ost_enable_wake_irq(ost_wake_irq[i], false);
}
mt6573_irq_mask_all(&mask);
ost_enable_wake_irq(MT6573_APOST_IRQ_LINE, true);
/* OST will periodically wake up */
wr = ost_enter_pwake_pause_mode();
mt6573_irq_mask_restore(&mask);
spin_unlock_irqrestore(&ost_lock, flags);
return wr;
}
static wake_reason_t __tcmfunc ost_enter_pwake_pause_mode(void)
{
u16 isr;
u32 ufn, wakesta;
unsigned long vbat, cnt = 0;
while (1) {
ufn = ost_get_wake_period(cnt) * 1000000 / OST_FRM_VAL;
ost_write32(OST_UFN, ufn);
ost_write32(OST_AFN, 0);
/* unmask wakeup sources */
ost_write32(OST_EVENT_MASK, ~ost_wake_src);
/* unmask Pause Interrupt, Pause Abort and UFN Timeout */
ost_write32(OST_INT_MASK, 0x0003);
ost_write16(OST_CON, OST_CON_UFN_DOWN | OST_CON_EN);
ost_write32(OST_CMD, OST_CMD_KEY | OST_CMD_CON_WR | OST_CMD_AFN_WR |
OST_CMD_UFN_WR | OST_CMD_OST_WR);
while (!(ost_read16(OST_STA) & OST_STA_CMD_CPL));
ost_write32(OST_CMD, OST_CMD_KEY | OST_CMD_PAUSE_STR);
while (!(ost_read16(OST_STA) & OST_STA_CMD_CPL));
/* flush L1 and L2 store buffers */
ost_write_sync();
/* enter WFI mode */
__asm__ __volatile__("mcr p15, 0, %0, c7, c0, 4" : : "r" (0));
wakesta = ost_read32(OST_WAKEUP_STA);
isr = ost_read16(OST_ISR);
ost_write32(OST_INT_MASK, 0x001f);
ost_write16(OST_ISR, 0x001f); /* write 1 clear */
ost_write_sync();
if (isr == 0x0004) { /* UFN Timeout */
vbat = BAT_Get_Battery_Voltage();
printk("vbat-%lu = %lu\n", ++cnt, vbat);
if (vbat <= SYSTEM_OFF_VOLTAGE) {
printk("low battery => wake up\n");
return WR_LOW_BAT;
}
} else {
ost_output_wake_reason(wakesta, isr);
return WR_WAKE_SRC;
}
}
return WR_NONE;
}
static void ost_output_wake_reason(u32 wakesta, u16 isr)
{
char str[128] = { 0 };
if (wakesta & WAKE_SRC_KP)
strcat(str, "KP ");
if (wakesta & WAKE_SRC_MSDC0)
strcat(str, "MSDC0 ");
if (wakesta & WAKE_SRC_EINT)
strcat(str, "EINT ");
if (wakesta & WAKE_SRC_RTC)
strcat(str, "RTC ");
if (wakesta & WAKE_SRC_CCIF_MD)
strcat(str, "CCIF_MD ");
printk("wake up by %s(0x%x)(0x%x)\n", str, wakesta, isr);
}
这个函数是判断机器是以何种方式唤醒的,比如:电源键,USB中断,modem电话,时钟等等。
函数proc_create_data("slp_md_sta", 0444, NULL, &slp_md_sta_fops, NULL);
static struct file_operations slp_md_sta_fops = {
.open = slp_md_sta_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
分享到:
相关推荐
pads logic格式的手机电路图,mtk6573平台,android系统
该文档是针对mtk6573平台搭建的文档,最近刚总结的。
MTK6573驱动
mtk recovery 适用于mtk6573 cpu
mtk6573驱动
魅蓝手机刷机安全,无毒。mtk6573刷机驱动魅蓝可用mtk6573刷机驱动魅蓝可用
MTK6573刷机软件好用MTK6573刷机软件
MTK6573 智能机平台参考sch+pcb。pads9.2格式
国产安卓MTK6589 MTK6577 MTK6575 MTK6573全系列手机ROOT权限破解 超牛
MTK6513-MTK6573必备驱动大全刷机必备
本软件使用于 mtk6573 的山寨机 高仿机
MTK6573 4G移动硬件开发资料data sheel 密码为:7639792933
Ubuntu10.04下配置MTK6573的Android编译运行环境
主要讲述MTK6573 LCD的驱动调试和代码分析,
mtk android2.3 Build Environment on ubuntu10.04.pdf mtk android LCM Customer Document.pdf mtk android Power Mnagagement Customer Document....mtk MT6573 Tool and production line solution introduction.pdf
某公司的参考layout,mtk6573平台,学习pads layout的好例子之一。
GC0308 MTK6573/6516平台调通,可移植
MTK6573_环境搭建,主要讲述MTK智能机编译环境的搭建以及过程中常遇到的问题,在我安装编译环境时帮了我大忙,所以上传上来,以帮助后来者
mtk MT6573 Yusu GPIO customer Document.pdf mtk smart_phone_flash_tool_Application_note.pdf mtk yusu keypad customer document.pdf mtk yusu touch panel customer document.pdf mtk build system ...
mtk6573处理器刷机 mtk 高仿g11