clk: sprd: add gate for pll clocks
authorXiaolong Zhang <xiaolong.zhang@unisoc.com>
Wed, 4 Mar 2020 07:27:24 +0000 (15:27 +0800)
committerStephen Boyd <sboyd@kernel.org>
Wed, 25 Mar 2020 02:03:56 +0000 (19:03 -0700)
Some sprd's gate clocks are used to the switch of pll, which
need to wait a certain time for stable after being enabled.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@unisoc.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@unisoc.com>
Link: https://lkml.kernel.org/r/20200304072730.9193-2-zhang.lyra@gmail.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/sprd/gate.c
drivers/clk/sprd/gate.h

index f59d1936b4120017e614ed48e28f0d567d0cf59d..574cfc116bbcd82f7403d7b00f371e37d611b2bf 100644 (file)
@@ -79,6 +79,17 @@ static int sprd_sc_gate_enable(struct clk_hw *hw)
 
        return 0;
 }
+
+static int sprd_pll_sc_gate_prepare(struct clk_hw *hw)
+{
+       struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+       clk_sc_gate_toggle(sg, true);
+       udelay(sg->udelay);
+
+       return 0;
+}
+
 static int sprd_gate_is_enabled(struct clk_hw *hw)
 {
        struct sprd_gate *sg = hw_to_sprd_gate(hw);
@@ -109,3 +120,9 @@ const struct clk_ops sprd_sc_gate_ops = {
 };
 EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);
 
+const struct clk_ops sprd_pll_sc_gate_ops = {
+       .unprepare      = sprd_sc_gate_disable,
+       .prepare        = sprd_pll_sc_gate_prepare,
+       .is_enabled     = sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_pll_sc_gate_ops);
index dc352ea55e1fa464b52e76d93f862b0b821550de..d380d77b8dce65e9c5593442fe5f9095d22fdc51 100644 (file)
@@ -14,16 +14,19 @@ struct sprd_gate {
        u32                     enable_mask;
        u16                     flags;
        u16                     sc_offset;
+       u16                     udelay;
 
        struct sprd_clk_common  common;
 };
 
-#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset,        \
-                            _enable_mask, _flags, _gate_flags, _ops)   \
+#define SPRD_SC_GATE_CLK_OPS_UDELAY(_struct, _name, _parent, _reg,     \
+                                   _sc_offset, _enable_mask, _flags,   \
+                                   _gate_flags, _udelay, _ops)         \
        struct sprd_gate _struct = {                                    \
                .enable_mask    = _enable_mask,                         \
                .sc_offset      = _sc_offset,                           \
                .flags          = _gate_flags,                          \
+               .udelay         = _udelay,                              \
                .common = {                                             \
                        .regmap         = NULL,                         \
                        .reg            = _reg,                         \
@@ -34,6 +37,12 @@ struct sprd_gate {
                }                                                       \
        }
 
+#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset,        \
+                            _enable_mask, _flags, _gate_flags, _ops)   \
+       SPRD_SC_GATE_CLK_OPS_UDELAY(_struct, _name, _parent, _reg,      \
+                                   _sc_offset, _enable_mask, _flags,   \
+                                   _gate_flags, 0, _ops)
+
 #define SPRD_GATE_CLK(_struct, _name, _parent, _reg,                   \
                      _enable_mask, _flags, _gate_flags)                \
        SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, 0,          \
@@ -46,6 +55,13 @@ struct sprd_gate {
                             _enable_mask, _flags, _gate_flags,         \
                             &sprd_sc_gate_ops)
 
+#define SPRD_PLL_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset,        \
+                           _enable_mask, _flags, _gate_flags, _udelay) \
+       SPRD_SC_GATE_CLK_OPS_UDELAY(_struct, _name, _parent, _reg,      \
+                                   _sc_offset, _enable_mask, _flags,   \
+                                   _gate_flags, _udelay,               \
+                                   &sprd_pll_sc_gate_ops)
+
 static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
 {
        struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
@@ -55,5 +71,6 @@ static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
 
 extern const struct clk_ops sprd_gate_ops;
 extern const struct clk_ops sprd_sc_gate_ops;
+extern const struct clk_ops sprd_pll_sc_gate_ops;
 
 #endif /* _SPRD_GATE_H_ */