clk: rockchip: support setting ddr clock via SCPI APIs
authorFinley Xiao <finley.xiao@rock-chips.com>
Sat, 25 Mar 2017 12:02:35 +0000 (20:02 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 6 Apr 2017 06:53:01 +0000 (14:53 +0800)
On rk3368, let a mcu scaling ddr clock via SCPI (System Control and
Power Interface) APIs.

Change-Id: I95342b876caad991e6d1319c5e4ec793365c7981
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
drivers/clk/rockchip/clk-ddr.c
drivers/clk/rockchip/clk.h

index 224e07e2c46b2a586c3b48b70679d9a697b88b31..c247c9aaf5f586290cb26bbf9ac7f540fcfec724 100644 (file)
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <soc/rockchip/rockchip_sip.h>
+#include <soc/rockchip/scpi.h>
 
 #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);
index 17161a09dd47b5b1dc8f71b115018f6700ebd416..c1e49b2767ec46d1343e184e4c49699442ae4b6b 100644 (file)
@@ -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,