aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Gorski <jonas.gorski@gmail.com>2019-04-18 07:12:08 -0400
committerStephen Boyd <sboyd@kernel.org>2019-04-23 13:57:48 -0400
commit3a727519651228d92793291516727d62c6887607 (patch)
treea42041be2089ae8724b54e771950069c67447e35
parent9427b71a850581112538c0b92f444d19a7aae28b (diff)
clk: mux: add explicit big endian support
Add a clock specific flag to switch register accesses to big endian, to allow runtime configuration of big endian mux clocks. Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/clk-mux.c22
-rw-r--r--include/linux/clk-provider.h4
2 files changed, 23 insertions, 3 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 2ad2df2e8909..61ad331b7ff4 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -23,6 +23,22 @@
23 * parent - parent is adjustable through clk_set_parent 23 * parent - parent is adjustable through clk_set_parent
24 */ 24 */
25 25
26static inline u32 clk_mux_readl(struct clk_mux *mux)
27{
28 if (mux->flags & CLK_MUX_BIG_ENDIAN)
29 return ioread32be(mux->reg);
30
31 return clk_readl(mux->reg);
32}
33
34static inline void clk_mux_writel(struct clk_mux *mux, u32 val)
35{
36 if (mux->flags & CLK_MUX_BIG_ENDIAN)
37 iowrite32be(val, mux->reg);
38 else
39 clk_writel(val, mux->reg);
40}
41
26int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, 42int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
27 unsigned int val) 43 unsigned int val)
28{ 44{
@@ -73,7 +89,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
73 struct clk_mux *mux = to_clk_mux(hw); 89 struct clk_mux *mux = to_clk_mux(hw);
74 u32 val; 90 u32 val;
75 91
76 val = clk_readl(mux->reg) >> mux->shift; 92 val = clk_mux_readl(mux) >> mux->shift;
77 val &= mux->mask; 93 val &= mux->mask;
78 94
79 return clk_mux_val_to_index(hw, mux->table, mux->flags, val); 95 return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
@@ -94,12 +110,12 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
94 if (mux->flags & CLK_MUX_HIWORD_MASK) { 110 if (mux->flags & CLK_MUX_HIWORD_MASK) {
95 reg = mux->mask << (mux->shift + 16); 111 reg = mux->mask << (mux->shift + 16);
96 } else { 112 } else {
97 reg = clk_readl(mux->reg); 113 reg = clk_mux_readl(mux);
98 reg &= ~(mux->mask << mux->shift); 114 reg &= ~(mux->mask << mux->shift);
99 } 115 }
100 val = val << mux->shift; 116 val = val << mux->shift;
101 reg |= val; 117 reg |= val;
102 clk_writel(reg, mux->reg); 118 clk_mux_writel(mux, reg);
103 119
104 if (mux->lock) 120 if (mux->lock)
105 spin_unlock_irqrestore(mux->lock, flags); 121 spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 0bc6d6f80b1a..4ae2257b63c6 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -509,6 +509,9 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
509 * indicate changing mux bits. 509 * indicate changing mux bits.
510 * CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired 510 * CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired
511 * frequency. 511 * frequency.
512 * CLK_MUX_BIG_ENDIAN - By default little endian register accesses are used for
513 * the mux register. Setting this flag makes the register accesses big
514 * endian.
512 */ 515 */
513struct clk_mux { 516struct clk_mux {
514 struct clk_hw hw; 517 struct clk_hw hw;
@@ -527,6 +530,7 @@ struct clk_mux {
527#define CLK_MUX_HIWORD_MASK BIT(2) 530#define CLK_MUX_HIWORD_MASK BIT(2)
528#define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */ 531#define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */
529#define CLK_MUX_ROUND_CLOSEST BIT(4) 532#define CLK_MUX_ROUND_CLOSEST BIT(4)
533#define CLK_MUX_BIG_ENDIAN BIT(5)
530 534
531extern const struct clk_ops clk_mux_ops; 535extern const struct clk_ops clk_mux_ops;
532extern const struct clk_ops clk_mux_ro_ops; 536extern const struct clk_ops clk_mux_ro_ops;