diff options
| author | Jonas Gorski <jonas.gorski@gmail.com> | 2019-04-18 07:12:07 -0400 |
|---|---|---|
| committer | Stephen Boyd <sboyd@kernel.org> | 2019-04-23 13:57:48 -0400 |
| commit | 9427b71a850581112538c0b92f444d19a7aae28b (patch) | |
| tree | c8d84b3dbb3c48593f86128459225ce67ba9cf6d | |
| parent | d1c8a501ec07290da5cc2d8dedb6692cf89078d8 (diff) | |
clk: multiplier: add explicit big endian support
Add a clock specific flag to switch register accesses to big endian, to
allow runtime configuration of big endian multiplier clocks.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
| -rw-r--r-- | drivers/clk/clk-multiplier.c | 22 | ||||
| -rw-r--r-- | include/linux/clk-provider.h | 4 |
2 files changed, 23 insertions, 3 deletions
diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c index 3c86f859c199..77327df9bf32 100644 --- a/drivers/clk/clk-multiplier.c +++ b/drivers/clk/clk-multiplier.c | |||
| @@ -11,6 +11,22 @@ | |||
| 11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | 13 | ||
| 14 | static inline u32 clk_mult_readl(struct clk_multiplier *mult) | ||
| 15 | { | ||
| 16 | if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN) | ||
| 17 | return ioread32be(mult->reg); | ||
| 18 | |||
| 19 | return clk_readl(mult->reg); | ||
| 20 | } | ||
| 21 | |||
| 22 | static inline void clk_mult_writel(struct clk_multiplier *mult, u32 val) | ||
| 23 | { | ||
| 24 | if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN) | ||
| 25 | iowrite32be(val, mult->reg); | ||
| 26 | else | ||
| 27 | clk_writel(val, mult->reg); | ||
| 28 | } | ||
| 29 | |||
| 14 | static unsigned long __get_mult(struct clk_multiplier *mult, | 30 | static unsigned long __get_mult(struct clk_multiplier *mult, |
| 15 | unsigned long rate, | 31 | unsigned long rate, |
| 16 | unsigned long parent_rate) | 32 | unsigned long parent_rate) |
| @@ -27,7 +43,7 @@ static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw, | |||
| 27 | struct clk_multiplier *mult = to_clk_multiplier(hw); | 43 | struct clk_multiplier *mult = to_clk_multiplier(hw); |
| 28 | unsigned long val; | 44 | unsigned long val; |
| 29 | 45 | ||
| 30 | val = clk_readl(mult->reg) >> mult->shift; | 46 | val = clk_mult_readl(mult) >> mult->shift; |
| 31 | val &= GENMASK(mult->width - 1, 0); | 47 | val &= GENMASK(mult->width - 1, 0); |
| 32 | 48 | ||
| 33 | if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS) | 49 | if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS) |
| @@ -118,10 +134,10 @@ static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 118 | else | 134 | else |
| 119 | __acquire(mult->lock); | 135 | __acquire(mult->lock); |
| 120 | 136 | ||
| 121 | val = clk_readl(mult->reg); | 137 | val = clk_mult_readl(mult); |
| 122 | val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift); | 138 | val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift); |
| 123 | val |= factor << mult->shift; | 139 | val |= factor << mult->shift; |
| 124 | clk_writel(val, mult->reg); | 140 | clk_mult_writel(mult, val); |
| 125 | 141 | ||
| 126 | if (mult->lock) | 142 | if (mult->lock) |
| 127 | spin_unlock_irqrestore(mult->lock, flags); | 143 | spin_unlock_irqrestore(mult->lock, flags); |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 7d5a32d83655..0bc6d6f80b1a 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
| @@ -666,6 +666,9 @@ void clk_hw_unregister_fractional_divider(struct clk_hw *hw); | |||
| 666 | * leaving the parent rate unmodified. | 666 | * leaving the parent rate unmodified. |
| 667 | * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be | 667 | * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be |
| 668 | * rounded to the closest integer instead of the down one. | 668 | * rounded to the closest integer instead of the down one. |
| 669 | * CLK_MULTIPLIER_BIG_ENDIAN - By default little endian register accesses are | ||
| 670 | * used for the multiplier register. Setting this flag makes the register | ||
| 671 | * accesses big endian. | ||
| 669 | */ | 672 | */ |
| 670 | struct clk_multiplier { | 673 | struct clk_multiplier { |
| 671 | struct clk_hw hw; | 674 | struct clk_hw hw; |
| @@ -680,6 +683,7 @@ struct clk_multiplier { | |||
| 680 | 683 | ||
| 681 | #define CLK_MULTIPLIER_ZERO_BYPASS BIT(0) | 684 | #define CLK_MULTIPLIER_ZERO_BYPASS BIT(0) |
| 682 | #define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1) | 685 | #define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1) |
| 686 | #define CLK_MULTIPLIER_BIG_ENDIAN BIT(2) | ||
| 683 | 687 | ||
| 684 | extern const struct clk_ops clk_multiplier_ops; | 688 | extern const struct clk_ops clk_multiplier_ops; |
| 685 | 689 | ||
