[PATCH v2 03/11] clk: berlin: use regmap
Antoine Tenart
antoine.tenart at free-electrons.com
Fri Mar 6 07:12:56 PST 2015
The Berlin clock driver was sharing a DT node with the pin controller
and the reset driver. All these device are now a sub-node of the chip
and system controllers and a regmap is available thanks to syscon to
access the registers safely.
Rework the Berlin clock driver to use the regmap provided by syscon.
Signed-off-by: Antoine Tenart <antoine.tenart at free-electrons.com>
---
drivers/clk/berlin/berlin2-avpll.c | 72 +++++++++++++-----------
drivers/clk/berlin/berlin2-avpll.h | 13 +++--
drivers/clk/berlin/berlin2-div.c | 82 +++++++++------------------
drivers/clk/berlin/berlin2-div.h | 4 +-
drivers/clk/berlin/berlin2-pll.c | 16 ++++--
drivers/clk/berlin/berlin2-pll.h | 7 ++-
drivers/clk/berlin/bg2.c | 112 +++++++++++++++++++------------------
drivers/clk/berlin/bg2q.c | 64 +++++++++++++--------
8 files changed, 188 insertions(+), 182 deletions(-)
diff --git a/drivers/clk/berlin/berlin2-avpll.c b/drivers/clk/berlin/berlin2-avpll.c
index fd0f26c38465..7244afb2251f 100644
--- a/drivers/clk/berlin/berlin2-avpll.c
+++ b/drivers/clk/berlin/berlin2-avpll.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include "berlin2-avpll.h"
@@ -115,7 +116,8 @@
struct berlin2_avpll_vco {
struct clk_hw hw;
- void __iomem *base;
+ struct regmap *regmap;
+ unsigned int offset;
u8 flags;
};
@@ -126,7 +128,7 @@ static int berlin2_avpll_vco_is_enabled(struct clk_hw *hw)
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg;
- reg = readl_relaxed(vco->base + VCO_CTRL0);
+ regmap_read(vco->regmap, vco->offset + VCO_CTRL0, ®);
if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
reg >>= 4;
@@ -138,12 +140,12 @@ static int berlin2_avpll_vco_enable(struct clk_hw *hw)
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg;
- reg = readl_relaxed(vco->base + VCO_CTRL0);
+ regmap_read(vco->regmap, vco->offset + VCO_CTRL0, ®);
if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
reg |= VCO_POWERUP << 4;
else
reg |= VCO_POWERUP;
- writel_relaxed(reg, vco->base + VCO_CTRL0);
+ regmap_write(vco->regmap, vco->offset + VCO_CTRL0, reg);
return 0;
}
@@ -153,12 +155,12 @@ static void berlin2_avpll_vco_disable(struct clk_hw *hw)
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg;
- reg = readl_relaxed(vco->base + VCO_CTRL0);
+ regmap_read(vco->regmap, vco->offset + VCO_CTRL0, ®);
if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
reg &= ~(VCO_POWERUP << 4);
else
reg &= ~VCO_POWERUP;
- writel_relaxed(reg, vco->base + VCO_CTRL0);
+ regmap_write(vco->regmap, vco->offset + VCO_CTRL0, reg);
}
static u8 vco_refdiv[] = { 1, 2, 4, 3 };
@@ -171,7 +173,7 @@ berlin2_avpll_vco_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
u64 freq = parent_rate;
/* AVPLL VCO frequency: Fvco = (Fref / refdiv) * fbdiv */
- reg = readl_relaxed(vco->base + VCO_CTRL1);
+ regmap_read(vco->regmap, vco->offset + VCO_CTRL1, ®);
refdiv = (reg & VCO_REFDIV_MASK) >> VCO_REFDIV_SHIFT;
refdiv = vco_refdiv[refdiv];
fbdiv = (reg & VCO_FBDIV_MASK) >> VCO_FBDIV_SHIFT;
@@ -188,9 +190,10 @@ static const struct clk_ops berlin2_avpll_vco_ops = {
.recalc_rate = berlin2_avpll_vco_recalc_rate,
};
-struct clk * __init berlin2_avpll_vco_register(void __iomem *base,
- const char *name, const char *parent_name,
- u8 vco_flags, unsigned long flags)
+struct clk * __init berlin2_avpll_vco_register(struct regmap *regmap,
+ unsigned int offset, const char *name,
+ const char *parent_name, u8 vco_flags,
+ unsigned long flags)
{
struct berlin2_avpll_vco *vco;
struct clk_init_data init;
@@ -199,7 +202,8 @@ struct clk * __init berlin2_avpll_vco_register(void __iomem *base,
if (!vco)
return ERR_PTR(-ENOMEM);
- vco->base = base;
+ vco->regmap = regmap;
+ vco->offset = offset;
vco->flags = vco_flags;
vco->hw.init = &init;
init.name = name;
@@ -213,7 +217,8 @@ struct clk * __init berlin2_avpll_vco_register(void __iomem *base,
struct berlin2_avpll_channel {
struct clk_hw hw;
- void __iomem *base;
+ struct regmap *regmap;
+ unsigned int offset;
u8 flags;
u8 index;
};
@@ -228,7 +233,7 @@ static int berlin2_avpll_channel_is_enabled(struct clk_hw *hw)
if (ch->index == 7)
return 1;
- reg = readl_relaxed(ch->base + VCO_CTRL10);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL10, ®);
reg &= VCO_POWERUP_CH1 << ch->index;
return !!reg;
@@ -239,9 +244,9 @@ static int berlin2_avpll_channel_enable(struct clk_hw *hw)
struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
u32 reg;
- reg = readl_relaxed(ch->base + VCO_CTRL10);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL10, ®);
reg |= VCO_POWERUP_CH1 << ch->index;
- writel_relaxed(reg, ch->base + VCO_CTRL10);
+ regmap_write(ch->regmap, ch->offset + VCO_CTRL10, reg);
return 0;
}
@@ -251,9 +256,9 @@ static void berlin2_avpll_channel_disable(struct clk_hw *hw)
struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
u32 reg;
- reg = readl_relaxed(ch->base + VCO_CTRL10);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL10, ®);
reg &= ~(VCO_POWERUP_CH1 << ch->index);
- writel_relaxed(reg, ch->base + VCO_CTRL10);
+ regmap_write(ch->regmap, ch->offset + VCO_CTRL10, reg);
}
static const u8 div_hdmi[] = { 1, 2, 4, 6 };
@@ -266,7 +271,7 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
u32 reg, div_av2, div_av3, divider = 1;
u64 freq = parent_rate;
- reg = readl_relaxed(ch->base + VCO_CTRL30);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL30, ®);
if ((reg & (VCO_DPLL_CH1_ENABLE << ch->index)) == 0)
goto skip_div;
@@ -275,13 +280,13 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
* (sync1 * div_hdmi * div_av1 * div_av2 * div_av3)
*/
- reg = readl_relaxed(ch->base + VCO_SYNC1n(ch->index));
+ regmap_read(ch->regmap, ch->offset + VCO_SYNC1n(ch->index), ®);
/* BG2/BG2CDs SYNC1 reg on AVPLL_B channel 1 is shifted by 4 */
if (ch->flags & BERLIN2_AVPLL_BIT_QUIRK && ch->index == 0)
reg >>= 4;
divider = reg & VCO_SYNC1_MASK;
- reg = readl_relaxed(ch->base + VCO_SYNC2n(ch->index));
+ regmap_read(ch->regmap, ch->offset + VCO_SYNC2n(ch->index), ®);
freq *= reg & VCO_SYNC2_MASK;
/* Channel 8 has no dividers */
@@ -292,7 +297,8 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
* HDMI divider start at VCO_CTRL11, bit 7; MSB is enable, lower 2 bit
* determine divider.
*/
- reg = readl_relaxed(ch->base + VCO_CTRL11) >> 7;
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL11, ®);
+ reg >>= 7;
reg = (reg >> (ch->index * 3));
if (reg & BIT(2))
divider *= div_hdmi[reg & 0x3];
@@ -302,10 +308,10 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
* determine divider.
*/
if (ch->index == 0) {
- reg = readl_relaxed(ch->base + VCO_CTRL11);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL11, ®);
reg >>= 28;
} else {
- reg = readl_relaxed(ch->base + VCO_CTRL12);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL12, ®);
reg >>= (ch->index-1) * 3;
}
if (reg & BIT(2))
@@ -316,13 +322,13 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
* zero is not a valid value.
*/
if (ch->index < 2) {
- reg = readl_relaxed(ch->base + VCO_CTRL12);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL12, ®);
reg >>= 18 + (ch->index * 7);
} else if (ch->index < 7) {
- reg = readl_relaxed(ch->base + VCO_CTRL13);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL13, ®);
reg >>= (ch->index - 2) * 7;
} else {
- reg = readl_relaxed(ch->base + VCO_CTRL14);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL14, ®);
}
div_av2 = reg & 0x7f;
if (div_av2)
@@ -334,10 +340,10 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
* are allowed. AV3 != 0 divides by AV2/2, AV3=0 is bypass.
*/
if (ch->index < 6) {
- reg = readl_relaxed(ch->base + VCO_CTRL14);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL14, ®);
reg >>= 7 + (ch->index * 4);
} else {
- reg = readl_relaxed(ch->base + VCO_CTRL15);
+ regmap_read(ch->regmap, ch->offset + VCO_CTRL15, ®);
}
div_av3 = reg & 0xf;
if (div_av2 && div_av3)
@@ -364,9 +370,10 @@ static const struct clk_ops berlin2_avpll_channel_ops = {
*/
static const u8 quirk_index[] __initconst = { 0, 6, 5, 4, 3, 2, 1, 7 };
-struct clk * __init berlin2_avpll_channel_register(void __iomem *base,
- const char *name, u8 index, const char *parent_name,
- u8 ch_flags, unsigned long flags)
+struct clk * __init berlin2_avpll_channel_register(struct regmap *regmap,
+ unsigned int offset, const char *name, u8 index,
+ const char *parent_name, u8 ch_flags,
+ unsigned long flags)
{
struct berlin2_avpll_channel *ch;
struct clk_init_data init;
@@ -375,7 +382,8 @@ struct clk * __init berlin2_avpll_channel_register(void __iomem *base,
if (!ch)
return ERR_PTR(-ENOMEM);
- ch->base = base;
+ ch->regmap = regmap;
+ ch->offset = offset;
if (ch_flags & BERLIN2_AVPLL_SCRAMBLE_QUIRK)
ch->index = quirk_index[index];
else
diff --git a/drivers/clk/berlin/berlin2-avpll.h b/drivers/clk/berlin/berlin2-avpll.h
index a37f5068d299..cdc2c5bd4706 100644
--- a/drivers/clk/berlin/berlin2-avpll.h
+++ b/drivers/clk/berlin/berlin2-avpll.h
@@ -19,18 +19,21 @@
#ifndef __BERLIN2_AVPLL_H
#define __BERLIN2_AVPLL_H
+#include <linux/regmap.h>
+
struct clk;
#define BERLIN2_AVPLL_BIT_QUIRK BIT(0)
#define BERLIN2_AVPLL_SCRAMBLE_QUIRK BIT(1)
struct clk * __init
-berlin2_avpll_vco_register(void __iomem *base, const char *name,
- const char *parent_name, u8 vco_flags, unsigned long flags);
+berlin2_avpll_vco_register(struct regmap *regmap, unsigned int offset,
+ const char *name, const char *parent_name, u8 vco_flags,
+ unsigned long flags);
struct clk * __init
-berlin2_avpll_channel_register(void __iomem *base, const char *name,
- u8 index, const char *parent_name, u8 ch_flags,
- unsigned long flags);
+berlin2_avpll_channel_register(struct regmap *regmap, unsigned int offset,
+ const char *name, u8 index, const char *parent_name,
+ u8 ch_flags, unsigned long flags);
#endif /* __BERLIN2_AVPLL_H */
diff --git a/drivers/clk/berlin/berlin2-div.c b/drivers/clk/berlin/berlin2-div.c
index 81ff97f8aa0b..ff708fe831d0 100644
--- a/drivers/clk/berlin/berlin2-div.c
+++ b/drivers/clk/berlin/berlin2-div.c
@@ -20,6 +20,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -63,9 +64,8 @@
struct berlin2_div {
struct clk_hw hw;
- void __iomem *base;
+ struct regmap *regmap;
struct berlin2_div_map map;
- spinlock_t *lock;
};
#define to_berlin2_div(hw) container_of(hw, struct berlin2_div, hw)
@@ -78,15 +78,9 @@ static int berlin2_div_is_enabled(struct clk_hw *hw)
struct berlin2_div_map *map = &div->map;
u32 reg;
- if (div->lock)
- spin_lock(div->lock);
-
- reg = readl_relaxed(div->base + map->gate_offs);
+ regmap_read(div->regmap, map->gate_offs, ®);
reg >>= map->gate_shift;
- if (div->lock)
- spin_unlock(div->lock);
-
return (reg & 0x1);
}
@@ -96,15 +90,9 @@ static int berlin2_div_enable(struct clk_hw *hw)
struct berlin2_div_map *map = &div->map;
u32 reg;
- if (div->lock)
- spin_lock(div->lock);
-
- reg = readl_relaxed(div->base + map->gate_offs);
+ regmap_read(div->regmap, map->gate_offs, ®);
reg |= BIT(map->gate_shift);
- writel_relaxed(reg, div->base + map->gate_offs);
-
- if (div->lock)
- spin_unlock(div->lock);
+ regmap_write(div->regmap, map->gate_offs, reg);
return 0;
}
@@ -115,15 +103,9 @@ static void berlin2_div_disable(struct clk_hw *hw)
struct berlin2_div_map *map = &div->map;
u32 reg;
- if (div->lock)
- spin_lock(div->lock);
-
- reg = readl_relaxed(div->base + map->gate_offs);
+ regmap_read(div->regmap, map->gate_offs, ®);
reg &= ~BIT(map->gate_shift);
- writel_relaxed(reg, div->base + map->gate_offs);
-
- if (div->lock)
- spin_unlock(div->lock);
+ regmap_write(div->regmap, map->gate_offs, reg);
}
static int berlin2_div_set_parent(struct clk_hw *hw, u8 index)
@@ -132,28 +114,24 @@ static int berlin2_div_set_parent(struct clk_hw *hw, u8 index)
struct berlin2_div_map *map = &div->map;
u32 reg;
- if (div->lock)
- spin_lock(div->lock);
-
/* index == 0 is PLL_SWITCH */
- reg = readl_relaxed(div->base + map->pll_switch_offs);
+ regmap_read(div->regmap, map->pll_switch_offs, ®);
if (index == 0)
reg &= ~BIT(map->pll_switch_shift);
else
reg |= BIT(map->pll_switch_shift);
- writel_relaxed(reg, div->base + map->pll_switch_offs);
+ regmap_write(div->regmap, map->pll_switch_offs, reg);
/* index > 0 is PLL_SELECT */
if (index > 0) {
- reg = readl_relaxed(div->base + map->pll_select_offs);
+ regmap_read(div->regmap, map->pll_switch_offs,
+ ®);
reg &= ~(PLL_SELECT_MASK << map->pll_select_shift);
reg |= (index - 1) << map->pll_select_shift;
- writel_relaxed(reg, div->base + map->pll_select_offs);
+ regmap_write(div->regmap, map->pll_switch_offs,
+ reg);
}
- if (div->lock)
- spin_unlock(div->lock);
-
return 0;
}
@@ -164,22 +142,17 @@ static u8 berlin2_div_get_parent(struct clk_hw *hw)
u32 reg;
u8 index = 0;
- if (div->lock)
- spin_lock(div->lock);
-
/* PLL_SWITCH == 0 is index 0 */
- reg = readl_relaxed(div->base + map->pll_switch_offs);
+ regmap_read(div->regmap, map->pll_switch_offs, ®);
reg &= BIT(map->pll_switch_shift);
if (reg) {
- reg = readl_relaxed(div->base + map->pll_select_offs);
+ regmap_read(div->regmap, map->pll_switch_offs,
+ ®);
reg >>= map->pll_select_shift;
reg &= PLL_SELECT_MASK;
index = 1 + reg;
}
- if (div->lock)
- spin_unlock(div->lock);
-
return index;
}
@@ -190,13 +163,11 @@ static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw,
struct berlin2_div_map *map = &div->map;
u32 divsw, div3sw, divider = 1;
- if (div->lock)
- spin_lock(div->lock);
+ regmap_read(div->regmap, map->div_switch_offs, &divsw);
+ divsw &= (1 << map->div_switch_shift);
- divsw = readl_relaxed(div->base + map->div_switch_offs) &
- (1 << map->div_switch_shift);
- div3sw = readl_relaxed(div->base + map->div3_switch_offs) &
- (1 << map->div3_switch_shift);
+ regmap_read(div->regmap, map->div3_switch_offs, &div3sw);
+ div3sw &= (1 << map->div3_switch_shift);
/* constant divide-by-3 (dominant) */
if (div3sw != 0) {
@@ -207,15 +178,13 @@ static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw,
/* clock divider determined by DIV_SELECT */
} else {
u32 reg;
- reg = readl_relaxed(div->base + map->div_select_offs);
+ regmap_read(div->regmap, map->div_select_offs,
+ ®);
reg >>= map->div_select_shift;
reg &= DIV_SELECT_MASK;
divider = clk_div[reg];
}
- if (div->lock)
- spin_unlock(div->lock);
-
return parent_rate / divider;
}
@@ -236,9 +205,9 @@ static const struct clk_ops berlin2_div_mux_ops = {
struct clk * __init
berlin2_div_register(const struct berlin2_div_map *map,
- void __iomem *base, const char *name, u8 div_flags,
+ struct regmap *regmap, const char *name, u8 div_flags,
const char **parent_names, int num_parents,
- unsigned long flags, spinlock_t *lock)
+ unsigned long flags)
{
const struct clk_ops *mux_ops = &berlin2_div_mux_ops;
const struct clk_ops *rate_ops = &berlin2_div_rate_ops;
@@ -251,8 +220,7 @@ berlin2_div_register(const struct berlin2_div_map *map,
/* copy div_map to allow __initconst */
memcpy(&div->map, map, sizeof(*map));
- div->base = base;
- div->lock = lock;
+ div->regmap = regmap;
if ((div_flags & BERLIN2_DIV_HAS_GATE) == 0)
gate_ops = NULL;
diff --git a/drivers/clk/berlin/berlin2-div.h b/drivers/clk/berlin/berlin2-div.h
index 15e3384f3116..8b726561cd00 100644
--- a/drivers/clk/berlin/berlin2-div.h
+++ b/drivers/clk/berlin/berlin2-div.h
@@ -82,8 +82,8 @@ struct berlin2_div_data {
struct clk * __init
berlin2_div_register(const struct berlin2_div_map *map,
- void __iomem *base, const char *name, u8 div_flags,
+ struct regmap *regmap, const char *name, u8 div_flags,
const char **parent_names, int num_parents,
- unsigned long flags, spinlock_t *lock);
+ unsigned long flags);
#endif /* __BERLIN2_DIV_H */
diff --git a/drivers/clk/berlin/berlin2-pll.c b/drivers/clk/berlin/berlin2-pll.c
index bdc506b03824..96fbb643d37d 100644
--- a/drivers/clk/berlin/berlin2-pll.c
+++ b/drivers/clk/berlin/berlin2-pll.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <asm/div64.h>
@@ -36,7 +37,8 @@ struct berlin2_pll_map {
struct berlin2_pll {
struct clk_hw hw;
- void __iomem *base;
+ struct regmap *regmap;
+ unsigned int offset;
struct berlin2_pll_map map;
};
@@ -64,7 +66,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
u32 val, fbdiv, rfdiv, vcodivsel, vcodiv;
u64 rate = parent_rate;
- val = readl_relaxed(pll->base + SPLL_CTRL0);
+ regmap_read(pll->regmap, SPLL_CTRL0, &val);
fbdiv = (val >> map->fbdiv_shift) & FBDIV_MASK;
rfdiv = (val >> map->rfdiv_shift) & RFDIV_MASK;
if (rfdiv == 0) {
@@ -72,7 +74,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
rfdiv = 1;
}
- val = readl_relaxed(pll->base + SPLL_CTRL1);
+ regmap_read(pll->regmap, SPLL_CTRL1, &val);
vcodivsel = (val >> map->divsel_shift) & DIVSEL_MASK;
vcodiv = map->vcodiv[vcodivsel];
if (vcodiv == 0) {
@@ -93,8 +95,9 @@ static const struct clk_ops berlin2_pll_ops = {
struct clk * __init
berlin2_pll_register(const struct berlin2_pll_map *map,
- void __iomem *base, const char *name,
- const char *parent_name, unsigned long flags)
+ struct regmap *regmap, unsigned int offset,
+ const char *name, const char *parent_name,
+ unsigned long flags)
{
struct clk_init_data init;
struct berlin2_pll *pll;
@@ -105,7 +108,8 @@ berlin2_pll_register(const struct berlin2_pll_map *map,
/* copy pll_map to allow __initconst */
memcpy(&pll->map, map, sizeof(*map));
- pll->base = base;
+ pll->regmap = regmap;
+ pll->offset = offset;
pll->hw.init = &init;
init.name = name;
init.ops = &berlin2_pll_ops;
diff --git a/drivers/clk/berlin/berlin2-pll.h b/drivers/clk/berlin/berlin2-pll.h
index 8831ce27ac1e..9e2f6b172e51 100644
--- a/drivers/clk/berlin/berlin2-pll.h
+++ b/drivers/clk/berlin/berlin2-pll.h
@@ -19,6 +19,8 @@
#ifndef __BERLIN2_PLL_H
#define __BERLIN2_PLL_H
+#include <linux/regmap.h>
+
struct clk;
struct berlin2_pll_map {
@@ -31,7 +33,8 @@ struct berlin2_pll_map {
struct clk * __init
berlin2_pll_register(const struct berlin2_pll_map *map,
- void __iomem *base, const char *name,
- const char *parent_name, unsigned long flags);
+ struct regmap *regmap, unsigned int offset,
+ const char *name, const char *parent_name,
+ unsigned long flags);
#endif /* __BERLIN2_PLL_H */
diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
index 515fb133495c..d6a379ac01a6 100644
--- a/drivers/clk/berlin/bg2.c
+++ b/drivers/clk/berlin/bg2.c
@@ -20,8 +20,10 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <dt-bindings/clock/berlin2.h>
@@ -94,8 +96,6 @@
#define MAX_CLKS 41
static struct clk *clks[MAX_CLKS];
static struct clk_onecell_data clk_data;
-static DEFINE_SPINLOCK(lock);
-static void __iomem *gbase;
enum {
REFCLK, VIDEO_EXT0,
@@ -502,14 +502,19 @@ static const struct berlin2_gate_data bg2_gates[] __initconst = {
static void __init berlin2_clock_setup(struct device_node *np)
{
+ struct device_node *parent_np = of_get_parent(np);
+ struct regmap *regmap;
const char *parent_names[9];
struct clk *clk;
u8 avpll_flags = 0;
int n;
- gbase = of_iomap(np, 0);
- if (!gbase)
+ regmap = syscon_node_to_regmap(parent_np);
+ of_node_put(parent_np);
+ if (IS_ERR(regmap)) {
+ pr_err("Unable to retrieve regmap: %ld\n", PTR_ERR(regmap));
return;
+ }
/* overwrite default clock names with DT provided ones */
clk = of_clk_get_by_name(np, clk_names[REFCLK]);
@@ -525,119 +530,119 @@ static void __init berlin2_clock_setup(struct device_node *np)
}
/* simple register PLLs */
- clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
+ clk = berlin2_pll_register(&bg2_pll_map, regmap, REG_SYSPLLCTL0,
clk_names[SYSPLL], clk_names[REFCLK], 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
- clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
+ clk = berlin2_pll_register(&bg2_pll_map, regmap, REG_MEMPLLCTL0,
clk_names[MEMPLL], clk_names[REFCLK], 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
- clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
+ clk = berlin2_pll_register(&bg2_pll_map, regmap, REG_CPUPLLCTL0,
clk_names[CPUPLL], clk_names[REFCLK], 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
/* audio/video VCOs */
- clk = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
+ clk = berlin2_avpll_vco_register(regmap, REG_AVPLLCTL0, "avpll_vcoA",
clk_names[REFCLK], avpll_flags, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
for (n = 0; n < 8; n++) {
- clk = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
+ clk = berlin2_avpll_channel_register(regmap, REG_AVPLLCTL0,
clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
avpll_flags, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
}
- clk = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
+ clk = berlin2_avpll_vco_register(regmap, REG_AVPLLCTL31, "avpll_vcoB",
clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
avpll_flags, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
for (n = 0; n < 8; n++) {
- clk = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
+ clk = berlin2_avpll_channel_register(regmap, REG_AVPLLCTL31,
clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
}
/* reference clock bypass switches */
parent_names[0] = clk_names[SYSPLL];
parent_names[1] = clk_names[REFCLK];
- clk = clk_register_mux(NULL, "syspll_byp", parent_names, 2,
- 0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, "syspll_byp", parent_names, 2,
+ 0, regmap, REG_CLKSWITCH0, 0, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
clk_names[SYSPLL] = __clk_get_name(clk);
parent_names[0] = clk_names[MEMPLL];
parent_names[1] = clk_names[REFCLK];
- clk = clk_register_mux(NULL, "mempll_byp", parent_names, 2,
- 0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, "mempll_byp", parent_names, 2,
+ 0, regmap, REG_CLKSWITCH0, 1, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
clk_names[MEMPLL] = __clk_get_name(clk);
parent_names[0] = clk_names[CPUPLL];
parent_names[1] = clk_names[REFCLK];
- clk = clk_register_mux(NULL, "cpupll_byp", parent_names, 2,
- 0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, "cpupll_byp", parent_names, 2,
+ 0, regmap, REG_CLKSWITCH0, 2, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
clk_names[CPUPLL] = __clk_get_name(clk);
/* clock muxes */
parent_names[0] = clk_names[AVPLL_B3];
parent_names[1] = clk_names[AVPLL_A3];
- clk = clk_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
- 0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, clk_names[AUDIO1_PLL], parent_names,
+ 2, 0, regmap, REG_CLKSELECT2, 29, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
parent_names[0] = clk_names[VIDEO0_PLL];
parent_names[1] = clk_names[VIDEO_EXT0];
- clk = clk_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
- 0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, clk_names[VIDEO0_IN], parent_names,
+ 2, 0, regmap, REG_CLKSELECT3, 4, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
parent_names[0] = clk_names[VIDEO1_PLL];
parent_names[1] = clk_names[VIDEO_EXT0];
- clk = clk_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
- 0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, clk_names[VIDEO1_IN], parent_names,
+ 2, 0, regmap, REG_CLKSELECT3, 6, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
parent_names[0] = clk_names[AVPLL_A2];
parent_names[1] = clk_names[AVPLL_B2];
- clk = clk_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
- 0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, clk_names[VIDEO1_PLL], parent_names,
+ 2, 0,regmap, REG_CLKSELECT3, 7, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
parent_names[0] = clk_names[VIDEO2_PLL];
parent_names[1] = clk_names[VIDEO_EXT0];
- clk = clk_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
- 0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, clk_names[VIDEO2_IN], parent_names,
+ 2, 0, regmap, REG_CLKSELECT3, 9, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
parent_names[0] = clk_names[AVPLL_B1];
parent_names[1] = clk_names[AVPLL_A5];
- clk = clk_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
- 0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
+ clk = clk_register_mux_regmap(NULL, clk_names[VIDEO2_PLL], parent_names,
+ 2, 0, regmap, REG_CLKSELECT3, 10, 1, 0);
if (IS_ERR(clk))
- goto bg2_fail;
+ return;
/* clock divider cells */
for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
@@ -647,18 +652,18 @@ static void __init berlin2_clock_setup(struct device_node *np)
for (k = 0; k < dd->num_parents; k++)
parent_names[k] = clk_names[dd->parent_ids[k]];
- clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
+ clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, regmap,
dd->name, dd->div_flags, parent_names,
- dd->num_parents, dd->flags, &lock);
+ dd->num_parents, dd->flags);
}
/* clock gate cells */
for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
const struct berlin2_gate_data *gd = &bg2_gates[n];
- clks[CLKID_GETH0 + n] = clk_register_gate(NULL, gd->name,
- gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
- gd->bit_idx, 0, &lock);
+ clks[CLKID_GETH0 + n] = clk_register_gate_regmap(NULL, gd->name,
+ gd->parent_name, gd->flags, regmap, REG_CLKENABLE,
+ gd->bit_idx, 0);
}
/* twdclk is derived from cpu/3 */
@@ -672,7 +677,7 @@ static void __init berlin2_clock_setup(struct device_node *np)
pr_err("%s: Unable to register leaf clock %d\n",
np->full_name, n);
- goto bg2_fail;
+ return;
}
/* register clk-provider */
@@ -681,11 +686,8 @@ static void __init berlin2_clock_setup(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
return;
-
-bg2_fail:
- iounmap(gbase);
}
CLK_OF_DECLARE(berlin2_clock, "marvell,berlin2-chip-ctrl",
berlin2_clock_setup);
-CLK_OF_DECLARE(berlin2cd_clock, "marvell,berlin2cd-chip-ctrl",
+CLK_OF_DECLARE(berlin2cd_clock, "marvell,berlin2-clk",
berlin2_clock_setup);
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
index 440ef81ab15c..25bedca9e350 100644
--- a/drivers/clk/berlin/bg2q.c
+++ b/drivers/clk/berlin/bg2q.c
@@ -19,9 +19,12 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/device.h>
#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <dt-bindings/clock/berlin2q.h>
@@ -46,11 +49,9 @@
#define REG_SDIO1XIN_CLKCTL 0x015c
#define MAX_CLKS 27
+
static struct clk *clks[MAX_CLKS];
static struct clk_onecell_data clk_data;
-static DEFINE_SPINLOCK(lock);
-static void __iomem *gbase;
-static void __iomem *cpupll_base;
enum {
REFCLK,
@@ -290,24 +291,45 @@ static const struct berlin2_gate_data bg2q_gates[] __initconst = {
static void __init berlin2q_clock_setup(struct device_node *np)
{
+ struct device_node *parent_np = of_get_parent(np);
const char *parent_names[9];
+ struct regmap *regmap, *cpupll_regmap;
+ struct regmap_config *rmconfig;
+ struct resource res;
struct clk *clk;
+ void __iomem *cpupll_base;
int n;
- gbase = of_iomap(np, 0);
- if (!gbase) {
- pr_err("%s: Unable to map global base\n", np->full_name);
+ regmap = syscon_node_to_regmap(parent_np);
+ of_node_put(parent_np);
+ if (IS_ERR(regmap)) {
+ pr_err("Unable to retrieve regmap: %ld\n", PTR_ERR(regmap));
return;
}
+ rmconfig = kzalloc(sizeof(*rmconfig), GFP_KERNEL);
+ if (!rmconfig)
+ return;
+
+ if (of_address_to_resource(parent_np, 1, &res))
+ return;
+
/* BG2Q CPU PLL is not part of global registers */
- cpupll_base = of_iomap(np, 1);
+ cpupll_base = ioremap(res.start, resource_size(&res));
if (!cpupll_base) {
pr_err("%s: Unable to map cpupll base\n", np->full_name);
- iounmap(gbase);
return;
}
+ rmconfig->reg_bits = 32;
+ rmconfig->val_bits = 32;
+ rmconfig->reg_stride = 4;
+ rmconfig->max_register = resource_size(&res);
+
+ cpupll_regmap = regmap_init_mmio(NULL, cpupll_base, rmconfig);
+ if (IS_ERR(cpupll_regmap))
+ return;
+
/* overwrite default clock names with DT provided ones */
clk = of_clk_get_by_name(np, clk_names[REFCLK]);
if (!IS_ERR(clk)) {
@@ -316,15 +338,15 @@ static void __init berlin2q_clock_setup(struct device_node *np)
}
/* simple register PLLs */
- clk = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
+ clk = berlin2_pll_register(&bg2q_pll_map, regmap, REG_SYSPLLCTL0,
clk_names[SYSPLL], clk_names[REFCLK], 0);
if (IS_ERR(clk))
- goto bg2q_fail;
+ return;
- clk = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
+ clk = berlin2_pll_register(&bg2q_pll_map, cpupll_regmap, 0,
clk_names[CPUPLL], clk_names[REFCLK], 0);
if (IS_ERR(clk))
- goto bg2q_fail;
+ return;
/* TODO: add BG2Q AVPLL */
@@ -341,18 +363,18 @@ static void __init berlin2q_clock_setup(struct device_node *np)
for (k = 0; k < dd->num_parents; k++)
parent_names[k] = clk_names[dd->parent_ids[k]];
- clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
+ clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, regmap,
dd->name, dd->div_flags, parent_names,
- dd->num_parents, dd->flags, &lock);
+ dd->num_parents, dd->flags);
}
/* clock gate cells */
for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
const struct berlin2_gate_data *gd = &bg2q_gates[n];
- clks[CLKID_GFX2DAXI + n] = clk_register_gate(NULL, gd->name,
- gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
- gd->bit_idx, 0, &lock);
+ clks[CLKID_GFX2DAXI + n] = clk_register_gate_regmap(NULL,
+ gd->name, gd->parent_name, gd->flags,
+ regmap, REG_CLKENABLE, gd->bit_idx, 0);
}
/*
@@ -370,7 +392,7 @@ static void __init berlin2q_clock_setup(struct device_node *np)
pr_err("%s: Unable to register leaf clock %d\n",
np->full_name, n);
- goto bg2q_fail;
+ return;
}
/* register clk-provider */
@@ -379,10 +401,6 @@ static void __init berlin2q_clock_setup(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
return;
-
-bg2q_fail:
- iounmap(cpupll_base);
- iounmap(gbase);
}
-CLK_OF_DECLARE(berlin2q_clock, "marvell,berlin2q-chip-ctrl",
+CLK_OF_DECLARE(berlin2q_clock, "marvell,berlin2q-clk",
berlin2q_clock_setup);
--
2.3.1
More information about the linux-arm-kernel
mailing list