rk3128 平台rk818电源管理驱动移植

2019-07-14 00:28发布

 

一、rk3128加上rk818电源管理驱动

RK3128 加上rk818电源管理驱动之后,导致内核死机、工作各种稳定。死机现象各不相同,内核起来之后跑一下死在printk 打印函数里面、遇到NULL kernel painc 内存异常、Internal error: Oops 等等异常情况。基本上断定电源管理部分出问题 出现这些问题两种情况 1、        电源驱动RK818 没有加载上去 a)    需要检查驱动和gpio有没有配置对   2、        电源管理芯片输出的 电压不稳定 CPU、DDR、GPU 等电压太低,导致跑飞 主要是设计电路板是要严格配置阻抗,同时微调RK818 输出电压 CPU 启动的时候,从低的主频经过几次跳频,电压太低导致CPU、DDR工作异常  
 

二、驱动移植

1、配置驱动

make menuconfig Linux/arm 3.10.0Kernel Configuration      Device Drivers  --->     Multifunction device drivers             *]RK818 Power Management chip    Device Drivers  --->              -*-Power supply class support  --->  [*]   RK818Battery driver     Device Drivers  --->    [*] Real Time Clock --->             -*-   rk818 rtc for rk                                2、        修改dts文件gpio Rk818 sleep 接到主控  PMIC_SLEEP(GPIO3_C1) INT_OC接到主控  PMIC_INT(GPIO1_B1)   &rk818 { gpios =<&gpio1 GPIO_B1GPIO_ACTIVE_HIGH>,<&gpio3 GPIO_C1 GPIO_ACTIVE_LOW>; } RK818挂载在I2C0上   &i2c0 {        status = "okay";        rk818: rk818@1c {                 reg = <0x1c>;  /*从机地址*/                 status = "okay";        }; }  

三、配置RK818输出电压

vim rk3128-box.dts         &clk_core_dvfs_table {                 operating-points = <                         /* KHz    uV */ /*描述主控工作频率时RK818输出电压*/                         816000 1000000                         1008000 1200000                         /*1000000 1425000*/                         >;            /*动态调整频率的时候,对应匹配的电压*/                        virt-temp-limit-1-cpu-busy = <                         /* target-temp  limit-freq */                                 75      1008000                                 85      1200000                                 95      1200000                                 100     1200000                                 >;                        virt-temp-limit-2-cpu-busy = <                         /* target-temp  limit-freq */                                 75      912000                                 85      1008000                                 95      1104000                                 100     1200000                                 >;                         virt-temp-limit-3-cpu-busy= <                         /* target-temp  limit-freq */                                 75      816000                                 85      912000                                 95      100800                                 100     110400                                 >;                        virt-temp-limit-4-cpu-busy = <                         /* target-temp  limit-freq */                                 75      696000                                 85      816000                                 95      912000                                 100     100800                                 >;                         temp-limit-enable =<1>;                         target-temp =<85>;                 status="okay";         };   rk818 当中配置主控的工作电压,operating-points 在变动cpu工作频率的时候,输出电压,限定工作在  816Mhz(1.2V)  到1008000 (1.5V) 。temp-limit-enable 使能临时变动CPU 工作主频,以表当中的target-temp=85里面的值来做参考   这样最终跳动的频率表如下: virt-temp-limit-1-cpu-busy[85]=1200000 (高于实际设置的operating-points,不会设置进去) virt-temp-limit-2-cpu-busy=1008000 virt-temp-limit-3-cpu-busy=912000 virt-temp-limit-4-cpu-busy=816000   gpu频率和电压如下设置:         &clk_gpu_dvfs_table {                 operating-points = <                         /* KHz    uV */                         200000 950000                         300000 975000                         400000 1075000                         >;                 status="okay";         };             DDR 频率对应的工作表:(查看ddr手册,在533Mhz 时候工作电压为1.5V)         &clk_ddr_dvfs_table {                 operating-points = <                         /* KHz    uV */                         200000 1000000                         300000 1100000                         400000 1200000                        533000 1250000                         >; }   根据跑飞现象相应的都将这个表里面的电压往上提供0.1-0.2v左右 DDR电压在533Mhz 设置RK818输出在1.5V,才能正常工作   从新编译之后,不会出现内存崩溃现象   启动之后,一直打印如下信息   [    7.671300] vdd_logic: unsupportable voltagerange: 1500000-1425000uV [    7.671317] DVFS ERR:        dvfs_regulator_set_voltage_readback:now read back to check voltage [    7.673312] DVFS ERR:        dvfs_regulator_set_voltage_readback:set ERROR AND NOT effected, volt=1300000 [    7.673720] DVFS ERR:        dvfs_scale_volt_direct: vd_logic setvoltage up err ret = -22, Vnew = 1500000(was 1300000)mV [    7.680868] DVFS WARNING:    dvfs_reset_volt:vd(vd_logic) try to reloadvolt = 1300000 [    7.700680] enter dvfs_target: clk(clk_gpu)new_rate = 297000000 Hz, old_rate = 200000000 Hz     设置vdd_am和vdd_logic 电压错误     [    7.218360] dvfs_clk_set_rate:dvfsnode(clk_gpu) set rate(400000000) [    7.218405] DVFS WARNING:    dvfs_reset_volt:vd(vd_logic) try to reloadvolt = 1300000 [    7.218441] regulator_set_voltage rdev-min_uV=1500000 max_uV=1500000 [    7.218462] vdd_logic: unsupportable voltagerange: 1500000-1425000uV [    7.218480] DVFS ERR:        dvfs_regulator_set_voltage_readback:now read back to check voltage [    7.220468] DVFS ERR:        dvfs_regulator_set_voltage_readback:set ERROR AND NOT effected, volt=1300000 (dvfs_regulator_set_voltage_readback 先设置再读取电压,读取出来的电压为1.3V 函数异常退出)       [    7.220875] DVFS ERR:        dvfs_scale_volt_direct: vd_logic setvoltage up err ret = -22, Vnew = 1500000(was 1300000)mV                             根据频率设置电压错误 ,最小电压是 1.5V 最大电压是 1.3V   查询代码调用过程 vim arch/arm/mach-rockchip/dvfs.c当中如下 1645 intof_dvfs_init(void) { 1681                 vd->vd_dvfs_target =dvfs_target; } //根据时钟来调整rk818电压输出  int dvfs_clk_set_rate(struct dvfs_node*clk_dvfs_node, unsigned long rate) {          printk("%s:dvfs node(%s) setrate(%lu) ",   // gpu 400M 出错                 __func__,clk_dvfs_node->name, rate);       ret =clk_dvfs_node->vd->vd_dvfs_target(clk_dvfs_node, rate);   } static intdvfs_target(struct dvfs_node *clk_dvfs_node, unsigned long rate) { //调用dvfs_scale_volt_direct 函数根据频率设置电压 //最后一次加载vdd_logic 错误,需要回复设置       ret =dvfs_reset_volt(clk_dvfs_node->vd);        //获取新的电压(打印出来的值一直是1.5V,获取配置表当中最大电压)       volt_new =dvfs_vd_get_newvolt_byclk(clk_dvfs_node);             //将最大电压设置进去, ret = dvfs_scale_volt_direct(clk_dvfs_node->vd, volt_new);         }    //根据频率设置电压 static intdvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new) { ……………………………………………….         if(!IS_ERR_OR_NULL(vd_clk->regulator)) {                 ret =dvfs_regulator_set_voltage_readback(vd_clk->regulator, volt_new, volt_new); ………………………………………………… } static intdvfs_regulator_set_voltage_readback(struct regulator *regulator, int min_uV,int max_uV) {           ret = dvfs_regulator_set_voltage(regulator,max_uV, max_uV);         if (ret < 0) {                 DVFS_ERR("%s: now readback to check voltage ", __func__);                 mdelay(2);                 read_back =dvfs_regulator_get_voltage(regulator);                 if (read_back == max_uV) {                         DVFS_ERR("%s: setERROR but already effected, volt=%d ", __func__, read_back);                         ret = 0;                 } else {                         DVFS_ERR("%s: setERROR AND NOT effected, volt=%d ", __func__, read_back);                 }         }           return ret; } //根据频率设置电压错误 ,最小电压是 1.5V 最大电压是 1.3V   #definedvfs_regulator_set_voltage regulator_set_voltage 跟踪到drivers/regulator/core.c       int regulator_set_voltage(struct regulator*regulator, int min_uV, int max_uV)       进去 min_uV =1500000 max_uV=1500000       这个函数regulator_set_voltage 这两个值写入到regulator->min_uV ,regulator->max_uV       传人的值不对导致dvfs_regulator_set_voltage_readback 函数里面异常退出   从打印信息来看vdd_logic 和gpu 设置电压错误,根据整个过程,加上调试信息,cpu和gpu频率和电压一直跳动     将DDR的电压表设置如下:         &clk_ddr_dvfs_table {                 operating-points = <                         /* KHz    uV */                         200000 1200000                         300000 1300000                         400000 1400000                         533000 1500000                         >; }  

提高core 主控电压

        &clk_core_dvfs_table {                 operating-points = <                         /* KHz    uV */ /*描述主控工作频率时RK818输出电压*/                        816000 1200000                        1008000 1500000                         /*1000000 1425000*/                         >;   关闭动态调整的频率和电压   重新编译,更新固件,开机基本正常