From e039790fb29227f646e91e6d7ec7c3e89c584243 Mon Sep 17 00:00:00 2001 From: Paolo Sabatino Date: Tue, 6 Jul 2021 14:21:52 +0000 Subject: [PATCH 1/5] rk3228/rk3328: fix ddr clock gate, add SIP v2 calls --- drivers/clk/rockchip/clk-ddr.c | 130 ++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk-rk3228.c | 14 ++-- drivers/clk/rockchip/clk-rk3328.c | 7 +- drivers/clk/rockchip/clk.h | 3 +- 4 files changed, 143 insertions(+), 11 deletions(-) diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c index 86718c54e..b16b3795f 100644 --- a/drivers/clk/rockchip/clk-ddr.c +++ b/drivers/clk/rockchip/clk-ddr.c @@ -87,6 +87,133 @@ static const struct clk_ops rockchip_ddrclk_sip_ops = { .get_parent = rockchip_ddrclk_get_parent, }; +/* See v4.4/include/dt-bindings/display/rk_fb.h */ +#define SCREEN_NULL 0 +#define SCREEN_HDMI 6 + +static inline int rk_drm_get_lcdc_type(void) +{ + return SCREEN_NULL; +} + +struct share_params { + u32 hz; + u32 lcdc_type; + u32 vop; + u32 vop_dclk_mode; + u32 sr_idle_en; + u32 addr_mcu_el3; + /* + * 1: need to wait flag1 + * 0: never wait flag1 + */ + u32 wait_flag1; + /* + * 1: need to wait flag1 + * 0: never wait flag1 + */ + u32 wait_flag0; + u32 complt_hwirq; + /* if need, add parameter after */ +}; + +struct rockchip_ddrclk_data { + u32 inited_flag; + void __iomem *share_memory; +}; + +static struct rockchip_ddrclk_data ddr_data; + +static void rockchip_ddrclk_data_init(void) +{ + struct arm_smccc_res res; + + arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM, + 1, SHARE_PAGE_TYPE_DDR, 0, + 0, 0, 0, 0, &res); + + if (!res.a0) { + ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12); + ddr_data.inited_flag = 1; + } +} + +static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw, + unsigned long drate, + unsigned long prate) +{ + struct share_params *p; + struct arm_smccc_res res; + + if (!ddr_data.inited_flag) + rockchip_ddrclk_data_init(); + + p = (struct share_params *)ddr_data.share_memory; + + p->hz = drate; + p->lcdc_type = rk_drm_get_lcdc_type(); + p->wait_flag1 = 1; + p->wait_flag0 = 1; + + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, + SHARE_PAGE_TYPE_DDR, 0, + ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE, + 0, 0, 0, 0, &res); + + if ((int)res.a1 == -6) { + pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000); + /* TODO: rockchip_dmcfreq_wait_complete(); */ + } + + return res.a0; +} + +static unsigned long rockchip_ddrclk_sip_recalc_rate_v2 + (struct clk_hw *hw, unsigned long parent_rate) +{ + struct arm_smccc_res res; + + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, + SHARE_PAGE_TYPE_DDR, 0, + ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE, + 0, 0, 0, 0, &res); + if (!res.a0) + return res.a1; + else + return 0; +} + +static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + struct share_params *p; + struct arm_smccc_res res; + + if (!ddr_data.inited_flag) + rockchip_ddrclk_data_init(); + + p = (struct share_params *)ddr_data.share_memory; + + p->hz = rate; + + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, + SHARE_PAGE_TYPE_DDR, 0, + ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE, + 0, 0, 0, 0, &res); + if (!res.a0) + return res.a1; + else + return 0; +} + +static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = { + .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2, + .set_rate = rockchip_ddrclk_sip_set_rate_v2, + .round_rate = rockchip_ddrclk_sip_round_rate_v2, + .get_parent = rockchip_ddrclk_get_parent, +}; + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, const char *const *parent_names, u8 num_parents, int mux_offset, @@ -114,6 +241,9 @@ struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, case ROCKCHIP_DDRCLK_SIP: init.ops = &rockchip_ddrclk_sip_ops; break; + case ROCKCHIP_DDRCLK_SIP_V2: + init.ops = &rockchip_ddrclk_sip_ops_v2; + break; default: pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag); kfree(ddrclk); diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 1f9176a5c..96393aa16 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -218,9 +218,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(4), 8, 5, DFLAGS), /* PD_DDR */ - COMPOSITE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, - RK2928_CLKGATE_CON(0), 2, GFLAGS), + COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, + RK2928_CLKSEL_CON(26), 8, 2, 0, 2, + ROCKCHIP_DDRCLK_SIP_V2), GATE(0, "ddrphy4x", "clk_ddrphy_src", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 1, GFLAGS), FACTOR_GATE(0, "ddrc", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, @@ -576,8 +576,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), - GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), - GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), + GATE(0, "pclk_ddr_upctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), + GATE(0, "pclk_ddr_mon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS), GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), @@ -652,8 +652,8 @@ static const char *const rk3228_critical_clocks[] __initconst = { "sclk_initmem_mbist", "aclk_initmem", "hclk_rom", - "pclk_ddrupctl", - "pclk_ddrmon", + "pclk_ddr_upctl", + "pclk_ddr_mon", "pclk_msch_noc", "pclk_stimer", "pclk_ddrphy", diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c index cc18dbc18..5fdd611bb 100644 --- a/drivers/clk/rockchip/clk-rk3328.c +++ b/drivers/clk/rockchip/clk-rk3328.c @@ -317,9 +317,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { RK3328_CLKGATE_CON(14), 1, GFLAGS), /* PD_DDR */ - COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED, - RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, - RK3328_CLKGATE_CON(0), 4, GFLAGS), + COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, + RK3328_CLKSEL_CON(3), 8, 2, 0, 3, + ROCKCHIP_DDRCLK_SIP_V2), + GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(18), 6, GFLAGS), GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index ae059b774..fdaa81ebb 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -363,7 +363,8 @@ struct clk *rockchip_clk_register_mmc(const char *name, * DDRCLK flags, including method of setting the rate * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. */ -#define ROCKCHIP_DDRCLK_SIP BIT(0) +#define ROCKCHIP_DDRCLK_SIP 0x01 +#define ROCKCHIP_DDRCLK_SIP_V2 0x03 struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, const char *const *parent_names, -- 2.25.1