clk: gate: add explicit big endian support
authorJonas Gorski <jonas.gorski@gmail.com>
Thu, 18 Apr 2019 11:12:06 +0000 (13:12 +0200)
committerStephen Boyd <sboyd@kernel.org>
Tue, 23 Apr 2019 17:57:48 +0000 (10:57 -0700)
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>
drivers/clk/clk-gate.c
include/linux/clk-provider.h

index f05823c..6ced7b1 100644 (file)
  * parent - fixed parent.  No clk_set_parent support
  */
 
+static inline u32 clk_gate_readl(struct clk_gate *gate)
+{
+       if (gate->flags & CLK_GATE_BIG_ENDIAN)
+               return ioread32be(gate->reg);
+
+       return clk_readl(gate->reg);
+}
+
+static inline void clk_gate_writel(struct clk_gate *gate, u32 val)
+{
+       if (gate->flags & CLK_GATE_BIG_ENDIAN)
+               iowrite32be(val, gate->reg);
+       else
+               clk_writel(val, gate->reg);
+}
+
 /*
  * It works on following logic:
  *
@@ -55,7 +71,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
                if (set)
                        reg |= BIT(gate->bit_idx);
        } else {
-               reg = clk_readl(gate->reg);
+               reg = clk_gate_readl(gate);
 
                if (set)
                        reg |= BIT(gate->bit_idx);
@@ -63,7 +79,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
                        reg &= ~BIT(gate->bit_idx);
        }
 
-       clk_writel(reg, gate->reg);
+       clk_gate_writel(gate, reg);
 
        if (gate->lock)
                spin_unlock_irqrestore(gate->lock, flags);
@@ -88,7 +104,7 @@ int clk_gate_is_enabled(struct clk_hw *hw)
        u32 reg;
        struct clk_gate *gate = to_clk_gate(hw);
 
-       reg = clk_readl(gate->reg);
+       reg = clk_gate_readl(gate);
 
        /* if a set bit disables this clk, flip it before masking */
        if (gate->flags & CLK_GATE_SET_TO_DISABLE)
index 7c68619..7d5a32d 100644 (file)
@@ -349,6 +349,9 @@ void of_fixed_clk_setup(struct device_node *np);
  *     of this register, and mask of gate bits are in higher 16-bit of this
  *     register.  While setting the gate bits, higher 16-bit should also be
  *     updated to indicate changing gate bits.
+ * CLK_GATE_BIG_ENDIAN - by default little endian register accesses are used for
+ *     the gate register.  Setting this flag makes the register accesses big
+ *     endian.
  */
 struct clk_gate {
        struct clk_hw hw;
@@ -362,6 +365,7 @@ struct clk_gate {
 
 #define CLK_GATE_SET_TO_DISABLE                BIT(0)
 #define CLK_GATE_HIWORD_MASK           BIT(1)
+#define CLK_GATE_BIG_ENDIAN            BIT(2)
 
 extern const struct clk_ops clk_gate_ops;
 struct clk *clk_register_gate(struct device *dev, const char *name,