235 lines
7.2 KiB
Diff
235 lines
7.2 KiB
Diff
|
From e039790fb29227f646e91e6d7ec7c3e89c584243 Mon Sep 17 00:00:00 2001
|
||
|
From: Paolo Sabatino <paolo.sabatino@gmail.com>
|
||
|
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
|
||
|
|