linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/15] tz1090: add clock components
@ 2014-11-19 23:15 James Hogan
  2014-11-19 23:15 ` [PATCH 01/15] clk: divider: replace bitfield width with mask James Hogan
                   ` (14 more replies)
  0 siblings, 15 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Emilio López, Heiko Stuebner, Ian Campbell,
	Kumar Gala, Mark Rutland, Pawel Moll, Rob Herring, Sascha Hauer,
	Shawn Guo, Tero Kristo, linux-omap, linux-rockchip

This patchset adds common clock framework support for the TZ1090 SoC.

Patches 1 and 2 are generic and switch clk-divider to use masks
internally instead of shifts and width. Patch 1 came from Mike's divider
DT bindings patchset from a while back. This is required by the TZ1090
divider binding (patch 13).

Patches 3 to 14 add TZ1090 clock types and associated DT bindings,
specifically:
* PLLs (True Circuits, but TZ1090 specific register interface)
* Gate banks (a register containing clock gate bits)
* Mux banks (a register containing clock mux bits)
* Clock deleters (delete up to 1023 out of every 1024 clocks)
* PDC clock (combined divider and mux)
* Divider clock (pretty basic divider, but specific to TZ1090)

Finally patch 15 defines most of the TZ1090 clocks using these
components, with a few placeholders for less interesting clocks from
more complex components. This is mostly for reference to give an idea
how the clock components are intended to be used, and I'll take this one
through the metag tree when the drivers/clk/ stuff is accepted.

James Hogan (14):
  clk: divider: expose new clk_register_divider_mask
  dt: binding: add binding for tz1090-pll clock
  clk: tz1090: add PLL clock driver
  dt: binding: add binding for TZ1090 gate bank
  clk: tz1090: add gate bank clock driver
  dt: binding: add binding for TZ1090 mux bank
  clk: tz1090: add mux bank clock driver
  dt: binding: add binding for TZ1090 clock deleter
  clk: tz1090: add deleter clock driver
  dt: binding: add binding for TZ1090 PDC clock
  clk: tz1090: add PDC clock driver
  dt: binding: add binding for TZ1090 divider clock
  clk: tz1090: add divider clock driver
  metag: tz1090: add TZ1090 clocks to device tree

Mike Turquette (1):
  clk: divider: replace bitfield width with mask

 .../bindings/clock/img,tz1090-deleter.txt          |  40 ++
 .../bindings/clock/img,tz1090-divider.txt          |  37 +
 .../bindings/clock/img,tz1090-gate-bank.txt        |  52 ++
 .../bindings/clock/img,tz1090-mux-bank.txt         |  56 ++
 .../bindings/clock/img,tz1090-pdc-clock.txt        |  44 ++
 .../devicetree/bindings/clock/img,tz1090-pll.txt   |  33 +
 arch/arm/mach-imx/clk-busy.c                       |   2 +-
 arch/arm/mach-imx/clk-fixup-div.c                  |   2 +-
 arch/metag/Kconfig.soc                             |   1 +
 arch/metag/boot/dts/tz1090.dtsi                    |   4 +
 arch/metag/boot/dts/tz1090_clk.dtsi                | 784 +++++++++++++++++++++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-divider.c                          |  58 +-
 drivers/clk/mxs/clk-div.c                          |   2 +-
 drivers/clk/rockchip/clk.c                         |   2 +-
 drivers/clk/st/clk-flexgen.c                       |   4 +-
 drivers/clk/st/clkgen-mux.c                        |   4 +-
 drivers/clk/st/clkgen-pll.c                        |   2 +-
 drivers/clk/sunxi/clk-sunxi.c                      |   2 +-
 drivers/clk/ti/divider.c                           |   2 +-
 drivers/clk/tz1090/Makefile                        |   7 +
 drivers/clk/tz1090/clk-tz1090-deleter.c            | 188 +++++
 drivers/clk/tz1090/clk-tz1090-divider.c            |  96 +++
 drivers/clk/tz1090/clk-tz1090-gate-bank.c          | 199 ++++++
 drivers/clk/tz1090/clk-tz1090-mux-bank.c           | 191 +++++
 drivers/clk/tz1090/clk-tz1090-pdc.c                | 185 +++++
 drivers/clk/tz1090/clk-tz1090-pll.c                | 305 ++++++++
 include/linux/clk-private.h                        |   2 +-
 include/linux/clk-provider.h                       |   7 +-
 29 files changed, 2282 insertions(+), 30 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-deleter.txt
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-divider.txt
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-gate-bank.txt
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-mux-bank.txt
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-pdc-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-pll.txt
 create mode 100644 arch/metag/boot/dts/tz1090_clk.dtsi
 create mode 100644 drivers/clk/tz1090/Makefile
 create mode 100644 drivers/clk/tz1090/clk-tz1090-deleter.c
 create mode 100644 drivers/clk/tz1090/clk-tz1090-divider.c
 create mode 100644 drivers/clk/tz1090/clk-tz1090-gate-bank.c
 create mode 100644 drivers/clk/tz1090/clk-tz1090-mux-bank.c
 create mode 100644 drivers/clk/tz1090/clk-tz1090-pdc.c
 create mode 100644 drivers/clk/tz1090/clk-tz1090-pll.c

Cc: "Emilio López" <emilio@elopez.com.ar>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Tero Kristo <t-kristo@ti.com>
Cc: linux-omap@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
-- 
2.0.4


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/15] clk: divider: replace bitfield width with mask
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-20 11:19   ` Tero Kristo
  2014-11-19 23:15 ` [PATCH 02/15] clk: divider: expose new clk_register_divider_mask James Hogan
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Emilio López, Sascha Hauer, Shawn Guo,
	Tero Kristo, linux-omap, linux-rockchip

From: Mike Turquette <mturquette@linaro.org>

The forthcoming Device Tree binding for the divider clock type will use
a bitfield mask instead of bitfield width, which is what the current
basic divider implementation uses.

This patch replaces the u8 width in struct clk_divider with a u32 mask.
The divider code is updated to use the bit mask internally but the two
registration functions still accept the width to maintain compatibility
with existing users.

Also updated in this patch is the clk-private.h divider macro and
various clock divider implementations that are based on struct
clk_divider.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
[james.hogan@imgtec.com: forward port, fix new uses of width]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Cc: "Emilio López" <emilio@elopez.com.ar>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Tero Kristo <t-kristo@ti.com>
Cc: linux-omap@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
---
Changes since original:
- Forward ported
- Adjust new div_mask from recent patch "clk-divider: Fix READ_ONLY when
  divider > 1"
- Updated assignment of clk_divider::width in imx, rockchip, st, sunxi,
  ti clock components to use mask instead (not tested), using the
  following semantic patch:

virtual context
virtual patch

@depends on context@
struct clk_divider clk;
expression e;
@@
*clk.width = e

@depends on patch@
struct clk_divider clk;
expression e;
@@
-clk.width = fls(e)
+clk.mask = e

@depends on patch@
struct clk_divider *clk;
expression e;
@@
-clk->width = fls(e)
+clk->mask = e

@depends on patch@
struct clk_divider clk;
expression e;
@@
-clk.width = e
+clk.mask = BIT(e) - 1

@depends on patch@
struct clk_divider *clk;
expression e;
@@
-clk->width = e
+clk->mask = BIT(e) - 1
---
 arch/arm/mach-imx/clk-busy.c      |  2 +-
 arch/arm/mach-imx/clk-fixup-div.c |  2 +-
 drivers/clk/clk-divider.c         | 33 ++++++++++++++++-----------------
 drivers/clk/mxs/clk-div.c         |  2 +-
 drivers/clk/rockchip/clk.c        |  2 +-
 drivers/clk/st/clk-flexgen.c      |  4 ++--
 drivers/clk/st/clkgen-mux.c       |  4 ++--
 drivers/clk/st/clkgen-pll.c       |  2 +-
 drivers/clk/sunxi/clk-sunxi.c     |  2 +-
 drivers/clk/ti/divider.c          |  2 +-
 include/linux/clk-private.h       |  2 +-
 include/linux/clk-provider.h      |  2 +-
 12 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c
index 4bb1bc4..bc88e38 100644
--- a/arch/arm/mach-imx/clk-busy.c
+++ b/arch/arm/mach-imx/clk-busy.c
@@ -95,7 +95,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
 
 	busy->div.reg = reg;
 	busy->div.shift = shift;
-	busy->div.width = width;
+	busy->div.mask = BIT(width) - 1;
 	busy->div.lock = &imx_ccm_lock;
 	busy->div_ops = &clk_divider_ops;
 
diff --git a/arch/arm/mach-imx/clk-fixup-div.c b/arch/arm/mach-imx/clk-fixup-div.c
index 21db020..af33b7a 100644
--- a/arch/arm/mach-imx/clk-fixup-div.c
+++ b/arch/arm/mach-imx/clk-fixup-div.c
@@ -115,7 +115,7 @@ struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
 
 	fixup_div->divider.reg = reg;
 	fixup_div->divider.shift = shift;
-	fixup_div->divider.width = width;
+	fixup_div->divider.mask = BIT(width) - 1;
 	fixup_div->divider.lock = &imx_ccm_lock;
 	fixup_div->divider.hw.init = &init;
 	fixup_div->ops = &clk_divider_ops;
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index c0a842b..a432cf8 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -30,8 +30,6 @@
 
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
-#define div_mask(d)	((1 << ((d)->width)) - 1)
-
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
 {
 	unsigned int maxdiv = 0;
@@ -57,12 +55,12 @@ static unsigned int _get_table_mindiv(const struct clk_div_table *table)
 static unsigned int _get_maxdiv(struct clk_divider *divider)
 {
 	if (divider->flags & CLK_DIVIDER_ONE_BASED)
-		return div_mask(divider);
+		return divider->mask;
 	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
-		return 1 << div_mask(divider);
+		return 1 << divider->mask;
 	if (divider->table)
 		return _get_table_maxdiv(divider->table);
-	return div_mask(divider) + 1;
+	return divider->mask + 1;
 }
 
 static unsigned int _get_table_div(const struct clk_div_table *table,
@@ -116,7 +114,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	unsigned int div, val;
 
 	val = clk_readl(divider->reg) >> divider->shift;
-	val &= div_mask(divider);
+	val &= divider->mask;
 
 	div = _get_div(divider, val);
 	if (!div) {
@@ -266,7 +264,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 	/* if read only, just return current value */
 	if (divider->flags & CLK_DIVIDER_READ_ONLY) {
 		bestdiv = readl(divider->reg) >> divider->shift;
-		bestdiv &= div_mask(divider);
+		bestdiv &= divider->mask;
 		bestdiv = _get_div(divider, bestdiv);
 		return bestdiv;
 	}
@@ -341,17 +339,17 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	value = _get_val(divider, div);
 
-	if (value > div_mask(divider))
-		value = div_mask(divider);
+	if (value > divider->mask)
+		value = divider->mask;
 
 	if (divider->lock)
 		spin_lock_irqsave(divider->lock, flags);
 
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
-		val = div_mask(divider) << (divider->shift + 16);
+		val = divider->mask << (divider->shift + 16);
 	} else {
 		val = clk_readl(divider->reg);
-		val &= ~(div_mask(divider) << divider->shift);
+		val &= ~(divider->mask << divider->shift);
 	}
 	val |= value << divider->shift;
 	clk_writel(val, divider->reg);
@@ -371,7 +369,7 @@ EXPORT_SYMBOL_GPL(clk_divider_ops);
 
 static struct clk *_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width,
+		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
@@ -380,8 +378,9 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	struct clk_init_data init;
 
 	if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
-		if (width + shift > 16) {
-			pr_warn("divider value exceeds LOWORD field\n");
+		if ((mask << shift) & 0xffff0000) {
+			pr_warn("%s: divider value exceeds LOWORD field\n",
+					__func__);
 			return ERR_PTR(-EINVAL);
 		}
 	}
@@ -402,7 +401,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	/* struct clk_divider assignments */
 	div->reg = reg;
 	div->shift = shift;
-	div->width = width;
+	div->mask = mask;
 	div->flags = clk_divider_flags;
 	div->lock = lock;
 	div->hw.init = &init;
@@ -435,7 +434,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
 	return _register_divider(dev, name, parent_name, flags, reg, shift,
-			width, clk_divider_flags, NULL, lock);
+			((1 << width) - 1), clk_divider_flags, NULL, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_divider);
 
@@ -460,6 +459,6 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 		spinlock_t *lock)
 {
 	return _register_divider(dev, name, parent_name, flags, reg, shift,
-			width, clk_divider_flags, table, lock);
+			((1 << width) - 1), clk_divider_flags, table, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_divider_table);
diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c
index 90e1da9..af2428e 100644
--- a/drivers/clk/mxs/clk-div.c
+++ b/drivers/clk/mxs/clk-div.c
@@ -96,7 +96,7 @@ struct clk *mxs_clk_div(const char *name, const char *parent_name,
 
 	div->divider.reg = reg;
 	div->divider.shift = shift;
-	div->divider.width = width;
+	div->divider.mask = BIT(width) - 1;
 	div->divider.flags = CLK_DIVIDER_ONE_BASED;
 	div->divider.lock = &mxs_lock;
 	div->divider.hw.init = &init;
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 880a266..9024a0e 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -87,7 +87,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 		div->flags = div_flags;
 		div->reg = base + muxdiv_offset;
 		div->shift = div_shift;
-		div->width = div_width;
+		div->mask = BIT(div_width) - 1;
 		div->lock = lock;
 		div->table = div_table;
 		div_ops = &clk_divider_ops;
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 2282cef..603d5d6 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -203,7 +203,7 @@ struct clk *clk_register_flexgen(const char *name,
 	/* Pre-divider config */
 	fgxbar->pdiv.lock = lock;
 	fgxbar->pdiv.reg = reg + 0x58 + idx * 4;
-	fgxbar->pdiv.width = 10;
+	fgxbar->pdiv.mask = BIT(10) - 1;
 
 	/* Final divider's gate config */
 	fgxbar->fgate.lock = lock;
@@ -213,7 +213,7 @@ struct clk *clk_register_flexgen(const char *name,
 	/* Final divider config */
 	fgxbar->fdiv.lock = lock;
 	fgxbar->fdiv.reg = fdiv_reg;
-	fgxbar->fdiv.width = 6;
+	fgxbar->fdiv.mask = BIT(6) - 1;
 
 	fgxbar->hw.init = &init;
 
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 79dc40b..85a1165 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -260,7 +260,7 @@ struct clk *clk_register_genamux(const char *name,
 		 * Divider config for each input
 		 */
 		void __iomem *divbase = reg + muxdata->div_offsets[i];
-		genamux->div[i].width = divider_width;
+		genamux->div[i].mask = BIT(divider_width) - 1;
 		genamux->div[i].reg = divbase + (idx * sizeof(u32));
 
 		/*
@@ -773,7 +773,7 @@ void __init st_of_clkgen_vcc_setup(struct device_node *np)
 
 		div->reg = reg + VCC_DIV_OFFSET;
 		div->shift = 2 * i;
-		div->width = 2;
+		div->mask = BIT(2) - 1;
 		div->flags = CLK_DIVIDER_POWER_OF_TWO |
 			CLK_DIVIDER_ROUND_CLOSEST;
 
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index 29769d7..0d76278 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -575,7 +575,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
 	div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
 	div->reg = reg + pll_data->odf[odf].offset;
 	div->shift = pll_data->odf[odf].shift;
-	div->width = fls(pll_data->odf[odf].mask);
+	div->mask = pll_data->odf[odf].mask;
 	div->lock = odf_lock;
 
 	clk = clk_register_composite(NULL, odf_name, &parent_name, 1,
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index d5dc951..a23d393 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1015,7 +1015,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
 
 			divider->reg = reg;
 			divider->shift = data->div[i].shift;
-			divider->width = SUNXI_DIVISOR_WIDTH;
+			divider->mask = BIT(SUNXI_DIVISOR_WIDTH) - 1;
 			divider->flags = flags;
 			divider->lock = &clk_lock;
 			divider->table = data->div[i].table;
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index bff2b5b..c27e01e 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -285,7 +285,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	/* struct clk_divider assignments */
 	div->reg = reg;
 	div->shift = shift;
-	div->width = width;
+	div->mask = BIT(width) - 1;
 	div->flags = clk_divider_flags;
 	div->lock = lock;
 	div->hw.init = &init;
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 0ca5f60..40bc1b2 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -130,7 +130,7 @@ struct clk {
 		},						\
 		.reg = _reg,					\
 		.shift = _shift,				\
-		.width = _width,				\
+		.mask = ((1 << _width) - 1),			\
 		.flags = _divider_flags,			\
 		.table = _table,				\
 		.lock = _lock,					\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2839c63..2c00215 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -338,7 +338,7 @@ struct clk_divider {
 	struct clk_hw	hw;
 	void __iomem	*reg;
 	u8		shift;
-	u8		width;
+	u32		mask;
 	u8		flags;
 	const struct clk_div_table	*table;
 	spinlock_t	*lock;
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/15] clk: divider: expose new clk_register_divider_mask
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
  2014-11-19 23:15 ` [PATCH 01/15] clk: divider: replace bitfield width with mask James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 03/15] dt: binding: add binding for tz1090-pll clock James Hogan
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

Expose a new function clk_register_divider_mask to set up a mask based
divider. This will be used by the upcoming TZ1090 divider driver whose
DT binding takes a mask rather than a shift and width.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
---
 drivers/clk/clk-divider.c    | 25 +++++++++++++++++++++++++
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index a432cf8..23ef3df 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -462,3 +462,28 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 			((1 << width) - 1), clk_divider_flags, table, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_divider_table);
+
+/**
+ * clk_register_divider_mask - register a mask based divider clock with
+ * the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @mask: mask of bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+struct clk *clk_register_divider_mask(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u32 mask,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock)
+{
+	return _register_divider(dev, name, parent_name, flags, reg, shift,
+			mask, clk_divider_flags, table, lock);
+}
+EXPORT_SYMBOL_GPL(clk_register_divider_mask);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2c00215..85048fb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -361,6 +361,11 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock);
+struct clk *clk_register_divider_mask(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u32 mask,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock);
 
 /**
  * struct clk_mux - multiplexer clock
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/15] dt: binding: add binding for tz1090-pll clock
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
  2014-11-19 23:15 ` [PATCH 01/15] clk: divider: replace bitfield width with mask James Hogan
  2014-11-19 23:15 ` [PATCH 02/15] clk: divider: expose new clk_register_divider_mask James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 04/15] clk: tz1090: add PLL clock driver James Hogan
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

Add simple device tree binding for TZ1090 PLL clock. It takes a couple
of registers, and has a single reference clock source.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 .../devicetree/bindings/clock/img,tz1090-pll.txt   | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-pll.txt

diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-pll.txt b/Documentation/devicetree/bindings/clock/img,tz1090-pll.txt
new file mode 100644
index 0000000..20aa622
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-pll.txt
@@ -0,0 +1,33 @@
+Binding for TZ1090 Phase-Lock Loop (PLL) clocks.
+
+This binding uses the common clock binding[1]. These PLLs are configured with 2
+registers specified with the reg property. These contain various fields which
+among other things specify the reference divider value (r), the frequency
+divider value (f), and the output divider value (od). When enabled, the output
+clock rate is:
+
+    f_out = f_ref / r * (f / 2) / od
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : Shall be "img,tz1090-pll".
+- #clock-cells       : From common clock binding; shall be set to 0.
+- reg                : Address of configuration register pair.
+- clocks             : From common clock binding.
+
+Required source clocks:
+- 0                  : Reference clock used to generate the output clock
+                       (doesn't have to be named).
+
+Optional properties:
+- clock-output-names : From common clock binding.
+
+Example:
+	sys_pll {
+		compatible = "img,tz1090-pll";
+		#clock-cells = <0>;
+		clocks = <&sysclk0_sw>;
+		reg = <0x02005950 0x8>;	/* CR_TOP_SYSPLL_CTL{0,1} */
+		clock-output-names = "sys_pll";
+	};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/15] clk: tz1090: add PLL clock driver
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (2 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 03/15] dt: binding: add binding for tz1090-pll clock James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 05/15] dt: binding: add binding for TZ1090 gate bank James Hogan
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

Add a driver for the main PLLs in the TZ1090 SoC, the system PLL and the
ADC PLL. The system PLL is used to derive the core Meta clock, the DDR
clock, and the system clock. The ADC PLL can be used for various
purposes, but is usually used for the pixel clock.

The PLL is a True Circuits PLL, but the arrangement of the fields in the
registers is I believe specific to the TZ1090 SoC.

The driver supports recalc_rate, round_rate, and set_rate operations.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
 drivers/clk/Makefile                |   1 +
 drivers/clk/tz1090/Makefile         |   2 +
 drivers/clk/tz1090/clk-tz1090-pll.c | 305 ++++++++++++++++++++++++++++++++++++
 3 files changed, 308 insertions(+)
 create mode 100644 drivers/clk/tz1090/Makefile
 create mode 100644 drivers/clk/tz1090/clk-tz1090-pll.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..ca486ed 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
+obj-$(CONFIG_SOC_TZ1090)		+= tz1090/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
new file mode 100644
index 0000000..14f2d33
--- /dev/null
+++ b/drivers/clk/tz1090/Makefile
@@ -0,0 +1,2 @@
+# Makefile for TZ1090-specific clocks
+obj-y		+= clk-tz1090-pll.o
diff --git a/drivers/clk/tz1090/clk-tz1090-pll.c b/drivers/clk/tz1090/clk-tz1090-pll.c
new file mode 100644
index 0000000..b51e6e7
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-pll.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * True Circuits PLL in TZ1090 SoC.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+
+#define PLL_CTL0		0
+#define  PLL_CTL0_BWADJ_M		0xfff
+#define  PLL_CTL0_BWADJ_S		20
+#define  PLL_CTL0_CLKF_M		0x1fff
+#define  PLL_CTL0_CLKF_S		4
+#define  PLL_CTL0_CLKOD_M		0x7
+#define  PLL_CTL0_CLKOD_S		0
+#define PLL_CTL1		4
+#define  PLL_CTL1_RESET_B		BIT(28)
+#define  PLL_CTL1_FASTEN_B		BIT(27)
+#define  PLL_CTL1_ENSAT_B		BIT(26)
+#define  PLL_CTL1_BYPASS_B		BIT(25)
+#define  PLL_CTL1_PWRDN_B		BIT(24)
+#define  PLL_CTL1_CLKR_M		0x3f
+#define  PLL_CTL1_CLKR_S		0
+
+/**
+ * struct clk_tz1090_pll - PLL in TZ1090
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	first of two registers
+ *
+ * PLL in TZ1090.  Implements .recalc_rate, .set_rate and .round_rate
+ */
+struct clk_tz1090_pll {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+};
+
+/*
+ * DOC: TZ1090 adjustable PLL clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_tz1090_pll(_hw) container_of(_hw, struct clk_tz1090_pll, hw)
+
+static unsigned long clk_tz1090_pll_recalc_rate(struct clk_hw *hw,
+						unsigned long f_in)
+{
+	struct clk_tz1090_pll *pll = to_clk_tz1090_pll(hw);
+	u32 ctl0, ctl1;
+	unsigned int clk_f;	/* feedback divide */
+	unsigned int clk_od;	/* output divide */
+	unsigned int clk_r;	/* reference divide */
+	unsigned long f_out;
+
+	ctl0 = readl(pll->reg + PLL_CTL0);
+	ctl1 = readl(pll->reg + PLL_CTL1);
+
+	/* Bypass? */
+	if (ctl1 & PLL_CTL1_BYPASS_B)
+		return f_in;
+
+	/* Get divider values */
+	clk_f  = 1 + ((ctl0 >> PLL_CTL0_CLKF_S)  & PLL_CTL0_CLKF_M);
+	clk_od = 1 + ((ctl0 >> PLL_CTL0_CLKOD_S) & PLL_CTL0_CLKOD_M);
+	clk_r  = 1 + ((ctl1 >> PLL_CTL1_CLKR_S)  & PLL_CTL1_CLKR_M);
+
+	/*
+	 * formula:
+	 * f_out = (f_in / clk_r) * (clk_f / 2) / clk_od
+	 *       = (f_in * clk_f) / (2 * clk_r * clk_od)
+	 */
+	f_out = div_u64((u64)f_in * clk_f,
+			2 * clk_r * clk_od);
+	return f_out;
+}
+
+/* finds best pll parameters and returns rate on success (or 0) */
+static int clk_tz1090_pll_bestvals(struct clk_hw *hw, unsigned long parent_rate,
+				   unsigned long rate, unsigned long *clkf,
+				   unsigned long *clkr, unsigned long *clkod)
+{
+	unsigned long odmin, odmax;
+	unsigned long bestf = 1, bestr = 1, bestod = 1;
+	unsigned long rod2, cur, best = 0;
+	unsigned long f, r, od;
+
+	/* 120MHz/freq < od < 600MHz/freq */
+	odmin = 120000000/rate + 1;
+	odmax = 600000000/rate;
+
+	if (odmin < 1)
+		odmin = 1;
+	if (odmax > PLL_CTL0_CLKOD_M + 1)
+		odmax = PLL_CTL0_CLKOD_M + 1;
+
+	/*
+	 * Search through valid combinations of od and r, starting with lower
+	 * output divider values to get a lower intermediate frequency.
+	 */
+	for (od = odmin; od <= odmax; ++od) {
+		for (r = 1; r <= PLL_CTL1_CLKR_M + 1; ++r) {
+			/*
+			 * Calculate best f for given r and od, rounding down
+			 * So for f, freq <= rate
+			 * And for f+1, freq > rate
+			 * We have to do rate+1 because rate may have itself
+			 * been rounded down.
+			 */
+			rod2 = 2 * r * od;
+			f = div_u64((u64)(rate + 1) * rod2, parent_rate);
+			if (f < 1)
+				continue;
+			if (f > PLL_CTL0_CLKF_M + 1)
+				f = PLL_CTL0_CLKF_M + 1;
+
+			/* Calculate final rate and see if it's the best */
+			cur = div_u64((u64)parent_rate * f, rod2);
+			if (cur > best) {
+				bestf = f;
+				bestr = r;
+				bestod = od;
+				best = cur;
+				/* Can't improve on a perfect match */
+				if (cur == rate)
+					goto done;
+			}
+		}
+	}
+	if (!best)
+		return 0;
+done:
+	pr_debug("clk_tz1090_pll: final %lu/%lu * %lu/2/%lu=%lu (req=%lu, err=%ld)\n",
+		 parent_rate, bestr, bestf, bestod, best, rate, best - rate);
+
+	*clkf = bestf;
+	*clkr = bestr;
+	*clkod = bestod;
+	return best;
+}
+
+static long clk_tz1090_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *prate)
+{
+	unsigned long clkf, clkr, clkod;
+	unsigned long parent_rate = *prate;
+
+	return clk_tz1090_pll_bestvals(hw, parent_rate, rate, &clkf, &clkr,
+				       &clkod);
+}
+
+static int clk_tz1090_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct clk_tz1090_pll *pll = to_clk_tz1090_pll(hw);
+	unsigned long clkf, clkr, clkod, bwadj;
+	u32 ctl0, ctl1;
+
+	if (!clk_tz1090_pll_bestvals(hw, parent_rate, rate,
+				     &clkf, &clkr, &clkod))
+		return -EINVAL;
+
+	/* offset the values ready to go in the PLL registers */
+	--clkr;
+	--clkf;
+	--clkod;
+	bwadj = clkf / 2;
+
+	/* bypass, reset and configure PLL */
+	ctl0 =	(bwadj << PLL_CTL0_BWADJ_S) |
+		(clkf  << PLL_CTL0_CLKF_S)  |
+		(clkod << PLL_CTL0_CLKOD_S);
+	ctl1 =	PLL_CTL1_RESET_B  |
+		PLL_CTL1_ENSAT_B  |
+		PLL_CTL1_BYPASS_B |
+		(clkr  << PLL_CTL1_CLKR_S);
+	writel(ctl1, pll->reg + PLL_CTL1);
+	writel(ctl0, pll->reg + PLL_CTL0);
+
+	/* allow 5us after clkf before deasserting reset */
+	udelay(5);
+
+	/* take PLL out of reset and enable fasten */
+	ctl1 &= ~PLL_CTL1_RESET_B;
+	ctl1 |= PLL_CTL1_FASTEN_B;
+	writel(ctl1, pll->reg + PLL_CTL1);
+
+	/* count at least 500 divided ref clks to allow time to lock */
+	msleep(1 + 500*1000*(clkr+1)/parent_rate);
+
+	/* take PLL out of fasten / bypass */
+	ctl1 &= ~PLL_CTL1_FASTEN_B;
+	ctl1 &= ~PLL_CTL1_BYPASS_B;
+	writel(ctl1, pll->reg + PLL_CTL1);
+
+	return 0;
+}
+
+static const struct clk_ops clk_tz1090_pll_ops = {
+	.recalc_rate = clk_tz1090_pll_recalc_rate,
+	.round_rate = clk_tz1090_pll_round_rate,
+	.set_rate = clk_tz1090_pll_set_rate,
+};
+
+/**
+ * clk_register_tz1090_pll_setup - register a PLL with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ *
+ * Register a TZ1090 PLL clock to the clock framework.
+ */
+static struct clk *__init clk_register_tz1090_pll(struct device *dev,
+						  const char *name,
+						  const char *parent_name,
+						  unsigned long flags,
+						  void __iomem *reg)
+{
+	struct clk_tz1090_pll *div;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct clk_tz1090_pll), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_tz1090_pll_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_tz1090_pll assignments */
+	div->reg = reg;
+	div->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(dev, &div->hw);
+
+	if (IS_ERR(clk))
+		kfree(div);
+
+	return clk;
+}
+
+/**
+ * of_tz1090_pll_setup() - Setup function for PLL in TZ1090
+ */
+static void __init of_tz1090_pll_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s(%s): could not read parent clock\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s(%s): of_iomap failed\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	clk = clk_register_tz1090_pll(NULL, clk_name, parent_name, 0, reg);
+	if (IS_ERR(clk))
+		goto err_iounmap;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+	return;
+
+err_iounmap:
+	iounmap(reg);
+}
+CLK_OF_DECLARE(tz1090_pll_clk, "img,tz1090-pll", of_tz1090_pll_setup);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/15] dt: binding: add binding for TZ1090 gate bank
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (3 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 04/15] clk: tz1090: add PLL clock driver James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 06/15] clk: tz1090: add gate bank clock driver James Hogan
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

Add DT binding for a bank of clock gates in the TZ1090 SoC. There are
several such registers which contain only bits controlling clock gates.

The bit-mask property determines the mask of bits of the register which
control gates. The number of input (and output) clocks is equal to the
number of set bits in the bit-mask, and the clocks and
clock-output-names arrays list the clocks/names from the least
significant set bit in the mask to the most significant set bit.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 .../bindings/clock/img,tz1090-gate-bank.txt        | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-gate-bank.txt

diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-gate-bank.txt b/Documentation/devicetree/bindings/clock/img,tz1090-gate-bank.txt
new file mode 100644
index 0000000..7a93f6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-gate-bank.txt
@@ -0,0 +1,52 @@
+Binding for TZ1090 clock gate bank.
+
+This binding uses the common clock binding[1]. It assumes a register-mapped bank
+of clock gates, where each bit in the register can control a single gate. The
+number of clocks in the bank is specified indirectly by the number of set bits
+in the bit-mask property.
+
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : shall be "img,tz1090-gate-bank".
+- #clock-cells       : from common clock binding; shall be set to 1.
+- reg                : base address for register controlling gates
+- bit-mask           : bitmask of bits in register controlling gates
+- clocks             : clock specifiers of parent clock of each gate with bit
+                       set in bit-mask
+- clock-output-names : from common clock binding. Name of each gate with bit set
+                       in bit-mask
+
+Clock Specifier Definition:
+- <1st-cell>: gate number, counting from 0 (the gate controlled by the lowest
+              set bit in bit-mask) to the number of gates - 1 (i.e.  omitting
+              any clear bits in bit-mask)
+
+Examples:
+	clkenab {
+		compatible = "img,tz1090-gate-bank";
+		#clock-cells = <1>;
+		reg = <0x0200590c 0x4>;
+		bit-mask = <0x020b7220>;
+		clock-output-names =
+			"out0_en",
+			"out1_en",
+			"i2s_en",
+			"scb_en",
+			"uart_en",
+			"ext_stc1_en",
+			"ext_stc1_en",
+			"usb_en",
+			"adcpll_en";
+		clocks =
+			<&clkswitch 5>,
+			<&clkswitch 9>,
+			<&clkswitch 12>,
+			<&clkswitch 13>,
+			<&clkswitch 14>,
+			<&clkswitch 15>,
+			<&clkswitch 16>,
+			<&clkswitch 18>,
+			<&clkswitch 24>;
+	};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/15] clk: tz1090: add gate bank clock driver
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (4 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 05/15] dt: binding: add binding for TZ1090 gate bank James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 07/15] dt: binding: add binding for TZ1090 mux bank James Hogan
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

Add a clock driver for banks of clock gates in the TZ1090 SoC. A single
32 bit register controls up to 32 separate clock gates. The driver
instantiates separate generic clock gates. The clock operations are
wrapped in order to acquire and release the Meta global exclusive lock
(__global_lock2) to ensure atomicity with other non-Linux cores and
threads which may need to control some of the clocks.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
 drivers/clk/tz1090/Makefile               |   1 +
 drivers/clk/tz1090/clk-tz1090-gate-bank.c | 199 ++++++++++++++++++++++++++++++
 2 files changed, 200 insertions(+)
 create mode 100644 drivers/clk/tz1090/clk-tz1090-gate-bank.c

diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
index 14f2d33..ce36250 100644
--- a/drivers/clk/tz1090/Makefile
+++ b/drivers/clk/tz1090/Makefile
@@ -1,2 +1,3 @@
 # Makefile for TZ1090-specific clocks
+obj-y		+= clk-tz1090-gate-bank.o
 obj-y		+= clk-tz1090-pll.o
diff --git a/drivers/clk/tz1090/clk-tz1090-gate-bank.c b/drivers/clk/tz1090/clk-tz1090-gate-bank.c
new file mode 100644
index 0000000..a8c396c
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-gate-bank.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Clock gate bank
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/global_lock.h>
+
+/**
+ * struct clk_tz1090_gate - tz1090 gating clock
+ *
+ * @mux:	the parent class
+ * @ops:	pointer to clk_ops of parent class
+ *
+ * Clock which can gate its output. Extends basic mux by using a global
+ * exclusive lock when read-modify-writing the mux field so that multiple
+ * threads/cores can use different fields in the same register.
+ */
+struct clk_tz1090_gate {
+	struct clk_gate		gate;
+	const struct clk_ops	*ops;
+};
+
+static inline struct clk_tz1090_gate *to_clk_tz1090_gate(struct clk_hw *hw)
+{
+	struct clk_gate *gate = container_of(hw, struct clk_gate, hw);
+
+	return container_of(gate, struct clk_tz1090_gate, gate);
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static int clk_tz1090_gate_enable(struct clk_hw *hw)
+{
+	struct clk_tz1090_gate *gate = to_clk_tz1090_gate(hw);
+	int ret;
+	unsigned long flags;
+
+	__global_lock2(flags);
+	ret = gate->ops->enable(&gate->gate.hw);
+	__global_unlock2(flags);
+
+	return ret;
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static void clk_tz1090_gate_disable(struct clk_hw *hw)
+{
+	struct clk_tz1090_gate *gate = to_clk_tz1090_gate(hw);
+	unsigned long flags;
+
+	__global_lock2(flags);
+	gate->ops->disable(&gate->gate.hw);
+	__global_unlock2(flags);
+}
+
+static int clk_tz1090_gate_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tz1090_gate *gate = to_clk_tz1090_gate(hw);
+
+	return gate->ops->is_enabled(&gate->gate.hw);
+}
+
+static const struct clk_ops clk_tz1090_gate_ops = {
+	.enable = clk_tz1090_gate_enable,
+	.disable = clk_tz1090_gate_disable,
+	.is_enabled = clk_tz1090_gate_is_enabled,
+};
+
+/**
+ * clk_register_tz1090_gate - register a TZ1090 gate clock with clock framework
+ * @name: name of this clock
+ * @parent_name: name of this clock's parent
+ * @flags: framework-specific flags for this clock
+ * @reg: register address to control gating of this clock
+ * @bit_idx: which bit in the register controls gating of this clock
+ * @clk_gate_flags: gate-specific flags for this clock
+ */
+static struct clk *__init clk_register_tz1090_gate(const char *name,
+				const char *parent_name, unsigned long flags,
+				void __iomem *reg, u8 bit_idx,
+				u8 clk_gate_flags)
+{
+	struct clk_tz1090_gate *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the gate */
+	gate = kzalloc(sizeof(struct clk_tz1090_gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_tz1090_gate_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_gate assignments */
+	gate->gate.reg = reg;
+	gate->gate.bit_idx = bit_idx;
+	gate->gate.flags = clk_gate_flags;
+	gate->gate.hw.init = &init;
+
+	/* struct clk_tz1090_gate assignments */
+	gate->ops = &clk_gate_ops;
+
+	clk = clk_register(NULL, &gate->gate.hw);
+
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
+
+/**
+ * of_tz1090_gate_bank_setup() - Setup function for gate bank in TZ1090
+ */
+static void __init of_tz1090_gate_bank_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	const char *parent_name;
+	u32 mask;
+	unsigned int shift, i;
+	unsigned int successes = 0;
+	struct clk_onecell_data *provider_data = NULL;
+	int count;
+
+	if (of_property_read_u32(node, "bit-mask", &mask))
+		return;
+
+	count = of_property_count_strings(node, "clock-output-names");
+	if (count < 1)
+		return;
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s(%s): of_iomap failed\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	provider_data = kzalloc(sizeof(*provider_data), GFP_KERNEL);
+	if (!provider_data)
+		goto done;
+	provider_data->clks = kcalloc(count, sizeof(provider_data->clks[0]),
+				      GFP_KERNEL);
+	if (!provider_data->clks)
+		goto done;
+
+	for (i = 0; mask && i < count; ++i) {
+		/* Find next set bit in mask */
+		shift = ffs(mask) - 1;
+		mask &= ~BIT(shift);
+
+		if (of_property_read_string_index(node, "clock-output-names", i,
+						  &clk_name))
+			goto done;
+
+
+		parent_name = of_clk_get_parent_name(node, i);
+		if (!parent_name)
+			goto done;
+
+		++provider_data->clk_num;
+		clk = clk_register_tz1090_gate(clk_name, parent_name,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, reg,
+				shift, 0);
+		if (!IS_ERR(clk))
+			++successes;
+		provider_data->clks[i] = clk;
+	}
+done:
+
+	if (!successes) {
+		if (provider_data) {
+			kfree(provider_data->clks);
+			kfree(provider_data);
+		}
+		iounmap(reg);
+		return;
+	}
+
+	of_clk_add_provider(node, of_clk_src_onecell_get, provider_data);
+}
+CLK_OF_DECLARE(tz1090_gate_bank_clk, "img,tz1090-gate-bank",
+	       of_tz1090_gate_bank_setup);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/15] dt: binding: add binding for TZ1090 mux bank
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (5 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 06/15] clk: tz1090: add gate bank clock driver James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 08/15] clk: tz1090: add mux bank clock driver James Hogan
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

Add DT binding for a bank of clock muxes in the TZ1090 SoC. There are
several such registers which contain only bits controlling clock muxes.

The bit-mask property determines the mask of bits of the register which
control muxes. The number of output clocks is equal to the number of set
bits in the bit-mask, and the clock-output-names array lists the
names from the least significant set bit in the mask to the most
significant set bit. The number of input clocks is double the number of
output clocks since each bit muxes between two input clocks, so the
clocks array lists two input clocks per set bit.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 .../bindings/clock/img,tz1090-mux-bank.txt         | 56 ++++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-mux-bank.txt

diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-mux-bank.txt b/Documentation/devicetree/bindings/clock/img,tz1090-mux-bank.txt
new file mode 100644
index 0000000..2272f87
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-mux-bank.txt
@@ -0,0 +1,56 @@
+Binding for TZ1090 clock mux bank.
+
+This binding uses the common clock binding[1]. It assumes a register-mapped bank
+of clock muxes, where each bit in the register can control a single mux. The
+number of clocks in the bank is specified indirectly by the number of set bits
+in the bit-mask property.
+
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : shall be "img,tz1090-mux-bank".
+- #clock-cells       : from common clock binding; shall be set to 1.
+- reg                : base address for register controlling muxes
+- bit-mask           : bitmask of bits in register controlling muxes
+- clocks             : clock specifiers of two parent clocks for each mux with a
+                       bit set in bit-mask
+- clock-output-names : from common clock binding. Name of each mux with bit set
+                       in bit-mask
+
+Clock Specifier Definition:
+- <1st-cell>: mux number, counting from 0 (the mux controlled by the lowest set
+              bit in bit-mask) to the number of muxes - 1 (i.e.  omitting any
+              clear bits in bit-mask).
+
+Examples:
+	/*                       ___________
+	 * xtal1         ------o|clkout0_sw0\______
+	 * afe_progdiv1_to_soc -|___________/  2   |
+	 * sys_clk_undeleted --o|clkout0_sw1\____  |
+	 * if0_sw        -------|___________/  3 | |
+	 *                 ,-;==================='-'
+	 *                 | |   ___________
+	 * clkout0_sw0     | `-o|clkout0_sw2\______
+	 * xtal2         --|----|___________/  4   |
+	 *                 |  _____________________|
+	 *                 | |   ___________
+	 * clkout0_sw2     | `-o|clkout0_sw3\___________
+	 * clkout0_sw1     `----|___________/  5
+	 */
+	clkswitch: clkswitch {
+		compatible = "img,tz1090-mux-bank";
+		#clock-cells = <1>;
+		reg = <0x02005908 0x4>;
+		bit-mask = <0x0000003c>;
+		clock-output-names =
+			"out0_sw0",
+			"out0_sw1",
+			"out0_sw2",
+			"out0_sw3",
+		clocks =
+			<&xtal1>,		<&afe_progdiv1_to_soc>,
+			<&sys_clk_undeleted>,	<&clkswitch2 6>,
+			<&clkswitch 0>,		<&xtal2>,
+			<&clkswitch 2>,		<&clkswitch 1>,
+	};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/15] clk: tz1090: add mux bank clock driver
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (6 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 07/15] dt: binding: add binding for TZ1090 mux bank James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 09/15] dt: binding: add binding for TZ1090 clock deleter James Hogan
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

Add a clock driver for banks of clock muxes in the TZ1090 SoC. A single
32 bit register controls up to 32 separate clock muxes. The driver
instantiates separate generic clock muxes. The clock operations are
wrapped in order to acquire and release the Meta global exclusive lock
(__global_lock2) to ensure atomicity with other non-Linux cores and
threads which may need to control some of the clocks.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
 drivers/clk/tz1090/Makefile              |   1 +
 drivers/clk/tz1090/clk-tz1090-mux-bank.c | 191 +++++++++++++++++++++++++++++++
 2 files changed, 192 insertions(+)
 create mode 100644 drivers/clk/tz1090/clk-tz1090-mux-bank.c

diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
index ce36250..ee6a6fe 100644
--- a/drivers/clk/tz1090/Makefile
+++ b/drivers/clk/tz1090/Makefile
@@ -1,3 +1,4 @@
 # Makefile for TZ1090-specific clocks
 obj-y		+= clk-tz1090-gate-bank.o
+obj-y		+= clk-tz1090-mux-bank.o
 obj-y		+= clk-tz1090-pll.o
diff --git a/drivers/clk/tz1090/clk-tz1090-mux-bank.c b/drivers/clk/tz1090/clk-tz1090-mux-bank.c
new file mode 100644
index 0000000..d9a2345
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-mux-bank.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Clock mux bank
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/global_lock.h>
+
+/**
+ * struct clk_tz1090_mux - tz1090 multiplexer clock
+ *
+ * @mux:	the parent class
+ * @ops:	pointer to clk_ops of parent class
+ *
+ * Clock with multiple selectable parents. Extends basic mux by using a global
+ * exclusive lock when read-modify-writing the mux field so that multiple
+ * threads/cores can use different fields in the same register.
+ */
+struct clk_tz1090_mux {
+	struct clk_mux		mux;
+	const struct clk_ops	*ops;
+};
+
+static inline struct clk_tz1090_mux *to_clk_tz1090_mux(struct clk_hw *hw)
+{
+	struct clk_mux *mux = container_of(hw, struct clk_mux, hw);
+
+	return container_of(mux, struct clk_tz1090_mux, mux);
+}
+
+static u8 clk_tz1090_mux_get_parent(struct clk_hw *hw)
+{
+	struct clk_tz1090_mux *mux = to_clk_tz1090_mux(hw);
+
+	return mux->ops->get_parent(&mux->mux.hw);
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static int clk_tz1090_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_tz1090_mux *mux = to_clk_tz1090_mux(hw);
+	int ret;
+	unsigned long flags;
+
+	__global_lock2(flags);
+	ret = mux->ops->set_parent(&mux->mux.hw, index);
+	__global_unlock2(flags);
+
+	return ret;
+}
+
+static long clk_tz1090_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate,
+				     struct clk **best_parent)
+{
+	struct clk_tz1090_mux *mux = to_clk_tz1090_mux(hw);
+
+	return mux->ops->determine_rate(&mux->mux.hw, rate, prate, best_parent);
+}
+
+static const struct clk_ops clk_tz1090_mux_ops = {
+	.get_parent = clk_tz1090_mux_get_parent,
+	.set_parent = clk_tz1090_mux_set_parent,
+	.determine_rate = clk_tz1090_mux_determine_rate,
+};
+
+struct clk *__init
+clk_register_tz1090_mux(const char *name, const char **parent_names,
+			unsigned long flags, void __iomem *reg, u8 shift,
+			u8 clk_mux_flags)
+{
+	struct clk_tz1090_mux *mux;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the mux */
+	mux = kzalloc(sizeof(struct clk_tz1090_mux), GFP_KERNEL);
+	if (!mux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_tz1090_mux_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = 2;
+
+	/* struct clk_mux assignments */
+	mux->mux.reg = reg;
+	mux->mux.shift = shift;
+	mux->mux.mask = 0x1;
+	mux->mux.flags = clk_mux_flags;
+	mux->mux.hw.init = &init;
+
+	/* struct clk_tz1090_mux assignments */
+	mux->ops = &clk_mux_ops;
+
+	clk = clk_register(NULL, &mux->mux.hw);
+
+	if (IS_ERR(clk))
+		kfree(mux);
+
+	return clk;
+}
+
+/**
+ * of_tz1090_mux_bank_setup() - Setup function for mux bank in TZ1090
+ */
+static void __init of_tz1090_mux_bank_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	const char *parent_name[2];
+	u32 mask;
+	unsigned int shift, i, j;
+	unsigned int successes = 0;
+	struct clk_onecell_data *provider_data = NULL;
+	int count;
+
+	if (of_property_read_u32(node, "bit-mask", &mask))
+		return;
+
+	count = of_property_count_strings(node, "clock-output-names");
+	if (count < 1)
+		return;
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s(%s): of_iomap failed\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	provider_data = kzalloc(sizeof(*provider_data), GFP_KERNEL);
+	if (!provider_data)
+		goto done;
+	provider_data->clks = kcalloc(count, sizeof(provider_data->clks[0]),
+				      GFP_KERNEL);
+	if (!provider_data->clks)
+		goto done;
+
+	for (i = 0; mask && i < count; ++i) {
+		/* Find next set bit in mask */
+		shift = ffs(mask) - 1;
+		mask &= ~BIT(shift);
+
+		if (of_property_read_string_index(node, "clock-output-names", i,
+						  &clk_name))
+			goto done;
+
+
+		for (j = 0; j < 2; ++j) {
+			parent_name[j] = of_clk_get_parent_name(node, i*2 + j);
+			if (!parent_name[j])
+				goto done;
+		}
+
+		++provider_data->clk_num;
+		clk = clk_register_tz1090_mux(clk_name, parent_name,
+					      CLK_SET_RATE_PARENT, reg, shift,
+					      0);
+		if (!IS_ERR(clk))
+			++successes;
+		provider_data->clks[i] = clk;
+	}
+done:
+
+	if (!successes) {
+		if (provider_data) {
+			kfree(provider_data->clks);
+			kfree(provider_data);
+		}
+		iounmap(reg);
+		return;
+	}
+
+	of_clk_add_provider(node, of_clk_src_onecell_get, provider_data);
+}
+CLK_OF_DECLARE(tz1090_mux_bank_clk, "img,tz1090-mux-bank",
+	       of_tz1090_mux_bank_setup);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/15] dt: binding: add binding for TZ1090 clock deleter
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (7 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 08/15] clk: tz1090: add mux bank clock driver James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 10/15] clk: tz1090: add deleter clock driver James Hogan
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

Add DT binding for the clock deleters in the TZ1090 SoC, which delete up
to 1023 out of every 1024 clock pulses of the input clock.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 .../bindings/clock/img,tz1090-deleter.txt          | 40 ++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-deleter.txt

diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-deleter.txt b/Documentation/devicetree/bindings/clock/img,tz1090-deleter.txt
new file mode 100644
index 0000000..0f595be
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-deleter.txt
@@ -0,0 +1,40 @@
+Binding for TZ1090 clock deleter.
+
+This binding uses the common clock binding[1]. The TZ1090 clock deleters can be
+configured to delete a certain fraction of the input clock pulses, so the output
+frequency is:
+
+    deleted_cycles = (reg & bit_mask) >> bit_shift
+    f_out = f_in * (cycle_period - deleted_cycles) / cycle_period
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : Shall be "img,tz1090-deleter".
+- #clock-cells       : From common clock binding; shall be set to 0.
+- reg                : Address of configuration register.
+- bit-mask           : Shift of config value field in configuration register.
+- clocks             : From common clock binding.
+
+Required source clocks:
+- 0                  : Reference clock which is deleted to produce the output
+                       clock (doesn't have to be named).
+
+Optional properties:
+- clock-output-names : From common clock binding.
+- bit-shift          : Number of bits to shift the bit-mask, defaults to
+                       (ffs(mask) - 1) if not present.
+- cycle-period       : Period from which clocks are deleted, defaults to
+                       (1 << (fls(mask) - bit-shift)) if not present.
+
+Example:
+	meta_clkdelete {
+		compatible = "img,tz1090-deleter";
+		#clock-cells = <0>;
+		clocks = <&sys_clk_x2_undeleted>;
+		reg = <0x0200591c 0x4>;
+		bit-mask = <0x000003ff>;
+		/* implicit bit-shift = <0> */
+		/* implicit cycle-period = <1024> */
+		clock-output-names = "meta";
+	};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/15] clk: tz1090: add deleter clock driver
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (8 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 09/15] dt: binding: add binding for TZ1090 clock deleter James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 11/15] dt: binding: add binding for TZ1090 PDC clock James Hogan
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

Add driver for TZ1090 clock deleter, which deletes up to 1023 out of
every 1024 clock pulses. Two of these exist, one for the Meta core and
the other for the system clock.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
 drivers/clk/tz1090/Makefile             |   1 +
 drivers/clk/tz1090/clk-tz1090-deleter.c | 188 ++++++++++++++++++++++++++++++++
 2 files changed, 189 insertions(+)
 create mode 100644 drivers/clk/tz1090/clk-tz1090-deleter.c

diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
index ee6a6fe..d17e48c 100644
--- a/drivers/clk/tz1090/Makefile
+++ b/drivers/clk/tz1090/Makefile
@@ -1,4 +1,5 @@
 # Makefile for TZ1090-specific clocks
+obj-y		+= clk-tz1090-deleter.o
 obj-y		+= clk-tz1090-gate-bank.o
 obj-y		+= clk-tz1090-mux-bank.o
 obj-y		+= clk-tz1090-pll.o
diff --git a/drivers/clk/tz1090/clk-tz1090-deleter.c b/drivers/clk/tz1090/clk-tz1090-deleter.c
new file mode 100644
index 0000000..b814430
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-deleter.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2012 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Clock deleter in TZ1090
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+/**
+ * struct clk_tz1090_deleter - Clock deleter
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	delete register
+ * @period:	cycle period
+ * @mask:	bit mask of delete field
+ * @shift:	start bit of delete field
+ *
+ * Deleter in TZ1090.  Implements .recalc_rate, .set_rate and .round_rate
+ */
+struct clk_tz1090_deleter {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u32		period;
+	u32		mask;
+	u8		shift;
+};
+
+/*
+ * DOC: TZ1090 adjustable deleter clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable in hardware but set_rate unimplemented.
+ *		clk->rate = (parent->rate * (period - delete)) / period
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+#define to_clk_tz1090_deleter(_hw) \
+	container_of(_hw, struct clk_tz1090_deleter, hw)
+
+static unsigned long clk_tz1090_deleter_recalc_rate(struct clk_hw *hw,
+						    unsigned long parent_rate)
+{
+	struct clk_tz1090_deleter *deleter = to_clk_tz1090_deleter(hw);
+	u32 delete;
+	u64 rate;
+
+	delete = (readl(deleter->reg) & deleter->mask) >> deleter->shift;
+	rate = (u64)parent_rate * (deleter->period - delete);
+	do_div(rate, deleter->period);
+	return rate;
+}
+
+static const struct clk_ops clk_tz1090_deleter_ops = {
+	.recalc_rate = clk_tz1090_deleter_recalc_rate,
+};
+
+/**
+ * clk_register_tz1090_deleter_setup - register a clock deleter clock
+ * @dev:		device registering this clock
+ * @name:		name of this clock
+ * @parent_name:	name of clock's parent
+ * @flags:		framework-specific flags
+ * @reg:		register address to adjust deleter
+ * @period:		delete cycle period
+ * @mask:		mask of delete field
+ * @shift:		start bit of delete field
+ *
+ * Register a TZ1090 clock deleter with the clock framework.
+ */
+static struct clk *__init clk_register_tz1090_deleter(struct device *dev,
+						      const char *name,
+						      const char *parent_name,
+						      unsigned long flags,
+						      void __iomem *reg,
+						      u32 period,
+						      u32 mask,
+						      u8 shift)
+{
+	struct clk_tz1090_deleter *deleter;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	deleter = kzalloc(sizeof(struct clk_tz1090_deleter), GFP_KERNEL);
+	if (!deleter)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_tz1090_deleter_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_tz1090_deleter assignments */
+	deleter->reg = reg;
+	deleter->period = period;
+	deleter->mask = mask;
+	deleter->shift = shift;
+	deleter->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(dev, &deleter->hw);
+
+	if (IS_ERR(clk))
+		kfree(deleter);
+
+	return clk;
+}
+
+#ifdef CONFIG_OF
+/**
+ * of_tz1090_deleter_setup() - Setup function for clock deleter
+ */
+static void __init of_tz1090_deleter_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	u32 mask, shift, period;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	if (of_property_read_u32(node, "bit-mask", &mask)) {
+		pr_err("%s(%s): could not read bit-mask property\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	if (of_property_read_u32(node, "bit-shift", &shift)) {
+		shift = ffs(mask) - 1;
+		pr_debug("%s(%s): bit-shift property defaults to %u\n",
+			 __func__, clk_name, shift);
+	}
+
+	if (of_property_read_u32(node, "cycle-period", &period)) {
+		period = fls(mask);
+		if (shift > period) {
+			pr_err("%s(%s): bit-shift %u beyond top of bit-mask %#x\n",
+			       __func__, clk_name, shift, mask);
+			return;
+		}
+		period = 1 << (period - shift);
+		pr_debug("%s(%s): cycle-period property defaults to %u\n",
+			 __func__, clk_name, period);
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s(%s): could not read parent clock\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s(%s): of_iomap failed\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	clk = clk_register_tz1090_deleter(NULL, clk_name, parent_name, 0, reg,
+					  period, mask, shift);
+	if (IS_ERR(clk))
+		goto err_iounmap;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+	return;
+
+err_iounmap:
+	iounmap(reg);
+}
+CLK_OF_DECLARE(tz1090_deleter_clk, "img,tz1090-deleter",
+	       of_tz1090_deleter_setup);
+#endif /* CONFIG_OF */
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/15] dt: binding: add binding for TZ1090 PDC clock
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (9 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 10/15] clk: tz1090: add deleter clock driver James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 12/15] clk: tz1090: add PDC clock driver James Hogan
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

The TZ1090 PDC (PowerDown Controller) clock should be at 32.768KHz, and
is generated either directly from the XTAL3 clock or by dividing the
XTAL1 clock. Both the divide and the mux are in a single register which
also contains GPIO output data, and may need to be used by other
non-Linux cores and threads, so create a special clock binding for this
clock.

It essentially has just two clock inputs, and two clock outputs.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 .../bindings/clock/img,tz1090-pdc-clock.txt        | 44 ++++++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-pdc-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-pdc-clock.txt b/Documentation/devicetree/bindings/clock/img,tz1090-pdc-clock.txt
new file mode 100644
index 0000000..68e2eee
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-pdc-clock.txt
@@ -0,0 +1,44 @@
+Binding for TZ1090 PDC clock.
+
+This binding uses the common clock binding[1]. It has two input clocks
+(clocks[0..1]), two output clocks (out[0..1]), and a memory-mapped register
+(reg) controlling a divider and a mux atomically with respect to other fields
+and (non-Linux) threads or cores.
+
+              _____
+clocks[0] ___| div |______________________
+             |_____|  |    ____   out[0]
+                      `--o| sw \__________
+clocks[1] ----------------|____/  out[1]
+
+
+out[0] = clocks[0] / (reg[26:16] + 1)
+out[1] = reg[30] ? clocks[1] : out[0]
+
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : shall be "img,tz1090-pdc-clock".
+- #clock-cells       : from common clock binding; shall be set to 1.
+- reg                : base address for register controlling mux and divider
+- clocks             : clock specifiers of two parent clocks
+- clock-output-names : from common clock binding. Name of two output clocks.
+
+Clock Specifier Definition:
+- <1st-cell>: output clock number.
+
+Examples:
+	/*           ___________
+	 * xtal1 ___| xtal1_div |____________________________
+	 *          |___________|  |    ________   xtal1_div
+	 *                         `--o| rtc_sw \____________
+	 * xtal3 ----------------------|________/  32khz
+	 */
+	pdc_clk {
+		compatible = "img,tz1090-pdc-clock";
+		#clock-cells = <1>;
+		reg = <0x02006500 4>;	/* SOC_GPIO_CONTROL0 */
+		clocks = <&xtal1>, <&xtal3>;
+		clock-output-names = "xtal1_div", "32khz";
+	};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 12/15] clk: tz1090: add PDC clock driver
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (10 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 11/15] dt: binding: add binding for TZ1090 PDC clock James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 13/15] dt: binding: add binding for TZ1090 divider clock James Hogan
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

The TZ1090 PDC (PowerDown Controller) clock should be at 32.768KHz, and
is generated either directly from the XTAL3 clock or by dividing the
XTAL1 clock. Both the divide and the mux are in a single register which
also contains GPIO output data, and may need to be used by other
non-Linux cores and threads, so create a special clock type for this
clock.

Two subclocks are created, a divider and a mux. The divider wraps the
generic divider but takes the Meta exclusive lock when setting the rate.
The mux uses the existing mux wrapper in clk-tz1090-mux-bank.c which
also takes the Meta exclusive lock when changing the parent.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
 drivers/clk/tz1090/Makefile         |   1 +
 drivers/clk/tz1090/clk-tz1090-pdc.c | 185 ++++++++++++++++++++++++++++++++++++
 2 files changed, 186 insertions(+)
 create mode 100644 drivers/clk/tz1090/clk-tz1090-pdc.c

diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
index d17e48c..92e38a8 100644
--- a/drivers/clk/tz1090/Makefile
+++ b/drivers/clk/tz1090/Makefile
@@ -2,4 +2,5 @@
 obj-y		+= clk-tz1090-deleter.o
 obj-y		+= clk-tz1090-gate-bank.o
 obj-y		+= clk-tz1090-mux-bank.o
+obj-y		+= clk-tz1090-pdc.o
 obj-y		+= clk-tz1090-pll.o
diff --git a/drivers/clk/tz1090/clk-tz1090-pdc.c b/drivers/clk/tz1090/clk-tz1090-pdc.c
new file mode 100644
index 0000000..e4ac145
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-pdc.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 PDC Clock (divider + mux)
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/global_lock.h>
+
+/* The TZ1090 PDC clock makes use of the TZ1090 mux wrapper (from mux bank) */
+struct clk *__init
+clk_register_tz1090_mux(const char *name, const char **parent_names,
+			unsigned long flags, void __iomem *reg, u8 shift,
+			u8 clk_mux_flags);
+
+/**
+ * struct clk_tz1090_div - tz1090 divider clock
+ *
+ * @div:	the parent class
+ * @ops:	pointer to clk_ops of parent class
+ *
+ * Divider clock whose field shares a register with other fields which may be
+ * used by multiple threads/cores and other drivers.
+ */
+struct clk_tz1090_div {
+	struct clk_divider	div;
+	const struct clk_ops	*ops;
+};
+
+static inline struct clk_tz1090_div *to_clk_tz1090_div(struct clk_hw *hw)
+{
+	struct clk_divider *div = container_of(hw, struct clk_divider, hw);
+
+	return container_of(div, struct clk_tz1090_div, div);
+}
+
+static unsigned long clk_tz1090_divider_recalc_rate(struct clk_hw *hw,
+						    unsigned long parent_rate)
+{
+	struct clk_tz1090_div *div = to_clk_tz1090_div(hw);
+
+	return div->ops->recalc_rate(&div->div.hw, parent_rate);
+}
+
+static long clk_tz1090_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+					  unsigned long *prate)
+{
+	struct clk_tz1090_div *div = to_clk_tz1090_div(hw);
+
+	return div->ops->round_rate(&div->div.hw, rate, prate);
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static int clk_tz1090_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long parent_rate)
+{
+	struct clk_tz1090_div *div = to_clk_tz1090_div(hw);
+	int ret;
+	unsigned long flags;
+
+	__global_lock2(flags);
+	ret = div->ops->set_rate(&div->div.hw, rate, parent_rate);
+	__global_unlock2(flags);
+
+	return ret;
+}
+
+static const struct clk_ops clk_tz1090_div_ops = {
+	.recalc_rate = clk_tz1090_divider_recalc_rate,
+	.round_rate = clk_tz1090_divider_round_rate,
+	.set_rate = clk_tz1090_divider_set_rate,
+};
+
+static struct clk *__init
+clk_register_tz1090_divider(const char *name, const char *parent_name,
+			    unsigned long flags, void __iomem *reg, u8 shift,
+			    u32 mask, u8 clk_divider_flags)
+{
+	struct clk_tz1090_div *div;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct clk_tz1090_div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_tz1090_div_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_divider assignments */
+	div->div.reg = reg;
+	div->div.shift = shift;
+	div->div.mask = mask;
+	div->div.flags = clk_divider_flags;
+	div->div.hw.init = &init;
+
+	/* struct clk_tz1090_div assignments */
+	div->ops = &clk_divider_ops;
+
+	/* register the clock */
+	clk = clk_register(NULL, &div->div.hw);
+
+	if (IS_ERR(clk))
+		kfree(div);
+
+	return clk;
+}
+
+/**
+ * of_tz1090_pdc_clk_setup() - Setup function for PDC 32.768KHz clock in TZ1090
+ */
+static void __init of_tz1090_pdc_clk_setup(struct device_node *node)
+{
+	void __iomem *reg;
+	const char *clk_names[2];
+	const char *parent_names[2];
+	unsigned int i;
+	struct clk_onecell_data *provider_data;
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s(%s): of_iomap failed\n",
+		       __func__, node->name);
+		return;
+	}
+
+	for (i = 0; i < 2; ++i) {
+		/* input clocks */
+		parent_names[i] = of_clk_get_parent_name(node, i);
+		if (!parent_names[i]) {
+			pr_err("%s(%s): failed to get parent %u\n",
+			       __func__, node->name, i);
+			return;
+		}
+
+		/* output clocks */
+		if (of_property_read_string_index(node, "clock-output-names", i,
+						  &clk_names[i])) {
+			pr_err("%s(%s): failed to get clock %u name\n",
+			       __func__, node->name, i);
+			return;
+		}
+	}
+
+	provider_data = kzalloc(sizeof(*provider_data), GFP_KERNEL);
+	if (!provider_data)
+		return;
+	provider_data->clk_num = 2;
+	provider_data->clks = kzalloc(sizeof(provider_data->clks[0])*2,
+				      GFP_KERNEL);
+	if (!provider_data->clks) {
+		kfree(provider_data);
+		return;
+	}
+
+	/* divide 1st parent clock (XTAL1) */
+	provider_data->clks[0] = clk_register_tz1090_divider(clk_names[0],
+					parent_names[0], 0, reg,
+					16,		/* shift */
+					BIT(11) - 1,	/* mask */
+					0);
+	parent_names[0] = clk_names[0];
+	/* mux divided 1st parent clock (XTAL1) and 2nd parent clock (XTAL3) */
+	provider_data->clks[1] = clk_register_tz1090_mux(clk_names[1],
+					parent_names, CLK_SET_RATE_PARENT, reg,
+					30,		/* bit */
+					0);
+
+	of_clk_add_provider(node, of_clk_src_onecell_get, provider_data);
+}
+CLK_OF_DECLARE(tz1090_pdc_clk, "img,tz1090-pdc-clock", of_tz1090_pdc_clk_setup);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 13/15] dt: binding: add binding for TZ1090 divider clock
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (11 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 12/15] clk: tz1090: add PDC clock driver James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 14/15] clk: tz1090: add divider clock driver James Hogan
  2014-11-19 23:15 ` [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree James Hogan
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

Add binding for TZ1090 divider clock. This supports a subset of the
functionality of the generic divider, and by being specific to the
TZ1090 SoC it allows policy decisions to be made from the driver.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 .../bindings/clock/img,tz1090-divider.txt          | 37 ++++++++++++++++++++++
 1 file changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/img,tz1090-divider.txt

diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-divider.txt b/Documentation/devicetree/bindings/clock/img,tz1090-divider.txt
new file mode 100644
index 0000000..25f9b9a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-divider.txt
@@ -0,0 +1,37 @@
+Binding for TZ1090 simple divider clock.
+
+This binding uses the common clock binding[1]. It assumes a register-mapped
+adjustable clock rate divider that does not gate and has only one input clock or
+parent. The value programmed into the register is one less than the actual
+divisor value. E.g:
+
+register value		actual divisor value
+0			1
+1			2
+2			3
+
+The binding must also provide the register to control the divider and the mask
+for the corresponding control bits. The shift is calculated from the mask as
+(ffs(mask) - 1)
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "divider-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link to phandle of parent clock
+- reg : base address for register controlling adjustable divider
+- bit-mask : arbitrary bitmask for programming the adjustable divider
+
+Optional properties:
+- clock-output-names : from common clock binding.
+
+Examples:
+	sys_clk_div: sys_clk_div {
+		compatible = "img,tz1090-divider";
+		#clock-cells = <0>;
+		clocks = <&sys_pll>;
+		reg = <0x02005914 0x4>;	/* CR_TOP_SYSCLK_DIV */
+		bit-mask = <0xff>;	/* CR_TOP_SYSDIV */
+		clock-output-names = "sys_div";
+	};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 14/15] clk: tz1090: add divider clock driver
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (12 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 13/15] dt: binding: add binding for TZ1090 divider clock James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-19 23:15 ` [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree James Hogan
  14 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree; +Cc: James Hogan

Add driver for TZ1090 clock divider, which divides an input clock by an
integer.

Two policy decisions are made depending on the MMIO address of the
divider:
- The UART clock divider sets CLK_SET_RATE_PARENT so that clock changes
  can propagate up to the CLK_UART_SW mux which allows more precision to
  be achieved.
- The Meta clock divider sets CLK_DIVIDER_READ_ONLY to prevent it being
  changed dynamically. This is normally set by the bootloader along with
  the system PLL and has a whole bunch of derivative peripheral clocks.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
 drivers/clk/tz1090/Makefile             |  1 +
 drivers/clk/tz1090/clk-tz1090-divider.c | 96 +++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 drivers/clk/tz1090/clk-tz1090-divider.c

diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
index 92e38a8..529c79c 100644
--- a/drivers/clk/tz1090/Makefile
+++ b/drivers/clk/tz1090/Makefile
@@ -1,5 +1,6 @@
 # Makefile for TZ1090-specific clocks
 obj-y		+= clk-tz1090-deleter.o
+obj-y		+= clk-tz1090-divider.o
 obj-y		+= clk-tz1090-gate-bank.o
 obj-y		+= clk-tz1090-mux-bank.o
 obj-y		+= clk-tz1090-pdc.o
diff --git a/drivers/clk/tz1090/clk-tz1090-divider.c b/drivers/clk/tz1090/clk-tz1090-divider.c
new file mode 100644
index 0000000..92788f1
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-divider.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Basic clock divider in TZ1090 SoC.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define CR_TOP_UARTCLK_DIV 0x02005928
+#define CR_TOP_META_CLKDIV 0x02005918
+
+/**
+ * tz1090_divider_policy() - Apply policy based on the specific divider.
+ * @res:		MMIO resource.
+ * @flags:		Clock flags to be modified depending on the divider.
+ * @divider_flags:	Divider flags to be modified depending on the divider.
+ */
+static void tz1090_divider_policy(const struct resource *res,
+				  unsigned long *flags, u8 *divider_flags)
+{
+	switch (res->start) {
+	case CR_TOP_UARTCLK_DIV:
+		/*
+		 * UART clock changes must propagate up to CLK_UART_SW, which
+		 * muxes between XTAL1 and sys_clk_undeleted, in order to get
+		 * enough precision.
+		 */
+		*flags |= CLK_SET_RATE_PARENT;
+		break;
+	case CR_TOP_META_CLKDIV:
+		/*
+		 * The output of this divider is sys_clk_undeleted. It is set up
+		 * by the bootloader along with the system PLL, and has a whole
+		 * bunch of derivative peripheral clocks. It would be a really
+		 * bad idea to allow it to change on the fly.
+		 */
+		*divider_flags |= CLK_DIVIDER_READ_ONLY;
+		break;
+	}
+}
+
+/**
+ * tz1090_divider_clk_setup() - Setup function for TZ1090 divider clock.
+ * @node:	DT node.
+ */
+static void tz1090_divider_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	const char *parent_name;
+	unsigned long flags = 0;
+	u8 divider_flags = 0;
+	u32 mask = 0;
+	u32 shift = 0;
+	struct resource res;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s: no memory mapped for property reg\n", __func__);
+		return;
+	}
+
+	if (of_property_read_u32(node, "bit-mask", &mask)) {
+		pr_err("%s: missing bit-mask property for %s\n",
+		       __func__, node->name);
+		return;
+	}
+
+	/* Apply policy decisions depending on which divider this is */
+	if (of_address_to_resource(node, 0, &res))
+		return;
+	tz1090_divider_policy(&res, &flags, &divider_flags);
+
+	clk = clk_register_divider_mask(NULL, clk_name, parent_name, flags, reg,
+					shift, mask, divider_flags, NULL, NULL);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(divider_clk, "img,tz1090-divider", tz1090_divider_clk_setup);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree
  2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
                   ` (13 preceding siblings ...)
  2014-11-19 23:15 ` [PATCH 14/15] clk: tz1090: add divider clock driver James Hogan
@ 2014-11-19 23:15 ` James Hogan
  2014-11-20 12:56   ` Heiko Stübner
  14 siblings, 1 reply; 22+ messages in thread
From: James Hogan @ 2014-11-19 23:15 UTC (permalink / raw)
  To: Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: James Hogan, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala

Enable the common clock framework for the TZ1090 SoC, add a tz1090_clk
device tree file describing the clocks, and connect the Meta core clock
so that the rate of the Meta timer can be determined.

Most of the clock tree is described apart from some AFE clocks which
aren't usually of much interest to Linux. These are represented with
placeholder clocks.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-metag@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 arch/metag/Kconfig.soc              |   1 +
 arch/metag/boot/dts/tz1090.dtsi     |   4 +
 arch/metag/boot/dts/tz1090_clk.dtsi | 784 ++++++++++++++++++++++++++++++++++++
 3 files changed, 789 insertions(+)
 create mode 100644 arch/metag/boot/dts/tz1090_clk.dtsi

diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc
index 973640f..93c21c3 100644
--- a/arch/metag/Kconfig.soc
+++ b/arch/metag/Kconfig.soc
@@ -17,6 +17,7 @@ config META21_FPGA
 config SOC_TZ1090
 	bool "Toumaz Xenif TZ1090 SoC (Comet)"
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select COMMON_CLK
 	select IMGPDC_IRQ
 	select METAG_LNKGET_AROUND_CACHE
 	select METAG_META21
diff --git a/arch/metag/boot/dts/tz1090.dtsi b/arch/metag/boot/dts/tz1090.dtsi
index 24ea7d2..9e8ef8b 100644
--- a/arch/metag/boot/dts/tz1090.dtsi
+++ b/arch/metag/boot/dts/tz1090.dtsi
@@ -9,12 +9,16 @@
 #include "skeleton.dtsi"
 
 #include <dt-bindings/interrupt-controller/irq.h>
+#include "tz1090_clk.dtsi"
 
 / {
 	compatible = "toumaz,tz1090", "img,meta";
 
 	interrupt-parent = <&intc>;
 
+	clocks = <&meta_core_clk>;
+	clock-names = "core";
+
 	intc: interrupt-controller {
 		compatible = "img,meta-intc";
 		interrupt-controller;
diff --git a/arch/metag/boot/dts/tz1090_clk.dtsi b/arch/metag/boot/dts/tz1090_clk.dtsi
new file mode 100644
index 0000000..e21362d
--- /dev/null
+++ b/arch/metag/boot/dts/tz1090_clk.dtsi
@@ -0,0 +1,784 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * ============ CLOCK SPECIFIER DEFINITIONS ============
+ */
+
+#define CLK_XTAL1_DIV	&pdc_clk	0
+#define CLK_32KHZ	&pdc_clk	1
+
+#define CLK_SYSCLK0_SW	&top_clkswitch	0	/* bit 0 */
+#define CLK_SYSCLK1_SW	&top_clkswitch	1	/* bit 1 */
+#define CLK_OUT0_SW0	&top_clkswitch	2	/* bit 2 */
+#define CLK_OUT0_SW1	&top_clkswitch	3	/* bit 3 */
+#define CLK_OUT0_SW2	&top_clkswitch	4	/* bit 4 */
+#define CLK_OUT0_SW3	&top_clkswitch	5	/* bit 5 */
+#define CLK_OUT1_SW0	&top_clkswitch	6	/* bit 6 */
+#define CLK_OUT1_SW1	&top_clkswitch	7	/* bit 7 */
+#define CLK_OUT1_SW2	&top_clkswitch	8	/* bit 8 */
+#define CLK_OUT1_SW3	&top_clkswitch	9	/* bit 9 */
+#define CLK_I2S_SW2	&top_clkswitch	10	/* bit 10 */
+#define CLK_I2S_SW0	&top_clkswitch	11	/* bit 11 */
+#define CLK_I2S_SW1	&top_clkswitch	12	/* bit 12 */
+#define CLK_SCB_SW	&top_clkswitch	13	/* bit 13 */
+#define CLK_UART_SW	&top_clkswitch	14	/* bit 14 */
+#define CLK_ESTC0_SW	&top_clkswitch	15	/* bit 16 */
+#define CLK_ESTC1_SW	&top_clkswitch	16	/* bit 17 */
+#define CLK_USB_SW0	&top_clkswitch	17	/* bit 18 */
+#define CLK_USB_SW1	&top_clkswitch	18	/* bit 19 */
+#define CLK_AFE_SW0	&top_clkswitch	19	/* bit 20 */
+#define CLK_AFE_SW1	&top_clkswitch	20	/* bit 21 */
+#define CLK_ADCPLL_SW0	&top_clkswitch	21	/* bit 22 */
+#define CLK_ADCPLL_SW1	&top_clkswitch	22	/* bit 23 */
+#define CLK_ADCPLL_SW2	&top_clkswitch	23	/* bit 24 */
+#define CLK_ADCPLL_SW3	&top_clkswitch	24	/* bit 25 */
+#define CLK_USB_SW2	&top_clkswitch	25	/* bit 28 */
+#define CLK_USB_SW3	&top_clkswitch	26	/* bit 29 */
+
+#define CLK_PIXEL_SW0	&top_clkswitch2	0	/* bit 0 */
+#define CLK_PIXEL_SW1	&top_clkswitch2	1	/* bit 1 */
+#define CLK_PIXEL_SW2	&top_clkswitch2	2	/* bit 2 */
+#define CLK_PIXEL_SW3	&top_clkswitch2	3	/* bit 3 */
+#define CLK_PIXEL_SW4	&top_clkswitch2	4	/* bit 4 */
+#define CLK_IF1_SW	&top_clkswitch2	5	/* bit 5 */
+#define CLK_IF0_SW	&top_clkswitch2	6	/* bit 6 */
+#define CLK_DAC0_SW	&top_clkswitch2	7	/* bit 8 */
+#define CLK_UCC1_SW	&top_clkswitch2	8	/* bit 9 */
+#define CLK_UCC0_SW	&top_clkswitch2	9	/* bit 10 */
+
+#define CLK_OUT0_EN	&top_clkenab	0	/* bit 5 */
+#define CLK_OUT1_EN	&top_clkenab	1	/* bit 9 */
+#define CLK_I2S_EN	&top_clkenab	2	/* bit 12 */
+#define CLK_SCB_EN	&top_clkenab	3	/* bit 13 */
+#define CLK_UART_EN	&top_clkenab	4	/* bit 14 */
+#define CLK_ESTC0_EN	&top_clkenab	5	/* bit 16 */
+#define CLK_ESTC1_EN	&top_clkenab	6	/* bit 17 */
+#define CLK_USB_EN	&top_clkenab	7	/* bit 19 */
+#define CLK_ADCPLL_EN	&top_clkenab	8	/* bit 25 */
+
+#define CLK_PIXEL_EN	&top_clkenab2	0	/* bit 2 */
+#define CLK_IF1_EN	&top_clkenab2	1	/* bit 5 */
+#define CLK_IF0_EN	&top_clkenab2	2	/* bit 6 */
+#define CLK_EADC_EN	&top_clkenab2	3	/* bit 7 */
+#define CLK_DAC0_EN	&top_clkenab2	4	/* bit 8 */
+#define CLK_UCC1_EN	&top_clkenab2	5	/* bit 9 */
+#define CLK_UCC0_EN	&top_clkenab2	6	/* bit 10 */
+
+#define SYSCLK_SCB0	&perip_clken	0	/* bit 0 */
+#define SYSCLK_SCB1	&perip_clken	1	/* bit 1 */
+#define SYSCLK_SCB2	&perip_clken	2	/* bit 2 */
+#define SYSCLK_SDIO	&perip_clken	3	/* bit 3 */
+#define SYSCLK_UART0	&perip_clken	4	/* bit 4 */
+#define SYSCLK_UART1	&perip_clken	5	/* bit 5 */
+#define SYSCLK_SPIM	&perip_clken	6	/* bit 6 */
+#define SYSCLK_SPIS	&perip_clken	7	/* bit 7 */
+#define SYSCLK_SPIM1	&perip_clken	8	/* bit 8 */
+#define SYSCLK_I2SOUT	&perip_clken	9	/* bit 9 */
+#define SYSCLK_I2SIN	&perip_clken	10	/* bit 10 */
+#define SYSCLK_LCD	&perip_clken	11	/* bit 11 */
+#define SYSCLK_SDHOST	&perip_clken	12	/* bit 12 */
+#define SYSCLK_USB	&perip_clken	13	/* bit 13 */
+
+#define CLK_2D_EN	&hep_clken	0	/* bit 0 */
+#define CLK_DDR_EN	&hep_clken	1	/* bit 1 */
+#define CLK_PDP_EN	&hep_clken	2	/* bit 2 */
+
+#define CLK_SYSCLK_X2_UNDELETED		CLK_SYSCLK1_SW
+#define CLK_UCC1			CLK_UCC1_EN
+
+#define CLK_AFE_PROGDIV1_TO_SOC	&afe_progdiv1_to_soc
+#define CLK_AFE_PROGDIV3_TO_SOC	&afe_progdiv3_to_soc
+#define CLK_IQADC_SYNC_TO_SOC	&iqadc_sync_to_soc
+#define CLK_AFE_RXSYNC_TO_SOC	&afe_rxsync_to_soc
+#define CLK_AFE_TXSYNC_TO_SOC	&afe_txsync_to_soc
+
+/ {
+	soc {
+		/*
+		 * ============ EXTERNAL CLOCKS/OSCILLATORS ============
+		 */
+
+		/* XTAL1 frequency is specified in reset bootstrap config */
+		xtal1: xtal1 {
+			compatible = "specified-clock";
+			#clock-cells = <0>;
+			reg = <0x02004004 0x4>;	/* CR_PERIP_RESET_CFG */
+			bit-mask = <0x00000f00>;	/* FXTAL */
+			/*	 FXTAL	Frequency */
+			table = <0	16384000>,
+				<1	19200000>,
+				<2	24000000>,
+				<3	24576000>,
+				<4	26000000>,
+				<5	36000000>,
+				<6	36864000>,
+				<7	38400000>,
+				<8	40000000>,
+				<9	48000000>;
+			clock-output-names = "xtal1";
+		};
+
+		/* XTAL2 oscillator (board specific, but 12MHz recommended) */
+		xtal2: xtal2 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "xtal2";
+		};
+
+		/* XTAL3 oscillator (32.768KHz if fitted, assume not fitted) */
+		xtal3: xtal3 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "xtal3";
+		};
+
+		ext_adc_dac: ext_adc_dac {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "ext_adc_dac";
+		};
+
+
+		/*
+		 * ============ POWERDOWN CONTROLLER CLOCKS ============
+		 */
+
+		/*           ___________
+		 * xtal1 ___| xtal1_div |____________________________
+		 *          |___________|  |    ________   xtal1_div
+		 *                         `--o| rtc_sw \____________
+		 * xtal3 ----------------------|________/  32khz
+		 */
+		pdc_clk: pdc_clk {
+			compatible = "img,tz1090-pdc-clock";
+			#clock-cells = <1>;
+			reg = <0x02006500 4>;	/* SOC_GPIO_CONTROL0 */
+			clocks = <&xtal1>, <&xtal3>;
+			clock-output-names = "xtal1_div", "32khz";
+		};
+
+
+		/*
+		 * ============ AFE CLOCKS (PLACEHOLDERS) ============
+		 */
+
+		afe_progdiv1_to_soc: afe_progdiv1_to_soc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "afe_progdiv1_to_soc";
+		};
+		afe_progdiv3_to_soc: afe_progdiv3_to_soc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "afe_progdiv3_to_soc";
+		};
+		iqadc_sync_to_soc: iqadc_sync_to_soc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "iqadc_sync_to_soc";
+		};
+		afe_rxsync_to_soc: afe_rxsync_to_soc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "afe_rxsync_to_soc";
+		};
+		afe_txsync_to_soc: afe_txsync_to_soc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "afe_txsync_to_soc";
+		};
+
+		/*
+		 * ============ TOP LEVEL CLOCK SWITCHES ============
+		 */
+
+		/*
+		 * CR_TOP_CLKSWITCH
+		 *                       ___________
+		 * xtal1         ------o|sysclk0_sw \___________
+		 * xtal2         -------|___________/  0
+		 * xtal1         ------o|sysclk1_sw \___________
+		 * sys_clk_div   -------|___________/  1 sys_clk_x2_undeleted
+		 * xtal1         ------o|clkout0_sw0\______
+		 * afe_progdiv1_to_soc -|___________/  2   |
+		 * sys_clk_undeleted --o|clkout0_sw1\____  |
+		 * if0_sw        -------|___________/  3 | |
+		 *                 ,-;==================='-'
+		 *                 | |   ___________
+		 * clkout0_sw0     | `-o|clkout0_sw2\______
+		 * xtal2         --|----|___________/  4   |
+		 *                 |  _____________________|
+		 *                 | |   ___________
+		 * clkout0_sw2     | `-o|clkout0_sw3\___________
+		 * clkout0_sw1     `----|___________/  5
+		 * xtal1         ------o|clkout1_sw0\______
+		 * xtal2         -------|___________/  6   |
+		 * sys_clk_undeleted --o|clkout1_sw1\____  |
+		 * if1_sw        -------|___________/  7 | |
+		 *                 ,-;==================='-'
+		 *                 | |   ___________
+		 * adcpll_clk    --|-|-o|clkout1_sw2\______
+		 * clkout1_sw1     `-|--|___________/  8   |
+		 *                  _|_____________________|
+		 *                 | |   ___________
+		 * clkout1_sw0     | `-o|clkout1_sw3\___________
+		 * clkout1_sw2     `----|___________/  9
+		 * xtal1         ------o| i2s_sw2   \______
+		 * sys_clk_undeleted ---|___________/ 10   |
+		 * xtal2         ------o| i2s_sw0   \____  |
+		 * adcpll_clk    -------|___________/ 11 | |
+		 *                 ,-;==================='-'
+		 *                 | |   ___________
+		 * i2s_sw2         | `-o| i2s_sw1   \___________
+		 * i2s_sw0         `----|___________/ 12
+		 * xtal1         ------o| scb_sw    \___________
+		 * sys_clk_undeleted ---|___________/ 13
+		 * xtal1         ------o| uart_sw   \___________
+		 * sys_clk_undeleted ---|___________/ 14
+		 * xtal1         ------o|ext_stc0_sw\___________
+		 * xtal2         -------|___________/ 16
+		 * xtal1         ------o|ext_stc1_sw\___________
+		 * xtal2         -------|___________/ 17
+		 * adcpll_clk    ------o|  usb_sw0  \______
+		 * afe_progdiv3_to_soc -|___________/ 18   |
+		 *                    _____________________|
+		 *                   |   ___________
+		 * usb_sw3         ,-|-o|  usb_sw1  \___________
+		 * usb_sw0         | `--|___________/ 19
+		 * xtal1         --|---o|  afe_sw0  \___________
+		 * afe_sw1       ,-|----|___________/ 20
+		 *               `-`=======================:-.
+		 *                       ___________       | |
+		 * adcpll_en     ------o|  afe_sw1  \______| |
+		 * xtal2         -------|___________/ 21     |
+		 * xtal1         ------o|adcpll_sw0 \________|__
+		 * xtal2         -------|___________/ 22     |
+		 * xtal1         ------o|adcpll_sw1 \______  |
+		 * xtal2         -------|___________/ 23   | |
+		 *                    _____________________| |
+		 *                   |   ___________         |
+		 * adcpll_en     ----|-o|adcpll_sw2 \________|__
+		 * adcpll_sw1        `--|___________/ 24     |
+		 *                                           |
+		 *                       ___________         |
+		 * sys_clk_undeleted ---|adcpll_sw3 \________|__
+		 * adcpll_clk    -------|___________/ 25     |
+		 * xtal1         -------|  usb_sw2  \______  |
+		 * xtal2         -------|___________/ 28   | |
+		 *                    _____________________| |
+		 *                   |   ___________         |
+		 * usb_sw2           `--|  usb_sw3  \________|
+		 * sys_clk_undeleted ---|___________/ 29
+		 */
+		top_clkswitch: top_clkswitch {
+			compatible = "img,tz1090-mux-bank";
+			#clock-cells = <1>;
+			reg = <0x02005908 0x4>;	/* CR_TOP_CLKSWITCH */
+			bit-mask = <0x33ff7fff>;
+			clock-output-names =
+				"sysclk0_sw",
+				"sys_clk_x2_undeleted",
+				"out0_sw0",
+				"out0_sw1",
+				"out0_sw2",
+				"out0_sw3",
+				"out1_sw0",
+				"out1_sw1",
+				"out1_sw2",
+				"out1_sw3",
+				"i2s_sw2",
+				"i2s_sw0",
+				"i2s_sw1",
+				"scb_sw",
+				"uart_sw",
+				"ext_stc0_sw",
+				"ext_stc1_sw",
+				"usb_sw0",
+				"usb_sw1",
+				"afe_sw0",
+				"afe_sw1",
+				"adcpll_sw0",
+				"adcpll_sw1",
+				"adcpll_sw2",
+				"adcpll_sw3",
+				"usb_sw2",
+				"usb_sw3";
+			clocks =
+				<&xtal1>,		<&xtal2>,
+				<&xtal1>,		<&sys_clk_div>,
+				<&xtal1>,		<CLK_AFE_PROGDIV1_TO_SOC>,
+				<&sys_clk_undeleted>,	<CLK_IF0_SW>,
+				<CLK_OUT0_SW0>,		<&xtal2>,
+				<CLK_OUT0_SW2>,		<CLK_OUT0_SW1>,
+				<&xtal1>,		<&xtal2>,
+				<&sys_clk_undeleted>,	<CLK_IF1_SW>,
+				<&adcpll_clk>,		<CLK_OUT1_SW1>,
+				<CLK_OUT1_SW0>,		<CLK_OUT1_SW2>,
+				<&xtal1>,		<&sys_clk_undeleted>,
+				<&xtal2>,		<&adcpll_clk>,
+				<CLK_I2S_SW2>,		<CLK_I2S_SW0>,
+				<&xtal1>,		<&sys_clk_undeleted>,
+				<&xtal1>,		<&sys_clk_undeleted>,
+				<&xtal1>,		<&xtal2>,
+				<&xtal1>,		<&xtal2>,
+				<&adcpll_clk>,		<CLK_AFE_PROGDIV3_TO_SOC>,
+				<CLK_USB_SW3>,		<CLK_USB_SW0>,
+				<&xtal1>,		<CLK_AFE_SW1>,
+				<CLK_ADCPLL_EN>,	<&xtal2>,
+				<&xtal1>,		<&xtal2>,
+				<&xtal1>,		<&xtal2>,
+				<CLK_ADCPLL_EN>,	<CLK_ADCPLL_SW1>,
+				<&sys_clk_undeleted>,	<&adcpll_clk>,
+				<&xtal1>,		<&xtal2>,
+				<CLK_USB_SW2>,		<&sys_clk_undeleted>;
+		};
+
+		/*
+		 * CR_TOP_CLKSWITCH2
+		 *                            ___________
+		 * xtal1              ------o| pixel_sw0 \______
+		 * pixel_sw3            ,----|___________/  0   |
+		 * sys_clk_undeleted  --+---o| pixel_sw1 \____  |
+		 * pixel_sw4            | ,--|___________/  1 | |
+		 *                      `-`===================|=|=:-.
+		 *                      ,-;==================='-' | |
+		 *                      | |   ___________         | |
+		 * pixel_sw0            | `-o| pixel_sw2 \________|_|___
+		 * pixel_sw1            `----|___________/  2     | |
+		 * adcpll_clk         ------o| pixel_sw3 \________| |
+		 * afe_progdiv3_to_soc ------|___________/  3       |
+		 * usb_phy_clk        ------o| pixel_sw4 \__________|
+		 * xtal2              -------|___________/  4
+		 * iqadc_sync_to_soc  ------o| if1_sw1   \______________
+		 * ext_adc_dac        --+----|___________/  5
+		 * afe_rxsync_to_soc  --|---o| if0_sw    \______________
+		 * ext_adc_dac          |`---|___________/  6
+		 * afe_txsync_to_soc  --|---o| dac0_sw   \______________
+		 * ext_adc_dac          `----|___________/  8
+		 * ucc1_clk_del       ------o| ucc1_sw   \______________
+		 * ucc0_clk_del       --+----|___________/  9
+		 * ucc0_clk_del         `---o| ucc0_sw   \______________
+		 * sys_clk            -------|___________/  10
+		 */
+		top_clkswitch2: top_clkswitch2 {
+			compatible = "img,tz1090-mux-bank";
+			#clock-cells = <1>;
+			reg = <0x02005988 0x4>;	/* CR_TOP_CLKSWITCH2 */
+			bit-mask = <0x0000077f>;
+			clock-output-names =
+				"pixel_sw0",
+				"pixel_sw1",
+				"pixel_sw2",
+				"pixel_sw3",
+				"pixel_sw4",
+				"if1_sw1",
+				"if0_sw",
+				"dac0_sw",
+				"ucc1_sw",
+				"ucc0_sw";
+			clocks =
+				<&xtal1>,		<CLK_PIXEL_SW3>,
+				<&sys_clk_undeleted>,	<CLK_PIXEL_SW4>,
+				<CLK_PIXEL_SW0>,	<CLK_PIXEL_SW1>,
+				<&adcpll_clk>,		<&afe_progdiv3_to_soc>,
+				<&usb_phy_clk>,		<&xtal2>,
+				<CLK_IQADC_SYNC_TO_SOC>,<&ext_adc_dac>,
+				<CLK_AFE_RXSYNC_TO_SOC>,<&ext_adc_dac>,
+				<CLK_AFE_TXSYNC_TO_SOC>,<&ext_adc_dac>,
+				<&ucc1_clk_del>,	<&ucc0_clk_del>,
+				<&ucc0_clk_del>,	<&sys_clk>;
+		};
+
+		/*
+		 * ============ TOP LEVEL CLOCK GATES ============
+		 */
+
+		/*
+		 * CR_TOP_CLKENAB
+		 */
+		top_clkenab: top_clkenab {
+			compatible = "img,tz1090-gate-bank";
+			#clock-cells = <1>;
+			reg = <0x0200590c 0x4>;	/* CR_TOP_CLKENAB */
+			bit-mask = <0x020b7220>;
+			clock-output-names =
+				"out0_en",
+				"out1_en",
+				"i2s_en",
+				"scb_en",
+				"uart_en",
+				"ext_stc1_en",
+				"ext_stc1_en",
+				"usb_en",
+				"adcpll_en";
+			clocks =
+				<CLK_OUT0_SW3>,
+				<CLK_OUT1_SW3>,
+				<CLK_I2S_SW1>,
+				<CLK_SCB_SW>,
+				<CLK_UART_SW>,
+				<CLK_ESTC0_SW>,
+				<CLK_ESTC1_SW>,
+				<CLK_USB_SW1>,
+				<CLK_ADCPLL_SW3>;
+		};
+
+		/*
+		 * CR_TOP_CLKENAB2
+		 */
+		top_clkenab2: top_clkenab2 {
+			compatible = "img,tz1090-gate-bank";
+			#clock-cells = <1>;
+			reg = <0x0200598c 0x4>;	/* CR_TOP_CLKENAB2 */
+			bit-mask = <0x000007e4>;
+			clock-output-names =
+				"pixel_en",
+				"if1_en",
+				"if0_en",
+				"ext_adc_dac_en",
+				"dac0_en",
+				"ucc1_en",
+				"ucc0_en";
+			clocks =
+				<CLK_PIXEL_SW2>,
+				<CLK_IF1_SW>,
+				<CLK_IF0_SW>,
+				<&ext_adc_dac>,
+				<CLK_DAC0_SW>,
+				<CLK_UCC1_SW>,
+				<CLK_UCC0_SW>;
+		};
+
+		/*
+		 * ============ PLL CLOCKS ============
+		 */
+
+		/* sysclk0_sw ---[sys_pll]--- */
+		sys_pll: sys_pll {
+			compatible = "img,tz1090-pll";
+			#clock-cells = <0>;
+			clocks = <CLK_SYSCLK0_SW>;
+			reg = <0x02005950 0x8>;	/* CR_TOP_SYSPLL_CTL{0,1} */
+			clock-output-names = "sys_pll";
+		};
+
+		/* adcpll_sw0 ---[adcpll]--- */
+		adcpll_clk: adcpll_clk {
+			compatible = "img,tz1090-pll";
+			#clock-cells = <0>;
+			clocks = <CLK_ADCPLL_SW0>;
+			reg = <0x02005958 0x8>;	/* CR_TOP_ADCPLL_CTL{0,1} */
+			clock-output-names = "adcpll";
+		};
+
+		/*
+		 * ============ CLOCK DELETERS ============
+		 */
+
+		/* sys_clk_undeleted ---[clkdelete]--- sys_clk */
+		sys_clk: sys_clk_del {
+			compatible = "img,tz1090-deleter";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005910 0x4>;	/* CR_TOP_CLKDELETE */
+			bit-mask = <0x000003ff>; /* CR_TOP_CLKDELETE */
+			clock-output-names = "sys";
+		};
+
+		/* sys_clk_x2_undeleted ---[meta_clkdelete]--- meta_core_clk */
+		meta_core_clk: meta_clk_del {
+			compatible = "img,tz1090-deleter";
+			#clock-cells = <0>;
+			clocks = <CLK_SYSCLK_X2_UNDELETED>;
+			reg = <0x0200591c 0x4>;	/* CR_TOP_META_CLKDELETE */
+			bit-mask = <0x000003ff>; /* CR_TOP_META_CLKDELETE */
+			clock-output-names = "meta";
+		};
+
+		/* sys_clk_undeleted ---[clkdelete]--- ucc0_clk_del */
+		ucc0_clk_del: uccp0_clk_del {
+			compatible = "img,tz1090-deleter";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x020059a4 0x4>;	/* CR_TOP_UCC0_CLKDELETE */
+			bit-mask = <0x000003ff>; /* CR_TOP_UCC0_CLKDELETE */
+			clock-output-names = "ucc0";
+		};
+
+		/* sys_clk_undeleted ---[clkdelete]--- ucc1_clk_del */
+		ucc1_clk_del: uccp1_clk_del {
+			compatible = "img,tz1090-deleter";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x020059a8 0x4>;	/* CR_TOP_UCC1_CLKDELETE */
+			bit-mask = <0x000003ff>; /* CR_TOP_UCC1_CLKDELETE */
+			clock-output-names = "ucc1";
+		};
+
+		/*
+		 * ============ CLOCK DIVIDERS ============
+		 */
+
+		/* sys_pll ---[sys_clk_div]--- */
+		sys_clk_div: sys_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_pll>;
+			reg = <0x02005914 0x4>;	/* CR_TOP_SYSCLK_DIV */
+			bit-mask = <0xff>;	/* CR_TOP_SYSDIV */
+			clock-output-names = "sys_div";
+		};
+
+		/* sys_clk_x2_undeleted ---[meta_clk_div]--- sys_clk_undeleted */
+		sys_clk_undeleted: meta_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_SYSCLK_X2_UNDELETED>;
+			reg = <0x02005918 0x4>;	/* CR_TOP_META_CLKDIV */
+			bit-mask = <0x3>;	/* CR_TOP_META_X2_EN */
+			clock-output-names = "sys_clk_undeleted";
+		};
+
+		/* afe_sw0 ---[afe_clk_div]--- afe_clk */
+		afe_clk: afe_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_AFE_SW0>;
+			reg = <0x02005920 0x4>;	/* CR_TOP_AFE_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "afe";
+		};
+
+		/* adcpll_sw2 ---[adcpll_clk_div]--- adcpll_div */
+		adcpll_div: adcpll_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_ADCPLL_SW2>;
+			reg = <0x02005924 0x4>;	/* CR_TOP_ADCPLL_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "adcpll_div";
+		};
+
+		/* uart_en ---[uart_clk_div]--- uart_clk */
+		uart_clk: uart_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_UART_EN>;
+			reg = <0x02005928 0x4>;	/* CR_TOP_UARTCLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "uart";
+		};
+
+		/* sys_clk_undeleted ---[pdm_clk_div]--- pdm_clk */
+		pdm_clk: pdm_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005930 0x4>;	/* CR_TOP_PDMCK_CTL */
+			bit-mask = <0x7>;
+			clock-output-names = "pdm";
+		};
+
+		/* sys_clk_undeleted ---[spi0_clk_div]--- spi0_clk */
+		spi0_clk: spi0_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005934 0x4>;	/* CR_TOP_SPICLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "spi0";
+		};
+
+		/* sys_clk_undeleted ---[spi1_clk_div]--- spi1_clk */
+		spi1_clk: spi1_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005938 0x4>;	/* CR_TOP_SPI1CLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "spi1";
+		};
+
+		/* i2s_en ---[i2sm_clk_div]--- i2sm */
+		i2sm_clk: i2sm_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_I2S_EN>;
+			reg = <0x0200593c 0x4>;	/* CR_TOP_I2SCLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "i2sm";
+		};
+
+		/* usb_en ---[usbpll_clk_div]--- usb_phy_clk */
+		usb_phy_clk: usbpll_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_USB_EN>;
+			reg = <0x02005940 0x4>;	/* CR_TOP_USB_PLLDIV */
+			bit-mask = <0xff>;
+			clock-output-names = "usb_phy";
+		};
+
+		/* sys_clk_undeleted ---[sdhost_clk_div]--- sdhost_clk */
+		sdhost_clk: sdhost_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005944 0x4>;	/* CR_TOP_SDHOSTCLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "sdhost";
+		};
+
+		/* sys_clk_undeleted ---[ring_osc_clk_div]--- ring_osc_clk */
+		ring_osc_clk: ring_osc_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005948 0x4>;	/* CR_TOP_RING_OP_DIV */
+			bit-mask = <0xf>;
+			clock-output-names = "ring_osc";
+		};
+
+		/* i2sm_clk ---[i2s_clk_div2]--- i2s_clk */
+		i2s_clk: i2s_clk_div2 {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&i2sm_clk>;
+			reg = <0x02005990 0x4>;	/* CR_TOP_I2S_DIV2 */
+			bit-mask = <0xff>;
+			clock-output-names = "i2s";
+		};
+
+		/* sys_clk_undeleted ---[meta_trace_clk_div]--- meta_trace_clk */
+		meta_trace_clk: meta_trace_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <&sys_clk_undeleted>;
+			reg = <0x02005994 0x4>;	/* CR_TOP_META_TRACE_CLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "meta_trace";
+		};
+
+		/* pixel_en ---[pixel_clk_div]--- pixel_clk */
+		pixel_clk: pixel_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_PIXEL_EN>;
+			reg = <0x02005998 0x4>;	/* CR_TOP_PIXEL_CLK_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "pixel";
+		};
+
+		/* clkout0_en ---[clkout0_clk_div]--- clkout0 */
+		clkout0: clkout0_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_OUT0_EN>;
+			reg = <0x0200599c 0x4>;	/* CR_TOP_CLKOUT0_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "out0";
+		};
+
+		/* clkout1_en ---[clkout1_clk_div]--- clkout1 */
+		clkout1: clkout1_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_OUT1_EN>;
+			reg = <0x020059a0 0x4>;	/* CR_TOP_CLKOUT1_DIV */
+			bit-mask = <0xff>;
+			clock-output-names = "out1";
+		};
+
+		/* ddr_en ---[ddr_clk_div]--- ddr_clk */
+		ddr_clk: ddr_clk_div {
+			compatible = "img,tz1090-divider";
+			#clock-cells = <0>;
+			clocks = <CLK_DDR_EN>;
+			reg = <0x020059ac 0x4>;	/* CR_TOP_DDR_CLKDIV */
+			bit-mask = <0xff>;
+			clock-output-names = "ddr";
+		};
+
+		/*
+		 * ============ PERIPHERAL SYSTEM CLOCK GATES ============
+		 *
+		 * CR_PERIP_CLKEN
+		 *
+		 * sys_clk ---[CR_PERIP_*_SYS_CLK_EN]--- sys_*
+		 */
+		perip_clken: perip_clken {
+			compatible = "img,tz1090-gate-bank";
+			#clock-cells = <1>;
+			reg = <0x02004010 0x4>;	/* CR_PERIP_CLKEN */
+			bit-mask = <0x00003fff>;
+			clock-output-names =
+				"sys_scb0",
+				"sys_scb1",
+				"sys_scb2",
+				"sys_sdio",
+				"sys_uart0",
+				"sys_uart1",
+				"sys_spim",
+				"sys_spis",
+				"sys_spim1",
+				"sys_i2sout",
+				"sys_i2sin",
+				"sys_lcd",
+				"sys_sdhost",
+				"sys_usb";
+			clocks =
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>,
+				<&sys_clk>;
+		};
+
+		/*
+		 * ============ HIGH END PERIPHERAL SYSTEM CLOCK GATES ============
+		 *
+		 * CR_HEP_CLK_EN
+		 *
+		 * sys_clk              -+--[CR_2D_CLK_EN     ]--- 0 sys_2d
+		 * sys_clk_x2_undeleted -|--[CR_DDR_CLK_EN    ]--- 1 ddr_en
+		 * sys_clk               `--[CR_PDP_PDI_CLK_EN]--- 2 sys_pdp
+		 */
+		hep_clken: hep_clken {
+			compatible = "img,tz1090-gate-bank";
+			#clock-cells = <1>;
+			reg = <0x02008c04 0x4>;	/* CR_HEP_CLK_EN */
+			bit-mask = <0x00000007>;
+			clock-output-names =
+				"sys_2d",
+				"ddr_en",
+				"sys_pdp";
+			clocks =
+				<&sys_clk>,
+				<CLK_SYSCLK_X2_UNDELETED>,
+				<&sys_clk>;
+		};
+	};
+};
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/15] clk: divider: replace bitfield width with mask
  2014-11-19 23:15 ` [PATCH 01/15] clk: divider: replace bitfield width with mask James Hogan
@ 2014-11-20 11:19   ` Tero Kristo
  2014-11-20 11:59     ` James Hogan
  0 siblings, 1 reply; 22+ messages in thread
From: Tero Kristo @ 2014-11-20 11:19 UTC (permalink / raw)
  To: James Hogan, Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: Emilio López, Sascha Hauer, Shawn Guo, linux-omap, linux-rockchip

On 11/20/2014 01:15 AM, James Hogan wrote:
> From: Mike Turquette <mturquette@linaro.org>
>
> The forthcoming Device Tree binding for the divider clock type will use
> a bitfield mask instead of bitfield width, which is what the current
> basic divider implementation uses.
>
> This patch replaces the u8 width in struct clk_divider with a u32 mask.
> The divider code is updated to use the bit mask internally but the two
> registration functions still accept the width to maintain compatibility
> with existing users.
>
> Also updated in this patch is the clk-private.h divider macro and
> various clock divider implementations that are based on struct
> clk_divider.
>
> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> [james.hogan@imgtec.com: forward port, fix new uses of width]
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Tested-by: Shawn Guo <shawn.guo@linaro.org>
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Heiko Stuebner <heiko@sntech.de>
> Cc: "Emilio López" <emilio@elopez.com.ar>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Cc: Tero Kristo <t-kristo@ti.com>
> Cc: linux-omap@vger.kernel.org
> Cc: linux-rockchip@lists.infradead.org
> ---
> Changes since original:
> - Forward ported
> - Adjust new div_mask from recent patch "clk-divider: Fix READ_ONLY when
>    divider > 1"
> - Updated assignment of clk_divider::width in imx, rockchip, st, sunxi,
>    ti clock components to use mask instead (not tested), using the
>    following semantic patch:

Hi James/Mike,

This patch currently causes a build breakage with omap2plus_defconfig. 
Reason being you are modifying the clk_divider struct, but not touching 
the code under drivers/clk/ti/divider.c which uses it. The fixes are 
basically the same you have done for clk-divider.c, the contents of this 
file are mostly just copied under TI clock driver.

-Tero

>
> virtual context
> virtual patch
>
> @depends on context@
> struct clk_divider clk;
> expression e;
> @@
> *clk.width = e
>
> @depends on patch@
> struct clk_divider clk;
> expression e;
> @@
> -clk.width = fls(e)
> +clk.mask = e
>
> @depends on patch@
> struct clk_divider *clk;
> expression e;
> @@
> -clk->width = fls(e)
> +clk->mask = e
>
> @depends on patch@
> struct clk_divider clk;
> expression e;
> @@
> -clk.width = e
> +clk.mask = BIT(e) - 1
>
> @depends on patch@
> struct clk_divider *clk;
> expression e;
> @@
> -clk->width = e
> +clk->mask = BIT(e) - 1
> ---
>   arch/arm/mach-imx/clk-busy.c      |  2 +-
>   arch/arm/mach-imx/clk-fixup-div.c |  2 +-
>   drivers/clk/clk-divider.c         | 33 ++++++++++++++++-----------------
>   drivers/clk/mxs/clk-div.c         |  2 +-
>   drivers/clk/rockchip/clk.c        |  2 +-
>   drivers/clk/st/clk-flexgen.c      |  4 ++--
>   drivers/clk/st/clkgen-mux.c       |  4 ++--
>   drivers/clk/st/clkgen-pll.c       |  2 +-
>   drivers/clk/sunxi/clk-sunxi.c     |  2 +-
>   drivers/clk/ti/divider.c          |  2 +-
>   include/linux/clk-private.h       |  2 +-
>   include/linux/clk-provider.h      |  2 +-
>   12 files changed, 29 insertions(+), 30 deletions(-)
>
> diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c
> index 4bb1bc4..bc88e38 100644
> --- a/arch/arm/mach-imx/clk-busy.c
> +++ b/arch/arm/mach-imx/clk-busy.c
> @@ -95,7 +95,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
>
>   	busy->div.reg = reg;
>   	busy->div.shift = shift;
> -	busy->div.width = width;
> +	busy->div.mask = BIT(width) - 1;
>   	busy->div.lock = &imx_ccm_lock;
>   	busy->div_ops = &clk_divider_ops;
>
> diff --git a/arch/arm/mach-imx/clk-fixup-div.c b/arch/arm/mach-imx/clk-fixup-div.c
> index 21db020..af33b7a 100644
> --- a/arch/arm/mach-imx/clk-fixup-div.c
> +++ b/arch/arm/mach-imx/clk-fixup-div.c
> @@ -115,7 +115,7 @@ struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
>
>   	fixup_div->divider.reg = reg;
>   	fixup_div->divider.shift = shift;
> -	fixup_div->divider.width = width;
> +	fixup_div->divider.mask = BIT(width) - 1;
>   	fixup_div->divider.lock = &imx_ccm_lock;
>   	fixup_div->divider.hw.init = &init;
>   	fixup_div->ops = &clk_divider_ops;
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index c0a842b..a432cf8 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -30,8 +30,6 @@
>
>   #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
>
> -#define div_mask(d)	((1 << ((d)->width)) - 1)
> -
>   static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
>   {
>   	unsigned int maxdiv = 0;
> @@ -57,12 +55,12 @@ static unsigned int _get_table_mindiv(const struct clk_div_table *table)
>   static unsigned int _get_maxdiv(struct clk_divider *divider)
>   {
>   	if (divider->flags & CLK_DIVIDER_ONE_BASED)
> -		return div_mask(divider);
> +		return divider->mask;
>   	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
> -		return 1 << div_mask(divider);
> +		return 1 << divider->mask;
>   	if (divider->table)
>   		return _get_table_maxdiv(divider->table);
> -	return div_mask(divider) + 1;
> +	return divider->mask + 1;
>   }
>
>   static unsigned int _get_table_div(const struct clk_div_table *table,
> @@ -116,7 +114,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>   	unsigned int div, val;
>
>   	val = clk_readl(divider->reg) >> divider->shift;
> -	val &= div_mask(divider);
> +	val &= divider->mask;
>
>   	div = _get_div(divider, val);
>   	if (!div) {
> @@ -266,7 +264,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
>   	/* if read only, just return current value */
>   	if (divider->flags & CLK_DIVIDER_READ_ONLY) {
>   		bestdiv = readl(divider->reg) >> divider->shift;
> -		bestdiv &= div_mask(divider);
> +		bestdiv &= divider->mask;
>   		bestdiv = _get_div(divider, bestdiv);
>   		return bestdiv;
>   	}
> @@ -341,17 +339,17 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
>
>   	value = _get_val(divider, div);
>
> -	if (value > div_mask(divider))
> -		value = div_mask(divider);
> +	if (value > divider->mask)
> +		value = divider->mask;
>
>   	if (divider->lock)
>   		spin_lock_irqsave(divider->lock, flags);
>
>   	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
> -		val = div_mask(divider) << (divider->shift + 16);
> +		val = divider->mask << (divider->shift + 16);
>   	} else {
>   		val = clk_readl(divider->reg);
> -		val &= ~(div_mask(divider) << divider->shift);
> +		val &= ~(divider->mask << divider->shift);
>   	}
>   	val |= value << divider->shift;
>   	clk_writel(val, divider->reg);
> @@ -371,7 +369,7 @@ EXPORT_SYMBOL_GPL(clk_divider_ops);
>
>   static struct clk *_register_divider(struct device *dev, const char *name,
>   		const char *parent_name, unsigned long flags,
> -		void __iomem *reg, u8 shift, u8 width,
> +		void __iomem *reg, u8 shift, u32 mask,
>   		u8 clk_divider_flags, const struct clk_div_table *table,
>   		spinlock_t *lock)
>   {
> @@ -380,8 +378,9 @@ static struct clk *_register_divider(struct device *dev, const char *name,
>   	struct clk_init_data init;
>
>   	if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
> -		if (width + shift > 16) {
> -			pr_warn("divider value exceeds LOWORD field\n");
> +		if ((mask << shift) & 0xffff0000) {
> +			pr_warn("%s: divider value exceeds LOWORD field\n",
> +					__func__);
>   			return ERR_PTR(-EINVAL);
>   		}
>   	}
> @@ -402,7 +401,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
>   	/* struct clk_divider assignments */
>   	div->reg = reg;
>   	div->shift = shift;
> -	div->width = width;
> +	div->mask = mask;
>   	div->flags = clk_divider_flags;
>   	div->lock = lock;
>   	div->hw.init = &init;
> @@ -435,7 +434,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
>   		u8 clk_divider_flags, spinlock_t *lock)
>   {
>   	return _register_divider(dev, name, parent_name, flags, reg, shift,
> -			width, clk_divider_flags, NULL, lock);
> +			((1 << width) - 1), clk_divider_flags, NULL, lock);
>   }
>   EXPORT_SYMBOL_GPL(clk_register_divider);
>
> @@ -460,6 +459,6 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
>   		spinlock_t *lock)
>   {
>   	return _register_divider(dev, name, parent_name, flags, reg, shift,
> -			width, clk_divider_flags, table, lock);
> +			((1 << width) - 1), clk_divider_flags, table, lock);
>   }
>   EXPORT_SYMBOL_GPL(clk_register_divider_table);
> diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c
> index 90e1da9..af2428e 100644
> --- a/drivers/clk/mxs/clk-div.c
> +++ b/drivers/clk/mxs/clk-div.c
> @@ -96,7 +96,7 @@ struct clk *mxs_clk_div(const char *name, const char *parent_name,
>
>   	div->divider.reg = reg;
>   	div->divider.shift = shift;
> -	div->divider.width = width;
> +	div->divider.mask = BIT(width) - 1;
>   	div->divider.flags = CLK_DIVIDER_ONE_BASED;
>   	div->divider.lock = &mxs_lock;
>   	div->divider.hw.init = &init;
> diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
> index 880a266..9024a0e 100644
> --- a/drivers/clk/rockchip/clk.c
> +++ b/drivers/clk/rockchip/clk.c
> @@ -87,7 +87,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
>   		div->flags = div_flags;
>   		div->reg = base + muxdiv_offset;
>   		div->shift = div_shift;
> -		div->width = div_width;
> +		div->mask = BIT(div_width) - 1;
>   		div->lock = lock;
>   		div->table = div_table;
>   		div_ops = &clk_divider_ops;
> diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
> index 2282cef..603d5d6 100644
> --- a/drivers/clk/st/clk-flexgen.c
> +++ b/drivers/clk/st/clk-flexgen.c
> @@ -203,7 +203,7 @@ struct clk *clk_register_flexgen(const char *name,
>   	/* Pre-divider config */
>   	fgxbar->pdiv.lock = lock;
>   	fgxbar->pdiv.reg = reg + 0x58 + idx * 4;
> -	fgxbar->pdiv.width = 10;
> +	fgxbar->pdiv.mask = BIT(10) - 1;
>
>   	/* Final divider's gate config */
>   	fgxbar->fgate.lock = lock;
> @@ -213,7 +213,7 @@ struct clk *clk_register_flexgen(const char *name,
>   	/* Final divider config */
>   	fgxbar->fdiv.lock = lock;
>   	fgxbar->fdiv.reg = fdiv_reg;
> -	fgxbar->fdiv.width = 6;
> +	fgxbar->fdiv.mask = BIT(6) - 1;
>
>   	fgxbar->hw.init = &init;
>
> diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
> index 79dc40b..85a1165 100644
> --- a/drivers/clk/st/clkgen-mux.c
> +++ b/drivers/clk/st/clkgen-mux.c
> @@ -260,7 +260,7 @@ struct clk *clk_register_genamux(const char *name,
>   		 * Divider config for each input
>   		 */
>   		void __iomem *divbase = reg + muxdata->div_offsets[i];
> -		genamux->div[i].width = divider_width;
> +		genamux->div[i].mask = BIT(divider_width) - 1;
>   		genamux->div[i].reg = divbase + (idx * sizeof(u32));
>
>   		/*
> @@ -773,7 +773,7 @@ void __init st_of_clkgen_vcc_setup(struct device_node *np)
>
>   		div->reg = reg + VCC_DIV_OFFSET;
>   		div->shift = 2 * i;
> -		div->width = 2;
> +		div->mask = BIT(2) - 1;
>   		div->flags = CLK_DIVIDER_POWER_OF_TWO |
>   			CLK_DIVIDER_ROUND_CLOSEST;
>
> diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
> index 29769d7..0d76278 100644
> --- a/drivers/clk/st/clkgen-pll.c
> +++ b/drivers/clk/st/clkgen-pll.c
> @@ -575,7 +575,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
>   	div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
>   	div->reg = reg + pll_data->odf[odf].offset;
>   	div->shift = pll_data->odf[odf].shift;
> -	div->width = fls(pll_data->odf[odf].mask);
> +	div->mask = pll_data->odf[odf].mask;
>   	div->lock = odf_lock;
>
>   	clk = clk_register_composite(NULL, odf_name, &parent_name, 1,
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index d5dc951..a23d393 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -1015,7 +1015,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
>
>   			divider->reg = reg;
>   			divider->shift = data->div[i].shift;
> -			divider->width = SUNXI_DIVISOR_WIDTH;
> +			divider->mask = BIT(SUNXI_DIVISOR_WIDTH) - 1;
>   			divider->flags = flags;
>   			divider->lock = &clk_lock;
>   			divider->table = data->div[i].table;
> diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
> index bff2b5b..c27e01e 100644
> --- a/drivers/clk/ti/divider.c
> +++ b/drivers/clk/ti/divider.c
> @@ -285,7 +285,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
>   	/* struct clk_divider assignments */
>   	div->reg = reg;
>   	div->shift = shift;
> -	div->width = width;
> +	div->mask = BIT(width) - 1;
>   	div->flags = clk_divider_flags;
>   	div->lock = lock;
>   	div->hw.init = &init;
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> index 0ca5f60..40bc1b2 100644
> --- a/include/linux/clk-private.h
> +++ b/include/linux/clk-private.h
> @@ -130,7 +130,7 @@ struct clk {
>   		},						\
>   		.reg = _reg,					\
>   		.shift = _shift,				\
> -		.width = _width,				\
> +		.mask = ((1 << _width) - 1),			\
>   		.flags = _divider_flags,			\
>   		.table = _table,				\
>   		.lock = _lock,					\
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 2839c63..2c00215 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -338,7 +338,7 @@ struct clk_divider {
>   	struct clk_hw	hw;
>   	void __iomem	*reg;
>   	u8		shift;
> -	u8		width;
> +	u32		mask;
>   	u8		flags;
>   	const struct clk_div_table	*table;
>   	spinlock_t	*lock;
>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/15] clk: divider: replace bitfield width with mask
  2014-11-20 11:19   ` Tero Kristo
@ 2014-11-20 11:59     ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-20 11:59 UTC (permalink / raw)
  To: Tero Kristo, Mike Turquette, linux-metag, linux-kernel, devicetree
  Cc: Emilio López, Sascha Hauer, Shawn Guo, linux-omap, linux-rockchip

[-- Attachment #1: Type: text/plain, Size: 753 bytes --]

On 20/11/14 11:19, Tero Kristo wrote:
> On 11/20/2014 01:15 AM, James Hogan wrote:
>> - Updated assignment of clk_divider::width in imx, rockchip, st, sunxi,
>>    ti clock components to use mask instead (not tested), using the
>>    following semantic patch:
> 
> Hi James/Mike,
> 
> This patch currently causes a build breakage with omap2plus_defconfig.
> Reason being you are modifying the clk_divider struct, but not touching
> the code under drivers/clk/ti/divider.c which uses it. The fixes are
> basically the same you have done for clk-divider.c, the contents of this
> file are mostly just copied under TI clock driver.

Thanks for pointing that out! I'll fix and improve my grep-fu to find
other such cases.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree
  2014-11-19 23:15 ` [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree James Hogan
@ 2014-11-20 12:56   ` Heiko Stübner
  2014-11-21 10:06     ` James Hogan
  0 siblings, 1 reply; 22+ messages in thread
From: Heiko Stübner @ 2014-11-20 12:56 UTC (permalink / raw)
  To: James Hogan
  Cc: Mike Turquette, linux-metag, linux-kernel, devicetree,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala

Hi James,

interestingly I only got the cover-letter, so had to find the other patches 
through my list-archive :-) .


Am Mittwoch, 19. November 2014, 23:15:43 schrieb James Hogan:
> Enable the common clock framework for the TZ1090 SoC, add a tz1090_clk
> device tree file describing the clocks, and connect the Meta core clock
> so that the rate of the Meta timer can be determined.
> 
> Most of the clock tree is described apart from some AFE clocks which
> aren't usually of much interest to Linux. These are represented with
> placeholder clocks.
> 
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Mike Turquette <mturquette@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Kumar Gala <galak@codeaurora.org>
> Cc: linux-metag@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> ---


I don't know enough about your clock structure, but it looks quite a bit like 
Mike's mail from May [0] may apply here too.

The register layout also suggests that it is indeed one clock ip-block:

0x02005908 0x4	CR_TOP_CLKSWITCH 
0x0200590c 0x4	CR_TOP_CLKENAB
0x02005950 0x4	CR_TOP_SYSPLL_CTL0
0x02005954 0x4	CR_TOP_SYSPLL_CTL1
0x02005988 0x4	CR_TOP_CLKSWITCH2
0x0200598c 0x4	CR_TOP_CLKENAB2
...


[0] https://lkml.org/lkml/2014/5/14/715



>  arch/metag/Kconfig.soc              |   1 +
>  arch/metag/boot/dts/tz1090.dtsi     |   4 +
>  arch/metag/boot/dts/tz1090_clk.dtsi | 784
> ++++++++++++++++++++++++++++++++++++ 3 files changed, 789 insertions(+)
>  create mode 100644 arch/metag/boot/dts/tz1090_clk.dtsi
> 
> diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc
> index 973640f..93c21c3 100644
> --- a/arch/metag/Kconfig.soc
> +++ b/arch/metag/Kconfig.soc
> @@ -17,6 +17,7 @@ config META21_FPGA
>  config SOC_TZ1090
>  	bool "Toumaz Xenif TZ1090 SoC (Comet)"
>  	select ARCH_WANT_OPTIONAL_GPIOLIB
> +	select COMMON_CLK
>  	select IMGPDC_IRQ
>  	select METAG_LNKGET_AROUND_CACHE
>  	select METAG_META21
> diff --git a/arch/metag/boot/dts/tz1090.dtsi
> b/arch/metag/boot/dts/tz1090.dtsi index 24ea7d2..9e8ef8b 100644
> --- a/arch/metag/boot/dts/tz1090.dtsi
> +++ b/arch/metag/boot/dts/tz1090.dtsi
> @@ -9,12 +9,16 @@
>  #include "skeleton.dtsi"
> 
>  #include <dt-bindings/interrupt-controller/irq.h>
> +#include "tz1090_clk.dtsi"
> 
>  / {
>  	compatible = "toumaz,tz1090", "img,meta";
> 
>  	interrupt-parent = <&intc>;
> 
> +	clocks = <&meta_core_clk>;
> +	clock-names = "core";
> +
>  	intc: interrupt-controller {
>  		compatible = "img,meta-intc";
>  		interrupt-controller;
> diff --git a/arch/metag/boot/dts/tz1090_clk.dtsi
> b/arch/metag/boot/dts/tz1090_clk.dtsi new file mode 100644
> index 0000000..e21362d
> --- /dev/null
> +++ b/arch/metag/boot/dts/tz1090_clk.dtsi
> @@ -0,0 +1,784 @@
> +/*
> + * Copyright (C) 2013 Imagination Technologies Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/*
> + * ============ CLOCK SPECIFIER DEFINITIONS ============
> + */
> +
> +#define CLK_XTAL1_DIV	&pdc_clk	0
> +#define CLK_32KHZ	&pdc_clk	1
> +
> +#define CLK_SYSCLK0_SW	&top_clkswitch	0	/* bit 0 */

I think the more established way is to specify only the index bit as named 
constant, not the whole phandle+index.


Heiko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree
  2014-11-20 12:56   ` Heiko Stübner
@ 2014-11-21 10:06     ` James Hogan
  2014-11-24 23:03       ` Heiko Stübner
  0 siblings, 1 reply; 22+ messages in thread
From: James Hogan @ 2014-11-21 10:06 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Mike Turquette, linux-metag, linux-kernel, devicetree,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala

[-- Attachment #1: Type: text/plain, Size: 2063 bytes --]

On Thu, Nov 20, 2014 at 01:56:24PM +0100, Heiko Stübner wrote:
> Hi James,
> 
> interestingly I only got the cover-letter, so had to find the other patches 
> through my list-archive :-) .

Hmm, sorry about that. I copy cover letter Cc list from the Ccs of the
patches, so not sure what happened there.

> 
> 
> Am Mittwoch, 19. November 2014, 23:15:43 schrieb James Hogan:
> > Enable the common clock framework for the TZ1090 SoC, add a tz1090_clk
> > device tree file describing the clocks, and connect the Meta core clock
> > so that the rate of the Meta timer can be determined.
> > 
> > Most of the clock tree is described apart from some AFE clocks which
> > aren't usually of much interest to Linux. These are represented with
> > placeholder clocks.
> > 
> > Signed-off-by: James Hogan <james.hogan@imgtec.com>
> > Cc: Mike Turquette <mturquette@linaro.org>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Pawel Moll <pawel.moll@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> > Cc: Kumar Gala <galak@codeaurora.org>
> > Cc: linux-metag@vger.kernel.org
> > Cc: devicetree@vger.kernel.org
> > ---
> 
> 
> I don't know enough about your clock structure, but it looks quite a bit like 
> Mike's mail from May [0] may apply here too.
> 
> The register layout also suggests that it is indeed one clock ip-block:
> 
> 0x02005908 0x4	CR_TOP_CLKSWITCH 
> 0x0200590c 0x4	CR_TOP_CLKENAB
> 0x02005950 0x4	CR_TOP_SYSPLL_CTL0
> 0x02005954 0x4	CR_TOP_SYSPLL_CTL1
> 0x02005988 0x4	CR_TOP_CLKSWITCH2
> 0x0200598c 0x4	CR_TOP_CLKENAB2
> ...
> 
> 
> [0] https://lkml.org/lkml/2014/5/14/715

Thanks, that does make sense. It's probably more like 4 memory regions
("top" level, "perip" peripheral registers, "hep" high end peripheral
registers, and "pdc" powerdown controller registers), but it could
certainly still have a single binding with multiple memory regions to
simplify the clock specifiers.

I'll take a look at doing it that way.

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree
  2014-11-21 10:06     ` James Hogan
@ 2014-11-24 23:03       ` Heiko Stübner
  2014-11-25 11:39         ` James Hogan
  0 siblings, 1 reply; 22+ messages in thread
From: Heiko Stübner @ 2014-11-24 23:03 UTC (permalink / raw)
  To: James Hogan
  Cc: Mike Turquette, linux-metag, linux-kernel, devicetree,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala

Am Freitag, 21. November 2014, 10:06:47 schrieb James Hogan:
> On Thu, Nov 20, 2014 at 01:56:24PM +0100, Heiko Stübner wrote:
> > I don't know enough about your clock structure, but it looks quite a bit
> > like Mike's mail from May [0] may apply here too.
> > 
> > The register layout also suggests that it is indeed one clock ip-block:
> > 
> > 0x02005908 0x4	CR_TOP_CLKSWITCH
> > 0x0200590c 0x4	CR_TOP_CLKENAB
> > 0x02005950 0x4	CR_TOP_SYSPLL_CTL0
> > 0x02005954 0x4	CR_TOP_SYSPLL_CTL1
> > 0x02005988 0x4	CR_TOP_CLKSWITCH2
> > 0x0200598c 0x4	CR_TOP_CLKENAB2
> > ...
> > 
> > 
> > [0] https://lkml.org/lkml/2014/5/14/715
> 
> Thanks, that does make sense. It's probably more like 4 memory regions
> ("top" level, "perip" peripheral registers, "hep" high end peripheral
> registers, and "pdc" powerdown controller registers), but it could
> certainly still have a single binding with multiple memory regions to
> simplify the clock specifiers.

It could also make sense to have 4 clock controller nodes for those. I guess 
it all depends on how the hardware is layed out.

For example on Rockchip SoCs, all of this is contained in the "APB CRU" (Clock 
and Reset Unit) with a memory region of <0x20000000 0x4000> - so here one 
hardware-block that contains all the clocks and also the reset controller.

On the other hand it might very well be more than one ip-block on your 
platform. 

So I guess it comes down to looking at the memory map [or documentation :-) ] 
to determine how many ip blocks there really are.


Heiko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree
  2014-11-24 23:03       ` Heiko Stübner
@ 2014-11-25 11:39         ` James Hogan
  0 siblings, 0 replies; 22+ messages in thread
From: James Hogan @ 2014-11-25 11:39 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Mike Turquette, linux-metag, linux-kernel, devicetree,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala

[-- Attachment #1: Type: text/plain, Size: 2352 bytes --]

On 24/11/14 23:03, Heiko Stübner wrote:
> Am Freitag, 21. November 2014, 10:06:47 schrieb James Hogan:
>> On Thu, Nov 20, 2014 at 01:56:24PM +0100, Heiko Stübner wrote:
>>> I don't know enough about your clock structure, but it looks quite a bit
>>> like Mike's mail from May [0] may apply here too.
>>>
>>> The register layout also suggests that it is indeed one clock ip-block:
>>>
>>> 0x02005908 0x4	CR_TOP_CLKSWITCH
>>> 0x0200590c 0x4	CR_TOP_CLKENAB
>>> 0x02005950 0x4	CR_TOP_SYSPLL_CTL0
>>> 0x02005954 0x4	CR_TOP_SYSPLL_CTL1
>>> 0x02005988 0x4	CR_TOP_CLKSWITCH2
>>> 0x0200598c 0x4	CR_TOP_CLKENAB2
>>> ...
>>>
>>>
>>> [0] https://lkml.org/lkml/2014/5/14/715
>>
>> Thanks, that does make sense. It's probably more like 4 memory regions
>> ("top" level, "perip" peripheral registers, "hep" high end peripheral
>> registers, and "pdc" powerdown controller registers), but it could
>> certainly still have a single binding with multiple memory regions to
>> simplify the clock specifiers.
> 
> It could also make sense to have 4 clock controller nodes for those. I guess 
> it all depends on how the hardware is layed out.
> 
> For example on Rockchip SoCs, all of this is contained in the "APB CRU" (Clock 
> and Reset Unit) with a memory region of <0x20000000 0x4000> - so here one 

/me twigs what CRU stands for!

> hardware-block that contains all the clocks and also the reset controller.
> 
> On the other hand it might very well be more than one ip-block on your 
> platform. 
> 
> So I guess it comes down to looking at the memory map [or documentation :-) ] 
> to determine how many ip blocks there really are.

I'll probably combine the TOP and HEP ones at least. HEP clock stuff is
much simpler than TOP, and a couple of clocks feed both ways between
them which otherwise wouldn't need to be visible, suggesting they're
pretty closely coupled.

PERIP is pretty much a single bank of 14 system clock gates for
individual peripherals, so that one's arguable. I'll probably separate
it as there's only 1 input clock so it wouldn't be at all messy.

PDC is pretty independent and can remain mostly unchanged (that is
consistent with irq, pinctrl and gpio drivers too, where PDC low power
stuff is independent and fits nicely into separate drivers).

Thanks for the suggestions!

James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2014-11-25 11:39 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-19 23:15 [PATCH 00/15] tz1090: add clock components James Hogan
2014-11-19 23:15 ` [PATCH 01/15] clk: divider: replace bitfield width with mask James Hogan
2014-11-20 11:19   ` Tero Kristo
2014-11-20 11:59     ` James Hogan
2014-11-19 23:15 ` [PATCH 02/15] clk: divider: expose new clk_register_divider_mask James Hogan
2014-11-19 23:15 ` [PATCH 03/15] dt: binding: add binding for tz1090-pll clock James Hogan
2014-11-19 23:15 ` [PATCH 04/15] clk: tz1090: add PLL clock driver James Hogan
2014-11-19 23:15 ` [PATCH 05/15] dt: binding: add binding for TZ1090 gate bank James Hogan
2014-11-19 23:15 ` [PATCH 06/15] clk: tz1090: add gate bank clock driver James Hogan
2014-11-19 23:15 ` [PATCH 07/15] dt: binding: add binding for TZ1090 mux bank James Hogan
2014-11-19 23:15 ` [PATCH 08/15] clk: tz1090: add mux bank clock driver James Hogan
2014-11-19 23:15 ` [PATCH 09/15] dt: binding: add binding for TZ1090 clock deleter James Hogan
2014-11-19 23:15 ` [PATCH 10/15] clk: tz1090: add deleter clock driver James Hogan
2014-11-19 23:15 ` [PATCH 11/15] dt: binding: add binding for TZ1090 PDC clock James Hogan
2014-11-19 23:15 ` [PATCH 12/15] clk: tz1090: add PDC clock driver James Hogan
2014-11-19 23:15 ` [PATCH 13/15] dt: binding: add binding for TZ1090 divider clock James Hogan
2014-11-19 23:15 ` [PATCH 14/15] clk: tz1090: add divider clock driver James Hogan
2014-11-19 23:15 ` [PATCH 15/15] metag: tz1090: add TZ1090 clocks to device tree James Hogan
2014-11-20 12:56   ` Heiko Stübner
2014-11-21 10:06     ` James Hogan
2014-11-24 23:03       ` Heiko Stübner
2014-11-25 11:39         ` James Hogan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).