aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Gorski <jonas.gorski@gmail.com>2019-04-18 07:12:06 -0400
committerStephen Boyd <sboyd@kernel.org>2019-04-23 13:57:48 -0400
commitd1c8a501ec07290da5cc2d8dedb6692cf89078d8 (patch)
treee5a3bf9dd51357e5e87a08ac1b346c6fb8b35d69
parent58a2b4c9bdf98452fec95bb1a5eeed60c01f621a (diff)
clk: gate: add explicit big endian support
Add a clock specific flag to switch register accesses to big endian, to allow runtime configuration of big endian gated clocks. Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/clk-gate.c22
-rw-r--r--include/linux/clk-provider.h4
2 files changed, 23 insertions, 3 deletions
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index f05823cd9b21..6ced7b1f5585 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -23,6 +23,22 @@
23 * parent - fixed parent. No clk_set_parent support 23 * parent - fixed parent. No clk_set_parent support
24 */ 24 */
25 25
26static inline u32 clk_gate_readl(struct clk_gate *gate)
27{
28 if (gate->flags & CLK_GATE_BIG_ENDIAN)
29 return ioread32be(gate->reg);
30
31 return clk_readl(gate->reg);
32}
33
34static inline void clk_gate_writel(struct clk_gate *gate, u32 val)
35{
36 if (gate->flags & CLK_GATE_BIG_ENDIAN)
37 iowrite32be(val, gate->reg);
38 else
39 clk_writel(val, gate->reg);
40}
41
26/* 42/*
27 * It works on following logic: 43 * It works on following logic:
28 * 44 *
@@ -55,7 +71,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
55 if (set) 71 if (set)
56 reg |= BIT(gate->bit_idx); 72 reg |= BIT(gate->bit_idx);
57 } else { 73 } else {
58 reg = clk_readl(gate->reg); 74 reg = clk_gate_readl(gate);
59 75
60 if (set) 76 if (set)
61 reg |= BIT(gate->bit_idx); 77 reg |= BIT(gate->bit_idx);
@@ -63,7 +79,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
63 reg &= ~BIT(gate->bit_idx); 79 reg &= ~BIT(gate->bit_idx);
64 } 80 }
65 81
66 clk_writel(reg, gate->reg); 82 clk_gate_writel(gate, reg);
67 83
68 if (gate->lock) 84 if (gate->lock)
69 spin_unlock_irqrestore(gate->lock, flags); 85 spin_unlock_irqrestore(gate->lock, flags);
@@ -88,7 +104,7 @@ int clk_gate_is_enabled(struct clk_hw *hw)
88 u32 reg; 104 u32 reg;
89 struct clk_gate *gate = to_clk_gate(hw); 105 struct clk_gate *gate = to_clk_gate(hw);
90 106
91 reg = clk_readl(gate->reg); 107 reg = clk_gate_readl(gate);
92 108
93 /* if a set bit disables this clk, flip it before masking */ 109 /* if a set bit disables this clk, flip it before masking */
94 if (gate->flags & CLK_GATE_SET_TO_DISABLE) 110 if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7c6861995505..7d5a32d83655 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -349,6 +349,9 @@ void of_fixed_clk_setup(struct device_node *np);
349 * of this register, and mask of gate bits are in higher 16-bit of this 349 * of this register, and mask of gate bits are in higher 16-bit of this
350 * register. While setting the gate bits, higher 16-bit should also be 350 * register. While setting the gate bits, higher 16-bit should also be
351 * updated to indicate changing gate bits. 351 * updated to indicate changing gate bits.
352 * CLK_GATE_BIG_ENDIAN - by default little endian register accesses are used for
353 * the gate register. Setting this flag makes the register accesses big
354 * endian.
352 */ 355 */
353struct clk_gate { 356struct clk_gate {
354 struct clk_hw hw; 357 struct clk_hw hw;
@@ -362,6 +365,7 @@ struct clk_gate {
362 365
363#define CLK_GATE_SET_TO_DISABLE BIT(0) 366#define CLK_GATE_SET_TO_DISABLE BIT(0)
364#define CLK_GATE_HIWORD_MASK BIT(1) 367#define CLK_GATE_HIWORD_MASK BIT(1)
368#define CLK_GATE_BIG_ENDIAN BIT(2)
365 369
366extern const struct clk_ops clk_gate_ops; 370extern const struct clk_ops clk_gate_ops;
367struct clk *clk_register_gate(struct device *dev, const char *name, 371struct clk *clk_register_gate(struct device *dev, const char *name,