platform: rk3026 MID
pmu: axp192
system: android4.2
日前碰到机器休眠arm电压偏高的问题。自己找问题,找啊找,就是找不到,一直改那个arm电压表,没用,因为那个表是机器运行时的arm动态电压调整。
当机器休眠时的arm电压是另外设置的,不在这个表格内。
baord-rk3026-86v.c文件中的arm电压表如下:
/*********************************************************** * clock ************************************************************/ static struct cpufreq_frequency_table dvfs_arm_table[] = { {.frequency = 312 * 1000, .index = 950 * 1000}, {.frequency = 504 * 1000, .index = 1200 * 1000}, {.frequency = 816 * 1000, .index = 1275 * 1000}, {.frequency = 912 * 1000, .index = 1350 * 1000}, {.frequency = 1008 * 1000, .index = 1400 * 1000}, {.frequency = CPUFREQ_TABLE_END}, };用工具测量arm电压,确实会随着cpu的频率而动态变化。但是机器休眠的时候cpu是不工作的,频率大概是24M,所以arm电压设置就不在这个表格内了。(这个表格在哪里被调用以后在更新to be continued).
arm电压是由axp192的dcdc2来输出实现动态调压。原理图如下:
根据这个思路,arm休眠电压必须去pmu的代码里面设置。机器休眠的时候,pmu也是跟着休眠,所以最后设置arm电压的任务就落在了suspend函数。
上面完全错了,设置arm休眠电压不是在axp的suspend函数里面,而是在i2c的suspend函数里面。不过这个i2c和一般的i2c又有区别,等有时间仔细研究(to be continued).
在kernel/arm/arch/mach-rk2928/i2c_sram.c文件中,suspend函数首先将arm电压保存在arm_voltage中了,然后将arm电压设置为1v。在resume函数中,将arm电压设置为休眠前的arm_voltage电压:
void __sramfunc rk30_suspend_voltage_set(unsigned int vol)
{
uint8 slaveaddr;
uint8 slavereg;
uint8 data,ret = 0;
uint8 rtc_status_reg = 0x11;
sram_i2c_init(); //init i2c device
#if defined(CONFIG_MFD_TPS65910)
if(pmic_is_tps65910())
{
slaveaddr = 0x2d; //slave device addr
slavereg = 0x22; // reg addr
data = 0x1C; //set arm 1.0v
ret = sram_i2c_read(slaveaddr, rtc_status_reg);
sram_i2c_write(slaveaddr, rtc_status_reg, ret);
arm_voltage = sram_i2c_read(slaveaddr, slavereg);
#if defined ( CONFIG_ARCH_RK3026)
logic_voltage = sram_i2c_read(slaveaddr, 0x25);
sram_i2c_write(slaveaddr, 0x25, data);//
#endif
//sram_printhex(ret);
sram_i2c_write(slaveaddr, slavereg, data);//
}
#endif
#if defined(CONFIG_REGULATOR_ACT8931)
if(pmic_is_act8931())
{
slaveaddr = 0x5b; //slave device addr
slavereg = 0x40; // reg addr
data = 0x10; //set arm 1.0v
arm_voltage = sram_i2c_read(slaveaddr, slavereg);
//sram_printhex(ret);
sram_i2c_write(slaveaddr, slavereg, data);//
sram_i2c_write(slaveaddr,( slavereg+0x1), data);//
}
#endif
#if defined(CONFIG_KP_AXP19)
slaveaddr = 0x34; //slave device addr
slavereg = 0x23; // reg addr
data = 0x0a; //set arm 1.0v // 0.7v + data*0.025v
// ret = sram_i2c_read(slaveaddr, rtc_status_reg);
// sram_i2c_write(slaveaddr, rtc_status_reg, ret);
arm_voltage = sram_i2c_read(slaveaddr, slavereg);//保存休眠前arm电压值
//sram_printhex(ret);
sram_i2c_write(slaveaddr, slavereg, data);//
#endif
sram_i2c_deinit(); //deinit i2c device
}
void __sramfunc rk30_suspend_voltage_resume(unsigned int vol)
{
uint8 slaveaddr;
uint8 slavereg;
uint8 data,ret = 0;
#if defined ( CONFIG_ARCH_RK3026)
uint8 data2;
data2 = logic_voltage;
#endif
data = arm_voltage;
sram_i2c_init(); //init i2c device
#if defined(CONFIG_MFD_TPS65910)
if(pmic_is_tps65910())
{
slaveaddr = 0x2d; //slave device addr
slavereg = 0x22; // reg add
sram_i2c_write(slaveaddr, slavereg, data);
sram_udelay(20000);
#if defined ( CONFIG_ARCH_RK3026)
sram_i2c_write(slaveaddr, 0x25, data2);
sram_udelay(20000);
#endif
}
#endif
#if defined(CONFIG_REGULATOR_ACT8931)
if(pmic_is_act8931())
{
slaveaddr = 0x5b; //slave device addr
slavereg = 0x40; // reg addr
sram_i2c_write(slaveaddr, slavereg, data);
sram_i2c_write(slaveaddr, (slavereg+0x1), data);
sram_udelay(20000);
}
#endif
#if defined(CONFIG_KP_AXP19)
slaveaddr = 0x34; //slave device addr
slavereg = 0x23; // reg add
sram_i2c_write(slaveaddr, slavereg, data);//写入休眠前arm电压值
sram_udelay(20000);
#endif
sram_i2c_deinit(); //deinit i2c device
}