Commit 9427b71a authored by Jonas Gorski's avatar Jonas Gorski Committed by Stephen Boyd
Browse files

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: default avatarJonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent d1c8a501
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -11,6 +11,22 @@
#include <linux/of.h>
#include <linux/slab.h>

static inline u32 clk_mult_readl(struct clk_multiplier *mult)
{
	if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
		return ioread32be(mult->reg);

	return clk_readl(mult->reg);
}

static inline void clk_mult_writel(struct clk_multiplier *mult, u32 val)
{
	if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
		iowrite32be(val, mult->reg);
	else
		clk_writel(val, mult->reg);
}

static unsigned long __get_mult(struct clk_multiplier *mult,
				unsigned long rate,
				unsigned long parent_rate)
@@ -27,7 +43,7 @@ static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
	struct clk_multiplier *mult = to_clk_multiplier(hw);
	unsigned long val;

	val = clk_readl(mult->reg) >> mult->shift;
	val = clk_mult_readl(mult) >> mult->shift;
	val &= GENMASK(mult->width - 1, 0);

	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,
	else
		__acquire(mult->lock);

	val = clk_readl(mult->reg);
	val = clk_mult_readl(mult);
	val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
	val |= factor << mult->shift;
	clk_writel(val, mult->reg);
	clk_mult_writel(mult, val);

	if (mult->lock)
		spin_unlock_irqrestore(mult->lock, flags);
+4 −0
Original line number Diff line number Diff line
@@ -666,6 +666,9 @@ void clk_hw_unregister_fractional_divider(struct clk_hw *hw);
 *	leaving the parent rate unmodified.
 * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be
 *	rounded to the closest integer instead of the down one.
 * CLK_MULTIPLIER_BIG_ENDIAN - By default little endian register accesses are
 *	used for the multiplier register.  Setting this flag makes the register
 *	accesses big endian.
 */
struct clk_multiplier {
	struct clk_hw	hw;
@@ -680,6 +683,7 @@ struct clk_multiplier {

#define CLK_MULTIPLIER_ZERO_BYPASS		BIT(0)
#define CLK_MULTIPLIER_ROUND_CLOSEST	BIT(1)
#define CLK_MULTIPLIER_BIG_ENDIAN		BIT(2)

extern const struct clk_ops clk_multiplier_ops;