Previously, only direct register read/write was supported. Now a per-clock regmap can be provided for same purpose, which allows the clock drivers to access clock registers behind e.g. I2C bus. Signed-off-by: Tero Kristo <t-kristo@xxxxxx> --- drivers/clk/clk-divider.c | 6 +++--- drivers/clk/clk-gate.c | 6 +++--- drivers/clk/clk-mux.c | 6 +++--- include/linux/clk-provider.h | 23 +++++++++++++++++++---- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 8d3009e..9c17b1a 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, struct clk_divider *divider = to_clk_divider(hw); unsigned int div, val; - val = clk_readl(divider->reg) >> divider->shift; + val = clk_readl(divider->reg, divider->regmap) >> divider->shift; val &= div_mask(divider); div = _get_div(divider, val); @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { val = div_mask(divider) << (divider->shift + 16); } else { - val = clk_readl(divider->reg); + val = clk_readl(divider->reg, divider->regmap); val &= ~(div_mask(divider) << divider->shift); } val |= value << divider->shift; - clk_writel(val, divider->reg); + clk_writel(val, divider->reg, divider->regmap); if (divider->lock) spin_unlock_irqrestore(divider->lock, flags); diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 4a58c55..3c7f686 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -58,7 +58,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_readl(gate->reg, gate->regmap); if (set) reg |= BIT(gate->bit_idx); @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable) reg &= ~BIT(gate->bit_idx); } - clk_writel(reg, gate->reg); + clk_writel(reg, gate->reg, gate->regmap); if (gate->lock) spin_unlock_irqrestore(gate->lock, flags); @@ -89,7 +89,7 @@ static 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_readl(gate->reg, gate->regmap); /* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 4f96ff3..68eb8c2 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so * val = 0x4 really means "bit 2, index starts at bit 0" */ - val = clk_readl(mux->reg) >> mux->shift; + val = clk_readl(mux->reg, mux->regmap) >> mux->shift; val &= mux->mask; if (mux->table) { @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) if (mux->flags & CLK_MUX_HIWORD_MASK) { val = mux->mask << (mux->shift + 16); } else { - val = clk_readl(mux->reg); + val = clk_readl(mux->reg, mux->regmap); val &= ~(mux->mask << mux->shift); } val |= index << mux->shift; - clk_writel(val, mux->reg); + clk_writel(val, mux->reg, mux->regmap); if (mux->lock) spin_unlock_irqrestore(mux->lock, flags); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 7e59253..63ff78c 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -13,6 +13,7 @@ #include <linux/clk.h> #include <linux/io.h> +#include <linux/regmap.h> #ifdef CONFIG_COMMON_CLK @@ -209,6 +210,7 @@ void of_fixed_clk_setup(struct device_node *np); * * @hw: handle between common and hardware-specific interfaces * @reg: register controlling gate + * @regmap: regmap for accessing the gate register (if any) * @bit_idx: single bit controlling gate * @flags: hardware-specific flags * @lock: register lock @@ -227,6 +229,7 @@ void of_fixed_clk_setup(struct device_node *np); struct clk_gate { struct clk_hw hw; void __iomem *reg; + struct regmap *regmap; u8 bit_idx; u8 flags; spinlock_t *lock; @@ -251,6 +254,7 @@ struct clk_div_table { * * @hw: handle between common and hardware-specific interfaces * @reg: register containing the divider + * @regmap: regmap for accessing the divider register (if any) * @shift: shift to the divider bit field * @width: width of the divider bit field * @table: array of value/divider pairs, last entry should have div = 0 @@ -279,6 +283,7 @@ struct clk_div_table { struct clk_divider { struct clk_hw hw; void __iomem *reg; + struct regmap *regmap; u8 shift; u8 width; u8 flags; @@ -326,6 +331,7 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, struct clk_mux { struct clk_hw hw; void __iomem *reg; + struct regmap *regmap; u32 *table; u32 mask; u8 shift; @@ -512,14 +518,23 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, * for improved portability across platforms */ -static inline u32 clk_readl(u32 __iomem *reg) +static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap) { - return readl(reg); + u32 val; + + if (regmap) + regmap_read(regmap, (u32)reg, &val); + else + val = readl(reg); + return val; } -static inline void clk_writel(u32 val, u32 __iomem *reg) +static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap) { - writel(val, reg); + if (regmap) + regmap_write(regmap, (u32)reg, val); + else + writel(val, reg); } #endif /* CONFIG_COMMON_CLK */ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html