1. 程式人生 > >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: [email protected] {

                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*/

                        >;

關閉動態調整的頻率和電壓

重新編譯,更新韌體,開機基本正常