首页 » 技术分享 » rk3128 平台rk818电源管理驱动移植

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

 
文章目录

 

一、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)\n",   // 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\n", __func__);

                mdelay(2);

                read_back =dvfs_regulator_get_voltage(regulator);

                if (read_back == max_uV) {

                        DVFS_ERR("%s: setERROR but already effected, volt=%d\n", __func__, read_back);

                        ret = 0;

                } else {

                        DVFS_ERR("%s: setERROR AND NOT effected, volt=%d\n", __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*/

                        >;

 

关闭动态调整的频率和电压

 

重新编译,更新固件,开机基本正常

转载自原文链接, 如需删除请联系管理员。

原文链接:rk3128 平台rk818电源管理驱动移植,转载请注明来源!

0