From 968ccb6e8330739448c9fb40a6ed08013b17cbc7 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Sat, 25 Mar 2017 20:02:35 +0800 Subject: [PATCH 1/1] clk: rockchip: support setting ddr clock via SCPI APIs On rk3368, let a mcu scaling ddr clock via SCPI (System Control and Power Interface) APIs. Change-Id: I95342b876caad991e6d1319c5e4ec793365c7981 Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-ddr.c | 40 ++++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c index 224e07e2c46b..c247c9aaf5f5 100644 --- a/drivers/clk/rockchip/clk-ddr.c +++ b/drivers/clk/rockchip/clk-ddr.c @@ -20,9 +20,12 @@ #include #include #include +#include #include "clk.h" +#define MHZ (1000000) + struct rockchip_ddrclk { struct clk_hw hw; void __iomem *reg_base; @@ -102,6 +105,40 @@ static const struct clk_ops rockchip_ddrclk_sip_ops = { .get_parent = rockchip_ddrclk_get_parent, }; +static int rockchip_ddrclk_scpi_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + u32 ret; + u32 lcdc_type = 7; + + ret = scpi_ddr_set_clk_rate(drate / MHZ, lcdc_type); + + return ret; +} + +static unsigned long rockchip_ddrclk_scpi_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return (MHZ * scpi_ddr_get_clk_rate()); +} + +static long rockchip_ddrclk_scpi_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + rate = rate / MHZ; + rate = (rate / 12) * 12; + + return (rate * MHZ); +} + +static const struct clk_ops rockchip_ddrclk_scpi_ops = { + .recalc_rate = rockchip_ddrclk_scpi_recalc_rate, + .set_rate = rockchip_ddrclk_scpi_set_rate, + .round_rate = rockchip_ddrclk_scpi_round_rate, + .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, @@ -130,6 +167,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_SCPI: + init.ops = &rockchip_ddrclk_scpi_ops; + break; default: pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag); kfree(ddrclk); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 17161a09dd47..c1e49b2767ec 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -309,8 +309,10 @@ struct clk *rockchip_clk_register_mmc(const char *name, * there may have serval ways to set ddr clock, use * this flag to distinguish them. * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. + * ROCKCHIP_DDRCLK_SCPI: use SCPI APIs to let mcu change ddrclk rate. */ #define ROCKCHIP_DDRCLK_SIP 0x01 +#define ROCKCHIP_DDRCLK_SCPI 0x02 struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, const char *const *parent_names, -- 2.34.1