[RK3399][Android7.1] 除錯筆記 --- DDR工作頻率的獲取和設定
阿新 • • 發佈:2018-12-30
OS: Android 7.1
Board: Firefly-RK3399
Kernel: v4.4.55
之前有提到loader中有設定ddr頻率為800MHz,當kernel中開啟了ddr devfreq之後,驅動載入時會獲取ddr預設頻率。
rockchip_dmc.c:
static int rockchip_dmcfreq_probe(struct platform_device *pdev)
{
//根據name獲取對應的struct clk結構
data->dmc_clk = devm_clk_get(dev, "dmc_clk");
... ...
//獲取clk的當前rate
data->rate = clk_get_rate(data->dmc_clk);
......
}
一開始有個誤區,以為就是PCLK_DDR對應的預設rate,此rate在rk3399-vop-clk-set.dtsi中的cru node中定義,配置為200MHz,而開機列印的log是800MHz。後來找到了對應的clockc, id是SCLK_DDRCLK。
關於SCLK_DDRCLK的定義,在clk-rk3399.c中:
static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
......
COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc" , mux_ddrclk_p, 0,
RK3399_CLKSEL_CON(6), 4, 2, 0, 0, ROCKCHIP_DDRCLK_SIP),
};
它的註冊過程有:
rockchip_clk_register_branches ->
rockchip_clk_register_ddrclk -> //branch_type:branch_ddrc
init.ops = &rockchip_ddrclk_sip_ops; //ddr_flag: ROCKCHIP_DDRCLK_SIP
clk_register //註冊struct clk
其中的ops:
static const struct clk_ops rockchip_ddrclk_sip_ops = {
.recalc_rate = rockchip_ddrclk_sip_recalc_rate,
.set_rate = rockchip_ddrclk_sip_set_rate,
.round_rate = rockchip_ddrclk_sip_round_rate,
.get_parent = rockchip_ddrclk_get_parent,
};
這裡就有recalc_rate函式指標,系統開機後devfreq monitor thread會呼叫此函式來獲取當前ddr實際頻率
static unsigned long
rockchip_ddrclk_sip_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct arm_smccc_res res;
arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0,
ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE,
0, 0, 0, 0, &res);
return res.a0;
}
res.a0的值就是當前實際從暫存器讀出來的ddr rate, 為800MHz.
而ddr頻率的設定是通過set_rate回撥介面來實現
static int rockchip_ddrclk_sip_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
unsigned long flags;
struct arm_smccc_res res;
spin_lock_irqsave(ddrclk->lock, flags);
arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, drate, 0,
ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE,
0, 0, 0, 0, &res);
spin_unlock_irqrestore(ddrclk->lock, flags);
return res.a0;
}