Skip to contentSkip to conversation

ARM: TI SoC clock DT conversion

PATCH Superseded Tero Kristo 6 participants 106 messages Oct 25, 2013 – Nov 6, 2013

Subsystems (9)

v9 of 13 Superseded Latest is v13 →

lore
Share & tools
lore
#0 lore raw

v9 cover ARM: TI SoC clock DT conversion

Hi all,

Version 9 contains following major changes:
- Clock nodes changed to use offsets instead of direct memory addresses
* of_iomap() no longer called by individual clock drivers
* "prcm-driver" provides regmap for accessing the registers based on the offsets
* added support for regmaps to generic clock code
* added support for regmaps to clock code under mach-omap2
- Devicetree layout changed to be hierarchical: ocp->ip->clocks/clockdomains
* allows above mentioned offsets to be used
- Clock init mechanism changed completely, called now from prm_common.c, see patch #38. This patch contains some rather nasty looking hackery so if anybody has any idea how to make it cleaner, comments appreciated. Otherwise it can be cleaned later once strict hwmod dependencies are cleared and we don't need to do the early init hacks anymore.
- ti,mux-gate-clock type was killed, instead added support for ti,composite-clock (see patch #08 for base + components in patches #09 + #11 + #13)

Some minor changes also done:
- changed ti,autoidle-low to ti,invert-autoidle-bit
- ordering of patches changed to reflect merge locations (drivers/clk, arch/arm/boot/dts, arch/arm/mach-omap2)
- maybe some others, too much code to track.... should have covered most of the major comments from Paul though

Dependencies (included in the test branch):
- regmap: debugfs: Fix a boot time crash with early regmap init
- ARM: dts: OMAP5: Add mailbox dt node
- ARM: OMAP5/DRA7: realtime_counter: Configure CNTFRQ register(v4)
- clk: of: helper for determining number of parent clocks

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

DTS data branch: 3.12-rc6-dt-clks-for-benoit CLK driver branch: 3.12-rc6-dt-clks-for-mike Misc OMAP stuff branch: 3.12-rc6-dt-clks-for-tony Fully functioning test branch: 3.12-rc6-dt-clks-v9

-Tero

#1 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

Previously, only direct register read/write was supported. Now a per-clock regmap can be provided for same purpose, which allows the clock drivers to access clock registers behind e.g. I2C bus.

---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   23 +++++++++++++++++++----
 4 files changed, 28 insertions(+), 13 deletions(-)
drivers/clk/clk-divider.c +3 -3
index 8d3009e..9c17b1a 100644
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = clk_readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg, divider->regmap) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = clk_readl(divider->reg);
+		val = clk_readl(divider->reg, divider->regmap);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	clk_writel(val, divider->reg);
+	clk_writel(val, divider->reg, divider->regmap);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
drivers/clk/clk-gate.c +3 -3
index 4a58c55..3c7f686 100644
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = clk_readl(gate->reg);
+		reg = clk_readl(gate->reg, gate->regmap);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	clk_writel(reg, gate->reg);
+	clk_writel(reg, gate->reg, gate->regmap);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = clk_readl(gate->reg);
+	reg = clk_readl(gate->reg, gate->regmap);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
drivers/clk/clk-mux.c +3 -3
index 4f96ff3..68eb8c2 100644
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = clk_readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg, mux->regmap) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = clk_readl(mux->reg);
+		val = clk_readl(mux->reg, mux->regmap);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	clk_writel(val, mux->reg);
+	clk_writel(val, mux->reg, mux->regmap);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
include/linux/clk-provider.h +19 -4
index 7e59253..63ff78c 100644
@@ -13,6 +13,7 @@
 
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/regmap.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -209,6 +210,7 @@ void of_fixed_clk_setup(struct device_node *np);
  *
  * @hw:		handle between common and hardware-specific interfaces
  * @reg:	register controlling gate
+ * @regmap:	regmap for accessing the gate register (if any)
  * @bit_idx:	single bit controlling gate
  * @flags:	hardware-specific flags
  * @lock:	register lock
@@ -227,6 +229,7 @@ void of_fixed_clk_setup(struct device_node *np);
 struct clk_gate {
 	struct clk_hw hw;
 	void __iomem	*reg;
+	struct regmap	*regmap;
 	u8		bit_idx;
 	u8		flags;
 	spinlock_t	*lock;
@@ -251,6 +254,7 @@ struct clk_div_table {
  *
  * @hw:		handle between common and hardware-specific interfaces
  * @reg:	register containing the divider
+ * @regmap:	regmap for accessing the divider register (if any)
  * @shift:	shift to the divider bit field
  * @width:	width of the divider bit field
  * @table:	array of value/divider pairs, last entry should have div = 0
@@ -279,6 +283,7 @@ struct clk_div_table {
 struct clk_divider {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct regmap	*regmap;
 	u8		shift;
 	u8		width;
 	u8		flags;
@@ -326,6 +331,7 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 struct clk_mux {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct regmap	*regmap;
 	u32		*table;
 	u32		mask;
 	u8		shift;
@@ -512,14 +518,23 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
 {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
 }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
 {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
 }
 
 #endif /* CONFIG_COMMON_CLK */
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
include/linux/clk-provider.h +0 -0
index 7e59253..63ff78c 100644

[...]

Quoted 15 lines
include/linux/clk-provider.h +8 -3
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
 {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
 }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)

include/linux/clk-provider.h static inline const char *of_clk_get_parent_name(struct device_node *np, · line 540

Quoted 10 lines
include/linux/clk-provider.h +5 -1
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
 {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
 }
 
 #endif /* CONFIG_COMMON_CLK */

Might it not be better to introduce regmap variants? static inline void clk_regmap_writel(u32 val, u32 reg, struct regmap *regmap)
and corresponding readl? that allows cleaner readability for clk drivers that use regmap and those that dont.

regmap can also return error value that could also be handled as a result.

Signature · 2 lines
Regards,
Nishanth Menon
#3 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

Quoted 31 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
include/linux/clk-provider.h +0 -0
index 7e59253..63ff78c 100644

[...]

Quoted 23 lines
include/linux/clk-provider.h +13 -4
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
  {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
  }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
  {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
  }
Quoted 8 lines
Quoted 2 lines
  #endif /* CONFIG_COMMON_CLK */

Might it not be better to introduce regmap variants? static inline void clk_regmap_writel(u32 val, u32 reg, struct regmap *regmap)
and corresponding readl? that allows cleaner readability for clk drivers that use regmap and those that dont.

Well, doing that will introduce a lot of redundant code, as the checks for the presence of regmap must be copied all over the place. With this patch, all the generic clock drivers support internally both regmap or non-regmap register accesses.

Quoted 1 line

regmap can also return error value that could also be handled as a result.

True, however if the regmap fails for the clock code, not sure what we can do but panic. If this code is expanded, it is probably better to not inline it anymore.

-Tero

#4 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

Quoted 41 lines · Tero Kristo
Quoted 31 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
include/linux/clk-provider.h +0 -0
index 7e59253..63ff78c 100644

[...]

Quoted 23 lines
include/linux/clk-provider.h +13 -4
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
  {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
  }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
  {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
  }
Quoted 8 lines
Quoted 2 lines
  #endif /* CONFIG_COMMON_CLK */

Might it not be better to introduce regmap variants? static inline void clk_regmap_writel(u32 val, u32 reg, struct regmap *regmap)
and corresponding readl? that allows cleaner readability for clk drivers that use regmap and those that dont.

Quoted 5 lines

Well, doing that will introduce a lot of redundant code, as the checks for the presence of regmap must be copied all over the place. With this patch, all the generic clock drivers support internally both regmap or non-regmap register accesses.

using function pointers might be an appropriate solution. in general a low level reg access api that uses two different approaches sounds a little.. umm.. fishy..

Quoted 6 lines
Quoted 1 line

regmap can also return error value that could also be handled as a result.

True, however if the regmap fails for the clock code, not sure what we can do but panic. If this code is expanded, it is probably better to not inline it anymore.

let the compiler deal with that decision. regmap operation fail should be percollated back to initiator of the request. in some cases that will be ir-recoverable, but on other cases panic might be the right answer - at the low level we are in no position to make that distinction.

Signature · 2 lines
Regards,
Nishanth Menon
#5 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

Quoted 48 lines · Nishanth Menon
Quoted 41 lines · Tero Kristo
Quoted 31 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
include/linux/clk-provider.h +0 -0
index 7e59253..63ff78c 100644

[...]

Quoted 23 lines
include/linux/clk-provider.h +13 -4
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
   {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
   }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
   {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
   }
Quoted 8 lines
Quoted 2 lines
   #endif /* CONFIG_COMMON_CLK */

Might it not be better to introduce regmap variants? static inline void clk_regmap_writel(u32 val, u32 reg, struct regmap *regmap)
and corresponding readl? that allows cleaner readability for clk drivers that use regmap and those that dont.

Quoted 5 lines

Well, doing that will introduce a lot of redundant code, as the checks for the presence of regmap must be copied all over the place. With this patch, all the generic clock drivers support internally both regmap or non-regmap register accesses.

Quoted 3 lines

using function pointers might be an appropriate solution. in general a low level reg access api that uses two different approaches sounds a little.. umm.. fishy..

Initial work I did for v9 had clk_reg_ops struct in place which pretty much did this, however Mike recommended looking at the regmap so I did. I could put the reg_ops struct back and just have it use internally regmap if that would be better, but I guess we need comment from Mike how he wants this to be done.

We could have:

struct clk_reg_ops {
	int (*clk_readl)(u32 addr, u32 *val);
	int (*clk_writel)(u32 addr, u32 val);
};
struct clk_foo {
	...
	void __iomem *reg;
	struct clk_reg_ops *regops;
};
Quoted 11 lines
Quoted 7 lines
Quoted 2 lines

regmap can also return error value that could also be handled as a result.

True, however if the regmap fails for the clock code, not sure what we can do but panic. If this code is expanded, it is probably better to not inline it anymore.

let the compiler deal with that decision. regmap operation fail should be percollated back to initiator of the request. in some cases that will be ir-recoverable, but on other cases panic might be the right answer - at the low level we are in no position to make that distinction.

Currently, none of the clock drivers handle failures for regmap operations, I can of course add some sort of support for this given what we do with above point and what the API for the register accesses ends up like.

-Tero

#6 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

In reply to Tero Kristo
Quoted 42 lines · Tero Kristo
Quoted 31 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
include/linux/clk-provider.h +0 -0
index 7e59253..63ff78c 100644

[...]

Quoted 23 lines
include/linux/clk-provider.h +13 -4
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
 {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
 }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
 {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
 }
Quoted 8 lines
Quoted 2 lines

#endif /* CONFIG_COMMON_CLK */

Might it not be better to introduce regmap variants? static inline void clk_regmap_writel(u32 val, u32 reg, struct regmap *regmap)
and corresponding readl? that allows cleaner readability for clk drivers that use regmap and those that dont.

Quoted 4 lines

Well, doing that will introduce a lot of redundant code, as the checks for the presence of regmap must be copied all over the place. With this patch, all the generic clock drivers support internally both regmap or non-regmap register accesses.

Please keep in mind that the "identity" of clk_readl() and readl() only applies in the current source code (ARM only use of common CCF primitives), while patches are pending (currently under review and receiving further improvement) which introduce several alternative implementations of clk_readl() depending on the platform. Making all of them duplicate the "regmap vs direct register access" branch would be as bad. Keeping one set of clk_readl() and clk_writel() routines and adding #ifdefs around the direct register access would be rather ugly, and I understand that preprocessor ifdef counts should get reduced instead of introduced.

virtually yours
Gerhard Sittig

Signature · 3 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
#7 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

Quoted 48 lines · Gerhard Sittig
Quoted 42 lines · Tero Kristo
Quoted 31 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
include/linux/clk-provider.h +0 -0
index 7e59253..63ff78c 100644

[...]

Quoted 23 lines
include/linux/clk-provider.h +13 -4
-static inline u32 clk_readl(u32 __iomem *reg)
+static inline u32 clk_readl(u32 __iomem *reg, struct regmap *regmap)
  {
-	return readl(reg);
+	u32 val;
+
+	if (regmap)
+		regmap_read(regmap, (u32)reg, &val);
+	else
+		val = readl(reg);
+	return val;
  }
 
-static inline void clk_writel(u32 val, u32 __iomem *reg)
+static inline void clk_writel(u32 val, u32 __iomem *reg, struct regmap *regmap)
  {
-	writel(val, reg);
+	if (regmap)
+		regmap_write(regmap, (u32)reg, val);
+	else
+		writel(val, reg);
  }
Quoted 8 lines
Quoted 2 lines
  #endif /* CONFIG_COMMON_CLK */

Might it not be better to introduce regmap variants? static inline void clk_regmap_writel(u32 val, u32 reg, struct regmap *regmap)
and corresponding readl? that allows cleaner readability for clk drivers that use regmap and those that dont.

Quoted 4 lines

Well, doing that will introduce a lot of redundant code, as the checks for the presence of regmap must be copied all over the place. With this patch, all the generic clock drivers support internally both regmap or non-regmap register accesses.

Quoted 11 lines

Please keep in mind that the "identity" of clk_readl() and readl() only applies in the current source code (ARM only use of common CCF primitives), while patches are pending (currently under review and receiving further improvement) which introduce several alternative implementations of clk_readl() depending on the platform. Making all of them duplicate the "regmap vs direct register access" branch would be as bad. Keeping one set of clk_readl() and clk_writel() routines and adding #ifdefs around the direct register access would be rather ugly, and I understand that preprocessor ifdef counts should get reduced instead of introduced.

So, it might be better to provide platform / or clock specific clk_reg_ops or something, so we can cover all the possible cases easily.

The requirement from TI SoC point of view is that:

1) need to be able to specify custom register read/write ops
2) need to be able to provide an index parameter to the read/write ops
3) need to be able to provide a register offset to the read/write ops

This could be done in following way for example:

clk_readl / clk_writel would be accessed through a single platform specific struct which provides function pointers to both.

The content of 'reg' provided to the clk_readl / clk_writel would be internally interpreted as a

struct omap_clk_reg_internal {
	u16 offset;
	u16 index;
};

... the index part would be used to select the appropriate regmap to use, and TI SoC:s would be using 3...4 regmaps for actually accessing the physical registers themselves.

-Tero

Quoted 5 lines

virtually yours
Gerhard Sittig

#8 lore raw

PATCH v9 1/43 clk: Add support for regmap register read/write

In reply to Tero Kristo

Hi Tero,

Quoted 11 lines · On Friday 25 of October 2013 18:56:55 Tero Kristo wrote:

Previously, only direct register read/write was supported. Now a per-clock regmap can be provided for same purpose, which allows the clock drivers to access clock registers behind e.g. I2C bus.

---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   23 +++++++++++++++++++----
 4 files changed, 28 insertions(+), 13 deletions(-)

The idea itself sounds not bad, but patch description fails to specify what is the need for this. I mean, if you know that this will have some actual users, it is nice to specify them.

Also IMHO the variant with clk_reg_ops (but with regmap used) would look a bit better in terms of readability and extensibility, but I'm leaving this completely to Mike's decision.

(OR maybe you could migrate this fully to regmap, which can do MMIO accesses as well, without the need of having separate code paths for both in clock code?)

Best regards,
Tomasz

#9 lore raw

PATCH v9 2/43 clk: divider: add init call which supports regmap

In reply to Tero Kristo

Divider clock can now be initialized to use regmap for control register access.

---
 drivers/clk/clk-divider.c    |   37 ++++++++++++++++++++++++++++++++-----
 include/linux/clk-provider.h |    6 ++++++
 2 files changed, 38 insertions(+), 5 deletions(-)
drivers/clk/clk-divider.c +32 -5
index 9c17b1a..3767879 100644
@@ -251,7 +251,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, struct regmap *regmap, u8 shift, u8 width,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
@@ -281,6 +281,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 
 	/* struct clk_divider assignments */
 	div->reg = reg;
+	div->regmap = regmap;
 	div->shift = shift;
 	div->width = width;
 	div->flags = clk_divider_flags;
@@ -314,8 +315,8 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
-	return _register_divider(dev, name, parent_name, flags, reg, shift,
-			width, clk_divider_flags, NULL, lock);
+	return _register_divider(dev, name, parent_name, flags, reg, NULL,
+			shift, width, clk_divider_flags, NULL, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_divider);
 
@@ -339,7 +340,33 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
-	return _register_divider(dev, name, parent_name, flags, reg, shift,
-			width, clk_divider_flags, table, lock);
+	return _register_divider(dev, name, parent_name, flags, reg, NULL,
+			shift, width, clk_divider_flags, table, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_divider_table);
+
+/**
+ * clk_register_divider_table_regmap - register a table 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
+ * @regmap: regmap for accessing the divider register (if any)
+ * @shift: number of bits to shift the 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_table_regmap(struct device *dev,
+		const char *name, const char *parent_name, unsigned long flags,
+		void __iomem *reg, struct regmap *regmap, u8 shift, u8 width,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock)
+{
+	return _register_divider(dev, name, parent_name, flags, reg, regmap,
+			shift, width, clk_divider_flags, table, lock);
+}
+EXPORT_SYMBOL_GPL(clk_register_divider_table_regmap);
include/linux/clk-provider.h +6 -0
index 63ff78c..369d7c0 100644
@@ -306,12 +306,18 @@ 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_table_regmap(struct device *dev,
+		const char *name, const char *parent_name, unsigned long flags,
+		void __iomem *reg, struct regmap *regmap, u8 shift, u8 width,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock);
 
 /**
  * struct clk_mux - multiplexer clock
  *
  * @hw:		handle between common and hardware-specific interfaces
  * @reg:	register controlling multiplexer
+ * @regmap:	regmap for accessing the mux register (if any)
  * @shift:	shift to multiplexer bit field
  * @width:	width of mutliplexer bit field
  * @flags:	hardware-specific flags
Signature · 1 line
1.7.9.5
#10 lore raw

PATCH v9 3/43 clk: mux: add init call which supports regmap

In reply to Tero Kristo

Multiplexer clock can now be initialized to use regmap for control register access.

---
 drivers/clk/clk-mux.c        |   17 +++++++++++++++--
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 19 insertions(+), 2 deletions(-)
drivers/clk/clk-mux.c +15 -2
index 68eb8c2..2cf7d59 100644
@@ -113,9 +113,9 @@ const struct clk_ops clk_mux_ro_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
 
-struct clk *clk_register_mux_table(struct device *dev, const char *name,
+struct clk *clk_register_mux_table_regmap(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
-		void __iomem *reg, u8 shift, u32 mask,
+		void __iomem *reg, struct regmap *regmap, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
 	struct clk_mux *mux;
@@ -149,6 +149,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 
 	/* struct clk_mux assignments */
 	mux->reg = reg;
+	mux->regmap = regmap;
 	mux->shift = shift;
 	mux->mask = mask;
 	mux->flags = clk_mux_flags;
@@ -163,6 +164,18 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 
 	return clk;
 }
+EXPORT_SYMBOL_GPL(clk_register_mux_table_regmap);
+
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+		const char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u32 mask,
+		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
+{
+	return clk_register_mux_table_regmap(dev, name, parent_names,
+					     num_parents, flags, reg, NULL,
+					     shift, mask, clk_mux_flags, table,
+					     lock);
+}
 EXPORT_SYMBOL_GPL(clk_register_mux_table);
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
include/linux/clk-provider.h +4 -0
index 369d7c0..9a1423e 100644
@@ -362,6 +362,10 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
+struct clk *clk_register_mux_table_regmap(struct device *dev, const char *name,
+		const char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, struct regmap *regmap, u8 shift, u32 mask,
+		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
 void of_fixed_factor_clk_setup(struct device_node *node);
 
Signature · 1 line
1.7.9.5
#11 lore raw

PATCH v9 4/43 CLK: TI: Add DPLL clock support

In reply to Tero Kristo

The OMAP clock driver now supports DPLL clock type. This patch also adds support for DT DPLL nodes.

---
 .../devicetree/bindings/clock/ti/dpll.txt          |   81 +++
 arch/arm/mach-omap2/clock.h                        |  144 +----
 arch/arm/mach-omap2/clock3xxx.h                    |    2 -
 drivers/clk/Makefile                               |    1 +
 drivers/clk/ti/Makefile                            |    3 +
 drivers/clk/ti/dpll.c                              |  632 ++++++++++++++++++++
 include/linux/clk/ti.h                             |  161 +++++
 7 files changed, 879 insertions(+), 145 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/dpll.txt
 create mode 100644 drivers/clk/ti/Makefile
 create mode 100644 drivers/clk/ti/dpll.c
 create mode 100644 include/linux/clk/ti.h
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +81 -0
new file mode 100644
index 0000000..7b87721
@@ -0,0 +1,81 @@
+Binding for Texas Instruments DPLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped DPLL with usually two selectable input clocks
+(reference clock and bypass clock), with digital phase locked
+loop logic for multiplying the input clock to a desired output
+clock. This clock also typically supports different operation
+modes (locked, low power stop etc.) This binding has several
+sub-types, which effectively result in slightly different setup
+for the actual DPLL clock.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of:
+		"ti,omap3-dpll-clock",
+		"ti,omap3-dpll-core-clock",
+		"ti,omap3-dpll-per-clock",
+		"ti,omap3-dpll-per-j-type-clock",
+		"ti,omap4-dpll-clock",
+		"ti,omap4-dpll-x2-clock",
+		"ti,omap4-dpll-core-clock",
+		"ti,omap4-dpll-m4xen-clock",
+		"ti,omap4-dpll-j-type-clock",
+		"ti,am3-dpll-no-gate-clock",
+		"ti,am3-dpll-j-type-clock",
+		"ti,am3-dpll-no-gate-j-type-clock",
+		"ti,am3-dpll-clock",
+		"ti,am3-dpll-core-clock",
+		"ti,am3-dpll-x2-clock",
+
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks, first entry lists reference clock
+  and second entry bypass clock
+- reg : offsets for the register set for controlling the DPLL.
+  Registers are listed in following order:
+	"control" - contains the control register base address
+	"idlest" - contains the idle status register base address
+	"autoidle" - contains the autoidle register base address
+	"mult-div1" - contains the multiplier / divider register base address
+  ti,am3-* dpll types list the registers in the same order, except "autoidle"
+  register is left out as this hardware does not have it, e.g.:
+	reg = <0x40>, <0x50>, <0x60>;
+  results in following register map:
+	base + 0x40 - control
+	base + 0x50 - idlest
+	base + 0x60 - mult-div1
+
+Optional properties:
+- DPLL mode setting - defining any one or more of the following overrides
+  default setting.
+	- ti,low-power-stop : DPLL supports low power stop mode, gating output
+	- ti,low-power-bypass : DPLL output matches rate of parent bypass clock
+	- ti,lock : DPLL locks in programmed rate
+
+Examples:
+	dpll_core_ck: dpll_core_ck at 44e00490 {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-core-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x490>, <0x45c>, <0x488>, <0x468>;
+	};
+
+	dpll2_ck: dpll2_ck at 48004004 {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-dpll-clock";
+		clocks = <&sys_ck>, <&dpll2_fck>;
+		ti,low-power-stop;
+		ti,low-power-bypass;
+		ti,lock;
+		reg = <0x4>, <0x24>, <0x34>, <0x40>;
+	};
+
+	dpll_core_ck: dpll_core_ck at 44e00490 {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-core-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x90>, <0x5c>, <0x68>;
+	};
arch/arm/mach-omap2/clock.h +1 -143

195 lines not on this page · raw message

arch/arm/mach-omap2/clock3xxx.h +0 -2
index 8cd4b0a..dab90e2 100644
@@ -9,8 +9,6 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H
 
 int omap3xxx_clk_init(void);
-int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
-					unsigned long parent_rate);
 int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
 					unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
drivers/clk/Makefile +1 -0
index 7b11106..981e14ac 100644
@@ -32,6 +32,7 @@ obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
 obj-$(CONFIG_ARCH_ZYNQ)		+= zynq/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
+obj-$(CONFIG_ARCH_OMAP)		+= ti/
 
 obj-$(CONFIG_X86)		+= x86/
 
drivers/clk/ti/Makefile new file +3 -0
new file mode 100644
index 0000000..93177987
@@ -0,0 +1,3 @@
+ifneq ($(CONFIG_OF),)
+obj-y					+= dpll.o
+endif
drivers/clk/ti/dpll.c new file +632 -0

632 lines not on this page · raw message

include/linux/clk/ti.h new file +161 -0

161 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#12 lore raw

PATCH v9 4/43 CLK: TI: Add DPLL clock support

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 38 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +32 -0
new file mode 100644
index 0000000..7b87721
@@ -0,0 +1,81 @@
+Binding for Texas Instruments DPLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped DPLL with usually two selectable input clocks
+(reference clock and bypass clock), with digital phase locked
+loop logic for multiplying the input clock to a desired output
+clock. This clock also typically supports different operation
+modes (locked, low power stop etc.) This binding has several
+sub-types, which effectively result in slightly different setup
+for the actual DPLL clock.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of:
+		"ti,omap3-dpll-clock",
+		"ti,omap3-dpll-core-clock",
+		"ti,omap3-dpll-per-clock",
+		"ti,omap3-dpll-per-j-type-clock",
+		"ti,omap4-dpll-clock",
+		"ti,omap4-dpll-x2-clock",
+		"ti,omap4-dpll-core-clock",
+		"ti,omap4-dpll-m4xen-clock",
+		"ti,omap4-dpll-j-type-clock",
+		"ti,am3-dpll-no-gate-clock",
+		"ti,am3-dpll-j-type-clock",
+		"ti,am3-dpll-no-gate-j-type-clock",
+		"ti,am3-dpll-clock",
+		"ti,am3-dpll-core-clock",
+		"ti,am3-dpll-x2-clock",

Documentation/devicetree/bindings/clock/ti/dpll.txt line 42

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +10 -0
+
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks, first entry lists reference clock
+  and second entry bypass clock
+- reg : offsets for the register set for controlling the DPLL.
+  Registers are listed in following order:
+	"control" - contains the control register base address
+	"idlest" - contains the idle status register base address
+	"autoidle" - contains the autoidle register base address
+	"mult-div1" - contains the multiplier / divider register base address

If we move mult-div1 above autoidle, indices for control, idlest, mult-div1 will be constant with DPLLs that dont have autoidle. a little easier to debug.

Quoted 15 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +14 -0
+  ti,am3-* dpll types list the registers in the same order, except "autoidle"
+  register is left out as this hardware does not have it, e.g.:
+	reg = <0x40>, <0x50>, <0x60>;
+  results in following register map:
+	base + 0x40 - control
+	base + 0x50 - idlest
+	base + 0x60 - mult-div1
+
+Optional properties:
+- DPLL mode setting - defining any one or more of the following overrides
+  default setting.
+	- ti,low-power-stop : DPLL supports low power stop mode, gating output
+	- ti,low-power-bypass : DPLL output matches rate of parent bypass clock
+	- ti,lock : DPLL locks in programmed rate
Quoted 6 lines
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = ((1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),

arch/arm/mach-omap2/dpll3xxx.c: _omap3_dpll_write_clken(clk, DPLL_LOCKED);

There is no if checks for DPLL_LOCKED which is set with ti,lock, should we just drop it?

[...]

Quoted 5 lines
drivers/clk/ti/dpll.c new file +0 -0
new file mode 100644
index 0000000..89733c9

[...]

Quoted 14 lines
drivers/clk/ti/dpll.c new file +14 -0
+/**
+ * ti_clk_register_dpll() - Registers the DPLL clock
+ * @name:	Name of the clock node
+ * @parent_names: list of parent names
+ * @num_parents: num of parents in parent_names
+ * @flags:	init flags
+ * @dpll_data:	DPLL data
+ * @ops:	ops for DPLL
+ */
+static struct clk *ti_clk_register_dpll(const char *name,
+					const char **parent_names,
+					int num_parents, unsigned long flags,
+					struct dpll_data *dpll_data,
+					const struct clk_ops *ops,

drivers/clk/ti/dpll.c line 115

Quoted 10 lines
drivers/clk/ti/dpll.c new file +10 -0
+					struct regmap *regmap)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
+
+	/* allocate the divider */
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);

here and in every other driver - please dont add pr_err for kzalloc not able to allocate, kzalloc will provide the warning anyways.

Quoted 44 lines
drivers/clk/ti/dpll.c new file +44 -0
+		return ERR_PTR(-ENOMEM);
+	}
+
+	clk_hw->dpll_data = dpll_data;
+	clk_hw->ops = &clkhwops_omap3_dpll;
+	clk_hw->hw.init = &init;
+	clk_hw->regmap = regmap;
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed clk_register for %s (%ld)\n", __func__, name,
+		       PTR_ERR(clk));
+		kfree(clk_hw);
+	} else {
+		omap2_init_clk_hw_omap_clocks(clk);
+	}
+
+	return clk;
+}
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+	defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX)
+/**
+ * ti_clk_register_dpll_x2() -  Registers the DPLLx2 clock
+ * @dev:	device pointer (if any)
+ * @name:	Name of the clock node
+ * @parent_name: parent name (only 1 parent)
+ * @reg:	register address for DPLL
+ * @ops:	ops for DPLL
+ */
+static struct clk *ti_clk_register_dpll_x2(struct device_node *node,
+					   const struct clk_ops *ops,
+					   const struct clk_hw_omap_ops *hw_ops,
+					   struct regmap *regmap)
+{
+	struct clk *clk;

drivers/clk/ti/dpll.c line 169

Quoted 10 lines
drivers/clk/ti/dpll.c new file +10 -0
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
+	const char *name = node->name;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s: dpll_x2 must have parent\n", __func__);

print node->name as well?

drivers/clk/ti/dpll.c line 175

Quoted 6 lines
drivers/clk/ti/dpll.c new file +6 -0
+		return ERR_PTR(-EINVAL);
+	}
+
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);

^^ here again.

Quoted 24 lines
drivers/clk/ti/dpll.c new file +24 -0
+		return ERR_PTR(-ENOMEM);
+	}
+
+	clk_hw->ops = hw_ops;
+	of_property_read_u32(node, "reg", (u32 *)&clk_hw->clksel_reg);
+	clk_hw->regmap = regmap;
+	clk_hw->hw.init = &init;
+
+	init.name = name;
+	init.ops = ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (IS_ERR(clk))
+		kfree(clk_hw);
+	else
+		omap2_init_clk_hw_omap_clocks(clk);
+
+	return clk;
+}
+#endif

[...]

drivers/clk/ti/dpll.c

Quoted 2 lines
drivers/clk/ti/dpll.c new file +2 -0
+
+#ifdef CONFIG_ARCH_OMAP3

just a mention - I understand we are still in transition and we need these #ifdefs, but eventually, we should be able to make the dpll.c independent of SoC variant #ifdefs.
[...]

Signature · 2 lines
Regards,
Nishanth Menon
#13 lore raw

PATCH v9 4/43 CLK: TI: Add DPLL clock support

Quoted 46 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 43 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +37 -0
new file mode 100644
index 0000000..7b87721
@@ -0,0 +1,81 @@
+Binding for Texas Instruments DPLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped DPLL with usually two selectable input clocks
+(reference clock and bypass clock), with digital phase locked
+loop logic for multiplying the input clock to a desired output
+clock. This clock also typically supports different operation
+modes (locked, low power stop etc.) This binding has several
+sub-types, which effectively result in slightly different setup
+for the actual DPLL clock.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of:
+		"ti,omap3-dpll-clock",
+		"ti,omap3-dpll-core-clock",
+		"ti,omap3-dpll-per-clock",
+		"ti,omap3-dpll-per-j-type-clock",
+		"ti,omap4-dpll-clock",
+		"ti,omap4-dpll-x2-clock",
+		"ti,omap4-dpll-core-clock",
+		"ti,omap4-dpll-m4xen-clock",
+		"ti,omap4-dpll-j-type-clock",
+		"ti,am3-dpll-no-gate-clock",
+		"ti,am3-dpll-j-type-clock",
+		"ti,am3-dpll-no-gate-j-type-clock",
+		"ti,am3-dpll-clock",
+		"ti,am3-dpll-core-clock",
+		"ti,am3-dpll-x2-clock",
+
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks, first entry lists reference clock
+  and second entry bypass clock
+- reg : offsets for the register set for controlling the DPLL.
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/dpll.txt line 42

Quoted 5 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +5 -0
+  Registers are listed in following order:
+	"control" - contains the control register base address
+	"idlest" - contains the idle status register base address
+	"autoidle" - contains the autoidle register base address
+	"mult-div1" - contains the multiplier / divider register base address

If we move mult-div1 above autoidle, indices for control, idlest, mult-div1 will be constant with DPLLs that dont have autoidle. a little easier to debug.

Hmm yea, might be a good idea to do that. Can change that for next rev.

Quoted 23 lines
Quoted 16 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +14 -0
+  ti,am3-* dpll types list the registers in the same order, except "autoidle"
+  register is left out as this hardware does not have it, e.g.:
+	reg = <0x40>, <0x50>, <0x60>;
+  results in following register map:
+	base + 0x40 - control
+	base + 0x50 - idlest
+	base + 0x60 - mult-div1
+
+Optional properties:
+- DPLL mode setting - defining any one or more of the following overrides
+  default setting.
+	- ti,low-power-stop : DPLL supports low power stop mode, gating output
+	- ti,low-power-bypass : DPLL output matches rate of parent bypass clock
+	- ti,lock : DPLL locks in programmed rate
Quoted 6 lines
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = ((1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),

arch/arm/mach-omap2/dpll3xxx.c: _omap3_dpll_write_clken(clk, DPLL_LOCKED);

Quoted 2 lines

There is no if checks for DPLL_LOCKED which is set with ti,lock, should we just drop it?

Probably better to keep it in, as there might be some code in future which needs this. Kind of better for readability also, as the field is specified to list the valid modes for the DPLL. One could argue that current kernel code is wrong for _omap3_dpll_write_clken(clk, DPLL_LOCKED) as it does not check if the mode is valid for the DPLL or not.

Quoted 29 lines

[...]

Quoted 5 lines
drivers/clk/ti/dpll.c new file +0 -0
new file mode 100644
index 0000000..89733c9

[...]

Quoted 19 lines
drivers/clk/ti/dpll.c new file +19 -0
+/**
+ * ti_clk_register_dpll() - Registers the DPLL clock
+ * @name:	Name of the clock node
+ * @parent_names: list of parent names
+ * @num_parents: num of parents in parent_names
+ * @flags:	init flags
+ * @dpll_data:	DPLL data
+ * @ops:	ops for DPLL
+ */
+static struct clk *ti_clk_register_dpll(const char *name,
+					const char **parent_names,
+					int num_parents, unsigned long flags,
+					struct dpll_data *dpll_data,
+					const struct clk_ops *ops,
+					struct regmap *regmap)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
Quoted 8 lines

drivers/clk/ti/dpll.c line 115

Quoted 5 lines
drivers/clk/ti/dpll.c new file +5 -0
+
+	/* allocate the divider */
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);

here and in every other driver - please dont add pr_err for kzalloc not able to allocate, kzalloc will provide the warning anyways.

Oh it does? Never seen that happen as kzalloc never failed for me. :) However, I can remove these as I don't think they will ever happen anyway.

Quoted 49 lines
Quoted 49 lines
drivers/clk/ti/dpll.c new file +48 -0
+		return ERR_PTR(-ENOMEM);
+	}
+
+	clk_hw->dpll_data = dpll_data;
+	clk_hw->ops = &clkhwops_omap3_dpll;
+	clk_hw->hw.init = &init;
+	clk_hw->regmap = regmap;
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed clk_register for %s (%ld)\n", __func__, name,
+		       PTR_ERR(clk));
+		kfree(clk_hw);
+	} else {
+		omap2_init_clk_hw_omap_clocks(clk);
+	}
+
+	return clk;
+}
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+	defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX)
+/**
+ * ti_clk_register_dpll_x2() -  Registers the DPLLx2 clock
+ * @dev:	device pointer (if any)
+ * @name:	Name of the clock node
+ * @parent_name: parent name (only 1 parent)
+ * @reg:	register address for DPLL
+ * @ops:	ops for DPLL
+ */
+static struct clk *ti_clk_register_dpll_x2(struct device_node *node,
+					   const struct clk_ops *ops,
+					   const struct clk_hw_omap_ops *hw_ops,
+					   struct regmap *regmap)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
+	const char *name = node->name;
+	const char *parent_name;
Quoted 8 lines

drivers/clk/ti/dpll.c line 169

Quoted 6 lines
drivers/clk/ti/dpll.c new file +6 -0
+
+	of_property_read_string(node, "clock-output-names", &name);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s: dpll_x2 must have parent\n", __func__);

print node->name as well?

Mkay.

Quoted 35 lines

drivers/clk/ti/dpll.c line 175

Quoted 7 lines
drivers/clk/ti/dpll.c new file +6 -0
+		return ERR_PTR(-EINVAL);
+	}
+
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);

^^ here again.

Quoted 24 lines
drivers/clk/ti/dpll.c new file +24 -0
+		return ERR_PTR(-ENOMEM);
+	}
+
+	clk_hw->ops = hw_ops;
+	of_property_read_u32(node, "reg", (u32 *)&clk_hw->clksel_reg);
+	clk_hw->regmap = regmap;
+	clk_hw->hw.init = &init;
+
+	init.name = name;
+	init.ops = ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (IS_ERR(clk))
+		kfree(clk_hw);
+	else
+		omap2_init_clk_hw_omap_clocks(clk);
+
+	return clk;
+}
+#endif

[...]

Quoted 6 lines

drivers/clk/ti/dpll.c

Quoted 2 lines
drivers/clk/ti/dpll.c new file +2 -0
+
+#ifdef CONFIG_ARCH_OMAP3

just a mention - I understand we are still in transition and we need these #ifdefs, but eventually, we should be able to make the dpll.c independent of SoC variant #ifdefs.

Eventually yes. Currently it fails to compile if you do OMAP4 / OMAP5 only build, as you don't have the OMAP3 support routines in.

-Tero

#14 lore raw

PATCH v9 4/43 CLK: TI: Add DPLL clock support

Quoted 9 lines · Tero Kristo
Quoted 8 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
[...]

Quoted 5 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +0 -0
new file mode 100644
index 0000000..7b87721

[...]

Quoted 23 lines
Quoted 23 lines
Quoted 22 lines
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +14 -0
+  ti,am3-* dpll types list the registers in the same order, except "autoidle"
+  register is left out as this hardware does not have it, e.g.:
+	reg = <0x40>, <0x50>, <0x60>;
+  results in following register map:
+	base + 0x40 - control
+	base + 0x50 - idlest
+	base + 0x60 - mult-div1
+
+Optional properties:
+- DPLL mode setting - defining any one or more of the following overrides
+  default setting.
+	- ti,low-power-stop : DPLL supports low power stop mode, gating output
+	- ti,low-power-bypass : DPLL output matches rate of parent bypass clock
+	- ti,lock : DPLL locks in programmed rate
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = ((1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
arch/arm/mach-omap2/cclock3xxx_data.c:  .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),

arch/arm/mach-omap2/dpll3xxx.c: _omap3_dpll_write_clken(clk, DPLL_LOCKED);

Quoted 8 lines
Quoted 2 lines

There is no if checks for DPLL_LOCKED which is set with ti,lock, should we just drop it?

Probably better to keep it in, as there might be some code in future which needs this. Kind of better for readability also, as the field is specified to list the valid modes for the DPLL. One could argue that current kernel code is wrong for _omap3_dpll_write_clken(clk, DPLL_LOCKED) as it does not check if the mode is valid for the DPLL or not.

yep, the thought did cross my mind.

Quoted 39 lines
Quoted 30 lines

[...]

Quoted 5 lines
drivers/clk/ti/dpll.c new file +0 -0
new file mode 100644
index 0000000..89733c9

[...]

Quoted 19 lines
drivers/clk/ti/dpll.c new file +19 -0
+/**
+ * ti_clk_register_dpll() - Registers the DPLL clock
+ * @name:	Name of the clock node
+ * @parent_names: list of parent names
+ * @num_parents: num of parents in parent_names
+ * @flags:	init flags
+ * @dpll_data:	DPLL data
+ * @ops:	ops for DPLL
+ */
+static struct clk *ti_clk_register_dpll(const char *name,
+					const char **parent_names,
+					int num_parents, unsigned long flags,
+					struct dpll_data *dpll_data,
+					const struct clk_ops *ops,
+					struct regmap *regmap)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
Quoted 8 lines

drivers/clk/ti/dpll.c line 115

Quoted 5 lines
drivers/clk/ti/dpll.c new file +5 -0
+
+	/* allocate the divider */
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);

here and in every other driver - please dont add pr_err for kzalloc not able to allocate, kzalloc will provide the warning anyways.

Quoted 2 lines

Oh it does? Never seen that happen as kzalloc never failed for me. :) However, I can remove these as I don't think they will ever happen anyway.

There have been cleanups such as commit 38bb5253a95f2eb8cb765b7ab88aac686de6cb12 etc.. we dont want to introduce new ones now.

Quoted 29 lines
Quoted 22 lines
Quoted 21 lines
drivers/clk/ti/dpll.c new file +21 -0
+	clk_hw->ops = hw_ops;
+	of_property_read_u32(node, "reg", (u32 *)&clk_hw->clksel_reg);
+	clk_hw->regmap = regmap;
+	clk_hw->hw.init = &init;
+
+	init.name = name;
+	init.ops = ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (IS_ERR(clk))
+		kfree(clk_hw);
+	else
+		omap2_init_clk_hw_omap_clocks(clk);
+
+	return clk;
+}
+#endif

[...]

Quoted 6 lines

drivers/clk/ti/dpll.c

Quoted 2 lines
drivers/clk/ti/dpll.c new file +2 -0
+
+#ifdef CONFIG_ARCH_OMAP3

just a mention - I understand we are still in transition and we need these #ifdefs, but eventually, we should be able to make the dpll.c independent of SoC variant #ifdefs.

Quoted 2 lines

Eventually yes. Currently it fails to compile if you do OMAP4 / OMAP5 only build, as you don't have the OMAP3 support routines in.

fair enough.

Signature · 2 lines
Regards,
Nishanth Menon
#15 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

In reply to Tero Kristo

Some devices require their clocks to be available with a specific dev-id con-id mapping. With DT, the clocks can be found by default only with their name, or alternatively through the device node of the consumer. With drivers, that don't support DT fully yet, add mechanism to register specific clock names.

---
 drivers/clk/ti/Makefile |    2 +-
 drivers/clk/ti/clk.c    |   52 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h  |   23 +++++++++++++++++++++
 3 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/clk.c
drivers/clk/ti/Makefile +1 -1
index 93177987..05af5d8 100644
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= dpll.o
+obj-y					+= clk.o dpll.o
 endif
drivers/clk/ti/clk.c new file +52 -0

52 lines not on this page · raw message

include/linux/clk/ti.h +23 -0
index c187023..9786752 100644
@@ -15,6 +15,8 @@
 #ifndef __LINUX_CLK_TI_H__
 #define __LINUX_CLK_TI_H__
 
+#include <linux/clkdev.h>
+
 /**
  * struct dpll_data - DPLL registers and integration data
  * @mult_div1_reg: register containing the DPLL M and N bitfields
@@ -135,6 +137,25 @@ struct clk_hw_omap {
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE		0x1
 
+/**
+ * struct ti_dt_clk - OMAP DT clock alias declarations
+ * @lk: clock lookup definition
+ * @node_name: clock DT node to map to
+ */
+struct ti_dt_clk {
+	struct clk_lookup		lk;
+	char				*node_name;
+};
+
+#define DT_CLK(dev, con, name)		\
+	{				\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+		},			\
+		.node_name = name,	\
+	}
+
 void omap2_init_clk_hw_omap_clocks(struct clk *clk);
 int omap3_noncore_dpll_enable(struct clk_hw *hw);
 void omap3_noncore_dpll_disable(struct clk_hw *hw);
@@ -155,6 +176,8 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 
+void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
 
Signature · 1 line
1.7.9.5
#16 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

Quoted 9 lines · Tero Kristo

Some devices require their clocks to be available with a specific dev-id con-id mapping. With DT, the clocks can be found by default only with their name, or alternatively through the device node of the consumer. With drivers, that don't support DT fully yet, add mechanism to register specific clock names.

You guys are wonderful, by the way ;)

Quoted 11 lines
drivers/clk/ti/clk.c new file +11 -0
+void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
+{
+       struct ti_dt_clk *c;
+       struct device_node *node;
+       struct clk *clk;
+       struct of_phandle_args clkspec;
+
+       for (c = oclks; c->node_name != NULL; c++) {
+               node = of_find_node_by_name(NULL, c->node_name);
+               clkspec.np = node;
+               clk = of_clk_get_from_provider(&clkspec);

drivers/clk/ti/clk.c line 52

Quoted 10 lines
drivers/clk/ti/clk.c new file +10 -0
+
+               if (!IS_ERR(clk)) {
+                       c->lk.clk = clk;
+                       clkdev_add(&c->lk);
+               } else {
+                       pr_warn("%s: failed to lookup clock node %s\n",
+                               __func__, c->node_name);
+               }
+       }
+}

I have one question here, what makes this part of the patch TI-specific at all except the definition of the structure ti_dt_clk? Mapping DT clocks to generic clkdev legacy namings seems like it would be a necessary evil across *all* SoC platforms.

I would say there is a good case for this being generic and used by all platforms waiting for con->id/dev->id to be moved to DT-awareness, the structure itself is very generic within clkdev as long as the drivers conformed anyway (and if they didn't, none of this helps) and I don't think it really needs to be a TI-only thing. The next thing that's going to happen when another platform arrives that wants to do the same thing is duplication or consolidation - so it would probably be a good idea to make this generic to start.

While there the names could be a bit more descriptive - dt_clk_name_lookup_map_register(), struct dt_clk_name_lookup_map, DT_CLK_LOOKUP_MAP() ..? The current namespace makes it look like this is the absolute correct thing to do under all circumstances, but in fact this is purely for mapping the old way to the new, better way.. in the event a brand new platform arrives, with all new drivers (or only compliant drivers), none of this code should be implemented for it and it should be presented this way.

Thanks,
Matt Sealey <[email protected]>

#17 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

Quoted 49 lines · Matt Sealey
Quoted 9 lines · Tero Kristo

Some devices require their clocks to be available with a specific dev-id con-id mapping. With DT, the clocks can be found by default only with their name, or alternatively through the device node of the consumer. With drivers, that don't support DT fully yet, add mechanism to register specific clock names.

You guys are wonderful, by the way ;)

Quoted 11 lines
drivers/clk/ti/clk.c new file +11 -0
+void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
+{
+       struct ti_dt_clk *c;
+       struct device_node *node;
+       struct clk *clk;
+       struct of_phandle_args clkspec;
+
+       for (c = oclks; c->node_name != NULL; c++) {
+               node = of_find_node_by_name(NULL, c->node_name);
+               clkspec.np = node;
+               clk = of_clk_get_from_provider(&clkspec);

drivers/clk/ti/clk.c line 52

Quoted 10 lines
drivers/clk/ti/clk.c new file +10 -0
+
+               if (!IS_ERR(clk)) {
+                       c->lk.clk = clk;
+                       clkdev_add(&c->lk);
+               } else {
+                       pr_warn("%s: failed to lookup clock node %s\n",
+                               __func__, c->node_name);
+               }
+       }
+}

I have one question here, what makes this part of the patch TI-specific at all except the definition of the structure ti_dt_clk? Mapping DT clocks to generic clkdev legacy namings seems like it would be a necessary evil across *all* SoC platforms.

I would say there is a good case for this being generic and used by all platforms waiting for con->id/dev->id to be moved to DT-awareness, the structure itself is very generic within clkdev as long as the drivers conformed anyway (and if they didn't, none of this helps) and I don't think it really needs to be a TI-only thing. The next thing that's going to happen when another platform arrives that wants to do the same thing is duplication or consolidation - so it would probably be a good idea to make this generic to start.

Quoted 8 lines

While there the names could be a bit more descriptive - dt_clk_name_lookup_map_register(), struct dt_clk_name_lookup_map, DT_CLK_LOOKUP_MAP() ..? The current namespace makes it look like this is the absolute correct thing to do under all circumstances, but in fact this is purely for mapping the old way to the new, better way.. in the event a brand new platform arrives, with all new drivers (or only compliant drivers), none of this code should be implemented for it and it should be presented this way.

An earlier implementation of this patch (or at least a patch that tries to accomplish the same as this does, add support for legacy devices) did try to add generic solution. There was some discussion on it and I decided to drop it due to bad feedback.

See: http://www.spinics.net/lists/linux-omap/msg95147.html

-Tero

#18 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

Quoted 7 lines · Tero Kristo
Quoted 6 lines · Matt Sealey

I have one question here, what makes this part of the patch TI-specific at all except the definition of the structure ti_dt_clk? Mapping DT clocks to generic clkdev legacy namings seems like it would be a necessary evil across *all* SoC platforms.

Quoted 8 lines
Quoted 1 line

I would say there is a good case for this being generic

An earlier implementation of this patch (or at least a patch that tries to accomplish the same as this does, add support for legacy devices) did try to add generic solution. There was some discussion on it and I decided to drop it due to bad feedback.

See: http://www.spinics.net/lists/linux-omap/msg95147.html

I don't see anything that says this should not be generic, just that it was implemented relatively poorly at the time...

I agree with Tomasz, find_by_name in device trees is basically evil (it's only supposed to be used if you already know the name because something else passed it to you, and just want it's phandle, but names CAN be ambiguous. The real fix is always pass phandles and not strings of the name property), but that's not to say this thing needs to be TI-specific..

Ah well. If it ends up getting used elsewhere, it can be quickly patched into a generic version anyway, so.. yay!

I'm really interested in this all going in - but I would love to see where this is just all patched into a tree already. Pulling things out against a bunch of trees gave me more merge failures and weird happenings than I care to deal with. Is there a TI clock development tree with all this in somewhere publically accessible? I'd like to get a feel for how the DT looks and what's going on, I can't "see" it from the patches. Once it's there.. I'll spend a week or 5 doing all of the i.MX chips and you'll have a second test case for any problems :)

Ta,
Matt Sealey <[email protected]>

#19 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

Quoted 27 lines · Matt Sealey
Quoted 7 lines · Tero Kristo
Quoted 6 lines · Matt Sealey

I have one question here, what makes this part of the patch TI-specific at all except the definition of the structure ti_dt_clk? Mapping DT clocks to generic clkdev legacy namings seems like it would be a necessary evil across *all* SoC platforms.

Quoted 8 lines
Quoted 1 line

I would say there is a good case for this being generic

An earlier implementation of this patch (or at least a patch that tries to accomplish the same as this does, add support for legacy devices) did try to add generic solution. There was some discussion on it and I decided to drop it due to bad feedback.

See: http://www.spinics.net/lists/linux-omap/msg95147.html

I don't see anything that says this should not be generic, just that it was implemented relatively poorly at the time...

I agree with Tomasz, find_by_name in device trees is basically evil (it's only supposed to be used if you already know the name because something else passed it to you, and just want it's phandle, but names CAN be ambiguous. The real fix is always pass phandles and not strings of the name property), but that's not to say this thing needs to be TI-specific..

Quoted 2 lines

Ah well. If it ends up getting used elsewhere, it can be quickly patched into a generic version anyway, so.. yay!

Yeah, this can be converted to generic version easily if need be. The thing with this patch is also that it is kind of temporary solution, it should not be needed anymore once all the drivers are converted to DT.

Quoted 9 lines

I'm really interested in this all going in - but I would love to see where this is just all patched into a tree already. Pulling things out against a bunch of trees gave me more merge failures and weird happenings than I care to deal with. Is there a TI clock development tree with all this in somewhere publically accessible? I'd like to get a feel for how the DT looks and what's going on, I can't "see" it from the patches. Once it's there.. I'll spend a week or 5 doing all of the i.MX chips and you'll have a second test case for any problems :)

Did you try the fully integrated test tree I mentioned in the cover letter?

tree: https://github.com/t-kristo/linux-pm.git
branch: 3.12-rc6-dt-clks-v9

This has everything in it, and compiles cleanly.

-Tero

#20 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

In reply to Matt Sealey

Hi Matt,

Quoted 32 lines · On Tuesday 29 of October 2013 12:50:43 Matt Sealey wrote:
Quoted 9 lines · Tero Kristo

Some devices require their clocks to be available with a specific dev-id con-id mapping. With DT, the clocks can be found by default only with their name, or alternatively through the device node of the consumer. With drivers, that don't support DT fully yet, add mechanism to register specific clock names.

You guys are wonderful, by the way ;)

Quoted 19 lines
drivers/clk/ti/clk.c new file +17 -0
+void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
+{
+       struct ti_dt_clk *c;
+       struct device_node *node;
+       struct clk *clk;
+       struct of_phandle_args clkspec;
+
+       for (c = oclks; c->node_name != NULL; c++) {
+               node = of_find_node_by_name(NULL, c->node_name);
+               clkspec.np = node;
+               clk = of_clk_get_from_provider(&clkspec);
+
+               if (!IS_ERR(clk)) {
+                       c->lk.clk = clk;
+                       clkdev_add(&c->lk);
+               } else {
+                       pr_warn("%s: failed to lookup clock node

%s\n",
+ __func__, c->node_name);

Quoted 8 lines

drivers/clk/ti/clk.c line 52

Quoted 3 lines
drivers/clk/ti/clk.c new file +3 -0
+               }
+       }
+}

I have one question here, what makes this part of the patch TI-specific at all except the definition of the structure ti_dt_clk? Mapping DT clocks to generic clkdev legacy namings seems like it would be a necessary evil across *all* SoC platforms.

SoC platforms that are fully converted to Device Tree do not need any legacy clkdev namings, because they have all clkdev look-ups performed using data from DT (see generic clock bindings).

So this would be not "*all* SoC platforms", but instead "SoC platforms, which are currently undergoing conversion to DT or conversion of which is yet to be started".

Still this might be a good enough justification for having a generic solution for this problem, but I would wait with this until the real need on some of such platforms shows up. I don't see anything wrong in implementing this first as TI-specific quirk and then possibly making it generic if such need shows up.

By the way, we already have something like this in clk/samsung/clk.c . This is called aliases there and allows registering clkdev look-ups for particular clocks. However this is specific to our clock drivers that register all clocks inside a single clock privder, based on static ID assignment and all clocks statically listed in clock driver - see clk/samsung/clk-s3c64xx.c for an example.

Best regards,
Tomasz

Quoted 25 lines

I would say there is a good case for this being generic and used by all platforms waiting for con->id/dev->id to be moved to DT-awareness, the structure itself is very generic within clkdev as long as the drivers conformed anyway (and if they didn't, none of this helps) and I don't think it really needs to be a TI-only thing. The next thing that's going to happen when another platform arrives that wants to do the same thing is duplication or consolidation - so it would probably be a good idea to make this generic to start.

While there the names could be a bit more descriptive - dt_clk_name_lookup_map_register(), struct dt_clk_name_lookup_map, DT_CLK_LOOKUP_MAP() ..? The current namespace makes it look like this is the absolute correct thing to do under all circumstances, but in fact this is purely for mapping the old way to the new, better way.. in the event a brand new platform arrives, with all new drivers (or only compliant drivers), none of this code should be implemented for it and it should be presented this way.

Thanks,
Matt Sealey <[email protected]>

_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#21 lore raw

PATCH v9 5/43 CLK: TI: add DT alias clock registration mechanism

Quoted 7 lines · Tomasz Figa

Hi Matt,

Quoted 4 lines

I have one question here, what makes this part of the patch TI-specific at all except the definition of the structure ti_dt_clk? Mapping DT clocks to generic clkdev legacy namings seems like it would be a necessary evil across *all* SoC platforms.

Quoted 7 lines

SoC platforms that are fully converted to Device Tree do not need any legacy clkdev namings, because they have all clkdev look-ups performed using data from DT (see generic clock bindings).

So this would be not "*all* SoC platforms", but instead "SoC platforms, which are currently undergoing conversion to DT or conversion of which is yet to be started".

That is well understood here, I have a long-running hobby project to do this for i.MX5 and i.MX6 - I have a tree from months ago where I restructured the way clocks are probed for both these (moving from mach-imx to drivers/clk and putting in the right places) and successfully moved 8 clocks (on i.MX51, 3 core PLLs, some fixed clocks which got done in the meantime upstream, and one in the CCM - the CPU freq divider) with the correct references and it all operated really well.

In the meantime I had to add a bunch of weird hacks to the drivers to deal with the missing connection names, so this being generic would allow the core clock work to be finished while the drivers are brought up to the new convention.

Quoted 5 lines

Still this might be a good enough justification for having a generic solution for this problem, but I would wait with this until the real need on some of such platforms shows up. I don't see anything wrong in implementing this first as TI-specific quirk and then possibly making it generic if such need shows up.

Indeed.. and I would like to make use of it but I'm not coding on a TI platform or a Samsung platform:)

Quoted 6 lines

By the way, we already have something like this in clk/samsung/clk.c . This is called aliases there and allows registering clkdev look-ups for particular clocks. However this is specific to our clock drivers that register all clocks inside a single clock privder, based on static ID assignment and all clocks statically listed in clock driver - see clk/samsung/clk-s3c64xx.c for an example.

Right. I'll keep it in mind as I do this.

Thanks, this does make my life a lot easier, means I might have it working and submitted before the end of the month instead of sometime next year, I was dreading reworking all these drivers up front ;)

Matt Sealey <[email protected]>

#22 lore raw

PATCH v9 6/43 CLK: ti: add init support for clock IP blocks

In reply to Tero Kristo

ti_dt_clk_init_provider() can now be used to initialize the contents of a single clock IP block. This parses all the clocks under the IP block and calls the corresponding init function for them.

---
 drivers/clk/ti/clk.c   |   59 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h |    1 +
 2 files changed, 60 insertions(+)
drivers/clk/ti/clk.c +59 -0
index ad58b01..7f030d7 100644
@@ -19,6 +19,9 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 #include <linux/of.h>
+#include <linux/list.h>
+
+extern struct of_device_id __clk_of_table[];
 
 /**
  * ti_dt_clocks_register - register DT duplicate clocks during boot
@@ -50,3 +53,59 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
 		}
 	}
 }
+
+typedef int (*ti_of_clk_init_cb_t)(struct device_node *, struct regmap *);
+
+struct clk_init_item {
+	struct regmap *regmap;
+	struct device_node *np;
+	ti_of_clk_init_cb_t init_cb;
+	struct list_head node;
+};
+
+static LIST_HEAD(retry_list);
+
+void __init ti_dt_clk_init_provider(struct device_node *parent,
+				    struct regmap *regmap)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	ti_of_clk_init_cb_t clk_init_cb;
+	struct clk_init_item *retry;
+	struct clk_init_item *tmp;
+	int ret;
+
+	for_each_child_of_node(parent, np) {
+		match = of_match_node(__clk_of_table, np);
+		if (!match)
+			continue;
+		clk_init_cb = match->data;
+		pr_debug("%s: initializing: %s\n", __func__, np->name);
+		ret = clk_init_cb(np, regmap);
+		if (ret == -EAGAIN) {
+			pr_debug("%s: adding to again list...\n", np->name);
+			retry = kzalloc(sizeof(*retry), GFP_KERNEL);
+			retry->np = np;
+			retry->regmap = regmap;
+			retry->init_cb = clk_init_cb;
+			list_add(&retry->node, &retry_list);
+		} else if (ret) {
+			pr_err("%s: clock init failed for %s (%d)!\n", __func__,
+			       np->name, ret);
+		}
+	}
+
+	list_for_each_entry_safe(retry, tmp, &retry_list, node) {
+		pr_debug("%s: retry-init: %s\n", __func__, retry->np->name);
+		ret = retry->init_cb(retry->np, retry->regmap);
+		if (ret == -EAGAIN) {
+			pr_debug("%s failed again?\n", retry->np->name);
+		} else {
+			if (ret)
+				pr_err("%s: clock init failed for %s (%d)!\n",
+				       __func__, retry->np->name, ret);
+			list_del(&retry->node);
+			kfree(retry);
+		}
+	}
+}
include/linux/clk/ti.h +1 -0
index 9786752..7ab02fa 100644
@@ -177,6 +177,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
 
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
Signature · 1 line
1.7.9.5
#23 lore raw

PATCH v9 6/43 CLK: ti: add init support for clock IP blocks

Quoted 45 lines · Tero Kristo

ti_dt_clk_init_provider() can now be used to initialize the contents of a single clock IP block. This parses all the clocks under the IP block and calls the corresponding init function for them.

---
 drivers/clk/ti/clk.c   |   59 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h |    1 +
 2 files changed, 60 insertions(+)
drivers/clk/ti/clk.c +20 -0
index ad58b01..7f030d7 100644
@@ -19,6 +19,9 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 #include <linux/of.h>
+#include <linux/list.h>
+
+extern struct of_device_id __clk_of_table[];
 
 /**
  * ti_dt_clocks_register - register DT duplicate clocks during boot
@@ -50,3 +53,59 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
 		}
 	}
 }
+
+typedef int (*ti_of_clk_init_cb_t)(struct device_node *, struct regmap *);
+
+struct clk_init_item {
+	struct regmap *regmap;
+	struct device_node *np;
+	ti_of_clk_init_cb_t init_cb;
+	struct list_head node;
+};
+
+static LIST_HEAD(retry_list);
+
+void __init ti_dt_clk_init_provider(struct device_node *parent,
+				    struct regmap *regmap)
+{
+	const struct of_device_id *match;
+	struct device_node *np;

drivers/clk/ti/clk.c void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) · line 82

Quoted 10 lines
drivers/clk/ti/clk.c +10 -0
+	ti_of_clk_init_cb_t clk_init_cb;
+	struct clk_init_item *retry;
+	struct clk_init_item *tmp;
+	int ret;
+
+	for_each_child_of_node(parent, np) {
+		match = of_match_node(__clk_of_table, np);
+		if (!match)
+			continue;
+		clk_init_cb = match->data;

I must admit I am confused here.
a) of_clk_init (in the generic clk.c) uses of_clk_init_cb_t as match data. The prototype of the generic of_clk_init_cb_t is typedef void (*of_clk_init_cb_t)(struct device_node *);
b) both of_clk_init and ti_dt_clk_init_provider looks up clock nodes from __clk_of_table

I assume we need ti_dt_clk_init_provider to be always called with clock list, as a result of_clk_init(NULL); will never be invoked. This is counter productive as you have have generic non SoC clock providers as well who would have been invoked with of_clk_init(NULL);

I do strongly encourage using of_clk_init(NULL) and not having to switch the clk_init call back with SoC specific one as it forces un-intended dependency.

Further such as SoC specific callback should have been in a header.

drivers/clk/ti/clk.c void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) · line 83

Quoted 1 line
drivers/clk/ti/clk.c +1 -0
+		pr_debug("%s: initializing: %s\n", __func__, np->name);

one further comment - using pr_fmt will save us from using __func__ for every pr_* message :(

Quoted 41 lines
drivers/clk/ti/clk.c +28 -0
+		ret = clk_init_cb(np, regmap);
+		if (ret == -EAGAIN) {
+			pr_debug("%s: adding to again list...\n", np->name);
+			retry = kzalloc(sizeof(*retry), GFP_KERNEL);
+			retry->np = np;
+			retry->regmap = regmap;
+			retry->init_cb = clk_init_cb;
+			list_add(&retry->node, &retry_list);
+		} else if (ret) {
+			pr_err("%s: clock init failed for %s (%d)!\n", __func__,
+			       np->name, ret);
+		}
+	}
+
+	list_for_each_entry_safe(retry, tmp, &retry_list, node) {
+		pr_debug("%s: retry-init: %s\n", __func__, retry->np->name);
+		ret = retry->init_cb(retry->np, retry->regmap);
+		if (ret == -EAGAIN) {
+			pr_debug("%s failed again?\n", retry->np->name);
+		} else {
+			if (ret)
+				pr_err("%s: clock init failed for %s (%d)!\n",
+				       __func__, retry->np->name, ret);
+			list_del(&retry->node);
+			kfree(retry);
+		}
+	}
+}
include/linux/clk/ti.h +1 -0
index 9786752..7ab02fa 100644
@@ -177,6 +177,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
 
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
Signature · 2 lines
Regards,
Nishanth Menon
#24 lore raw

PATCH v9 6/43 CLK: ti: add init support for clock IP blocks

Quoted 50 lines · Nishanth Menon
Quoted 49 lines · Tero Kristo

ti_dt_clk_init_provider() can now be used to initialize the contents of a single clock IP block. This parses all the clocks under the IP block and calls the corresponding init function for them.

---
  drivers/clk/ti/clk.c   |   59 ++++++++++++++++++++++++++++++++++++++++++++++++
  include/linux/clk/ti.h |    1 +
  2 files changed, 60 insertions(+)
drivers/clk/ti/clk.c +24 -0
index ad58b01..7f030d7 100644
@@ -19,6 +19,9 @@
  #include <linux/clkdev.h>
  #include <linux/clk/ti.h>
  #include <linux/of.h>
+#include <linux/list.h>
+
+extern struct of_device_id __clk_of_table[];
 
  /**
   * ti_dt_clocks_register - register DT duplicate clocks during boot
@@ -50,3 +53,59 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
  		}
  	}
  }
+
+typedef int (*ti_of_clk_init_cb_t)(struct device_node *, struct regmap *);
+
+struct clk_init_item {
+	struct regmap *regmap;
+	struct device_node *np;
+	ti_of_clk_init_cb_t init_cb;
+	struct list_head node;
+};
+
+static LIST_HEAD(retry_list);
+
+void __init ti_dt_clk_init_provider(struct device_node *parent,
+				    struct regmap *regmap)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	ti_of_clk_init_cb_t clk_init_cb;
+	struct clk_init_item *retry;
+	struct clk_init_item *tmp;
+	int ret;
Quoted 8 lines

drivers/clk/ti/clk.c void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) · line 82

Quoted 6 lines
drivers/clk/ti/clk.c +6 -0
+
+	for_each_child_of_node(parent, np) {
+		match = of_match_node(__clk_of_table, np);
+		if (!match)
+			continue;
+		clk_init_cb = match->data;

I must admit I am confused here.

Yea this patch is something I am not quite comfortable myself yet and would like improvement ideas....

Quoted 5 lines

a) of_clk_init (in the generic clk.c) uses of_clk_init_cb_t as match data. The prototype of the generic of_clk_init_cb_t is typedef void (*of_clk_init_cb_t)(struct device_node *);
b) both of_clk_init and ti_dt_clk_init_provider looks up clock nodes from __clk_of_table

__clk_of_table contains the function pointers for the clock init functions, not clock nodes.

Quoted 5 lines

I assume we need ti_dt_clk_init_provider to be always called with clock list, as a result of_clk_init(NULL); will never be invoked. This is counter productive as you have have generic non SoC clock providers as well who would have been invoked with of_clk_init(NULL);

Can't call of_clk_init(NULL) anymore, as Paul wants to map the clock nodes under respective IP blocks. Two reasons here:

a) This requires me to pass some info from the IP block (CM1/CM2/PRM) to the clock init functions, basically the pointer to the memory map region (regmap.)
b) of_clk_init(NULL) will initialize all the clock nodes in the system, irrespective of the hierarchy considerations.

Only thing that can be done, is to make the API introduced in this patch a generic API and call it something like of_clk_init_children().

Quoted 4 lines

I do strongly encourage using of_clk_init(NULL) and not having to switch the clk_init call back with SoC specific one as it forces un-intended dependency.

Can't do this as mentioned above.

Quoted 8 lines

Further such as SoC specific callback should have been in a header.

drivers/clk/ti/clk.c void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) · line 83

Quoted 1 line
drivers/clk/ti/clk.c +1 -0
+		pr_debug("%s: initializing: %s\n", __func__, np->name);

one further comment - using pr_fmt will save us from using __func__ for every pr_* message :(

Hmm good comment, will fix that for next rev.

Quoted 44 lines
Quoted 42 lines
drivers/clk/ti/clk.c +28 -0
+		ret = clk_init_cb(np, regmap);
+		if (ret == -EAGAIN) {
+			pr_debug("%s: adding to again list...\n", np->name);
+			retry = kzalloc(sizeof(*retry), GFP_KERNEL);
+			retry->np = np;
+			retry->regmap = regmap;
+			retry->init_cb = clk_init_cb;
+			list_add(&retry->node, &retry_list);
+		} else if (ret) {
+			pr_err("%s: clock init failed for %s (%d)!\n", __func__,
+			       np->name, ret);
+		}
+	}
+
+	list_for_each_entry_safe(retry, tmp, &retry_list, node) {
+		pr_debug("%s: retry-init: %s\n", __func__, retry->np->name);
+		ret = retry->init_cb(retry->np, retry->regmap);
+		if (ret == -EAGAIN) {
+			pr_debug("%s failed again?\n", retry->np->name);
+		} else {
+			if (ret)
+				pr_err("%s: clock init failed for %s (%d)!\n",
+				       __func__, retry->np->name, ret);
+			list_del(&retry->node);
+			kfree(retry);
+		}
+	}
+}
include/linux/clk/ti.h +1 -0
index 9786752..7ab02fa 100644
@@ -177,6 +177,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
  			 unsigned long parent_rate);
 
  void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
 
  extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
  extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
#25 lore raw

PATCH v9 6/43 CLK: ti: add init support for clock IP blocks

Quoted 63 lines · Tero Kristo
Quoted 50 lines · Nishanth Menon
Quoted 49 lines · Tero Kristo

ti_dt_clk_init_provider() can now be used to initialize the contents of a single clock IP block. This parses all the clocks under the IP block and calls the corresponding init function for them.

---
  drivers/clk/ti/clk.c   |   59 ++++++++++++++++++++++++++++++++++++++++++++++++
  include/linux/clk/ti.h |    1 +
  2 files changed, 60 insertions(+)
drivers/clk/ti/clk.c +24 -0
index ad58b01..7f030d7 100644
@@ -19,6 +19,9 @@
  #include <linux/clkdev.h>
  #include <linux/clk/ti.h>
  #include <linux/of.h>
+#include <linux/list.h>
+
+extern struct of_device_id __clk_of_table[];
 
  /**
   * ti_dt_clocks_register - register DT duplicate clocks during boot
@@ -50,3 +53,59 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
  		}
  	}
  }
+
+typedef int (*ti_of_clk_init_cb_t)(struct device_node *, struct regmap *);
+
+struct clk_init_item {
+	struct regmap *regmap;
+	struct device_node *np;
+	ti_of_clk_init_cb_t init_cb;
+	struct list_head node;
+};
+
+static LIST_HEAD(retry_list);
+
+void __init ti_dt_clk_init_provider(struct device_node *parent,
+				    struct regmap *regmap)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	ti_of_clk_init_cb_t clk_init_cb;
+	struct clk_init_item *retry;
+	struct clk_init_item *tmp;
+	int ret;
Quoted 8 lines

drivers/clk/ti/clk.c void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) · line 82

Quoted 6 lines
drivers/clk/ti/clk.c +6 -0
+
+	for_each_child_of_node(parent, np) {
+		match = of_match_node(__clk_of_table, np);
+		if (!match)
+			continue;
+		clk_init_cb = match->data;

I must admit I am confused here.

Yea this patch is something I am not quite comfortable myself yet and would like improvement ideas....

Quoted 8 lines
Quoted 5 lines

a) of_clk_init (in the generic clk.c) uses of_clk_init_cb_t as match data. The prototype of the generic of_clk_init_cb_t is typedef void (*of_clk_init_cb_t)(struct device_node *);
b) both of_clk_init and ti_dt_clk_init_provider looks up clock nodes from __clk_of_table

__clk_of_table contains the function pointers for the clock init functions, not clock nodes.

yes, apologies, should have stated the prototypes of functions in a single __clk_of_table should not be two different argument list. The reason is as follows: CLK_OF_DECLARE fills up that list. there can be generic drivers such as [1] which might be registered, OR in the case of MULTI_ARCH - multiple other SoC drivers would have registered there. There is a bunch of stuff we could mess up here.

If we do not have a choice, if we would like to maintain a different prototype based init list, we should probably do it in a different structure - example __clk_of_table_regmap or something similar..

Quoted 10 lines
Quoted 6 lines

I assume we need ti_dt_clk_init_provider to be always called with clock list, as a result of_clk_init(NULL); will never be invoked. This is counter productive as you have have generic non SoC clock providers as well who would have been invoked with of_clk_init(NULL);

Can't call of_clk_init(NULL) anymore, as Paul wants to map the clock nodes under respective IP blocks. Two reasons here:

Quoted 8 lines

a) This requires me to pass some info from the IP block (CM1/CM2/PRM) to the clock init functions, basically the pointer to the memory map region (regmap.)
b) of_clk_init(NULL) will initialize all the clock nodes in the system, irrespective of the hierarchy considerations.

Only thing that can be done, is to make the API introduced in this patch a generic API and call it something like of_clk_init_children().

you still can do that:

of_prcm_init->ti_dt_clk_init_provider-> instead of matching nodes from __clk_of_table, you can make it __clk_of_regmap_table -> the CLK_OF_DECLARE will not be good enough here ofcourse, but this will probably belong to a generic regmap enabled clock support framework - i dont see much that is TI specific in drivers/clk/ti/clk.c and it makes sense to be part of generic clock framework handling as generic clock framework will receive regmap support based on previous patches. that allows for other platforms to use regmap based clk drivers as well.

[1] http://marc.info/?l=linux-omap&m=138331451210184&w=2

Signature · 2 lines
Regards,
Nishanth Menon
#26 lore raw

PATCH v9 6/43 CLK: ti: add init support for clock IP blocks

Quoted 106 lines · Nishanth Menon
Quoted 63 lines · Tero Kristo
Quoted 50 lines · Nishanth Menon
Quoted 49 lines · Tero Kristo

ti_dt_clk_init_provider() can now be used to initialize the contents of a single clock IP block. This parses all the clocks under the IP block and calls the corresponding init function for them.

---
   drivers/clk/ti/clk.c   |   59 ++++++++++++++++++++++++++++++++++++++++++++++++
   include/linux/clk/ti.h |    1 +
   2 files changed, 60 insertions(+)
drivers/clk/ti/clk.c +24 -0
index ad58b01..7f030d7 100644
@@ -19,6 +19,9 @@
   #include <linux/clkdev.h>
   #include <linux/clk/ti.h>
   #include <linux/of.h>
+#include <linux/list.h>
+
+extern struct of_device_id __clk_of_table[];
 
   /**
    * ti_dt_clocks_register - register DT duplicate clocks during boot
@@ -50,3 +53,59 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
   		}
   	}
   }
+
+typedef int (*ti_of_clk_init_cb_t)(struct device_node *, struct regmap *);
+
+struct clk_init_item {
+	struct regmap *regmap;
+	struct device_node *np;
+	ti_of_clk_init_cb_t init_cb;
+	struct list_head node;
+};
+
+static LIST_HEAD(retry_list);
+
+void __init ti_dt_clk_init_provider(struct device_node *parent,
+				    struct regmap *regmap)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	ti_of_clk_init_cb_t clk_init_cb;
+	struct clk_init_item *retry;
+	struct clk_init_item *tmp;
+	int ret;
Quoted 8 lines

drivers/clk/ti/clk.c void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) · line 82

Quoted 6 lines
drivers/clk/ti/clk.c +6 -0
+
+	for_each_child_of_node(parent, np) {
+		match = of_match_node(__clk_of_table, np);
+		if (!match)
+			continue;
+		clk_init_cb = match->data;

I must admit I am confused here.

Yea this patch is something I am not quite comfortable myself yet and would like improvement ideas....

Quoted 8 lines
Quoted 5 lines

a) of_clk_init (in the generic clk.c) uses of_clk_init_cb_t as match data. The prototype of the generic of_clk_init_cb_t is typedef void (*of_clk_init_cb_t)(struct device_node *);
b) both of_clk_init and ti_dt_clk_init_provider looks up clock nodes from __clk_of_table

__clk_of_table contains the function pointers for the clock init functions, not clock nodes.

yes, apologies, should have stated the prototypes of functions in a single __clk_of_table should not be two different argument list. The reason is as follows: CLK_OF_DECLARE fills up that list. there can be generic drivers such as [1] which might be registered, OR in the case of MULTI_ARCH - multiple other SoC drivers would have registered there. There is a bunch of stuff we could mess up here.

If we do not have a choice, if we would like to maintain a different prototype based init list, we should probably do it in a different structure - example __clk_of_table_regmap or something similar..

Quoted 10 lines
Quoted 6 lines

I assume we need ti_dt_clk_init_provider to be always called with clock list, as a result of_clk_init(NULL); will never be invoked. This is counter productive as you have have generic non SoC clock providers as well who would have been invoked with of_clk_init(NULL);

Can't call of_clk_init(NULL) anymore, as Paul wants to map the clock nodes under respective IP blocks. Two reasons here:

Quoted 8 lines

a) This requires me to pass some info from the IP block (CM1/CM2/PRM) to the clock init functions, basically the pointer to the memory map region (regmap.)
b) of_clk_init(NULL) will initialize all the clock nodes in the system, irrespective of the hierarchy considerations.

Only thing that can be done, is to make the API introduced in this patch a generic API and call it something like of_clk_init_children().

you still can do that:

Quoted 8 lines

of_prcm_init->ti_dt_clk_init_provider-> instead of matching nodes from __clk_of_table, you can make it __clk_of_regmap_table -> the CLK_OF_DECLARE will not be good enough here ofcourse, but this will probably belong to a generic regmap enabled clock support framework - i dont see much that is TI specific in drivers/clk/ti/clk.c and it makes sense to be part of generic clock framework handling as generic clock framework will receive regmap support based on previous patches. that allows for other platforms to use regmap based clk drivers as well.

Yea different init tables can be introduced, however I still need to split the support between hierarchical version and the blunt version that registers everything. Looking at the work from Jyri, its possible I need to add calls to both.

-Tero

Quoted 4 lines

[1] http://marc.info/?l=linux-omap&m=138331451210184&w=2

#27 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

In reply to Tero Kristo

TI clk driver now routes some of the basic clocks through own registration routine to allow autoidle support. This routine just checks a couple of device node properties and adds autoidle support if required, and just passes the registration forward to basic clocks.

---
 arch/arm/mach-omap2/clock.c |    6 +++
 drivers/clk/ti/Makefile     |    2 +-
 drivers/clk/ti/autoidle.c   |  109 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h      |    9 ++++
 4 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/autoidle.c
arch/arm/mach-omap2/clock.c +6 -0
index 0c38ca9..223f432b 100644
@@ -520,6 +520,9 @@ int omap2_clk_enable_autoidle_all(void)
 	list_for_each_entry(c, &clk_hw_omap_clocks, node)
 		if (c->ops && c->ops->allow_idle)
 			c->ops->allow_idle(c);
+
+	of_ti_clk_allow_autoidle_all();
+
 	return 0;
 }
 
@@ -539,6 +542,9 @@ int omap2_clk_disable_autoidle_all(void)
 	list_for_each_entry(c, &clk_hw_omap_clocks, node)
 		if (c->ops && c->ops->deny_idle)
 			c->ops->deny_idle(c);
+
+	of_ti_clk_deny_autoidle_all();
+
 	return 0;
 }
 
drivers/clk/ti/Makefile +1 -1
index 05af5d8..533efb4 100644
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o
+obj-y					+= clk.o dpll.o autoidle.o
 endif
drivers/clk/ti/autoidle.c new file +109 -0

109 lines not on this page · raw message

include/linux/clk/ti.h +9 -0
index 7ab02fa..e45005c 100644
@@ -178,6 +178,15 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
+int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
+
+#ifdef CONFIG_OF
+void of_ti_clk_allow_autoidle_all(void);
+void of_ti_clk_deny_autoidle_all(void);
+#else
+static inline void of_ti_clk_allow_autoidle_all(void) { }
+static inline void of_ti_clk_deny_autoidle_all(void) { }
+#endif
 
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
Signature · 1 line
1.7.9.5
#28 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

Quoted 92 lines · Tero Kristo

TI clk driver now routes some of the basic clocks through own registration routine to allow autoidle support. This routine just checks a couple of device node properties and adds autoidle support if required, and just passes the registration forward to basic clocks.

---
 arch/arm/mach-omap2/clock.c |    6 +++
 drivers/clk/ti/Makefile     |    2 +-
 drivers/clk/ti/autoidle.c   |  109 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h      |    9 ++++
 4 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/autoidle.c
arch/arm/mach-omap2/clock.c +6 -0
index 0c38ca9..223f432b 100644
@@ -520,6 +520,9 @@ int omap2_clk_enable_autoidle_all(void)
 	list_for_each_entry(c, &clk_hw_omap_clocks, node)
 		if (c->ops && c->ops->allow_idle)
 			c->ops->allow_idle(c);
+
+	of_ti_clk_allow_autoidle_all();
+
 	return 0;
 }
 
@@ -539,6 +542,9 @@ int omap2_clk_disable_autoidle_all(void)
 	list_for_each_entry(c, &clk_hw_omap_clocks, node)
 		if (c->ops && c->ops->deny_idle)
 			c->ops->deny_idle(c);
+
+	of_ti_clk_deny_autoidle_all();
+
 	return 0;
 }
 
drivers/clk/ti/Makefile +1 -1
index 05af5d8..533efb4 100644
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o
+obj-y					+= clk.o dpll.o autoidle.o
 endif
drivers/clk/ti/autoidle.c new file +39 -0
new file mode 100644
index 0000000..efa2a3e
@@ -0,0 +1,109 @@
+/*
+ * TI clock autoidle support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+struct clk_ti_autoidle {
+	u32			reg;
+	struct regmap		*regmap;
+	u8			shift;
+	u8			flags;
+	const char		*name;
+	struct list_head	node;
+};
+
+#define AUTOIDLE_LOW		0x1
+
+static LIST_HEAD(autoidle_clks);
+
+static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
+{

drivers/clk/ti/autoidle.c line 49

Quoted 10 lines
drivers/clk/ti/autoidle.c new file +10 -0
+	u32 val;
+
+	regmap_read(clk->regmap, clk->reg, &val);
+
+	if (clk->flags & AUTOIDLE_LOW)
+		val &= ~(1 << clk->shift);
+	else
+		val |= (1 << clk->shift);
+
+	regmap_write(clk->regmap, clk->reg, val);

regmap_update_bits ?

Quoted 4 lines
drivers/clk/ti/autoidle.c new file +4 -0
+}
+
+static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+{

drivers/clk/ti/autoidle.c line 63

Quoted 10 lines
drivers/clk/ti/autoidle.c new file +10 -0
+	u32 val;
+
+	regmap_read(clk->regmap, clk->reg, &val);
+
+	if (clk->flags & AUTOIDLE_LOW)
+		val |= (1 << clk->shift);
+	else
+		val &= ~(1 << clk->shift);
+
+	regmap_write(clk->regmap, clk->reg, val);

regmap_update_bits ?

and ofcourse error handling for regmap ops..

Quoted 10 lines
drivers/clk/ti/autoidle.c new file +10 -0
+}
+
+void of_ti_clk_allow_autoidle_all(void)
+{
+	struct clk_ti_autoidle *c;
+
+	list_for_each_entry(c, &autoidle_clks, node)
+		ti_allow_autoidle(c);
+}
+

drivers/clk/ti/autoidle.c line 83

Quoted 10 lines
drivers/clk/ti/autoidle.c new file +10 -0
+void of_ti_clk_deny_autoidle_all(void)
+{
+	struct clk_ti_autoidle *c;
+
+	list_for_each_entry(c, &autoidle_clks, node)
+		ti_deny_autoidle(c);
+}
+
+int __init of_ti_autoidle_setup(struct device_node *node,
+				struct regmap *regmap)

will be nice if you could kernel-doc all public functions at the very least.

Quoted 7 lines
drivers/clk/ti/autoidle.c new file +7 -0
+{
+	u32 shift;
+	struct clk_ti_autoidle *clk;
+
+	if (of_property_read_u32(node, "ti,autoidle-shift", &shift))
+		return 0;
+

drivers/clk/ti/autoidle.c line 100

Quoted 10 lines
drivers/clk/ti/autoidle.c new file +10 -0
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+
+	if (!clk) {
+		pr_err("%s: kzalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	clk->shift = shift;
+	clk->name = node->name;
+	of_property_read_u32(node, "reg", &clk->reg);

dt binding?
what happens if someone forgets this?

Quoted 30 lines
drivers/clk/ti/autoidle.c new file +9 -0
+	clk->regmap = regmap;
+
+	if (of_property_read_bool(node, "ti,invert-autoidle-bit"))
+		clk->flags |= AUTOIDLE_LOW;
+
+	list_add(&clk->node, &autoidle_clks);
+
+	return 0;
+}
include/linux/clk/ti.h +9 -0
index 7ab02fa..e45005c 100644
@@ -178,6 +178,15 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
+int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
+
+#ifdef CONFIG_OF
+void of_ti_clk_allow_autoidle_all(void);
+void of_ti_clk_deny_autoidle_all(void);
+#else
+static inline void of_ti_clk_allow_autoidle_all(void) { }
+static inline void of_ti_clk_deny_autoidle_all(void) { }
+#endif
 
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
Signature · 2 lines
Regards,
Nishanth Menon
#29 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

Quoted 96 lines · Nishanth Menon
Quoted 95 lines · Tero Kristo

TI clk driver now routes some of the basic clocks through own registration routine to allow autoidle support. This routine just checks a couple of device node properties and adds autoidle support if required, and just passes the registration forward to basic clocks.

---
  arch/arm/mach-omap2/clock.c |    6 +++
  drivers/clk/ti/Makefile     |    2 +-
  drivers/clk/ti/autoidle.c   |  109 +++++++++++++++++++++++++++++++++++++++++++
  include/linux/clk/ti.h      |    9 ++++
  4 files changed, 125 insertions(+), 1 deletion(-)

create mode 100644 drivers/clk/ti/autoidle.c

arch/arm/mach-omap2/clock.c +6 -0
index 0c38ca9..223f432b 100644
@@ -520,6 +520,9 @@ int omap2_clk_enable_autoidle_all(void)
  	list_for_each_entry(c, &clk_hw_omap_clocks, node)
  		if (c->ops && c->ops->allow_idle)
  			c->ops->allow_idle(c);
+
+	of_ti_clk_allow_autoidle_all();
+
  	return 0;
  }
 
@@ -539,6 +542,9 @@ int omap2_clk_disable_autoidle_all(void)
  	list_for_each_entry(c, &clk_hw_omap_clocks, node)
  		if (c->ops && c->ops->deny_idle)
  			c->ops->deny_idle(c);
+
+	of_ti_clk_deny_autoidle_all();
+
  	return 0;
  }
 
drivers/clk/ti/Makefile +1 -1
index 05af5d8..533efb4 100644
@@ -1,3 +1,3 @@
  ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o
+obj-y					+= clk.o dpll.o autoidle.o
  endif
drivers/clk/ti/autoidle.c new file +42 -0
new file mode 100644
index 0000000..efa2a3e
@@ -0,0 +1,109 @@
+/*
+ * TI clock autoidle support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+struct clk_ti_autoidle {
+	u32			reg;
+	struct regmap		*regmap;
+	u8			shift;
+	u8			flags;
+	const char		*name;
+	struct list_head	node;
+};
+
+#define AUTOIDLE_LOW		0x1
+
+static LIST_HEAD(autoidle_clks);
+
+static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
+{
+	u32 val;
+
+	regmap_read(clk->regmap, clk->reg, &val);
Quoted 8 lines

drivers/clk/ti/autoidle.c line 49

Quoted 7 lines
drivers/clk/ti/autoidle.c new file +7 -0
+
+	if (clk->flags & AUTOIDLE_LOW)
+		val &= ~(1 << clk->shift);
+	else
+		val |= (1 << clk->shift);
+
+	regmap_write(clk->regmap, clk->reg, val);

regmap_update_bits ?

Hmm yea that would work.

Quoted 7 lines
Quoted 7 lines
drivers/clk/ti/autoidle.c new file +7 -0
+}
+
+static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+{
+	u32 val;
+
+	regmap_read(clk->regmap, clk->reg, &val);
Quoted 8 lines

drivers/clk/ti/autoidle.c line 63

Quoted 7 lines
drivers/clk/ti/autoidle.c new file +7 -0
+
+	if (clk->flags & AUTOIDLE_LOW)
+		val |= (1 << clk->shift);
+	else
+		val &= ~(1 << clk->shift);
+
+	regmap_write(clk->regmap, clk->reg, val);

regmap_update_bits ?

Same.

Quoted 2 lines

and ofcourse error handling for regmap ops..

What do you propose to do in error case? Panic, WARN() or just printk?

Quoted 16 lines
Quoted 16 lines
drivers/clk/ti/autoidle.c new file +15 -0
+}
+
+void of_ti_clk_allow_autoidle_all(void)
+{
+	struct clk_ti_autoidle *c;
+
+	list_for_each_entry(c, &autoidle_clks, node)
+		ti_allow_autoidle(c);
+}
+
+void of_ti_clk_deny_autoidle_all(void)
+{
+	struct clk_ti_autoidle *c;
+
+	list_for_each_entry(c, &autoidle_clks, node)
Quoted 8 lines

drivers/clk/ti/autoidle.c line 83

Quoted 5 lines
drivers/clk/ti/autoidle.c new file +5 -0
+		ti_deny_autoidle(c);
+}
+
+int __init of_ti_autoidle_setup(struct device_node *node,
+				struct regmap *regmap)

will be nice if you could kernel-doc all public functions at the very least.

Ok, I can try to do that for next. :P

Quoted 13 lines
Quoted 13 lines
drivers/clk/ti/autoidle.c new file +12 -0
+{
+	u32 shift;
+	struct clk_ti_autoidle *clk;
+
+	if (of_property_read_u32(node, "ti,autoidle-shift", &shift))
+		return 0;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+
+	if (!clk) {
+		pr_err("%s: kzalloc failed\n", __func__);
+		return -ENOMEM;
Quoted 8 lines

drivers/clk/ti/autoidle.c line 100

Quoted 5 lines
drivers/clk/ti/autoidle.c new file +5 -0
+	}
+
+	clk->shift = shift;
+	clk->name = node->name;
+	of_property_read_u32(node, "reg", &clk->reg);

dt binding?
what happens if someone forgets this?

You get zero offset.

I can add a check for this though.

Quoted 33 lines
Quoted 31 lines
drivers/clk/ti/autoidle.c new file +9 -0
+	clk->regmap = regmap;
+
+	if (of_property_read_bool(node, "ti,invert-autoidle-bit"))
+		clk->flags |= AUTOIDLE_LOW;
+
+	list_add(&clk->node, &autoidle_clks);
+
+	return 0;
+}
include/linux/clk/ti.h +9 -0
index 7ab02fa..e45005c 100644
@@ -178,6 +178,15 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 
  void ti_dt_clocks_register(struct ti_dt_clk *oclks);
  void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
+int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
+
+#ifdef CONFIG_OF
+void of_ti_clk_allow_autoidle_all(void);
+void of_ti_clk_deny_autoidle_all(void);
+#else
+static inline void of_ti_clk_allow_autoidle_all(void) { }
+static inline void of_ti_clk_deny_autoidle_all(void) { }
+#endif
 
  extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
  extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
#30 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:

[...]

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/clk/ti/autoidle.c new file +0 -0
new file mode 100644
index 0000000..efa2a3e

[...]

Quoted 16 lines
Quoted 7 lines
Quoted 7 lines
drivers/clk/ti/autoidle.c new file +7 -0
+}
+
+static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+{
+	u32 val;
+
+	regmap_read(clk->regmap, clk->reg, &val);
Quoted 8 lines

drivers/clk/ti/autoidle.c line 63

Quoted 7 lines
drivers/clk/ti/autoidle.c new file +7 -0
+
+	if (clk->flags & AUTOIDLE_LOW)
+		val |= (1 << clk->shift);
+	else
+		val &= ~(1 << clk->shift);
+
+	regmap_write(clk->regmap, clk->reg, val);

regmap_update_bits ?

Quoted 6 lines

Same.

Quoted 2 lines

and ofcourse error handling for regmap ops..

What do you propose to do in error case? Panic, WARN() or just printk?

return error to caller and percolate back up the call stack.

one other thing I missed, will be nice to introduce a common bindings for autoidle which tends to be reused in other drivers..

Signature · 2 lines
Regards,
Nishanth Menon
#31 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

Quoted 27 lines · Nishanth Menon
Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:

[...]

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/clk/ti/autoidle.c new file +0 -0
new file mode 100644
index 0000000..efa2a3e

[...]

Quoted 16 lines
Quoted 15 lines
Quoted 4 lines
drivers/clk/ti/autoidle.c new file +4 -0
+}
+
+static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+{

drivers/clk/ti/autoidle.c line 63

Quoted 10 lines
drivers/clk/ti/autoidle.c new file +10 -0
+	u32 val;
+
+	regmap_read(clk->regmap, clk->reg, &val);
+
+	if (clk->flags & AUTOIDLE_LOW)
+		val |= (1 << clk->shift);
+	else
+		val &= ~(1 << clk->shift);
+
+	regmap_write(clk->regmap, clk->reg, val);

regmap_update_bits ?

Quoted 8 lines
Quoted 6 lines

Same.

Quoted 2 lines

and ofcourse error handling for regmap ops..

What do you propose to do in error case? Panic, WARN() or just printk?

return error to caller and percolate back up the call stack.

Ok can do that.

Quoted 2 lines

one other thing I missed, will be nice to introduce a common bindings for autoidle which tends to be reused in other drivers..

You mean documentation or? Autoidle from this patch is only used by two clock drivers (divider + fixed-factor.) DPLLs use completely different setup. Converting the interface clocks to use the same might be rather nasty thing to do.

-Tero

#32 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 11/01/2013 04:18 AM, Tero Kristo wrote:

[...]

Quoted 7 lines
Quoted 2 lines

one other thing I missed, will be nice to introduce a common bindings for autoidle which tends to be reused in other drivers..

You mean documentation or? Autoidle from this patch is only used by two clock drivers (divider + fixed-factor.) DPLLs use completely different setup. Converting the interface clocks to use the same might be rather nasty thing to do.

The definitions are common - so, yes, it will be nice to have autoidle.txt which is then pointed to by divider, fixed-clock etc..

Signature · 2 lines
Regards,
Nishanth Menon
#33 lore raw

PATCH v9 7/43 CLK: TI: add autoidle support

Quoted 8 lines · Nishanth Menon
Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 11/01/2013 04:18 AM, Tero Kristo wrote:

[...]

Quoted 3 lines
Quoted 2 lines

one other thing I missed, will be nice to introduce a common bindings for autoidle which tends to be reused in other drivers..

Quoted 6 lines
Quoted 4 lines

You mean documentation or? Autoidle from this patch is only used by two clock drivers (divider + fixed-factor.) DPLLs use completely different setup. Converting the interface clocks to use the same might be rather nasty thing to do.

The definitions are common - so, yes, it will be nice to have autoidle.txt which is then pointed to by divider, fixed-clock etc..

Ok can add that.

-Tero

#34 lore raw

PATCH v9 8/43 clk: ti: add composite clock support

In reply to Tero Kristo

This is a multipurpose clock node, which contains support for multiple sub-clocks. Uses basic composite clock type to implement the actual functionality, and TI specific gate, mux and divider clocks.

---
 .../devicetree/bindings/clock/ti/composite.txt     |   54 +++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/composite.c                         |  222 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    8 +
 4 files changed, 285 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/composite.txt
 create mode 100644 drivers/clk/ti/composite.c
Documentation/devicetree/bindings/clock/ti/composite.txt new file +54 -0
new file mode 100644
index 0000000..5f43c47
@@ -0,0 +1,54 @@
+Binding for TI composite clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped composite clock with multiple different sub-types;
+
+a multiplexer clock with multiple input clock signals or parents, one
+of which can be selected as output, this behaves exactly as [2]
+
+an adjustable clock rate divider, this behaves exactly as [3]
+
+a gating function which can be used to enable and disable the output
+clock, this behaves exactly as [4]
+
+The binding must provide a list of the component clocks that shall be
+merged to this clock. The component clocks shall be of one of the
+"ti,*composite*-clock" types.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/mux.txt
+[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[4] Documentation/devicetree/bindings/clock/ti/gate.txt
+
+Required properties:
+- compatible : shall be: "ti,composite-clock"
+- clocks : link phandles of component clocks
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Examples:
+
+usb_l4_gate_ick: usb_l4_gate_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-interface-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <5>;
+	reg = <0x0a10>;
+};
+
+usb_l4_div_ick: usb_l4_div_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-divider-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <4>;
+	ti,max-div = <1>;
+	reg = <0x0a40>;
+	ti,index-starts-at-one;
+};
+
+usb_l4_ick: usb_l4_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-clock";
+	clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+};
drivers/clk/ti/Makefile +1 -1
index 533efb4..a4a7595 100644
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o autoidle.o
+obj-y					+= clk.o dpll.o autoidle.o composite.o
 endif
drivers/clk/ti/composite.c new file +222 -0

222 lines not on this page · raw message

include/linux/clk/ti.h +8 -0
index e45005c..96c9725 100644
@@ -137,6 +137,13 @@ struct clk_hw_omap {
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE		0x1
 
+/* Composite clock component types */
+enum {
+	CLK_COMPONENT_TYPE_MUX = 0,
+	CLK_COMPONENT_TYPE_GATE,
+	CLK_COMPONENT_TYPE_DIVIDER
+};
+
 /**
  * struct ti_dt_clk - OMAP DT clock alias declarations
  * @lk: clock lookup definition
@@ -179,6 +186,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
 int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
+int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
Signature · 1 line
1.7.9.5
#35 lore raw

PATCH v9 8/43 clk: ti: add composite clock support

Quoted 146 lines · Tero Kristo

This is a multipurpose clock node, which contains support for multiple sub-clocks. Uses basic composite clock type to implement the actual functionality, and TI specific gate, mux and divider clocks.

---
 .../devicetree/bindings/clock/ti/composite.txt     |   54 +++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/composite.c                         |  222 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    8 +
 4 files changed, 285 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/composite.txt
 create mode 100644 drivers/clk/ti/composite.c
Documentation/devicetree/bindings/clock/ti/composite.txt new file +54 -0
new file mode 100644
index 0000000..5f43c47
@@ -0,0 +1,54 @@
+Binding for TI composite clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped composite clock with multiple different sub-types;
+
+a multiplexer clock with multiple input clock signals or parents, one
+of which can be selected as output, this behaves exactly as [2]
+
+an adjustable clock rate divider, this behaves exactly as [3]
+
+a gating function which can be used to enable and disable the output
+clock, this behaves exactly as [4]
+
+The binding must provide a list of the component clocks that shall be
+merged to this clock. The component clocks shall be of one of the
+"ti,*composite*-clock" types.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/mux.txt
+[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[4] Documentation/devicetree/bindings/clock/ti/gate.txt
+
+Required properties:
+- compatible : shall be: "ti,composite-clock"
+- clocks : link phandles of component clocks
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Examples:
+
+usb_l4_gate_ick: usb_l4_gate_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-interface-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <5>;
+	reg = <0x0a10>;
+};
+
+usb_l4_div_ick: usb_l4_div_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-divider-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <4>;
+	ti,max-div = <1>;
+	reg = <0x0a40>;
+	ti,index-starts-at-one;
+};
+
+usb_l4_ick: usb_l4_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-clock";
+	clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+};
drivers/clk/ti/Makefile +1 -1
index 533efb4..a4a7595 100644
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o autoidle.o
+obj-y					+= clk.o dpll.o autoidle.o composite.o
 endif
drivers/clk/ti/composite.c new file +57 -0
new file mode 100644
index 0000000..9ce7e54
@@ -0,0 +1,222 @@
+/*
+ * TI composite clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/list.h>
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+static unsigned long ti_composite_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	return -EINVAL;
+}
+
+static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	return -EINVAL;
+}
+
+static const struct clk_ops ti_composite_divider_ops = {
+	.recalc_rate	= &ti_composite_recalc_rate,
+	.round_rate	= &ti_composite_round_rate,
+	.set_rate	= &ti_composite_set_rate,
+};
+
+static const struct clk_ops ti_composite_gate_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+

drivers/clk/ti/composite.c line 67

Quoted 10 lines
drivers/clk/ti/composite.c new file +10 -0
+struct component_clk {
+	int num_parents;
+	const char **parent_names;
+	struct device_node *node;
+	int type;
+	struct clk_hw *hw;
+	struct list_head link;
+};
+
+static const char * __initdata component_clk_types[] = {

[CLK_COMPONENT_TYPE_MAX]?

Quoted 29 lines
drivers/clk/ti/composite.c new file +29 -0
+	"mux", "gate", "divider",
+};
+
+static LIST_HEAD(component_clks);
+
+static struct component_clk *_lookup_component(struct device_node *node, int i)
+{
+	int rc;
+	struct of_phandle_args clkspec;
+	struct component_clk *comp;
+
+	rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i,
+					&clkspec);
+	if (rc)
+		return NULL;
+
+	list_for_each_entry(comp, &component_clks, link) {
+		if (comp->node == clkspec.np)
+			return comp;
+	}
+	return NULL;
+}
+
+static inline struct clk_hw *_get_hw(struct component_clk *clk)
+{
+	if (clk)
+		return clk->hw;
+
+	return NULL;

drivers/clk/ti/composite.c line 106

Quoted 10 lines
drivers/clk/ti/composite.c new file +10 -0
+}
+
+static int __init of_ti_composite_clk_setup(struct device_node *node,
+					    struct regmap *regmap)
+{
+	int num_clks;
+	int i;
+	struct clk *clk;
+	struct component_clk *comp;
+	struct component_clk *clks[3] = { NULL };

sizeof(component_clk_types) or CLK_COMPONENT_TYPE_MAX instead of 3?

drivers/clk/ti/composite.c line 117

Quoted 11 lines
drivers/clk/ti/composite.c new file +11 -0
+	const char *name = node->name;
+	int num_parents = 0;
+	const char **parent_names = NULL;
+	int ret = 0;
+
+	/* Number of component clocks to be put inside this clock */
+	num_clks = of_clk_get_parent_count(node);
+
+	if (num_clks < 1) {
+		pr_err("%s: ti composite clk %s must have component(s)\n",
+		       __func__, name);

using pr_fmt will reduce the pr_err code.

drivers/clk/ti/composite.c line 129

Quoted 12 lines
drivers/clk/ti/composite.c new file +12 -0
+		return -EINVAL;
+	}
+
+	/* Check for presence of each component clock */
+	for (i = 0; i < num_clks; i++) {
+		comp = _lookup_component(node, i);
+		if (!comp)
+			return -EAGAIN;
+		if (clks[comp->type] != NULL) {
+			pr_err("%s: duplicate component types for %s (%s)!\n",
+			       __func__, name, component_clk_types[comp->type]);
+			return -EINVAL;

would you not want to do a cleanup of the list here?

drivers/clk/ti/composite.c line 135

Quoted 6 lines
drivers/clk/ti/composite.c new file +6 -0
+		}
+		clks[comp->type] = comp;
+	}
+
+	/* All components exists, proceed with registration */
+	for (i = 0; i < 3; i++) {

CLK_COMPONENT_TYPE_MAX instead

Quoted 4 lines
drivers/clk/ti/composite.c new file +4 -0
+		if (!clks[i])
+			continue;
+		if (clks[i]->num_parents) {
+			num_parents = clks[i]->num_parents;

drivers/clk/ti/composite.c line 149

Quoted 10 lines
drivers/clk/ti/composite.c new file +10 -0
+			parent_names = clks[i]->parent_names;
+		}
+	}
+
+	/* Enforce mux parents if exists */
+	comp = clks[CLK_COMPONENT_TYPE_MUX];
+	if (comp) {
+		num_parents = comp->num_parents;
+		parent_names = comp->parent_names;
+	}

you could move the for loop in the else case and reduce the loops to CLK_COMPONENT_TYPE_MUX+1 to CLK_COMPONENT_TYPE_MAX.

drivers/clk/ti/composite.c line 154

Quoted 5 lines
drivers/clk/ti/composite.c new file +5 -0
+
+	if (!num_parents) {
+		pr_err("%s: no parents found for %s!\n", __func__,
+		       name);
+		return -EINVAL;

would you not want to do a cleanup of the list here?

Quoted 14 lines
drivers/clk/ti/composite.c new file +14 -0
+	}
+
+	clk = clk_register_composite(NULL, name, parent_names, num_parents,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_MUX]),
+				     &clk_mux_ops,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_DIVIDER]),
+				     &ti_composite_divider_ops,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_GATE]),
+				     &ti_composite_gate_ops, 0);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		goto cleanup;
+	}

drivers/clk/ti/composite.c line 178

Quoted 10 lines
drivers/clk/ti/composite.c new file +10 -0
+
+	ret = PTR_ERR(clk);
+cleanup:
+	/* Free component clock list entries */
+	for (i = 0; i < 3; i++) {
+		if (!clks[i])
+			continue;
+		list_del(&clks[i]->link);
+		kfree(clks[i]);
+	}

could you not just do a kfree(clks[i]) and set the component_clks to NULL?

Further, if there are only 3 clocks that can ever be present and we do not allow for duplicates types, could we not do those checks in ti_clk_add_component instead of having a harder recovery in setup of composite clk?

Quoted 49 lines
drivers/clk/ti/composite.c new file +44 -0
+
+	return ret;
+}
+CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
+	       of_ti_composite_clk_setup);
+
+int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
+				int type)
+{
+	int num_parents;
+	const char **parent_names;
+	struct component_clk *clk;
+	int i;
+
+	num_parents = of_clk_get_parent_count(node);
+
+	if (num_parents < 1) {
+		pr_err("%s: component-clock %s must have parent(s)\n", __func__,
+		       node->name);
+		return -EINVAL;
+	}
+
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names)
+		return -ENOMEM;
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk) {
+		kfree(parent_names);
+		return -ENOMEM;
+	}
+
+	clk->num_parents = num_parents;
+	clk->parent_names = parent_names;
+	clk->hw = hw;
+	clk->node = node;
+	clk->type = type;
+	list_add(&clk->link, &component_clks);
+
+	return 0;
+}
include/linux/clk/ti.h +0 -0
index e45005c..96c9725 100644

include/linux/clk/ti.h struct clk_hw_omap { · line 144

Quoted 8 lines
include/linux/clk/ti.h +5 -0
@@ -137,6 +137,13 @@ struct clk_hw_omap {
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE		0x1
 
+/* Composite clock component types */
+enum {
+	CLK_COMPONENT_TYPE_MUX = 0,
+	CLK_COMPONENT_TYPE_GATE,
+	CLK_COMPONENT_TYPE_DIVIDER

adding a CLK_COMPONENT_TYPE_MAX will allow a better implementation

Quoted 14 lines
include/linux/clk/ti.h +3 -0
+};
+
 /**
  * struct ti_dt_clk - OMAP DT clock alias declarations
  * @lk: clock lookup definition
@@ -179,6 +186,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
 int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
+int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
Signature · 2 lines
Regards,
Nishanth Menon
#36 lore raw

PATCH v9 8/43 clk: ti: add composite clock support

Quoted 69 lines · Nishanth Menon
Quoted 68 lines · Tero Kristo

This is a multipurpose clock node, which contains support for multiple sub-clocks. Uses basic composite clock type to implement the actual functionality, and TI specific gate, mux and divider clocks.

---
 .../devicetree/bindings/clock/ti/composite.txt     |   54 +++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/composite.c                         |  222 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    8 +
 4 files changed, 285 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/composite.txt
 create mode 100644 drivers/clk/ti/composite.c
Documentation/devicetree/bindings/clock/ti/composite.txt new file +48 -0
new file mode 100644
index 0000000..5f43c47
@@ -0,0 +1,54 @@
+Binding for TI composite clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped composite clock with multiple different sub-types;
+
+a multiplexer clock with multiple input clock signals or parents, one
+of which can be selected as output, this behaves exactly as [2]
+
+an adjustable clock rate divider, this behaves exactly as [3]
+
+a gating function which can be used to enable and disable the output
+clock, this behaves exactly as [4]
+
+The binding must provide a list of the component clocks that shall be
+merged to this clock. The component clocks shall be of one of the
+"ti,*composite*-clock" types.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/mux.txt
+[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[4] Documentation/devicetree/bindings/clock/ti/gate.txt
+
+Required properties:
+- compatible : shall be: "ti,composite-clock"
+- clocks : link phandles of component clocks
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Examples:
+
+usb_l4_gate_ick: usb_l4_gate_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-interface-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <5>;
+	reg = <0x0a10>;
+};
+
+usb_l4_div_ick: usb_l4_div_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-divider-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <4>;
+	ti,max-div = <1>;
+	reg = <0x0a40>;
+	ti,index-starts-at-one;
+};
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/composite.txt line 54

Quoted 6 lines
Documentation/devicetree/bindings/clock/ti/composite.txt new file +6 -0
+
+usb_l4_ick: usb_l4_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-clock";
+	clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+};

From Topology perspective, would this be a better approach?

usb_l4_ick: usb_l4_ick {
	#clock-cells = <0>;
	compatible = "ti,composite-clock";

	usb_l4_gate_ick: usb_l4_gate_ick {
		#clock-cells = <0>;
		compatible = "ti,composite-interface-clock";
		clocks = <&l4_ick>;
		ti,bit-shift = <5>;
		reg = <0x0a10>;
	};

	usb_l4_div_ick: usb_l4_div_ick {
		#clock-cells = <0>;
		compatible = "ti,composite-divider-clock";
		clocks = <&l4_ick>;
		ti,bit-shift = <4>;
		ti,max-div = <1>;
		reg = <0x0a40>;
		ti,index-starts-at-one;
	};
};
Signature · 2 lines
Regards,
Nishanth Menon
#37 lore raw

PATCH v9 8/43 clk: ti: add composite clock support

Quoted 93 lines · Nishanth Menon
Quoted 67 lines · Nishanth Menon
Quoted 66 lines · Tero Kristo

This is a multipurpose clock node, which contains support for multiple sub-clocks. Uses basic composite clock type to implement the actual functionality, and TI specific gate, mux and divider clocks.

---
  .../devicetree/bindings/clock/ti/composite.txt     |   54 +++++
  drivers/clk/ti/Makefile                            |    2 +-
  drivers/clk/ti/composite.c                         |  222 ++++++++++++++++++++
  include/linux/clk/ti.h                             |    8 +
  4 files changed, 285 insertions(+), 1 deletion(-)

create mode 100644 Documentation/devicetree/bindings/clock/ti/composite.txt create mode 100644 drivers/clk/ti/composite.c

Documentation/devicetree/bindings/clock/ti/composite.txt new file +46 -0
new file mode 100644
index 0000000..5f43c47
@@ -0,0 +1,54 @@
+Binding for TI composite clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped composite clock with multiple different sub-types;
+
+a multiplexer clock with multiple input clock signals or parents, one
+of which can be selected as output, this behaves exactly as [2]
+
+an adjustable clock rate divider, this behaves exactly as [3]
+
+a gating function which can be used to enable and disable the output
+clock, this behaves exactly as [4]
+
+The binding must provide a list of the component clocks that shall be
+merged to this clock. The component clocks shall be of one of the
+"ti,*composite*-clock" types.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/mux.txt
+[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[4] Documentation/devicetree/bindings/clock/ti/gate.txt
+
+Required properties:
+- compatible : shall be: "ti,composite-clock"
+- clocks : link phandles of component clocks
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Examples:
+
+usb_l4_gate_ick: usb_l4_gate_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-interface-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <5>;
+	reg = <0x0a10>;
+};
+
+usb_l4_div_ick: usb_l4_div_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-divider-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <4>;
+	ti,max-div = <1>;
+	reg = <0x0a40>;
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/composite.txt line 54

Quoted 8 lines
Documentation/devicetree/bindings/clock/ti/composite.txt new file +8 -0
+	ti,index-starts-at-one;
+};
+
+usb_l4_ick: usb_l4_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-clock";
+	clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+};

From Topology perspective, would this be a better approach?

usb_l4_ick: usb_l4_ick {
	#clock-cells = <0>;
	compatible = "ti,composite-clock";

	usb_l4_gate_ick: usb_l4_gate_ick {
		#clock-cells = <0>;
		compatible = "ti,composite-interface-clock";
		clocks = <&l4_ick>;
		ti,bit-shift = <5>;
		reg = <0x0a10>;
	};

	usb_l4_div_ick: usb_l4_div_ick {
		#clock-cells = <0>;
Quoted 8 lines
		compatible = "ti,composite-divider-clock";
		clocks = <&l4_ick>;
		ti,bit-shift = <4>;
		ti,max-div = <1>;
		reg = <0x0a40>;
		ti,index-starts-at-one;
	};
};

Well I was considering this, however this would require extra level of registration also:

of_ti_composite_clk_setup ->
(match children against composite types)
of_ti_composite_divider_setup
of_ti_composite_gate_setup

Might be cleaner overall though, so I can take a look at this.

-Tero

#38 lore raw

PATCH v9 8/43 clk: ti: add composite clock support

In reply to Nishanth Menon
Quoted 150 lines · Nishanth Menon
Quoted 149 lines · Tero Kristo

This is a multipurpose clock node, which contains support for multiple sub-clocks. Uses basic composite clock type to implement the actual functionality, and TI specific gate, mux and divider clocks.

---
  .../devicetree/bindings/clock/ti/composite.txt     |   54 +++++
  drivers/clk/ti/Makefile                            |    2 +-
  drivers/clk/ti/composite.c                         |  222 ++++++++++++++++++++
  include/linux/clk/ti.h                             |    8 +
  4 files changed, 285 insertions(+), 1 deletion(-)

create mode 100644 Documentation/devicetree/bindings/clock/ti/composite.txt create mode 100644 drivers/clk/ti/composite.c

Documentation/devicetree/bindings/clock/ti/composite.txt new file +54 -0
new file mode 100644
index 0000000..5f43c47
@@ -0,0 +1,54 @@
+Binding for TI composite clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped composite clock with multiple different sub-types;
+
+a multiplexer clock with multiple input clock signals or parents, one
+of which can be selected as output, this behaves exactly as [2]
+
+an adjustable clock rate divider, this behaves exactly as [3]
+
+a gating function which can be used to enable and disable the output
+clock, this behaves exactly as [4]
+
+The binding must provide a list of the component clocks that shall be
+merged to this clock. The component clocks shall be of one of the
+"ti,*composite*-clock" types.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/mux.txt
+[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[4] Documentation/devicetree/bindings/clock/ti/gate.txt
+
+Required properties:
+- compatible : shall be: "ti,composite-clock"
+- clocks : link phandles of component clocks
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Examples:
+
+usb_l4_gate_ick: usb_l4_gate_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-interface-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <5>;
+	reg = <0x0a10>;
+};
+
+usb_l4_div_ick: usb_l4_div_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-divider-clock";
+	clocks = <&l4_ick>;
+	ti,bit-shift = <4>;
+	ti,max-div = <1>;
+	reg = <0x0a40>;
+	ti,index-starts-at-one;
+};
+
+usb_l4_ick: usb_l4_ick {
+	#clock-cells = <0>;
+	compatible = "ti,composite-clock";
+	clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+};
drivers/clk/ti/Makefile +1 -1
index 533efb4..a4a7595 100644
@@ -1,3 +1,3 @@
  ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o autoidle.o
+obj-y					+= clk.o dpll.o autoidle.o composite.o
  endif
drivers/clk/ti/composite.c new file +60 -0
new file mode 100644
index 0000000..9ce7e54
@@ -0,0 +1,222 @@
+/*
+ * TI composite clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/list.h>
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+static unsigned long ti_composite_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	return -EINVAL;
+}
+
+static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	return -EINVAL;
+}
+
+static const struct clk_ops ti_composite_divider_ops = {
+	.recalc_rate	= &ti_composite_recalc_rate,
+	.round_rate	= &ti_composite_round_rate,
+	.set_rate	= &ti_composite_set_rate,
+};
+
+static const struct clk_ops ti_composite_gate_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+struct component_clk {
+	int num_parents;
+	const char **parent_names;
Quoted 8 lines

drivers/clk/ti/composite.c line 67

Quoted 7 lines
drivers/clk/ti/composite.c new file +7 -0
+	struct device_node *node;
+	int type;
+	struct clk_hw *hw;
+	struct list_head link;
+};
+
+static const char * __initdata component_clk_types[] = {

[CLK_COMPONENT_TYPE_MAX]?

Yea can add a enum for that, good for the rest of the points listed for this.

Quoted 33 lines
Quoted 33 lines
drivers/clk/ti/composite.c new file +32 -0
+	"mux", "gate", "divider",
+};
+
+static LIST_HEAD(component_clks);
+
+static struct component_clk *_lookup_component(struct device_node *node, int i)
+{
+	int rc;
+	struct of_phandle_args clkspec;
+	struct component_clk *comp;
+
+	rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i,
+					&clkspec);
+	if (rc)
+		return NULL;
+
+	list_for_each_entry(comp, &component_clks, link) {
+		if (comp->node == clkspec.np)
+			return comp;
+	}
+	return NULL;
+}
+
+static inline struct clk_hw *_get_hw(struct component_clk *clk)
+{
+	if (clk)
+		return clk->hw;
+
+	return NULL;
+}
+
+static int __init of_ti_composite_clk_setup(struct device_node *node,
Quoted 8 lines

drivers/clk/ti/composite.c line 106

Quoted 7 lines
drivers/clk/ti/composite.c new file +7 -0
+					    struct regmap *regmap)
+{
+	int num_clks;
+	int i;
+	struct clk *clk;
+	struct component_clk *comp;
+	struct component_clk *clks[3] = { NULL };

sizeof(component_clk_types) or CLK_COMPONENT_TYPE_MAX instead of 3?

TYPE_MAX sounds good to me.

Quoted 5 lines
Quoted 5 lines
drivers/clk/ti/composite.c new file +5 -0
+	const char *name = node->name;
+	int num_parents = 0;
+	const char **parent_names = NULL;
+	int ret = 0;
+
Quoted 8 lines

drivers/clk/ti/composite.c line 117

Quoted 6 lines
drivers/clk/ti/composite.c new file +6 -0
+	/* Number of component clocks to be put inside this clock */
+	num_clks = of_clk_get_parent_count(node);
+
+	if (num_clks < 1) {
+		pr_err("%s: ti composite clk %s must have component(s)\n",
+		       __func__, name);

using pr_fmt will reduce the pr_err code.

True.

Quoted 14 lines

drivers/clk/ti/composite.c line 129

Quoted 13 lines
drivers/clk/ti/composite.c new file +12 -0
+		return -EINVAL;
+	}
+
+	/* Check for presence of each component clock */
+	for (i = 0; i < num_clks; i++) {
+		comp = _lookup_component(node, i);
+		if (!comp)
+			return -EAGAIN;
+		if (clks[comp->type] != NULL) {
+			pr_err("%s: duplicate component types for %s (%s)!\n",
+			       __func__, name, component_clk_types[comp->type]);
+			return -EINVAL;

would you not want to do a cleanup of the list here?

Might be a good idea yea.

Quoted 8 lines

drivers/clk/ti/composite.c line 135

Quoted 7 lines
drivers/clk/ti/composite.c new file +6 -0
+		}
+		clks[comp->type] = comp;
+	}
+
+	/* All components exists, proceed with registration */
+	for (i = 0; i < 3; i++) {

CLK_COMPONENT_TYPE_MAX instead

Yup.

Quoted 8 lines
Quoted 8 lines
drivers/clk/ti/composite.c new file +8 -0
+		if (!clks[i])
+			continue;
+		if (clks[i]->num_parents) {
+			num_parents = clks[i]->num_parents;
+			parent_names = clks[i]->parent_names;
+		}
+	}
+
Quoted 8 lines

drivers/clk/ti/composite.c line 149

Quoted 6 lines
drivers/clk/ti/composite.c new file +6 -0
+	/* Enforce mux parents if exists */
+	comp = clks[CLK_COMPONENT_TYPE_MUX];
+	if (comp) {
+		num_parents = comp->num_parents;
+		parent_names = comp->parent_names;
+	}

you could move the for loop in the else case and reduce the loops to CLK_COMPONENT_TYPE_MUX+1 to CLK_COMPONENT_TYPE_MAX.

Oh yea, good idea, wonder why I overlooked this.

Quoted 8 lines

drivers/clk/ti/composite.c line 154

Quoted 6 lines
drivers/clk/ti/composite.c new file +5 -0
+
+	if (!num_parents) {
+		pr_err("%s: no parents found for %s!\n", __func__,
+		       name);
+		return -EINVAL;

would you not want to do a cleanup of the list here?

Again, I think yes we would want to.

Quoted 28 lines
Quoted 15 lines
drivers/clk/ti/composite.c new file +14 -0
+	}
+
+	clk = clk_register_composite(NULL, name, parent_names, num_parents,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_MUX]),
+				     &clk_mux_ops,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_DIVIDER]),
+				     &ti_composite_divider_ops,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_GATE]),
+				     &ti_composite_gate_ops, 0);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		goto cleanup;
+	}

drivers/clk/ti/composite.c line 178

Quoted 10 lines
drivers/clk/ti/composite.c new file +10 -0
+
+	ret = PTR_ERR(clk);
+cleanup:
+	/* Free component clock list entries */
+	for (i = 0; i < 3; i++) {
+		if (!clks[i])
+			continue;
+		list_del(&clks[i]->link);
+		kfree(clks[i]);
+	}

could you not just do a kfree(clks[i]) and set the component_clks to NULL?

Quoted 4 lines

Further, if there are only 3 clocks that can ever be present and we do not allow for duplicates types, could we not do those checks in ti_clk_add_component instead of having a harder recovery in setup of composite clk?

The list is shared between all composite clocks, as we don't have knowledge into which clock each component will go to at the time of the component registration. Consider this setup (comp = component):

comp-a1
comp-a2
composite-a : comp-a1 + comp-a2
comp-b1
comp-b2
comp-b3
composite-b : comp-b1 + comp-b2 + comp-b3

Depending on clock init order, we will potentially have 5 components in the list at max, which of 2 + 2 are of same type.

Quoted 53 lines
Quoted 53 lines
drivers/clk/ti/composite.c new file +44 -0
+
+	return ret;
+}
+CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
+	       of_ti_composite_clk_setup);
+
+int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
+				int type)
+{
+	int num_parents;
+	const char **parent_names;
+	struct component_clk *clk;
+	int i;
+
+	num_parents = of_clk_get_parent_count(node);
+
+	if (num_parents < 1) {
+		pr_err("%s: component-clock %s must have parent(s)\n", __func__,
+		       node->name);
+		return -EINVAL;
+	}
+
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names)
+		return -ENOMEM;
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk) {
+		kfree(parent_names);
+		return -ENOMEM;
+	}
+
+	clk->num_parents = num_parents;
+	clk->parent_names = parent_names;
+	clk->hw = hw;
+	clk->node = node;
+	clk->type = type;
+	list_add(&clk->link, &component_clks);
+
+	return 0;
+}
include/linux/clk/ti.h +0 -0
index e45005c..96c9725 100644
@@ -137,6 +137,13 @@ struct clk_hw_omap {
  /* DPLL Type and DCO Selection Flags */
  #define DPLL_J_TYPE		0x1
 
Quoted 6 lines

include/linux/clk/ti.h struct clk_hw_omap { · line 144

Quoted 5 lines
include/linux/clk/ti.h +5 -0
+/* Composite clock component types */
+enum {
+	CLK_COMPONENT_TYPE_MUX = 0,
+	CLK_COMPONENT_TYPE_GATE,
+	CLK_COMPONENT_TYPE_DIVIDER

adding a CLK_COMPONENT_TYPE_MAX will allow a better implementation

Yea, and need to move MUX as last entry for one of the above comments.

Quoted 16 lines
Quoted 14 lines
include/linux/clk/ti.h +3 -0
+};
+
  /**
   * struct ti_dt_clk - OMAP DT clock alias declarations
   * @lk: clock lookup definition
@@ -179,6 +186,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
  void ti_dt_clocks_register(struct ti_dt_clk *oclks);
  void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
  int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
+int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
  #ifdef CONFIG_OF
  void of_ti_clk_allow_autoidle_all(void);
#39 lore raw

PATCH v9 8/43 clk: ti: add composite clock support

Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:

[..]

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/clk/ti/composite.c new file +0 -0
new file mode 100644
index 0000000..9ce7e54

[...]

Quoted 45 lines
Quoted 28 lines
Quoted 15 lines
drivers/clk/ti/composite.c new file +14 -0
+	}
+
+	clk = clk_register_composite(NULL, name, parent_names, num_parents,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_MUX]),
+				     &clk_mux_ops,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_DIVIDER]),
+				     &ti_composite_divider_ops,
+				     _get_hw(clks[CLK_COMPONENT_TYPE_GATE]),
+				     &ti_composite_gate_ops, 0);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		goto cleanup;
+	}

drivers/clk/ti/composite.c line 178

Quoted 10 lines
drivers/clk/ti/composite.c new file +10 -0
+
+	ret = PTR_ERR(clk);
+cleanup:
+	/* Free component clock list entries */
+	for (i = 0; i < 3; i++) {
+		if (!clks[i])
+			continue;
+		list_del(&clks[i]->link);
+		kfree(clks[i]);
+	}

could you not just do a kfree(clks[i]) and set the component_clks to NULL?

Quoted 4 lines

Further, if there are only 3 clocks that can ever be present and we do not allow for duplicates types, could we not do those checks in ti_clk_add_component instead of having a harder recovery in setup of composite clk?

The list is shared between all composite clocks, as we don't have knowledge into which clock each component will go to at the time of the component registration. Consider this setup (comp = component):

comp-a1
comp-a2
composite-a : comp-a1 + comp-a2
comp-b1
comp-b2
comp-b3
composite-b : comp-b1 + comp-b2 + comp-b3

Quoted 2 lines

Depending on clock init order, we will potentially have 5 components in the list at max, which of 2 + 2 are of same type.

makes sense. Thanks for clarifying.

Signature · 2 lines
Regards,
Nishanth Menon
#40 lore raw

PATCH v9 9/43 CLK: ti: add support for ti divider-clock

In reply to Tero Kristo

This patch adds support for TI divider clock binding, which simply uses the basic clock divider to provide the features needed.

---
 .../devicetree/bindings/clock/ti/divider.txt       |   86 +++++++
 drivers/clk/ti/Makefile                            |    3 +-
 drivers/clk/ti/divider.c                           |  239 ++++++++++++++++++++
 3 files changed, 327 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/divider.txt
 create mode 100644 drivers/clk/ti/divider.c
Documentation/devicetree/bindings/clock/ti/divider.txt new file +86 -0
new file mode 100644
index 0000000..65e3dcd
@@ -0,0 +1,86 @@
+Binding for TI divider clock
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+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.  By default 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
+
+This assumption may be modified by the following optional properties:
+
+ti,index-starts-at-one - valid divisor values start at 1, not the default
+of 0.  E.g:
+register value		actual divisor value
+1			1
+2			2
+3			3
+
+ti,index-power-of-two - valid divisor values are powers of two.  E.g:
+register value		actual divisor value
+0			1
+1			2
+2			4
+
+Additionally an array of valid dividers may be supplied like so:
+
+	dividers = <4>, <8>, <0>, <16>;
+
+Which will map the resulting values to a divisor table by their index:
+register value		actual divisor value
+0			4
+1			8
+2			<invalid divisor, skipped>
+3			16
+
+Any zero value in this array means the corresponding bit-value is invalid
+and must not be used.
+
+The binding must also provide the register to control the divider and
+unless the divider array is provided, min and max dividers. Optionally
+the number of bits to shift that mask, if necessary. If the shift value
+is missing it is the same as supplying a zero shift.
+
+Required properties:
+- compatible : shall be "ti,divider-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable divider
+
+Optional properties:
+- clock-output-names : from common clock binding.
+- ti,dividers : array of integers defining divisors
+- ti,bit-shift : number of bits to shift the divider value, defaults to 0
+- ti,min-div : min divisor for dividing the input clock rate, only
+  needed if the first divisor is offset from the default value (1)
+- ti,max-div : max divisor for dividing the input clock rate, only needed
+  if ti,dividers is not defined.
+- ti,index-starts-at-one : valid divisor programming starts at 1, not zero
+- ti,index-power-of-two : valid divisor programming must be a power of two
+- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock
+- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0
+- ti,set-rate-parent : clk_set_rate is propagated to parent
+
+Examples:
+dpll_usb_m2_ck: dpll_usb_m2_ck at 4a008190 {
+	#clock-cells = <0>;
+	compatible = "ti,divider-clock";
+	clocks = <&dpll_usb_ck>;
+	ti,max-div = <127>;
+	reg = <0x190>;
+	ti,index-starts-at-one;
+};
+
+aess_fclk: aess_fclk at 4a004528 {
+	#clock-cells = <0>;
+	compatible = "ti,divider-clock";
+	clocks = <&abe_clk>;
+	ti,bit-shift = <24>;
+	reg = <0x528>;
+	ti,max-div = <2>;
+};
drivers/clk/ti/Makefile +2 -1
index a4a7595..640ebf9 100644
@@ -1,3 +1,4 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o autoidle.o composite.o
+obj-y					+= clk.o dpll.o autoidle.o divider.o \
+					   composite.o
 endif
drivers/clk/ti/divider.c new file +239 -0

239 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#41 lore raw

PATCH v9 9/43 CLK: ti: add support for ti divider-clock

Quoted 40 lines · Tero Kristo

This patch adds support for TI divider clock binding, which simply uses the basic clock divider to provide the features needed.

---
 .../devicetree/bindings/clock/ti/divider.txt       |   86 +++++++
 drivers/clk/ti/Makefile                            |    3 +-
 drivers/clk/ti/divider.c                           |  239 ++++++++++++++++++++
 3 files changed, 327 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/divider.txt
 create mode 100644 drivers/clk/ti/divider.c
Documentation/devicetree/bindings/clock/ti/divider.txt new file +22 -0
new file mode 100644
index 0000000..65e3dcd
@@ -0,0 +1,86 @@
+Binding for TI divider clock
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+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.  By default 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
+
+This assumption may be modified by the following optional properties:
+
+ti,index-starts-at-one - valid divisor values start at 1, not the default
+of 0.  E.g:
+register value		actual divisor value
+1			1
+2			2
+3			3

Documentation/devicetree/bindings/clock/ti/divider.txt line 32

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +10 -0
+
+ti,index-power-of-two - valid divisor values are powers of two.  E.g:
+register value		actual divisor value
+0			1
+1			2
+2			4
+
+Additionally an array of valid dividers may be supplied like so:
+
+	dividers = <4>, <8>, <0>, <16>;

ti,dividers I believe.

Quoted 8 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +8 -0
+
+Which will map the resulting values to a divisor table by their index:
+register value		actual divisor value
+0			4
+1			8
+2			<invalid divisor, skipped>
+3			16
+

Documentation/devicetree/bindings/clock/ti/divider.txt line 50

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +10 -0
+Any zero value in this array means the corresponding bit-value is invalid
+and must not be used.
+
+The binding must also provide the register to control the divider and
+unless the divider array is provided, min and max dividers. Optionally
+the number of bits to shift that mask, if necessary. If the shift value
+is missing it is the same as supplying a zero shift.
+
+Required properties:
+- compatible : shall be "ti,divider-clock".

ti,composite-divider-clock undocumented?

Documentation/devicetree/bindings/clock/ti/divider.txt line 63

Quoted 13 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +13 -0
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable divider
+
+Optional properties:
+- clock-output-names : from common clock binding.
+- ti,dividers : array of integers defining divisors
+- ti,bit-shift : number of bits to shift the divider value, defaults to 0
+- ti,min-div : min divisor for dividing the input clock rate, only
+  needed if the first divisor is offset from the default value (1)
+- ti,max-div : max divisor for dividing the input clock rate, only needed
+  if ti,dividers is not defined.
+- ti,index-starts-at-one : valid divisor programming starts at 1, not zero

makes sense only if ti,dividers are not defined, right? CLK_DIVIDER_ONE_BASED is used with !table

Documentation/devicetree/bindings/clock/ti/divider.txt line 64

Quoted 1 line
Documentation/devicetree/bindings/clock/ti/divider.txt new file +1 -0
+- ti,index-power-of-two : valid divisor programming must be a power of two

makes sense only if ti,dividers are not defined, right? CLK_DIVIDER_POWER_OF_TWO is used with !table

Documentation/devicetree/bindings/clock/ti/divider.txt line 66

Quoted 2 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +2 -0
+- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock
+- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0

These are part of auto idle driver bindings, so maybe give a link to that?

Documentation/devicetree/bindings/clock/ti/divider.txt line 67

Quoted 1 line
Documentation/devicetree/bindings/clock/ti/divider.txt new file +1 -0
+- ti,set-rate-parent : clk_set_rate is propagated to parent

yeah - this is one of those properties that should probably become generic at a later point in time.

Quoted 9 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +9 -0
+
+Examples:
+dpll_usb_m2_ck: dpll_usb_m2_ck at 4a008190 {
+	#clock-cells = <0>;
+	compatible = "ti,divider-clock";
+	clocks = <&dpll_usb_ck>;
+	ti,max-div = <127>;
+	reg = <0x190>;
+	ti,index-starts-at-one;

Documentation/devicetree/bindings/clock/ti/divider.txt line 86

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +10 -0
+};
+
+aess_fclk: aess_fclk at 4a004528 {
+	#clock-cells = <0>;
+	compatible = "ti,divider-clock";
+	clocks = <&abe_clk>;
+	ti,bit-shift = <24>;
+	reg = <0x528>;
+	ti,max-div = <2>;
+};

an example of ti,dividers will be useful as well.

Quoted 67 lines
drivers/clk/ti/Makefile +2 -1
index a4a7595..640ebf9 100644
@@ -1,3 +1,4 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o autoidle.o composite.o
+obj-y					+= clk.o dpll.o autoidle.o divider.o \
+					   composite.o
 endif
drivers/clk/ti/divider.c new file +51 -0
new file mode 100644
index 0000000..787bc8f
@@ -0,0 +1,239 @@
+/*
+ * TI Divider Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+static struct clk_div_table
+__init *ti_clk_get_div_table(struct device_node *node)
+{
+	struct clk_div_table *table;
+	const __be32 *divspec;
+	u32 val;
+	u32 num_div;
+	u32 valid_div;
+	int i;
+
+	divspec = of_get_property(node, "ti,dividers", &num_div);
+
+	if (!divspec)
+		return NULL;
+
+	num_div /= 4;
+
+	valid_div = 0;
+
+	/* Determine required size for divider table */
+	for (i = 0; i < num_div; i++) {
+		of_property_read_u32_index(node, "ti,dividers", i, &val);
+		if (val)
+			valid_div++;
+	}
+
+	if (!valid_div) {

drivers/clk/ti/divider.c line 61

Quoted 10 lines
drivers/clk/ti/divider.c new file +10 -0
+		pr_err("%s: no valid dividers for %s table\n", __func__,
+		       node->name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
+
+	if (!table) {
+		pr_err("%s: unable to allocate memory for %s table\n", __func__,
+		       node->name);

you could drop this.

Quoted 28 lines
drivers/clk/ti/divider.c new file +28 -0
+		return ERR_PTR(-ENOMEM);
+	}
+
+	valid_div = 0;
+
+	for (i = 0; i < num_div; i++) {
+		of_property_read_u32_index(node, "ti,dividers", i, &val);
+		if (val) {
+			table[valid_div].div = val;
+			table[valid_div].val = i;
+			valid_div++;
+		}
+	}
+
+	return table;
+}
+
+static int _get_divider_width(struct device_node *node,
+			      const struct clk_div_table *table,
+			      u8 flags)
+{
+	u32 min_div;
+	u32 max_div;
+	u32 val = 0;
+	u32 div;
+
+	if (!table) {
+		/* Clk divider table not provided, determine min/max divs */

drivers/clk/ti/divider.c line 99

Quoted 10 lines
drivers/clk/ti/divider.c new file +10 -0
+		if (of_property_read_u32(node, "ti,min-div", &min_div)) {
+			pr_debug("%s: no min-div for %s, default=1\n",
+				 __func__, node->name);
+			min_div = 1;
+		}
+
+		if (of_property_read_u32(node, "ti,max-div", &max_div)) {
+			pr_err("%s: no max-div for %s!\n", __func__,
+			       node->name);
+			return -EINVAL;

will be nice to get warning if ti,divider is defined and any of the non-operational properties are defined as well.

Quoted 75 lines
drivers/clk/ti/divider.c new file +75 -0
+		}
+
+		/* Determine bit width for the field */
+		if (flags & CLK_DIVIDER_ONE_BASED)
+			val = 1;
+
+		div = min_div;
+
+		while (div < max_div) {
+			if (flags & CLK_DIVIDER_POWER_OF_TWO)
+				div <<= 1;
+			else
+				div++;
+			val++;
+		}
+	} else {
+		div = 0;
+
+		while (table[div].div) {
+			val = table[div].val;
+			div++;
+		}
+	}
+
+	return fls(val);
+}
+
+/**
+ * of_ti_divider_clk_setup() - Setup function for simple div rate clock
+ */
+static int __init of_ti_divider_clk_setup(struct device_node *node,
+					  struct regmap *regmap)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	const char *parent_name;
+	u8 clk_divider_flags = 0;
+	u8 width = 0;
+	u8 shift = 0;
+	struct clk_div_table *table = NULL;
+	u32 val = 0;
+	u32 flags = 0;
+	int ret = 0;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	if (of_property_read_u32(node, "reg", &val)) {
+		pr_err("%s: %s must have reg\n", __func__, clk_name);
+		return -EINVAL;
+	}
+
+	reg = (void *)val;
+
+	if (!of_property_read_u32(node, "ti,bit-shift", &val))
+		shift = val;
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		clk_divider_flags |= CLK_DIVIDER_ONE_BASED;
+
+	if (of_property_read_bool(node, "ti,index-power-of-two"))
+		clk_divider_flags |= CLK_DIVIDER_POWER_OF_TWO;
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		flags |= CLK_SET_RATE_PARENT;
+
+	table = ti_clk_get_div_table(node);
+
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+
+	ret = _get_divider_width(node, table, clk_divider_flags);
+	if (ret < 0)
+		goto cleanup;
+

drivers/clk/ti/divider.c line 184

Quoted 10 lines
drivers/clk/ti/divider.c new file +10 -0
+	width = ret;
+
+	clk = clk_register_divider_table_regmap(NULL, clk_name, parent_name,
+						flags, reg, regmap, shift,
+						width, clk_divider_flags, table,
+						NULL);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		ret = of_ti_autoidle_setup(node, regmap);

if this fails, table will be freed though, we have added provider and registerd table_regmap, no?

Quoted 14 lines
drivers/clk/ti/divider.c new file +14 -0
+	} else {
+		ret = PTR_ERR(clk);
+	}
+
+	if (!ret)
+		return 0;
+cleanup:
+	kfree(table);
+	return ret;
+}
+CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
+
+static int __init of_ti_composite_divider_clk_setup(struct device_node *node,
+						     struct regmap *regmap)

drivers/clk/ti/divider.c line 208

Quoted 10 lines
drivers/clk/ti/divider.c new file +10 -0
+{
+	struct clk_divider *div;
+	u32 val;
+	int ret;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return -ENOMEM;
+
+	of_property_read_u32(node, "reg", &val);

reg is a mandatory property, no? error checks?

drivers/clk/ti/divider.c line 215

Quoted 7 lines
drivers/clk/ti/divider.c new file +7 -0
+	div->reg = (void *)val;
+	div->regmap = regmap;
+
+	div->table = ti_clk_get_div_table(node);
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		div->flags |= CLK_DIVIDER_ONE_BASED;

alright, this does not really map back to ti,divder-clock style handling.. aren't they supposed to be consistent?
how about "ti,index-power-of-two", bit shift etc?

Quoted 25 lines
drivers/clk/ti/divider.c new file +24 -0
+
+	ret = _get_divider_width(node, div->table, div->flags);
+	if (ret < 0)
+		goto cleanup;
+
+	div->width = ret;
+
+	if (of_property_read_u32(node, "ti,bit-shift", &val)) {
+		pr_debug("%s: missing bit-shift property for %s, default=0\n",
+			 __func__, node->name);
+		val = 0;
+	}
+	div->shift = val;
+
+	ret = ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER);
+	if (!ret)
+		return 0;
+
+cleanup:
+	kfree(div);
+	return ret;
+}
+CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
+	       of_ti_composite_divider_clk_setup);
Signature · 2 lines
Regards,
Nishanth Menon
#42 lore raw

PATCH v9 9/43 CLK: ti: add support for ti divider-clock

Quoted 44 lines · Nishanth Menon
Quoted 43 lines · Tero Kristo

This patch adds support for TI divider clock binding, which simply uses the basic clock divider to provide the features needed.

---
  .../devicetree/bindings/clock/ti/divider.txt       |   86 +++++++
  drivers/clk/ti/Makefile                            |    3 +-
  drivers/clk/ti/divider.c                           |  239 ++++++++++++++++++++
  3 files changed, 327 insertions(+), 1 deletion(-)

create mode 100644 Documentation/devicetree/bindings/clock/ti/divider.txt create mode 100644 drivers/clk/ti/divider.c

Documentation/devicetree/bindings/clock/ti/divider.txt new file +25 -0
new file mode 100644
index 0000000..65e3dcd
@@ -0,0 +1,86 @@
+Binding for TI divider clock
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+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.  By default 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
+
+This assumption may be modified by the following optional properties:
+
+ti,index-starts-at-one - valid divisor values start at 1, not the default
+of 0.  E.g:
+register value		actual divisor value
+1			1
+2			2
+3			3
+
+ti,index-power-of-two - valid divisor values are powers of two.  E.g:
+register value		actual divisor value
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 32

Quoted 7 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +7 -0
+0			1
+1			2
+2			4
+
+Additionally an array of valid dividers may be supplied like so:
+
+	dividers = <4>, <8>, <0>, <16>;

ti,dividers I believe.

True.

Quoted 13 lines
Quoted 13 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +12 -0
+
+Which will map the resulting values to a divisor table by their index:
+register value		actual divisor value
+0			4
+1			8
+2			<invalid divisor, skipped>
+3			16
+
+Any zero value in this array means the corresponding bit-value is invalid
+and must not be used.
+
+The binding must also provide the register to control the divider and
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 50

Quoted 6 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +6 -0
+unless the divider array is provided, min and max dividers. Optionally
+the number of bits to shift that mask, if necessary. If the shift value
+is missing it is the same as supplying a zero shift.
+
+Required properties:
+- compatible : shall be "ti,divider-clock".

ti,composite-divider-clock undocumented?

Hmm yea true.

Quoted 17 lines
Quoted 4 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +3 -0
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable divider

Documentation/devicetree/bindings/clock/ti/divider.txt line 63

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +10 -0
+
+Optional properties:
+- clock-output-names : from common clock binding.
+- ti,dividers : array of integers defining divisors
+- ti,bit-shift : number of bits to shift the divider value, defaults to 0
+- ti,min-div : min divisor for dividing the input clock rate, only
+  needed if the first divisor is offset from the default value (1)
+- ti,max-div : max divisor for dividing the input clock rate, only needed
+  if ti,dividers is not defined.
+- ti,index-starts-at-one : valid divisor programming starts at 1, not zero

makes sense only if ti,dividers are not defined, right? CLK_DIVIDER_ONE_BASED is used with !table

Yeah, ignored if table is present.

Quoted 5 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 64

Quoted 2 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +1 -0
+- ti,index-power-of-two : valid divisor programming must be a power of two

makes sense only if ti,dividers are not defined, right? CLK_DIVIDER_POWER_OF_TWO is used with !table

Yea.

Quoted 5 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 66

Quoted 3 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +2 -0
+- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock
+- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0

These are part of auto idle driver bindings, so maybe give a link to that?

Yea can do.

Quoted 19 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 67

Quoted 2 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +1 -0
+- ti,set-rate-parent : clk_set_rate is propagated to parent

yeah - this is one of those properties that should probably become generic at a later point in time.

Quoted 13 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +13 -0
+
+Examples:
+dpll_usb_m2_ck: dpll_usb_m2_ck at 4a008190 {
+	#clock-cells = <0>;
+	compatible = "ti,divider-clock";
+	clocks = <&dpll_usb_ck>;
+	ti,max-div = <127>;
+	reg = <0x190>;
+	ti,index-starts-at-one;
+};
+
+aess_fclk: aess_fclk at 4a004528 {
+	#clock-cells = <0>;
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 86

Quoted 6 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +6 -0
+	compatible = "ti,divider-clock";
+	clocks = <&abe_clk>;
+	ti,bit-shift = <24>;
+	reg = <0x528>;
+	ti,max-div = <2>;
+};

an example of ti,dividers will be useful as well.

Ok.

Quoted 72 lines
Quoted 72 lines
drivers/clk/ti/Makefile +2 -1
index a4a7595..640ebf9 100644
@@ -1,3 +1,4 @@
  ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o dpll.o autoidle.o composite.o
+obj-y					+= clk.o dpll.o autoidle.o divider.o \
+					   composite.o
  endif
drivers/clk/ti/divider.c new file +55 -0
new file mode 100644
index 0000000..787bc8f
@@ -0,0 +1,239 @@
+/*
+ * TI Divider Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+static struct clk_div_table
+__init *ti_clk_get_div_table(struct device_node *node)
+{
+	struct clk_div_table *table;
+	const __be32 *divspec;
+	u32 val;
+	u32 num_div;
+	u32 valid_div;
+	int i;
+
+	divspec = of_get_property(node, "ti,dividers", &num_div);
+
+	if (!divspec)
+		return NULL;
+
+	num_div /= 4;
+
+	valid_div = 0;
+
+	/* Determine required size for divider table */
+	for (i = 0; i < num_div; i++) {
+		of_property_read_u32_index(node, "ti,dividers", i, &val);
+		if (val)
+			valid_div++;
+	}
+
+	if (!valid_div) {
+		pr_err("%s: no valid dividers for %s table\n", __func__,
+		       node->name);
+		return ERR_PTR(-EINVAL);
+	}
Quoted 8 lines

drivers/clk/ti/divider.c line 61

Quoted 6 lines
drivers/clk/ti/divider.c new file +6 -0
+
+	table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
+
+	if (!table) {
+		pr_err("%s: unable to allocate memory for %s table\n", __func__,
+		       node->name);

you could drop this.

True.

Quoted 34 lines
Quoted 34 lines
drivers/clk/ti/divider.c new file +33 -0
+		return ERR_PTR(-ENOMEM);
+	}
+
+	valid_div = 0;
+
+	for (i = 0; i < num_div; i++) {
+		of_property_read_u32_index(node, "ti,dividers", i, &val);
+		if (val) {
+			table[valid_div].div = val;
+			table[valid_div].val = i;
+			valid_div++;
+		}
+	}
+
+	return table;
+}
+
+static int _get_divider_width(struct device_node *node,
+			      const struct clk_div_table *table,
+			      u8 flags)
+{
+	u32 min_div;
+	u32 max_div;
+	u32 val = 0;
+	u32 div;
+
+	if (!table) {
+		/* Clk divider table not provided, determine min/max divs */
+		if (of_property_read_u32(node, "ti,min-div", &min_div)) {
+			pr_debug("%s: no min-div for %s, default=1\n",
+				 __func__, node->name);
+			min_div = 1;
+		}
Quoted 8 lines

drivers/clk/ti/divider.c line 99

Quoted 5 lines
drivers/clk/ti/divider.c new file +5 -0
+
+		if (of_property_read_u32(node, "ti,max-div", &max_div)) {
+			pr_err("%s: no max-div for %s!\n", __func__,
+			       node->name);
+			return -EINVAL;

will be nice to get warning if ti,divider is defined and any of the non-operational properties are defined as well.

Hmm ok, can add checks for those.

Quoted 81 lines
Quoted 81 lines
drivers/clk/ti/divider.c new file +80 -0
+		}
+
+		/* Determine bit width for the field */
+		if (flags & CLK_DIVIDER_ONE_BASED)
+			val = 1;
+
+		div = min_div;
+
+		while (div < max_div) {
+			if (flags & CLK_DIVIDER_POWER_OF_TWO)
+				div <<= 1;
+			else
+				div++;
+			val++;
+		}
+	} else {
+		div = 0;
+
+		while (table[div].div) {
+			val = table[div].val;
+			div++;
+		}
+	}
+
+	return fls(val);
+}
+
+/**
+ * of_ti_divider_clk_setup() - Setup function for simple div rate clock
+ */
+static int __init of_ti_divider_clk_setup(struct device_node *node,
+					  struct regmap *regmap)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	const char *parent_name;
+	u8 clk_divider_flags = 0;
+	u8 width = 0;
+	u8 shift = 0;
+	struct clk_div_table *table = NULL;
+	u32 val = 0;
+	u32 flags = 0;
+	int ret = 0;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	if (of_property_read_u32(node, "reg", &val)) {
+		pr_err("%s: %s must have reg\n", __func__, clk_name);
+		return -EINVAL;
+	}
+
+	reg = (void *)val;
+
+	if (!of_property_read_u32(node, "ti,bit-shift", &val))
+		shift = val;
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		clk_divider_flags |= CLK_DIVIDER_ONE_BASED;
+
+	if (of_property_read_bool(node, "ti,index-power-of-two"))
+		clk_divider_flags |= CLK_DIVIDER_POWER_OF_TWO;
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		flags |= CLK_SET_RATE_PARENT;
+
+	table = ti_clk_get_div_table(node);
+
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+
+	ret = _get_divider_width(node, table, clk_divider_flags);
+	if (ret < 0)
+		goto cleanup;
+
+	width = ret;
+
+	clk = clk_register_divider_table_regmap(NULL, clk_name, parent_name,
+						flags, reg, regmap, shift,
+						width, clk_divider_flags, table,
Quoted 8 lines

drivers/clk/ti/divider.c line 184

Quoted 5 lines
drivers/clk/ti/divider.c new file +5 -0
+						NULL);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		ret = of_ti_autoidle_setup(node, regmap);

if this fails, table will be freed though, we have added provider and registerd table_regmap, no?

Provider and regmap are shared for the whole IP block (CM/PRM whatever.) Those are only initialized once.

Quoted 19 lines
Quoted 19 lines
drivers/clk/ti/divider.c new file +18 -0
+	} else {
+		ret = PTR_ERR(clk);
+	}
+
+	if (!ret)
+		return 0;
+cleanup:
+	kfree(table);
+	return ret;
+}
+CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
+
+static int __init of_ti_composite_divider_clk_setup(struct device_node *node,
+						     struct regmap *regmap)
+{
+	struct clk_divider *div;
+	u32 val;
+	int ret;
Quoted 8 lines

drivers/clk/ti/divider.c line 208

Quoted 6 lines
drivers/clk/ti/divider.c new file +6 -0
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return -ENOMEM;
+
+	of_property_read_u32(node, "reg", &val);

reg is a mandatory property, no? error checks?

Ok can add. :P

Quoted 12 lines

drivers/clk/ti/divider.c line 215

Quoted 8 lines
drivers/clk/ti/divider.c new file +7 -0
+	div->reg = (void *)val;
+	div->regmap = regmap;
+
+	div->table = ti_clk_get_div_table(node);
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		div->flags |= CLK_DIVIDER_ONE_BASED;

alright, this does not really map back to ti,divder-clock style handling.. aren't they supposed to be consistent?
how about "ti,index-power-of-two", bit shift etc?

I can add non-used property checks yes.

Quoted 27 lines
Quoted 25 lines
drivers/clk/ti/divider.c new file +24 -0
+
+	ret = _get_divider_width(node, div->table, div->flags);
+	if (ret < 0)
+		goto cleanup;
+
+	div->width = ret;
+
+	if (of_property_read_u32(node, "ti,bit-shift", &val)) {
+		pr_debug("%s: missing bit-shift property for %s, default=0\n",
+			 __func__, node->name);
+		val = 0;
+	}
+	div->shift = val;
+
+	ret = ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER);
+	if (!ret)
+		return 0;
+
+cleanup:
+	kfree(div);
+	return ret;
+}
+CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
+	       of_ti_composite_divider_clk_setup);
#43 lore raw

PATCH v9 9/43 CLK: ti: add support for ti divider-clock

Quoted 379 lines · Tero Kristo
Quoted 50 lines · Nishanth Menon
Quoted 49 lines · Tero Kristo

This patch adds support for TI divider clock binding, which simply uses the basic clock divider to provide the features needed.

---
  .../devicetree/bindings/clock/ti/divider.txt       |   86 +++++++
  drivers/clk/ti/Makefile                            |    3 +-
  drivers/clk/ti/divider.c                           |  239
++++++++++++++++++++
  3 files changed, 327 insertions(+), 1 deletion(-)

create mode 100644
Documentation/devicetree/bindings/clock/ti/divider.txt
create mode 100644 drivers/clk/ti/divider.c

Documentation/devicetree/bindings/clock/ti/divider.txt new file +3 -0
new file mode 100644
index 0000000..65e3dcd
@@ -0,0 +1,86 @@
+Binding for TI divider clock
+
+Binding status: Unstable - ABI compatibility may be broken in the

future

Documentation/devicetree/bindings/clock/ti/divider.txt new file +3 -0
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped adjustable clock rate divider that does not gate and

has

Documentation/devicetree/bindings/clock/ti/divider.txt new file +11 -0
+only one input clock or parent.  By default 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
+
+This assumption may be modified by the following optional properties:
+
+ti,index-starts-at-one - valid divisor values start at 1, not the

default

Documentation/devicetree/bindings/clock/ti/divider.txt new file +8 -0
+of 0.  E.g:
+register value        actual divisor value
+1            1
+2            2
+3            3
+
+ti,index-power-of-two - valid divisor values are powers of two.  E.g:
+register value        actual divisor value
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 32

Quoted 7 lines
+0            1
+1            2
+2            4
Documentation/devicetree/bindings/clock/ti/divider.txt new file +4 -0
+
+Additionally an array of valid dividers may be supplied like so:
+
+    dividers = <4>, <8>, <0>, <16>;

ti,dividers I believe.

True.

Quoted 14 lines
Quoted 14 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +9 -0
+
+Which will map the resulting values to a divisor table by their index:
+register value        actual divisor value
+0            4
+1            8
+2            <invalid divisor, skipped>
+3            16
+
+Any zero value in this array means the corresponding bit-value is

invalid

Documentation/devicetree/bindings/clock/ti/divider.txt new file +3 -0
+and must not be used.
+
+The binding must also provide the register to control the divider and
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 50

Quoted 6 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +6 -0
+unless the divider array is provided, min and max dividers. Optionally
+the number of bits to shift that mask, if necessary. If the shift value
+is missing it is the same as supplying a zero shift.
+
+Required properties:
+- compatible : shall be "ti,divider-clock".

ti,composite-divider-clock undocumented?

Hmm yea true.

Quoted 12 lines
Quoted 12 lines
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable divider
Documentation/devicetree/bindings/clock/ti/divider.txt new file +5 -0
+
+Optional properties:
+- clock-output-names : from common clock binding.
+- ti,dividers : array of integers defining divisors
+- ti,bit-shift : number of bits to shift the divider value, defaults

to 0

+- ti,min-div : min divisor for dividing the input clock rate, only
+  needed if the first divisor is offset from the default value (1)
Quoted 8 lines
Quoted 5 lines

+- ti,max-div : max divisor for dividing the input clock rate, only needed
+ if ti,dividers is not defined.
+- ti,index-starts-at-one : valid divisor programming starts at 1, not zero

makes sense only if ti,dividers are not defined, right? CLK_DIVIDER_ONE_BASED is used with !table

Yeah, ignored if table is present.

Quoted 6 lines
Quoted 3 lines

+- ti,index-power-of-two : valid divisor programming must be a power of two

makes sense only if ti,dividers are not defined, right? CLK_DIVIDER_POWER_OF_TWO is used with !table

Yea.

Quoted 7 lines
Quoted 4 lines

+- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock
+- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0

These are part of auto idle driver bindings, so maybe give a link to that?

Yea can do.

Quoted 19 lines
Quoted 2 lines

+- ti,set-rate-parent : clk_set_rate is propagated to parent

yeah - this is one of those properties that should probably become generic at a later point in time.

Quoted 13 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +13 -0
+
+Examples:
+dpll_usb_m2_ck: dpll_usb_m2_ck at 4a008190 {
+    #clock-cells = <0>;
+    compatible = "ti,divider-clock";
+    clocks = <&dpll_usb_ck>;
+    ti,max-div = <127>;
+    reg = <0x190>;
+    ti,index-starts-at-one;
+};
+
+aess_fclk: aess_fclk at 4a004528 {
+    #clock-cells = <0>;
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/divider.txt line 86

Quoted 6 lines
Documentation/devicetree/bindings/clock/ti/divider.txt new file +6 -0
+    compatible = "ti,divider-clock";
+    clocks = <&abe_clk>;
+    ti,bit-shift = <24>;
+    reg = <0x528>;
+    ti,max-div = <2>;
+};

an example of ti,dividers will be useful as well.

Ok.

Quoted 73 lines
Quoted 73 lines
drivers/clk/ti/Makefile +2 -1
index a4a7595..640ebf9 100644
@@ -1,3 +1,4 @@
  ifneq ($(CONFIG_OF),)
-obj-y                    += clk.o dpll.o autoidle.o composite.o
+obj-y                    += clk.o dpll.o autoidle.o divider.o \
+                       composite.o
  endif
drivers/clk/ti/divider.c new file +56 -0
new file mode 100644
index 0000000..787bc8f
@@ -0,0 +1,239 @@
+/*
+ * TI Divider Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+static struct clk_div_table
+__init *ti_clk_get_div_table(struct device_node *node)
+{
+    struct clk_div_table *table;
+    const __be32 *divspec;
+    u32 val;
+    u32 num_div;
+    u32 valid_div;
+    int i;
+
+    divspec = of_get_property(node, "ti,dividers", &num_div);
+
+    if (!divspec)
+        return NULL;
+
+    num_div /= 4;
+
+    valid_div = 0;
+
+    /* Determine required size for divider table */
+    for (i = 0; i < num_div; i++) {
+        of_property_read_u32_index(node, "ti,dividers", i, &val);
+        if (val)
+            valid_div++;
+    }
+
+    if (!valid_div) {
+        pr_err("%s: no valid dividers for %s table\n", __func__,
+               node->name);
+        return ERR_PTR(-EINVAL);
+    }
+
Quoted 8 lines
Quoted 6 lines
drivers/clk/ti/divider.c new file +4 -0
+    table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
+
+    if (!table) {
+        pr_err("%s: unable to allocate memory for %s table\n",

__func__,
+ node->name);

you could drop this.

True.

Quoted 34 lines
Quoted 34 lines
drivers/clk/ti/divider.c new file +33 -0
+        return ERR_PTR(-ENOMEM);
+    }
+
+    valid_div = 0;
+
+    for (i = 0; i < num_div; i++) {
+        of_property_read_u32_index(node, "ti,dividers", i, &val);
+        if (val) {
+            table[valid_div].div = val;
+            table[valid_div].val = i;
+            valid_div++;
+        }
+    }
+
+    return table;
+}
+
+static int _get_divider_width(struct device_node *node,
+                  const struct clk_div_table *table,
+                  u8 flags)
+{
+    u32 min_div;
+    u32 max_div;
+    u32 val = 0;
+    u32 div;
+
+    if (!table) {
+        /* Clk divider table not provided, determine min/max divs */
+        if (of_property_read_u32(node, "ti,min-div", &min_div)) {
+            pr_debug("%s: no min-div for %s, default=1\n",
+                 __func__, node->name);
+            min_div = 1;
+        }
Quoted 8 lines

drivers/clk/ti/divider.c line 99

Quoted 5 lines
drivers/clk/ti/divider.c new file +5 -0
+
+        if (of_property_read_u32(node, "ti,max-div", &max_div)) {
+            pr_err("%s: no max-div for %s!\n", __func__,
+                   node->name);
+            return -EINVAL;

will be nice to get warning if ti,divider is defined and any of the non-operational properties are defined as well.

Hmm ok, can add checks for those.

Quoted 82 lines
Quoted 82 lines
drivers/clk/ti/divider.c new file +78 -0
+        }
+
+        /* Determine bit width for the field */
+        if (flags & CLK_DIVIDER_ONE_BASED)
+            val = 1;
+
+        div = min_div;
+
+        while (div < max_div) {
+            if (flags & CLK_DIVIDER_POWER_OF_TWO)
+                div <<= 1;
+            else
+                div++;
+            val++;
+        }
+    } else {
+        div = 0;
+
+        while (table[div].div) {
+            val = table[div].val;
+            div++;
+        }
+    }
+
+    return fls(val);
+}
+
+/**
+ * of_ti_divider_clk_setup() - Setup function for simple div rate clock
+ */
+static int __init of_ti_divider_clk_setup(struct device_node *node,
+                      struct regmap *regmap)
+{
+    struct clk *clk;
+    const char *clk_name = node->name;
+    void __iomem *reg;
+    const char *parent_name;
+    u8 clk_divider_flags = 0;
+    u8 width = 0;
+    u8 shift = 0;
+    struct clk_div_table *table = NULL;
+    u32 val = 0;
+    u32 flags = 0;
+    int ret = 0;
+
+    parent_name = of_clk_get_parent_name(node, 0);
+
+    if (of_property_read_u32(node, "reg", &val)) {
+        pr_err("%s: %s must have reg\n", __func__, clk_name);
+        return -EINVAL;
+    }
+
+    reg = (void *)val;
+
+    if (!of_property_read_u32(node, "ti,bit-shift", &val))
+        shift = val;
+
+    if (of_property_read_bool(node, "ti,index-starts-at-one"))
+        clk_divider_flags |= CLK_DIVIDER_ONE_BASED;
+
+    if (of_property_read_bool(node, "ti,index-power-of-two"))
+        clk_divider_flags |= CLK_DIVIDER_POWER_OF_TWO;
+
+    if (of_property_read_bool(node, "ti,set-rate-parent"))
+        flags |= CLK_SET_RATE_PARENT;
+
+    table = ti_clk_get_div_table(node);
+
+    if (IS_ERR(table))
+        return PTR_ERR(table);
+
+    ret = _get_divider_width(node, table, clk_divider_flags);
+    if (ret < 0)
+        goto cleanup;
+
+    width = ret;
+
+    clk = clk_register_divider_table_regmap(NULL, clk_name,

parent_name,

drivers/clk/ti/divider.c new file +2 -0
+                        flags, reg, regmap, shift,
+                        width, clk_divider_flags, table,
Quoted 8 lines

drivers/clk/ti/divider.c line 184

Quoted 5 lines
drivers/clk/ti/divider.c new file +5 -0
+                        NULL);
+
+    if (!IS_ERR(clk)) {
+        of_clk_add_provider(node, of_clk_src_simple_get, clk);
+        ret = of_ti_autoidle_setup(node, regmap);

if this fails, table will be freed though, we have added provider and registerd table_regmap, no?

Quoted 2 lines

Provider and regmap are shared for the whole IP block (CM/PRM whatever.) Those are only initialized once.

Some minor confusion here in my comment, sorry about that.

Regmap is shared for the whole IP block and initialized only once, we can't remove it here as it is not owned by this clock. For clock-provider / unregister part, I don't want to clean those up as 1) unregister doesn't currently do anything 2) autoidle setup is not critical failure, it just breaks PM. I can add error print for it though.

-Tero

Quoted 77 lines
Quoted 22 lines
Quoted 22 lines
drivers/clk/ti/divider.c new file +11 -0
+    } else {
+        ret = PTR_ERR(clk);
+    }
+
+    if (!ret)
+        return 0;
+cleanup:
+    kfree(table);
+    return ret;
+}
+CLK_OF_DECLARE(divider_clk, "ti,divider-clock",

of_ti_divider_clk_setup);

drivers/clk/ti/divider.c new file +2 -0
+
+static int __init of_ti_composite_divider_clk_setup(struct

device_node *node,

drivers/clk/ti/divider.c new file +5 -0
+                             struct regmap *regmap)
+{
+    struct clk_divider *div;
+    u32 val;
+    int ret;
Quoted 8 lines

drivers/clk/ti/divider.c line 208

Quoted 6 lines
drivers/clk/ti/divider.c new file +6 -0
+
+    div = kzalloc(sizeof(*div), GFP_KERNEL);
+    if (!div)
+        return -ENOMEM;
+
+    of_property_read_u32(node, "reg", &val);

reg is a mandatory property, no? error checks?

Ok can add. :P

Quoted 12 lines

drivers/clk/ti/divider.c line 215

Quoted 8 lines
drivers/clk/ti/divider.c new file +7 -0
+    div->reg = (void *)val;
+    div->regmap = regmap;
+
+    div->table = ti_clk_get_div_table(node);
+
+    if (of_property_read_bool(node, "ti,index-starts-at-one"))
+        div->flags |= CLK_DIVIDER_ONE_BASED;

alright, this does not really map back to ti,divder-clock style handling.. aren't they supposed to be consistent?
how about "ti,index-power-of-two", bit shift etc?

I can add non-used property checks yes.

Quoted 28 lines
Quoted 26 lines
drivers/clk/ti/divider.c new file +15 -0
+
+    ret = _get_divider_width(node, div->table, div->flags);
+    if (ret < 0)
+        goto cleanup;
+
+    div->width = ret;
+
+    if (of_property_read_u32(node, "ti,bit-shift", &val)) {
+        pr_debug("%s: missing bit-shift property for %s, default=0\n",
+             __func__, node->name);
+        val = 0;
+    }
+    div->shift = val;
+
+    ret = ti_clk_add_component(node, &div->hw,

CLK_COMPONENT_TYPE_DIVIDER);

drivers/clk/ti/divider.c new file +9 -0
+    if (!ret)
+        return 0;
+
+cleanup:
+    kfree(div);
+    return ret;
+}
+CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
+           of_ti_composite_divider_clk_setup);
#44 lore raw

PATCH v9 9/43 CLK: ti: add support for ti divider-clock

Quoted 3 lines · Tero Kristo
Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:

[...]

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/clk/ti/divider.c new file +0 -0
new file mode 100644
index 0000000..787bc8f

[...]

Quoted 10 lines
Quoted 9 lines
Quoted 6 lines

drivers/clk/ti/divider.c line 184

Quoted 3 lines
drivers/clk/ti/divider.c new file +3 -0
+    if (!IS_ERR(clk)) {
+        of_clk_add_provider(node, of_clk_src_simple_get, clk);
+        ret = of_ti_autoidle_setup(node, regmap);

if this fails, table will be freed though, we have added provider and registerd table_regmap, no?

Provider and regmap are shared for the whole IP block (CM/PRM whatever.) Those are only initialized once.

Quoted 7 lines

Some minor confusion here in my comment, sorry about that.

Regmap is shared for the whole IP block and initialized only once, we can't remove it here as it is not owned by this clock. For clock-provider / unregister part, I don't want to clean those up as 1) unregister doesn't currently do anything 2) autoidle setup is not critical failure, it just breaks PM. I can add error print for it though.

Would IP blocks driven by clocks work with the autoidle configuration broken? I believe we will be writing to DPLL_XYZ_GATE_CTRL? the usage I believe is around of_ti_clk_deny_autoidle_all/of_ti_clk_allow_autoidle_all which gets invoked in omap2_clk_disable_autoidle_all part of xyz SoC init call. is'nt the reason we do that to ensure we have no potential race when clocks dissapear on their own without explicit control in critical configuration paths?

Signature · 2 lines
Regards,
Nishanth Menon
#45 lore raw

PATCH v9 9/43 CLK: ti: add support for ti divider-clock

Quoted 31 lines · Nishanth Menon
Quoted 3 lines · Tero Kristo
Quoted 2 lines · Tero Kristo
Quoted 1 line · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:

[...]

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/clk/ti/divider.c new file +0 -0
new file mode 100644
index 0000000..787bc8f

[...]

Quoted 10 lines
Quoted 9 lines
Quoted 6 lines

drivers/clk/ti/divider.c line 184

Quoted 3 lines
drivers/clk/ti/divider.c new file +3 -0
+    if (!IS_ERR(clk)) {
+        of_clk_add_provider(node, of_clk_src_simple_get, clk);
+        ret = of_ti_autoidle_setup(node, regmap);

if this fails, table will be freed though, we have added provider and registerd table_regmap, no?

Provider and regmap are shared for the whole IP block (CM/PRM whatever.) Those are only initialized once.

Quoted 7 lines

Some minor confusion here in my comment, sorry about that.

Regmap is shared for the whole IP block and initialized only once, we can't remove it here as it is not owned by this clock. For clock-provider / unregister part, I don't want to clean those up as 1) unregister doesn't currently do anything 2) autoidle setup is not critical failure, it just breaks PM. I can add error print for it though.

Quoted 8 lines

Would IP blocks driven by clocks work with the autoidle configuration broken? I believe we will be writing to DPLL_XYZ_GATE_CTRL? the usage I believe is around of_ti_clk_deny_autoidle_all/of_ti_clk_allow_autoidle_all which gets invoked in omap2_clk_disable_autoidle_all part of xyz SoC init call. is'nt the reason we do that to ensure we have no potential race when clocks dissapear on their own without explicit control in critical configuration paths?

They will work, but they just don't transition to low-power mode ever.

-Tero

#46 lore raw

PATCH v9 10/43 clk: ti: add support for TI fixed factor clock

In reply to Tero Kristo

This behaves exactly in similar manner to basic fixed-factor-clock, but adds a few properties on top for handling clock hardware autoidling.

---
 .../bindings/clock/ti/fixed-factor-clock.txt       |   29 +++++++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/fixed-factor.c                      |   65 ++++++++++++++++++++
 3 files changed, 95 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt
 create mode 100644 drivers/clk/ti/fixed-factor.c
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +29 -0
new file mode 100644
index 0000000..60b9e34
@@ -0,0 +1,29 @@
+Binding for TI fixed factor rate clock sources.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,fixed-factor-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- ti,clock-div: fixed divider.
+- ti,clock-mult: fixed multiplier.
+- clocks: parent clock.
+
+Optional properties:
+- ti,autoidle-shift: bit shift of the autoidle enable bit for the clock
+- reg: offset for the autoidle register of this clock
+- ti,invert-autoidle-bit: autoidle is enabled by setting the bit to 0
+- ti,set-rate-parent: clk_set_rate is propagated to parent
+
+Example:
+	clock {
+		compatible = "ti,fixed-factor-clock";
+		clocks = <&parentclk>;
+		#clock-cells = <0>;
+		ti,clock-div = <2>;
+		ti,clock-mult = <1>;
+	};
drivers/clk/ti/Makefile +1 -1
index 640ebf9..f57fc4b 100644
@@ -1,4 +1,4 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   composite.o
+					   fixed-factor.o composite.o
 endif
drivers/clk/ti/fixed-factor.c new file +65 -0

65 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#47 lore raw

PATCH v9 10/43 clk: ti: add support for TI fixed factor clock

Quoted 27 lines · Tero Kristo

This behaves exactly in similar manner to basic fixed-factor-clock, but adds a few properties on top for handling clock hardware autoidling.

---
 .../bindings/clock/ti/fixed-factor-clock.txt       |   29 +++++++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/fixed-factor.c                      |   65 ++++++++++++++++++++
 3 files changed, 95 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt
 create mode 100644 drivers/clk/ti/fixed-factor.c
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +9 -0
new file mode 100644
index 0000000..60b9e34
@@ -0,0 +1,29 @@
+Binding for TI fixed factor rate clock sources.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:

Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt line 19

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +10 -0
+- compatible : shall be "ti,fixed-factor-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- ti,clock-div: fixed divider.
+- ti,clock-mult: fixed multiplier.
+- clocks: parent clock.
+
+Optional properties:
+- ti,autoidle-shift: bit shift of the autoidle enable bit for the clock
+- reg: offset for the autoidle register of this clock
+- ti,invert-autoidle-bit: autoidle is enabled by setting the bit to 0

The above three belong to autoidle stuff I think.. maybe pointing to it's binding will help?

Quoted 75 lines
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +10 -0
+- ti,set-rate-parent: clk_set_rate is propagated to parent
+
+Example:
+	clock {
+		compatible = "ti,fixed-factor-clock";
+		clocks = <&parentclk>;
+		#clock-cells = <0>;
+		ti,clock-div = <2>;
+		ti,clock-mult = <1>;
+	};
drivers/clk/ti/Makefile +1 -1
index 640ebf9..f57fc4b 100644
@@ -1,4 +1,4 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   composite.o
+					   fixed-factor.o composite.o
 endif
drivers/clk/ti/fixed-factor.c new file +49 -0
new file mode 100644
index 0000000..e0549c6
@@ -0,0 +1,65 @@
+/*
+ * TI Fixed Factor Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+/**
+ * of_ti_fixed_factor_clk_setup() - Setup function for TI fixed factor clock
+ */
+static int __init of_ti_fixed_factor_clk_setup(struct device_node *node,
+					       struct regmap *regmap)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	u32 div, mult;
+	u32 flags = 0;
+
+	if (of_property_read_u32(node, "ti,clock-div", &div)) {
+		pr_err("%s Fixed factor clock <%s> must have a clock-div property\n",
+		       __func__, node->name);
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "ti,clock-mult", &mult)) {
+		pr_err("%s Fixed factor clock <%s> must have a clokc-mult property\n",
+		       __func__, node->name);
+		return -EINVAL;
+	}
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))

drivers/clk/ti/fixed-factor.c line 59

Quoted 10 lines
drivers/clk/ti/fixed-factor.c new file +10 -0
+		flags |= CLK_SET_RATE_PARENT;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags,
+					mult, div);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return of_ti_autoidle_setup(node, regmap);

if this fails, remove provider and unregister?

Quoted 7 lines
drivers/clk/ti/fixed-factor.c new file +6 -0
+	}
+
+	return PTR_ERR(clk);
+}
+CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock",
+	       of_ti_fixed_factor_clk_setup);
Signature · 2 lines
Regards,
Nishanth Menon
#48 lore raw

PATCH v9 10/43 clk: ti: add support for TI fixed factor clock

Quoted 121 lines · Nishanth Menon
Quoted 27 lines · Tero Kristo

This behaves exactly in similar manner to basic fixed-factor-clock, but adds a few properties on top for handling clock hardware autoidling.

---
  .../bindings/clock/ti/fixed-factor-clock.txt       |   29 +++++++++
  drivers/clk/ti/Makefile                            |    2 +-
  drivers/clk/ti/fixed-factor.c                      |   65 ++++++++++++++++++++
  3 files changed, 95 insertions(+), 1 deletion(-)

create mode 100644 Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt create mode 100644 drivers/clk/ti/fixed-factor.c

Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +9 -0
new file mode 100644
index 0000000..60b9e34
@@ -0,0 +1,29 @@
+Binding for TI fixed factor rate clock sources.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:

Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt line 19

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +10 -0
+- compatible : shall be "ti,fixed-factor-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- ti,clock-div: fixed divider.
+- ti,clock-mult: fixed multiplier.
+- clocks: parent clock.
+
+Optional properties:
+- ti,autoidle-shift: bit shift of the autoidle enable bit for the clock
+- reg: offset for the autoidle register of this clock
+- ti,invert-autoidle-bit: autoidle is enabled by setting the bit to 0

The above three belong to autoidle stuff I think.. maybe pointing to it's binding will help?

Quoted 79 lines
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt new file +10 -0
+- ti,set-rate-parent: clk_set_rate is propagated to parent
+
+Example:
+	clock {
+		compatible = "ti,fixed-factor-clock";
+		clocks = <&parentclk>;
+		#clock-cells = <0>;
+		ti,clock-div = <2>;
+		ti,clock-mult = <1>;
+	};
drivers/clk/ti/Makefile +1 -1
index 640ebf9..f57fc4b 100644
@@ -1,4 +1,4 @@
  ifneq ($(CONFIG_OF),)
  obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   composite.o
+					   fixed-factor.o composite.o
  endif
drivers/clk/ti/fixed-factor.c new file +53 -0
new file mode 100644
index 0000000..e0549c6
@@ -0,0 +1,65 @@
+/*
+ * TI Fixed Factor Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+/**
+ * of_ti_fixed_factor_clk_setup() - Setup function for TI fixed factor clock
+ */
+static int __init of_ti_fixed_factor_clk_setup(struct device_node *node,
+					       struct regmap *regmap)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	u32 div, mult;
+	u32 flags = 0;
+
+	if (of_property_read_u32(node, "ti,clock-div", &div)) {
+		pr_err("%s Fixed factor clock <%s> must have a clock-div property\n",
+		       __func__, node->name);
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "ti,clock-mult", &mult)) {
+		pr_err("%s Fixed factor clock <%s> must have a clokc-mult property\n",
+		       __func__, node->name);
+		return -EINVAL;
+	}
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		flags |= CLK_SET_RATE_PARENT;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
Quoted 8 lines

drivers/clk/ti/fixed-factor.c line 59

Quoted 6 lines
drivers/clk/ti/fixed-factor.c new file +6 -0
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags,
+					mult, div);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return of_ti_autoidle_setup(node, regmap);

if this fails, remove provider and unregister?

Unregister is not supported currently. I don't think I want to do partial cleanup here, failing autoidle setup is not critical anyway. The system will still boot-up properly, only PM is potentially broken. Can add an error print though.

-Tero

Quoted 10 lines
Quoted 8 lines
drivers/clk/ti/fixed-factor.c new file +6 -0
+	}
+
+	return PTR_ERR(clk);
+}
+CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock",
+	       of_ti_fixed_factor_clk_setup);
#49 lore raw

PATCH v9 11/43 CLK: TI: add support for gate clock

In reply to Tero Kristo

This patch adds support for TI specific gate clocks. These behave as basic gate-clock, but have different ops / hw-ops for controlling the actual gate, for example waiting until the clock is ready. Several sub-types are supported:
- ti,gate-clock: basic gate clock with default ops/hwops
- ti,clkdm-gate-clock: clockdomain level gate control
- ti,dss-gate-clock: gate clock with DSS specific hardware handling
- ti,am35xx-gate-clock: gate clock with AM35xx specific hardware handling
- ti,hsdiv-gate-clock: gate clock with OMAP36xx hardware errata handling

---
 .../devicetree/bindings/clock/ti/gate.txt          |   77 ++++++
 arch/arm/mach-omap2/clock.h                        |   29 ---
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/gate.c                              |  258 ++++++++++++++++++++
 include/linux/clk/ti.h                             |   36 +++
 5 files changed, 372 insertions(+), 30 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/gate.txt
 create mode 100644 drivers/clk/ti/gate.c
Documentation/devicetree/bindings/clock/ti/gate.txt new file +77 -0
new file mode 100644
index 0000000..18c4d86
@@ -0,0 +1,77 @@
+Binding for Texas Instruments gate clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however,
+it supports a number of additional features. If no register
+is provided for this clock, the code assumes that a clockdomain
+will be controlled instead and the corresponding hw-ops for
+that is used.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+[3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt
+
+Required properties:
+- compatible : shall be one of:
+  "ti,gate-clock" - basic gate clock
+  "ti,wait-gate-clock" - gate clock which waits until clock is active before
+			 returning from clk_enable()
+  "ti,dss-gate-clock" - gate clock with DSS specific hardware handling
+  "ti,am35xx-gate-clock" - gate clock with AM35xx specific hardware handling
+  "ti,clkdm-gate-clock" - clockdomain gate clock, which derives its functional
+			  clock directly from a clockdomain, see [3] how
+			  to map clockdomains properly
+  "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling,
+			  required for a hardware errata
+- #clock-cells : from common clock binding; shall be set to 0
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable gate, not needed for
+	ti,clkdm-gate-clock type
+- ti,bit-shift : bit shift for programming the clock gate, not needed for
+		 ti,clkdm-gate-clock type
+
+Optional properties:
+- ti,set-bit-to-disable : inverts default gate programming. Setting the bit
+  gates the clock and clearing the bit ungates the clock.
+
+Examples:
+	mmchs2_fck: mmchs2_fck at 48004a00 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&core_96m_fck>;
+		reg = <0x48004a00 0x4>;
+		ti,bit-shift = <25>;
+	};
+
+	dss1_alwon_fck_3430es2: dss1_alwon_fck_3430es2 at 48004e00 {
+		#clock-cells = <0>;
+		compatible = "ti,dss-gate-clock";
+		clocks = <&dpll4_m4x2_ck>;
+		reg = <0x48004e00 0x4>;
+		ti,bit-shift = <0>;
+	};
+
+	emac_ick: emac_ick at 4800259c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x4800259c 0x4>;
+		ti,bit-shift = <1>;
+	};
+
+	emu_src_ck: emu_src_ck {
+		#clock-cells = <0>;
+		compatible = "ti,clkdm-gate-clock";
+		clocks = <&emu_src_mux_ck>;
+	};
+
+	dpll4_m2x2_ck: dpll4_m2x2_ck at 48004d00 {
+		#clock-cells = <0>;
+		compatible = "ti,hsdiv-gate-clock";
+		clocks = <&dpll4_m2x2_mul_ck>;
+		ti,bit-shift = <0x1b>;
+		reg = <0x48004d00 0x4>;
+		ti,set-bit-to-disable;
+	};
arch/arm/mach-omap2/clock.h +0 -29
index 079536a..08b3360 100644
@@ -179,25 +179,6 @@ struct clksel {
 	const struct clksel_rate *rates;
 };
 
-/*
- * struct clk.flags possibilities
- *
- * XXX document the rest of the clock flags here
- *
- * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
- *     bits share the same register.  This flag allows the
- *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
- *     should be used.  This is a temporary solution - a better approach
- *     would be to associate clock type-specific data with the clock,
- *     similar to the struct dpll_data approach.
- */
-#define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
-#define CLOCK_IDLE_CONTROL	(1 << 1)
-#define CLOCK_NO_IDLE_PARENT	(1 << 2)
-#define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
-#define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
-#define CLOCK_CLKOUTX2		(1 << 5)
-
 struct clk_hw_omap_ops {
 	void			(*find_idlest)(struct clk_hw_omap *oclk,
 					void __iomem **idlest_reg,
@@ -260,9 +241,6 @@ extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
 
 unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
 
-int omap2_dflt_clk_enable(struct clk_hw *hw);
-void omap2_dflt_clk_disable(struct clk_hw *hw);
-int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
 				   void __iomem **other_reg,
 				   u8 *other_bit);
@@ -291,16 +269,12 @@ extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
 extern struct clk dummy_ck;
 
-extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
-extern const struct clk_hw_omap_ops clkhwops_wait;
 extern const struct clk_hw_omap_ops clkhwops_iclk;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
 extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
 extern const struct clk_hw_omap_ops clkhwops_apll54;
 extern const struct clk_hw_omap_ops clkhwops_apll96;
@@ -318,8 +292,5 @@ extern const struct clksel_rate div31_1to31_rates[];
 
 extern int am33xx_clk_init(void);
 
-extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
-extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
-
 extern void omap_clocks_register(struct omap_clk *oclks, int cnt);
 #endif
drivers/clk/ti/Makefile +1 -1
index f57fc4b..7cba389 100644
@@ -1,4 +1,4 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   fixed-factor.o composite.o
+					   fixed-factor.o gate.o composite.o
 endif
drivers/clk/ti/gate.c new file +258 -0

258 lines not on this page · raw message

include/linux/clk/ti.h +36 -0
index 96c9725..29baca8 100644
@@ -129,6 +129,33 @@ struct clk_hw_omap {
 	struct regmap		*regmap;
 };
 
+/*
+ * struct clk_hw_omap.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * ENABLE_REG_32BIT: (OMAP1 only) clock control register must be accessed
+ *     with 32bit ops, by default OMAP1 uses 16bit ops.
+ * CLOCK_IDLE_CONTROL: (OMAP1 only) clock has autoidle support.
+ * CLOCK_NO_IDLE_PARENT: (OMAP1 only) when clock is enabled, its parent
+ *     clock is put to no-idle mode.
+ * ENABLE_ON_INIT: Clock is enabled on init.
+ * INVERT_ENABLE: By default, clock enable bit behavior is '1' enable, '0'
+ *     disable. This inverts the behavior making '0' enable and '1' disable.
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ */
+#define ENABLE_REG_32BIT        (1 << 0)        /* Use 32-bit access */
+#define CLOCK_IDLE_CONTROL      (1 << 1)
+#define CLOCK_NO_IDLE_PARENT    (1 << 2)
+#define ENABLE_ON_INIT          (1 << 3)        /* Enable upon framework init */
+#define INVERT_ENABLE           (1 << 4)        /* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2          (1 << 5)
+
 /* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
 #define DPLL_LOW_POWER_STOP	0x1
 #define DPLL_LOW_POWER_BYPASS	0x5
@@ -180,8 +207,13 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 void omap2_init_clk_clkdm(struct clk_hw *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
+int omap2_clkops_enable_clkdm(struct clk_hw *hw);
+void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
@@ -198,5 +230,9 @@ static inline void of_ti_clk_deny_autoidle_all(void) { }
 
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
 
 #endif
Signature · 1 line
1.7.9.5
#50 lore raw

PATCH v9 11/43 CLK: TI: add support for gate clock

Quoted 31 lines · Tero Kristo

This patch adds support for TI specific gate clocks. These behave as basic gate-clock, but have different ops / hw-ops for controlling the actual gate, for example waiting until the clock is ready. Several sub-types are supported:
- ti,gate-clock: basic gate clock with default ops/hwops
- ti,clkdm-gate-clock: clockdomain level gate control
- ti,dss-gate-clock: gate clock with DSS specific hardware handling
- ti,am35xx-gate-clock: gate clock with AM35xx specific hardware handling
- ti,hsdiv-gate-clock: gate clock with OMAP36xx hardware errata handling

---
 .../devicetree/bindings/clock/ti/gate.txt          |   77 ++++++
 arch/arm/mach-omap2/clock.h                        |   29 ---
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/gate.c                              |  258 ++++++++++++++++++++
 include/linux/clk/ti.h                             |   36 +++
 5 files changed, 372 insertions(+), 30 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/gate.txt
 create mode 100644 drivers/clk/ti/gate.c
Documentation/devicetree/bindings/clock/ti/gate.txt new file +4 -0
new file mode 100644
index 0000000..18c4d86
@@ -0,0 +1,77 @@
+Binding for Texas Instruments gate clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+

Documentation/devicetree/bindings/clock/ti/gate.txt line 14

Quoted 10 lines
Documentation/devicetree/bindings/clock/ti/gate.txt new file +10 -0
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however,
+it supports a number of additional features. If no register
+is provided for this clock, the code assumes that a clockdomain
+will be controlled instead and the corresponding hw-ops for
+that is used.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+[3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt

i think you may want to sequence patch #12 before this if you would like to refer to this.

Documentation/devicetree/bindings/clock/ti/gate.txt line 20

Quoted 6 lines
Documentation/devicetree/bindings/clock/ti/gate.txt new file +6 -0
+
+Required properties:
+- compatible : shall be one of:
+  "ti,gate-clock" - basic gate clock
+  "ti,wait-gate-clock" - gate clock which waits until clock is active before
+			 returning from clk_enable()

an example will be nice for this.

[...]

Quoted 5 lines
drivers/clk/ti/gate.c new file +0 -0
new file mode 100644
index 0000000..1a201f8

[...]

Quoted 26 lines
drivers/clk/ti/gate.c new file +26 -0
+/**
+ * omap36xx_gate_clk_enable_with_hsdiv_restore - enable clocks suffering
+ *         from HSDivider PWRDN problem Implements Errata ID: i556.
+ * @clk: DPLL output struct clk
+ *
+ * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
+ * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
+ * valueafter their respective PWRDN bits are set.  Any dummy write
+ * (Any other value different from the Read value) to the
+ * corresponding CM_CLKSEL register will refresh the dividers.
+ */
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
+{
+	struct clk_divider *parent;
+	struct clk_hw *parent_hw;
+	u32 dummy_v, orig_v;
+	int ret;
+
+	/* Clear PWRDN bit of HSDIVIDER */
+	ret = omap2_dflt_clk_enable(clk);
+
+	/* Parent is the x2 node, get parent of parent for the m2 div */
+	parent_hw = __clk_get_hw(__clk_get_parent(__clk_get_parent(clk->clk)));
+	parent = to_clk_divider(parent_hw);
+
+	/* Restore the dividers */

drivers/clk/ti/gate.c line 84

Quoted 10 lines
drivers/clk/ti/gate.c new file +10 -0
+	if (!ret) {
+		orig_v = __raw_readl(parent->reg);
+		dummy_v = orig_v;
+
+		/* Write any other value different from the Read value */
+		dummy_v ^= (1 << parent->shift);
+		__raw_writel(dummy_v, parent->reg);
+
+		/* Write the original divider */
+		__raw_writel(orig_v, parent->reg);

i think we already did state that these need to be regmap_updatebits..

Quoted 22 lines
drivers/clk/ti/gate.c new file +22 -0
+	}
+
+	return ret;
+}
+
+static int __init _of_ti_gate_clk_setup(struct device_node *node,
+					const struct clk_ops *ops,
+					const struct clk_hw_omap_ops *hw_ops,
+					struct regmap *regmap)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	u32 val;
+
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);
+		return -ENOMEM;
+	}

drivers/clk/ti/gate.c line 116

Quoted 10 lines
drivers/clk/ti/gate.c new file +10 -0
+
+	clk_hw->hw.init = &init;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+
+	if (!of_property_read_u32(node, "reg", &val))
+		clk_hw->enable_reg = (void *)val;

seems reg is a mandatory as per bindings for everything other than ti,clkdm-gate-clock.. no error handling?

drivers/clk/ti/gate.c line 121

Quoted 5 lines
drivers/clk/ti/gate.c new file +5 -0
+
+	clk_hw->regmap = regmap;
+
+	if (!of_property_read_u32(node, "ti,bit-shift", &val))
+		clk_hw->enable_bit = val;

Again -> bindings state this is mandatory for non ti,clkdm-gate-clock clocks. no error handling?

drivers/clk/ti/gate.c line 126

Quoted 5 lines
drivers/clk/ti/gate.c new file +5 -0
+	clk_hw->ops = hw_ops;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;

error checks for parent clk which seems to be mandatory?

Quoted 4 lines
drivers/clk/ti/gate.c new file +4 -0
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		init.flags |= CLK_SET_RATE_PARENT;
+

drivers/clk/ti/gate.c line 140

Quoted 10 lines
drivers/clk/ti/gate.c new file +10 -0
+	if (of_property_read_bool(node, "ti,set-bit-to-disable"))
+		clk_hw->flags |= INVERT_ENABLE;
+
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return 0;
+	}
+

free(clk_hw)?

Quoted 3 lines
drivers/clk/ti/gate.c new file +3 -0
+	return PTR_ERR(clk);
+}
+
Signature · 2 lines
Regards,
Nishanth Menon
#51 lore raw

PATCH v9 11/43 CLK: TI: add support for gate clock

Quoted 37 lines · Nishanth Menon
Quoted 36 lines · Tero Kristo

This patch adds support for TI specific gate clocks. These behave as basic gate-clock, but have different ops / hw-ops for controlling the actual gate, for example waiting until the clock is ready. Several sub-types are supported:
- ti,gate-clock: basic gate clock with default ops/hwops
- ti,clkdm-gate-clock: clockdomain level gate control
- ti,dss-gate-clock: gate clock with DSS specific hardware handling
- ti,am35xx-gate-clock: gate clock with AM35xx specific hardware handling
- ti,hsdiv-gate-clock: gate clock with OMAP36xx hardware errata handling

---
  .../devicetree/bindings/clock/ti/gate.txt          |   77 ++++++
  arch/arm/mach-omap2/clock.h                        |   29 ---
  drivers/clk/ti/Makefile                            |    2 +-
  drivers/clk/ti/gate.c                              |  258 ++++++++++++++++++++
  include/linux/clk/ti.h                             |   36 +++
  5 files changed, 372 insertions(+), 30 deletions(-)

create mode 100644 Documentation/devicetree/bindings/clock/ti/gate.txt create mode 100644 drivers/clk/ti/gate.c

Documentation/devicetree/bindings/clock/ti/gate.txt new file +9 -0
new file mode 100644
index 0000000..18c4d86
@@ -0,0 +1,77 @@
+Binding for Texas Instruments gate clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however,
+it supports a number of additional features. If no register
+is provided for this clock, the code assumes that a clockdomain
+will be controlled instead and the corresponding hw-ops for
Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/gate.txt line 14

Quoted 5 lines
Documentation/devicetree/bindings/clock/ti/gate.txt new file +5 -0
+that is used.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+[3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt

i think you may want to sequence patch #12 before this if you would like to refer to this.

Yea, can re-order based on this. Compiler doesn't really catch issues like this. :)

Quoted 8 lines

Documentation/devicetree/bindings/clock/ti/gate.txt line 20

Quoted 7 lines
Documentation/devicetree/bindings/clock/ti/gate.txt new file +6 -0
+
+Required properties:
+- compatible : shall be one of:
+  "ti,gate-clock" - basic gate clock
+  "ti,wait-gate-clock" - gate clock which waits until clock is active before
+			 returning from clk_enable()

an example will be nice for this.

Will add.

Quoted 39 lines

[...]

Quoted 5 lines
drivers/clk/ti/gate.c new file +0 -0
new file mode 100644
index 0000000..1a201f8

[...]

Quoted 30 lines
drivers/clk/ti/gate.c new file +30 -0
+/**
+ * omap36xx_gate_clk_enable_with_hsdiv_restore - enable clocks suffering
+ *         from HSDivider PWRDN problem Implements Errata ID: i556.
+ * @clk: DPLL output struct clk
+ *
+ * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
+ * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
+ * valueafter their respective PWRDN bits are set.  Any dummy write
+ * (Any other value different from the Read value) to the
+ * corresponding CM_CLKSEL register will refresh the dividers.
+ */
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
+{
+	struct clk_divider *parent;
+	struct clk_hw *parent_hw;
+	u32 dummy_v, orig_v;
+	int ret;
+
+	/* Clear PWRDN bit of HSDIVIDER */
+	ret = omap2_dflt_clk_enable(clk);
+
+	/* Parent is the x2 node, get parent of parent for the m2 div */
+	parent_hw = __clk_get_hw(__clk_get_parent(__clk_get_parent(clk->clk)));
+	parent = to_clk_divider(parent_hw);
+
+	/* Restore the dividers */
+	if (!ret) {
+		orig_v = __raw_readl(parent->reg);
+		dummy_v = orig_v;
+
Quoted 8 lines

drivers/clk/ti/gate.c line 84

Quoted 6 lines
drivers/clk/ti/gate.c new file +6 -0
+		/* Write any other value different from the Read value */
+		dummy_v ^= (1 << parent->shift);
+		__raw_writel(dummy_v, parent->reg);
+
+		/* Write the original divider */
+		__raw_writel(orig_v, parent->reg);

i think we already did state that these need to be regmap_updatebits..

Yea.

Quoted 28 lines
Quoted 28 lines
drivers/clk/ti/gate.c new file +27 -0
+	}
+
+	return ret;
+}
+
+static int __init _of_ti_gate_clk_setup(struct device_node *node,
+					const struct clk_ops *ops,
+					const struct clk_hw_omap_ops *hw_ops,
+					struct regmap *regmap)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	u32 val;
+
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw) {
+		pr_err("%s: could not allocate clk_hw_omap\n", __func__);
+		return -ENOMEM;
+	}
+
+	clk_hw->hw.init = &init;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
Quoted 8 lines

drivers/clk/ti/gate.c line 116

Quoted 5 lines
drivers/clk/ti/gate.c new file +5 -0
+	init.name = clk_name;
+	init.ops = ops;
+
+	if (!of_property_read_u32(node, "reg", &val))
+		clk_hw->enable_reg = (void *)val;

seems reg is a mandatory as per bindings for everything other than ti,clkdm-gate-clock.. no error handling?

Will add.

Quoted 9 lines

drivers/clk/ti/gate.c line 121

Quoted 6 lines
drivers/clk/ti/gate.c new file +5 -0
+
+	clk_hw->regmap = regmap;
+
+	if (!of_property_read_u32(node, "ti,bit-shift", &val))
+		clk_hw->enable_bit = val;

Again -> bindings state this is mandatory for non ti,clkdm-gate-clock clocks. no error handling?

Will add.

Quoted 8 lines

drivers/clk/ti/gate.c line 126

Quoted 6 lines
drivers/clk/ti/gate.c new file +5 -0
+	clk_hw->ops = hw_ops;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;

error checks for parent clk which seems to be mandatory?

Will add.

Quoted 17 lines
Quoted 5 lines
drivers/clk/ti/gate.c new file +4 -0
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		init.flags |= CLK_SET_RATE_PARENT;
+

drivers/clk/ti/gate.c line 140

Quoted 10 lines
drivers/clk/ti/gate.c new file +10 -0
+	if (of_property_read_bool(node, "ti,set-bit-to-disable"))
+		clk_hw->flags |= INVERT_ENABLE;
+
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return 0;
+	}
+

free(clk_hw)?

Hmm yea, missing.

Quoted 7 lines
Quoted 4 lines
drivers/clk/ti/gate.c new file +3 -0
+	return PTR_ERR(clk);
+}
+
#52 lore raw

PATCH v9 12/43 CLK: TI: add support for clockdomain binding

In reply to Tero Kristo

Some OMAP clocks require knowledge about their parent clockdomain for book keeping purposes. This patch creates a new DT binding for TI clockdomains, which act as a collection of device clocks.

---
 .../devicetree/bindings/clock/ti/clockdomain.txt   |   21 +++++++
 arch/arm/mach-omap2/clock.h                        |    1 -
 drivers/clk/ti/Makefile                            |    3 +-
 drivers/clk/ti/clockdomain.c                       |   58 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    3 +
 5 files changed, 84 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/clockdomain.txt
 create mode 100644 drivers/clk/ti/clockdomain.c
Documentation/devicetree/bindings/clock/ti/clockdomain.txt new file +21 -0
new file mode 100644
index 0000000..45e6f7c
@@ -0,0 +1,21 @@
+Binding for Texas Instruments clockdomain.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. Every clock on
+TI SoC belongs to one clockdomain, but software only needs this
+information for specific clocks which require their parent
+clockdomain to be controlled when the clock is enabled/disabled.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,clockdomain"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of clocks within this domain
+
+Examples:
+	dss_clkdm: dss_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
+	};
arch/arm/mach-omap2/clock.h +0 -1
index 08b3360..8be0279 100644
@@ -38,7 +38,6 @@ struct omap_clk {
 	}
 
 struct clockdomain;
-#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
 
 #define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)	\
 	static struct clk _name = {				\
drivers/clk/ti/Makefile +2 -1
index 7cba389..67056fb 100644
@@ -1,4 +1,5 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   fixed-factor.o gate.o composite.o
+					   fixed-factor.o gate.o clockdomain.o \
+					   composite.o
 endif
drivers/clk/ti/clockdomain.c new file +58 -0

58 lines not on this page · raw message

include/linux/clk/ti.h +3 -0
index 29baca8..70446fb 100644
@@ -190,6 +190,8 @@ struct ti_dt_clk {
 		.node_name = name,	\
 	}
 
+#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
+
 void omap2_init_clk_hw_omap_clocks(struct clk *clk);
 int omap3_noncore_dpll_enable(struct clk_hw *hw);
 void omap3_noncore_dpll_disable(struct clk_hw *hw);
@@ -217,6 +219,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
+void ti_dt_clockdomains_setup(void);
 int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
 int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
Signature · 1 line
1.7.9.5
#53 lore raw

PATCH v9 12/43 CLK: TI: add support for clockdomain binding

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 39 lines
drivers/clk/ti/clockdomain.c new file +33 -0
new file mode 100644
index 0000000..1b3099e
@@ -0,0 +1,58 @@
+/*
+ * OMAP clockdomain support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+static void __init of_ti_clockdomain_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_hw *clk_hw;
+	const char *clkdm_name = node->name;
+	int i;
+	int num_clks;
+
+	num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+

drivers/clk/ti/clockdomain.c line 43

Quoted 10 lines
drivers/clk/ti/clockdomain.c new file +10 -0
+	for (i = 0; i < num_clks; i++) {
+		clk = of_clk_get(node, i);
+		if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+			pr_warn("%s: can't setup clkdm for basic clk %s\n",
+				__func__, __clk_get_name(clk));
+			continue;
+		}
+		clk_hw = __clk_get_hw(clk);
+		to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name;
+		omap2_init_clk_clkdm(clk_hw);

eventually, this can disappear ofcourse.. and that will pave way to remove the clock domain data to dts as well.. but yes, we have to find a proper home for this away from current location..

drivers/clk/ti/clockdomain.c line 52

Quoted 9 lines
drivers/clk/ti/clockdomain.c new file +9 -0
+	}
+}
+
+static struct of_device_id ti_clkdm_match_table[] __initdata = {
+	{ .compatible = "ti,clockdomain" },
+	{ }
+};
+
+void __init ti_dt_clockdomains_setup(void)

since we are using of_clk_get, it will be good to provide documentation w.r.t when the call is expected to be invoked.

Quoted 6 lines
drivers/clk/ti/clockdomain.c new file +6 -0
+{
+	struct device_node *np;
+	for_each_matching_node(np, ti_clkdm_match_table) {
+		of_ti_clockdomain_setup(np);
+	}
+}
Signature · 2 lines
Regards,
Nishanth Menon
#54 lore raw

PATCH v9 12/43 CLK: TI: add support for clockdomain binding

Quoted 56 lines · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 39 lines
drivers/clk/ti/clockdomain.c new file +33 -0
new file mode 100644
index 0000000..1b3099e
@@ -0,0 +1,58 @@
+/*
+ * OMAP clockdomain support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <[email protected]>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+static void __init of_ti_clockdomain_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_hw *clk_hw;
+	const char *clkdm_name = node->name;
+	int i;
+	int num_clks;
+
+	num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+

drivers/clk/ti/clockdomain.c line 43

Quoted 10 lines
drivers/clk/ti/clockdomain.c new file +10 -0
+	for (i = 0; i < num_clks; i++) {
+		clk = of_clk_get(node, i);
+		if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+			pr_warn("%s: can't setup clkdm for basic clk %s\n",
+				__func__, __clk_get_name(clk));
+			continue;
+		}
+		clk_hw = __clk_get_hw(clk);
+		to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name;
+		omap2_init_clk_clkdm(clk_hw);

eventually, this can disappear ofcourse.. and that will pave way to remove the clock domain data to dts as well.. but yes, we have to find a proper home for this away from current location..

Quoted 12 lines

drivers/clk/ti/clockdomain.c line 52

Quoted 9 lines
drivers/clk/ti/clockdomain.c new file +9 -0
+	}
+}
+
+static struct of_device_id ti_clkdm_match_table[] __initdata = {
+	{ .compatible = "ti,clockdomain" },
+	{ }
+};
+
+void __init ti_dt_clockdomains_setup(void)

since we are using of_clk_get, it will be good to provide documentation w.r.t when the call is expected to be invoked.

I'll add some kerneldoc here.

-Tero

Quoted 10 lines
Quoted 7 lines
drivers/clk/ti/clockdomain.c new file +6 -0
+{
+	struct device_node *np;
+	for_each_matching_node(np, ti_clkdm_match_table) {
+		of_ti_clockdomain_setup(np);
+	}
+}
#55 lore raw

PATCH v9 13/43 clk: ti: add support for basic mux clock

In reply to Tero Kristo

ti,mux-clock provides now a binding for basic mux support. This is just using the basic clock type.

---
 Documentation/devicetree/bindings/clock/ti/mux.txt |   67 ++++++++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/mux.c                               |  129 ++++++++++++++++++++
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/mux.txt
 create mode 100644 drivers/clk/ti/mux.c
Documentation/devicetree/bindings/clock/ti/mux.txt new file +67 -0
new file mode 100644
index 0000000..9a2fd8e
@@ -0,0 +1,67 @@
+Binding for TI mux clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped multiplexer with multiple input clock signals or
+parents, one of which can be selected as output.  This clock does not
+gate or adjust the parent rate via a divider or multiplier.
+
+By default the "clocks" property lists the parents in the same order
+as they are programmed into the regster.  E.g:
+
+	clocks = <&foo_clock>, <&bar_clock>, <&baz_clock>;
+
+results in programming the register as follows:
+
+register value		selected parent clock
+0			foo_clock
+1			bar_clock
+2			baz_clock
+
+Some clock controller IPs do not allow a value of zero to be programmed
+into the register, instead indexing begins at 1.  The optional property
+"index-starts-at-one" modified the scheme as follows:
+
+register value		selected clock parent
+1			foo_clock
+2			bar_clock
+3			baz_clock
+
+The binding must provide the register to control the mux. Optionally
+the number of bits to shift the control field in the register can be
+supplied. If the shift value is missing it is the same as supplying
+a zero shift.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,mux-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks
+- reg : register offset for register controlling adjustable mux
+
+Optional properties:
+- ti,bit-shift : number of bits to shift the bit-mask, defaults to
+  0 if not present
+- ti,index-starts-at-one : valid input select programming starts at 1, not
+  zero
+- ti,set-rate-parent : clk_set_rate is propagated to parent clock
+
+Examples:
+
+sys_clkin_ck: sys_clkin_ck at 4a306110 {
+	#clock-cells = <0>;
+	compatible = "ti,mux-clock";
+	clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
+	reg = <0x4a306110 0x4>;
+	ti,index-starts-at-one;
+};
+
+abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck at 4a306108 {
+	#clock-cells = <0>;
+	compatible = "ti,mux-clock";
+	clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+	ti,bit-shift = <24>;
+	reg = <0x4a306108 0x4>;
+};
drivers/clk/ti/Makefile +1 -1
index 67056fb..ef61d39 100644
@@ -1,5 +1,5 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
-					   composite.o
+					   composite.o mux.o
 endif
drivers/clk/ti/mux.c new file +129 -0

129 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#56 lore raw

PATCH v9 13/43 clk: ti: add support for basic mux clock

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 5 lines
drivers/clk/ti/mux.c new file +0 -0
new file mode 100644
index 0000000..9c5259a

[...]

drivers/clk/ti/mux.c line 28

Quoted 4 lines
drivers/clk/ti/mux.c new file +4 -0
+/**
+ * of_mux_clk_setup() - Setup function for simple mux rate clock
+ */
+static int of_mux_clk_setup(struct device_node *node, struct regmap *regmap)
$ ./scripts/kernel-doc drivers/clk/ti/mux.c >/dev/null
Warning(drivers/clk/ti/mux.c:29): No description found for parameter
'node'
Warning(drivers/clk/ti/mux.c:29): No description found for parameter
'regmap'

I suggest in the next rev we do a verification if we have kernel doc errors as well..

Quoted 12 lines
drivers/clk/ti/mux.c new file +12 -0
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	int num_parents;
+	const char **parent_names;
+	int i;
+	u8 clk_mux_flags = 0;
+	u32 mask = 0;
+	u32 shift = 0;
+	u32 flags = 0;
+	u32 val;

drivers/clk/ti/mux.c line 50

Quoted 10 lines
drivers/clk/ti/mux.c new file +10 -0
+
+	num_parents = of_clk_get_parent_count(node);
+	if (num_parents < 1) {
+		pr_err("%s: mux-clock %s must have parent(s)\n",
+		       __func__, node->name);
+		return -EINVAL;
+	}
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names) {
+		pr_err("%s: memory alloc failed\n", __func__);

as discussed, could be dropped.

drivers/clk/ti/mux.c line 57

Quoted 7 lines
drivers/clk/ti/mux.c new file +7 -0
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	of_property_read_u32(node, "reg", &val);

is'nt this mandatory? error check?

drivers/clk/ti/mux.c line 62

Quoted 5 lines
drivers/clk/ti/mux.c new file +5 -0
+	reg = (void *)val;
+
+	if (of_property_read_u32(node, "ti,bit-shift", &shift)) {
+		pr_debug("%s: bit-shift property defaults to 0x%x for %s\n",
+			 __func__, shift, node->name);

why a debug if this is optional?

drivers/clk/ti/mux.c line 74

Quoted 12 lines
drivers/clk/ti/mux.c new file +12 -0
+	}
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		clk_mux_flags |= CLK_MUX_INDEX_ONE;
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		flags |= CLK_SET_RATE_PARENT;
+
+	/* Generate bit-mask based on parent info */
+	mask = num_parents;
+	if (!(clk_mux_flags & CLK_MUX_INDEX_ONE))
+		mask--;

we are assuming there wont be holes in the map (like reserved mux option?)

drivers/clk/ti/mux.c line 87

Quoted 13 lines
drivers/clk/ti/mux.c new file +13 -0
+
+	mask = (1 << fls(mask)) - 1;
+
+	clk = clk_register_mux_table_regmap(NULL, clk_name, parent_names,
+					    num_parents, flags, reg, regmap,
+					    shift, mask, clk_mux_flags, NULL,
+					    NULL);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return 0;
+	}
+

kfree(parent_names)?

Quoted 7 lines
drivers/clk/ti/mux.c new file +7 -0
+	return PTR_ERR(clk);
+}
+CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup);
+
+static int __init of_ti_composite_mux_clk_setup(struct device_node *node,
+						struct regmap *regmap)
+{

drivers/clk/ti/mux.c line 104

Quoted 10 lines
drivers/clk/ti/mux.c new file +10 -0
+	struct clk_mux *mux;
+	int num_parents;
+	int ret;
+	u32 val;
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return -ENOMEM;
+
+	of_property_read_u32(node, "reg", &val);

is'nt this mandatory? error check?

drivers/clk/ti/mux.c line 116

Quoted 12 lines
drivers/clk/ti/mux.c new file +12 -0
+
+	mux->reg = (void *)val;
+	mux->regmap = regmap;
+
+	if (of_property_read_u32(node, "ti,bit-shift", &val)) {
+		pr_debug("%s: no bit-shift for %s, default=0\n",
+			 __func__, node->name);
+		val = 0;
+	}
+	mux->shift = val;
+
+	num_parents = of_clk_get_parent_count(node);

mandatory parameter without check?

ti,index-starts-at-one, ti,set-rate-parent
these seem not supported here even though the bindings dont tell us that.

Quoted 14 lines
drivers/clk/ti/mux.c new file +13 -0
+
+	mux->mask = num_parents - 1;
+	mux->mask = (1 << fls(mux->mask)) - 1;
+
+	ret = ti_clk_add_component(node, &mux->hw, CLK_COMPONENT_TYPE_MUX);
+	if (!ret)
+		return 0;
+
+	kfree(mux);
+	return -ret;
+}
+CLK_OF_DECLARE(ti_composite_mux_clk_setup, "ti,composite-mux-clock",
+	       of_ti_composite_mux_clk_setup);
Signature · 2 lines
Regards,
Nishanth Menon
#57 lore raw

PATCH v9 13/43 clk: ti: add support for basic mux clock

Quoted 38 lines · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 5 lines
drivers/clk/ti/mux.c new file +0 -0
new file mode 100644
index 0000000..9c5259a

[...]

drivers/clk/ti/mux.c line 28

Quoted 4 lines
drivers/clk/ti/mux.c new file +4 -0
+/**
+ * of_mux_clk_setup() - Setup function for simple mux rate clock
+ */
+static int of_mux_clk_setup(struct device_node *node, struct regmap *regmap)
$ ./scripts/kernel-doc drivers/clk/ti/mux.c >/dev/null
Warning(drivers/clk/ti/mux.c:29): No description found for parameter
'node'
Warning(drivers/clk/ti/mux.c:29): No description found for parameter
'regmap'

I suggest in the next rev we do a verification if we have kernel doc errors as well..

Quoted 16 lines
drivers/clk/ti/mux.c new file +16 -0
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	int num_parents;
+	const char **parent_names;
+	int i;
+	u8 clk_mux_flags = 0;
+	u32 mask = 0;
+	u32 shift = 0;
+	u32 flags = 0;
+	u32 val;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (num_parents < 1) {
+		pr_err("%s: mux-clock %s must have parent(s)\n",
Quoted 8 lines

drivers/clk/ti/mux.c line 50

Quoted 6 lines
drivers/clk/ti/mux.c new file +6 -0
+		       __func__, node->name);
+		return -EINVAL;
+	}
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names) {
+		pr_err("%s: memory alloc failed\n", __func__);

as discussed, could be dropped.

Yep.

Quoted 10 lines

drivers/clk/ti/mux.c line 57

Quoted 8 lines
drivers/clk/ti/mux.c new file +7 -0
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	of_property_read_u32(node, "reg", &val);

is'nt this mandatory? error check?

Will add.

Quoted 8 lines

drivers/clk/ti/mux.c line 62

Quoted 6 lines
drivers/clk/ti/mux.c new file +5 -0
+	reg = (void *)val;
+
+	if (of_property_read_u32(node, "ti,bit-shift", &shift)) {
+		pr_debug("%s: bit-shift property defaults to 0x%x for %s\n",
+			 __func__, shift, node->name);

why a debug if this is optional?

Well, it might be good for debugging if someone forgets the shift when he was supposed to add one. I could also make this a required property, but this will increase the dtb size slightly, there are quite a few mux-clocks around with 0 bit-shift atm.

Quoted 15 lines

drivers/clk/ti/mux.c line 74

Quoted 13 lines
drivers/clk/ti/mux.c new file +12 -0
+	}
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		clk_mux_flags |= CLK_MUX_INDEX_ONE;
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		flags |= CLK_SET_RATE_PARENT;
+
+	/* Generate bit-mask based on parent info */
+	mask = num_parents;
+	if (!(clk_mux_flags & CLK_MUX_INDEX_ONE))
+		mask--;

we are assuming there wont be holes in the map (like reserved mux option?)

Yes. Currently this is the case at least, but we can add more beef to the binding to handle holes if this comes up in future. Or alternatively just add dummy-ck as mux parent and cover the holes that way.

Quoted 16 lines
Quoted 4 lines
drivers/clk/ti/mux.c new file +3 -0
+
+	mask = (1 << fls(mask)) - 1;
+

drivers/clk/ti/mux.c line 87

Quoted 10 lines
drivers/clk/ti/mux.c new file +10 -0
+	clk = clk_register_mux_table_regmap(NULL, clk_name, parent_names,
+					    num_parents, flags, reg, regmap,
+					    shift, mask, clk_mux_flags, NULL,
+					    NULL);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return 0;
+	}
+

kfree(parent_names)?

Yea, will add.

Quoted 11 lines
Quoted 11 lines
drivers/clk/ti/mux.c new file +10 -0
+	return PTR_ERR(clk);
+}
+CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup);
+
+static int __init of_ti_composite_mux_clk_setup(struct device_node *node,
+						struct regmap *regmap)
+{
+	struct clk_mux *mux;
+	int num_parents;
+	int ret;
Quoted 8 lines

drivers/clk/ti/mux.c line 104

Quoted 7 lines
drivers/clk/ti/mux.c new file +7 -0
+	u32 val;
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return -ENOMEM;
+
+	of_property_read_u32(node, "reg", &val);

is'nt this mandatory? error check?

Will add.

Quoted 15 lines

drivers/clk/ti/mux.c line 116

Quoted 13 lines
drivers/clk/ti/mux.c new file +12 -0
+
+	mux->reg = (void *)val;
+	mux->regmap = regmap;
+
+	if (of_property_read_u32(node, "ti,bit-shift", &val)) {
+		pr_debug("%s: no bit-shift for %s, default=0\n",
+			 __func__, node->name);
+		val = 0;
+	}
+	mux->shift = val;
+
+	num_parents = of_clk_get_parent_count(node);

mandatory parameter without check?

Will add.

Quoted 3 lines

ti,index-starts-at-one, ti,set-rate-parent
these seem not supported here even though the bindings dont tell us that.

Yeah, composite-mux-clock documentation is somewhat broken at the moment, will look at that.

Quoted 17 lines
Quoted 15 lines
drivers/clk/ti/mux.c new file +13 -0
+
+	mux->mask = num_parents - 1;
+	mux->mask = (1 << fls(mux->mask)) - 1;
+
+	ret = ti_clk_add_component(node, &mux->hw, CLK_COMPONENT_TYPE_MUX);
+	if (!ret)
+		return 0;
+
+	kfree(mux);
+	return -ret;
+}
+CLK_OF_DECLARE(ti_composite_mux_clk_setup, "ti,composite-mux-clock",
+	       of_ti_composite_mux_clk_setup);
#58 lore raw

PATCH v9 14/43 CLK: TI: add omap4 clock init file

In reply to Tero Kristo

clk-44xx.c now contains the clock init functionality for omap4, including DT clock registration and adding of static clkdev entries.

---
 arch/arm/mach-omap2/clock.h |    1 -
 drivers/clk/ti/Makefile     |    1 +
 drivers/clk/ti/clk-44xx.c   |  328 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h      |    3 +
 4 files changed, 332 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/clk-44xx.c
arch/arm/mach-omap2/clock.h +0 -1
index 8be0279..2a52da2 100644
@@ -247,7 +247,6 @@ void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
 				void __iomem **idlest_reg,
 				u8 *idlest_bit, u8 *idlest_val);
 int omap2_clk_enable_autoidle_all(void);
-int omap2_clk_disable_autoidle_all(void);
 void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
drivers/clk/ti/Makefile +1 -0
index ef61d39..381f1f8 100644
@@ -2,4 +2,5 @@ ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
 					   composite.o mux.o
+obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
 endif
drivers/clk/ti/clk-44xx.c new file +328 -0

328 lines not on this page · raw message

include/linux/clk/ti.h +3 -0
index 70446fb..81e1307 100644
@@ -211,6 +211,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
+int omap2_clk_disable_autoidle_all(void);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 int omap2_dflt_clk_enable(struct clk_hw *hw);
@@ -223,6 +224,8 @@ void ti_dt_clockdomains_setup(void);
 int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
 int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
+int omap4xxx_dt_clk_init(void);
+
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
 void of_ti_clk_deny_autoidle_all(void);
Signature · 1 line
1.7.9.5
#59 lore raw

PATCH v9 15/43 CLK: TI: add omap5 clock init file

In reply to Tero Kristo

clk-54xx.c now contains the clock init functionality for omap5, including DT clock registration and adding of static clkdev entries.

---
 arch/arm/mach-omap2/io.c  |    1 +
 drivers/clk/ti/Makefile   |    1 +
 drivers/clk/ti/clk-54xx.c |  239 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h    |    1 +
 4 files changed, 242 insertions(+)
 create mode 100644 drivers/clk/ti/clk-54xx.c
arch/arm/mach-omap2/io.c +1 -0
index ff2113c..e360ddf 100644
@@ -650,6 +650,7 @@ void __init omap5_init_early(void)
 	omap54xx_clockdomains_init();
 	omap54xx_hwmod_init();
 	omap_hwmod_init_postsetup();
+	omap_clk_init = omap5xxx_dt_clk_init;
 }
 #endif
 
drivers/clk/ti/Makefile +1 -0
index 381f1f8..935e5d2 100644
@@ -3,4 +3,5 @@ obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
 					   composite.o mux.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
+obj-$(CONFIG_SOC_OMAP5)			+= clk-54xx.o
 endif
drivers/clk/ti/clk-54xx.c new file +239 -0

239 lines not on this page · raw message

include/linux/clk/ti.h +1 -0
index 81e1307..55bcc83 100644
@@ -225,6 +225,7 @@ int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
 int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
 int omap4xxx_dt_clk_init(void);
+int omap5xxx_dt_clk_init(void);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
Signature · 1 line
1.7.9.5
#60 lore raw

PATCH v9 16/43 CLK: TI: omap5: Initialize USB_DPLL at boot

In reply to Tero Kristo

From: Roger Quadros <[email protected]>

USB_DPLL must be initialized and locked at boot so that USB modules can work.

---
 drivers/clk/ti/clk-54xx.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
drivers/clk/ti/clk-54xx.c +17 -1
index c876e6e..0ef9f58 100644
@@ -19,6 +19,12 @@
 
 #define OMAP5_DPLL_ABE_DEFFREQ				98304000
 
+/*
+ * OMAP543x TRM, section "3.6.3.9.5 DPLL_USB Preferred Settings"
+ * states it must be at 960MHz
+ */
+#define OMAP5_DPLL_USB_DEFFREQ				960000000
+
 static struct ti_dt_clk omap54xx_clks[] = {
 	DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
 	DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"),
@@ -220,7 +226,7 @@ static struct ti_dt_clk omap54xx_clks[] = {
 int __init omap5xxx_dt_clk_init(void)
 {
 	int rc;
-	struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck;
+	struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
 
 	ti_dt_clocks_register(omap54xx_clks);
 
@@ -235,5 +241,15 @@ int __init omap5xxx_dt_clk_init(void)
 	if (rc)
 		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
+	usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
+	rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ);
+	if (rc)
+		pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+	usb_dpll = clk_get_sys(NULL, "dpll_usb_m2_ck");
+	rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ/2);
+	if (rc)
+		pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__);
+
 	return 0;
 }
Signature · 1 line
1.7.9.5
#61 lore raw

PATCH v9 17/43 CLK: TI: DRA7: Add APLL support

In reply to Tero Kristo

From: J Keerthy <[email protected]>

The patch adds support for DRA7 PCIe APLL. The APLL sources the optional functional clocks for PCIe module.

APLL stands for Analog PLL. This is different when comapred with DPLL meaning Digital PLL, the phase detection is done using an analog circuit.

---
 .../devicetree/bindings/clock/ti/apll.txt          |   31 +++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/apll.c                              |  239 ++++++++++++++++++++
 3 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/apll.txt
 create mode 100644 drivers/clk/ti/apll.c
Documentation/devicetree/bindings/clock/ti/apll.txt new file +31 -0
new file mode 100644
index 0000000..7faf5a6
@@ -0,0 +1,31 @@
+Binding for Texas Instruments APLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped APLL with usually two selectable input clocks
+(reference clock and bypass clock), with analog phase locked
+loop logic for multiplying the input clock to a desired output
+clock. This clock also typically supports different operation
+modes (locked, low power stop etc.) APLL mostly behaves like
+a subtype of a DPLL [2], although a simplified one at that.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
+
+Required properties:
+- compatible : shall be "ti,dra7-apll-clock"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
+- reg : address and length of the register set for controlling the APLL.
+  It contains the information of registers in the following order:
+	"control" - contains the control register base address
+	"idlest" - contains the idlest register base address
+
+Examples:
+	apll_pcie_ck: apll_pcie_ck at 4a008200 {
+		#clock-cells = <0>;
+		clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
+		reg = <0x4a00821c 0x4>, <0x4a008220 0x4>;
+		compatible = "ti,dra7-apll-clock";
+	};
drivers/clk/ti/Makefile +1 -1
index 935e5d2..3d71e1e 100644
@@ -1,7 +1,7 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
-					   composite.o mux.o
+					   composite.o mux.o apll.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= clk-54xx.o
 endif
drivers/clk/ti/apll.c new file +239 -0

239 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#62 lore raw

PATCH v9 18/43 CLK: TI: add dra7 clock init file

In reply to Tero Kristo

clk-7xx.c now contains the clock init functionality for dra7, including DT clock registration and adding of static clkdev entries.

---
 drivers/clk/ti/Makefile  |    1 +
 drivers/clk/ti/clk-7xx.c |  332 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h   |    1 +
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/clk/ti/clk-7xx.c
drivers/clk/ti/Makefile +1 -0
index 3d71e1e..f8ae4b5 100644
@@ -4,4 +4,5 @@ obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   composite.o mux.o apll.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= clk-54xx.o
+obj-$(CONFIG_SOC_DRA7XX)		+= clk-7xx.o
 endif
drivers/clk/ti/clk-7xx.c new file +332 -0

332 lines not on this page · raw message

include/linux/clk/ti.h +1 -0
index 55bcc83..c4a8824 100644
@@ -226,6 +226,7 @@ int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
 int omap4xxx_dt_clk_init(void);
 int omap5xxx_dt_clk_init(void);
+int dra7xx_dt_clk_init(void);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
Signature · 1 line
1.7.9.5
#63 lore raw

PATCH v9 19/43 CLK: TI: add am33xx clock init file

In reply to Tero Kristo

clk-33xx.c now contains the clock init functionality for am33xx, including DT clock registration and adding of static clkdev entries.

This patch also moves the omap2_clk_enable_init_clocks declaration to the driver include, as this is needed by the am33xx clock init code.

---
 arch/arm/mach-omap2/clock.h |    1 -
 drivers/clk/ti/Makefile     |    1 +
 drivers/clk/ti/clk-33xx.c   |  161 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h      |    2 +
 4 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/clk-33xx.c
arch/arm/mach-omap2/clock.h +0 -1
index 2a52da2..b33f1e8 100644
@@ -247,7 +247,6 @@ void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
 				void __iomem **idlest_reg,
 				u8 *idlest_bit, u8 *idlest_val);
 int omap2_clk_enable_autoidle_all(void);
-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 			       const char *core_ck_name,
drivers/clk/ti/Makefile +1 -0
index f8ae4b5..7eb6f2b 100644
@@ -2,6 +2,7 @@ ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
 					   composite.o mux.o apll.o
+obj-$(CONFIG_SOC_AM33XX)		+= clk-33xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= clk-54xx.o
 obj-$(CONFIG_SOC_DRA7XX)		+= clk-7xx.o
drivers/clk/ti/clk-33xx.c new file +161 -0

161 lines not on this page · raw message

include/linux/clk/ti.h +2 -0
index c4a8824..de0cffc 100644
@@ -212,6 +212,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 int omap2_dflt_clk_enable(struct clk_hw *hw);
@@ -227,6 +228,7 @@ int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 int omap4xxx_dt_clk_init(void);
 int omap5xxx_dt_clk_init(void);
 int dra7xx_dt_clk_init(void);
+int am33xx_dt_clk_init(void);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
Signature · 1 line
1.7.9.5
#64 lore raw

PATCH v9 20/43 CLK: TI: add interface clock support for OMAP3

In reply to Tero Kristo

OMAP3 has interface clocks in addition to functional clocks, which require special handling for the autoidle and idle status register offsets mainly.

---
 .../devicetree/bindings/clock/ti/interface.txt     |   54 ++++++++
 arch/arm/mach-omap2/clock.h                        |    5 -
 drivers/clk/ti/Makefile                            |    1 +
 drivers/clk/ti/interface.c                         |  139 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    5 +
 5 files changed, 199 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/interface.txt
 create mode 100644 drivers/clk/ti/interface.c
Documentation/devicetree/bindings/clock/ti/interface.txt new file +54 -0
new file mode 100644
index 0000000..064e8ca
@@ -0,0 +1,54 @@
+Binding for Texas Instruments interface clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however,
+it supports a number of additional features, including
+companion clock finding (match corresponding functional gate
+clock) and hardware autoidle enable / disable.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+
+Required properties:
+- compatible : shall be one of:
+  "ti,omap3-interface-clock" - basic OMAP3 interface clock
+  "ti,omap3-no-wait-interface-clock" - interface clock which has no hardware
+				       capability for waiting clock to be ready
+  "ti,omap3-hsotgusb-interface-clock" - interface clock with USB specific HW
+					handling
+  "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling
+  "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling
+  "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling
+- #clock-cells : from common clock binding; shall be set to 0
+- clocks : link to phandle of parent clock
+- reg : base address for the control register
+
+Optional properties:
+- ti,bit-shift : bit shift for the bit enabling/disabling the clock (default 0)
+
+Examples:
+	aes1_ick: aes1_ick at 48004a14 {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-interface-clock";
+		clocks = <&security_l4_ick2>;
+		reg = <0x48004a14 0x4>;
+		ti,bit-shift = <3>;
+	};
+
+	cam_ick: cam_ick at 48004f10 {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-no-wait-interface-clock";
+		clocks = <&l4_ick>;
+		reg = <0x48004f10 0x4>;
+		ti,bit-shift = <0>;
+	};
+
+	ssi_ick_3430es2: ssi_ick_3430es2 at 48004a10 {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-ssi-interface-clock";
+		clocks = <&ssi_l4_ick>;
+		reg = <0x48004a10 0x4>;
+		ti,bit-shift = <0>;
+	};
arch/arm/mach-omap2/clock.h +0 -5
index b33f1e8..d1b227e 100644
@@ -266,13 +266,8 @@ extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
 extern struct clk dummy_ck;
 
-extern const struct clk_hw_omap_ops clkhwops_iclk;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
 extern const struct clk_hw_omap_ops clkhwops_apll54;
 extern const struct clk_hw_omap_ops clkhwops_apll96;
 extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
drivers/clk/ti/Makefile +1 -0
index 7eb6f2b..e42a703 100644
@@ -3,6 +3,7 @@ obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
 					   composite.o mux.o apll.o
 obj-$(CONFIG_SOC_AM33XX)		+= clk-33xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= interface.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= clk-54xx.o
 obj-$(CONFIG_SOC_DRA7XX)		+= clk-7xx.o
drivers/clk/ti/interface.c new file +139 -0

139 lines not on this page · raw message

include/linux/clk/ti.h +5 -0
index de0cffc..a197704 100644
@@ -243,6 +243,11 @@ extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
 extern const struct clk_hw_omap_ops clkhwops_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
 extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
+extern const struct clk_hw_omap_ops clkhwops_iclk;
 extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
 
 #endif
Signature · 1 line
1.7.9.5
#65 lore raw

PATCH v9 21/43 CLK: TI: add omap3 clock init file

In reply to Tero Kristo

clk-3xxx.c now contains the clock init functionality for omap3, including DT clock registration and adding of static clkdev entries.

---
 arch/arm/mach-omap2/clock3xxx.h |    1 -
 drivers/clk/ti/Makefile         |    2 +-
 drivers/clk/ti/clk-3xxx.c       |  400 +++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h          |    5 +
 4 files changed, 406 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/ti/clk-3xxx.c
arch/arm/mach-omap2/clock3xxx.h +0 -1
index dab90e2..78d9f56 100644
@@ -11,7 +11,6 @@
 int omap3xxx_clk_init(void);
 int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
 					unsigned long parent_rate);
-void omap3_clk_lock_dpll5(void);
 
 extern struct clk *sdrc_ick_p;
 extern struct clk *arm_fck_p;
drivers/clk/ti/Makefile +1 -1
index e42a703..ab386c8 100644
@@ -3,7 +3,7 @@ obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
 					   composite.o mux.o apll.o
 obj-$(CONFIG_SOC_AM33XX)		+= clk-33xx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= interface.o
+obj-$(CONFIG_ARCH_OMAP3)		+= interface.o clk-3xxx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= clk-54xx.o
 obj-$(CONFIG_SOC_DRA7XX)		+= clk-7xx.o
drivers/clk/ti/clk-3xxx.c new file +400 -0

400 lines not on this page · raw message

include/linux/clk/ti.h +5 -0
index a197704..a2edd27 100644
@@ -218,6 +218,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 int omap2_dflt_clk_enable(struct clk_hw *hw);
 void omap2_dflt_clk_disable(struct clk_hw *hw);
 int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap3_clk_lock_dpll5(void);
 
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, struct regmap *regmap);
@@ -225,6 +226,10 @@ void ti_dt_clockdomains_setup(void);
 int of_ti_autoidle_setup(struct device_node *node, struct regmap *regmap);
 int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
+int omap3430_dt_clk_init(void);
+int omap3630_dt_clk_init(void);
+int am35xx_dt_clk_init(void);
+int ti81xx_dt_clk_init(void);
 int omap4xxx_dt_clk_init(void);
 int omap5xxx_dt_clk_init(void);
 int dra7xx_dt_clk_init(void);
Signature · 1 line
1.7.9.5
#66 lore raw

PATCH v9 22/43 CLK: TI: add am43xx clock init file

In reply to Tero Kristo

clk-43xx.c now contains the clock init functionality for am43xx, including DT clock registration and adding of static clkdev entries.

---
 drivers/clk/ti/Makefile   |    2 +-
 drivers/clk/ti/clk-43xx.c |  118 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h    |    1 +
 3 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/clk-43xx.c
drivers/clk/ti/Makefile +1 -1
index ab386c8..007c3c2 100644
@@ -1,7 +1,7 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
 					   fixed-factor.o gate.o clockdomain.o \
-					   composite.o mux.o apll.o
+					   composite.o mux.o apll.o clk-43xx.o
 obj-$(CONFIG_SOC_AM33XX)		+= clk-33xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= interface.o clk-3xxx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clk-44xx.o
drivers/clk/ti/clk-43xx.c new file +118 -0

118 lines not on this page · raw message

include/linux/clk/ti.h +1 -0
index a2edd27..60368da 100644
@@ -234,6 +234,7 @@ int omap4xxx_dt_clk_init(void);
 int omap5xxx_dt_clk_init(void);
 int dra7xx_dt_clk_init(void);
 int am33xx_dt_clk_init(void);
+int am43xx_dt_clk_init(void);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
Signature · 1 line
1.7.9.5
#67 lore raw

PATCH v9 23/43 ARM: dts: omap4 clock data

In reply to Tero Kristo

This patch creates a unique node for each clock in the OMAP4 power, reset and clock manager (PRCM). OMAP443x and OMAP446x have slightly different clock tree which is taken into account in the data.

---
 arch/arm/boot/dts/omap4.dtsi           |    2 +
 arch/arm/boot/dts/omap443x-clocks.dtsi |   18 +
 arch/arm/boot/dts/omap443x.dtsi        |    2 +
 arch/arm/boot/dts/omap4460.dtsi        |    2 +
 arch/arm/boot/dts/omap446x-clocks.dtsi |   27 +
 arch/arm/boot/dts/omap44xx-clocks.dtsi | 1664 ++++++++++++++++++++++++++++++++
 6 files changed, 1715 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap443x-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap446x-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap44xx-clocks.dtsi
arch/arm/boot/dts/omap4.dtsi +2 -0
index 0d8fdba..26d48eb 100644
@@ -107,6 +107,8 @@
 		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
+		/include/ "omap44xx-clocks.dtsi"
+
 		counter32k: counter at 4a304000 {
 			compatible = "ti,omap-counter32k";
 			reg = <0x4a304000 0x20>;
arch/arm/boot/dts/omap443x-clocks.dtsi new file +18 -0
new file mode 100644
index 0000000..643755b
@@ -0,0 +1,18 @@
+/*
+ * Device Tree Source for OMAP4 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&prm {
+	bandgap_fclk: bandgap_fclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1888>;
+	};
+};
arch/arm/boot/dts/omap443x.dtsi +2 -0
index bcf455e..f67e191 100644
@@ -31,3 +31,5 @@
 		compatible = "ti,omap4430-bandgap";
 	};
 };
+
+/include/ "omap443x-clocks.dtsi"
arch/arm/boot/dts/omap4460.dtsi +2 -0
index c2f0f39..1758601 100644
@@ -39,3 +39,5 @@
 		gpios = <&gpio3 22 0>; /* tshut */
 	};
 };
+
+/include/ "omap446x-clocks.dtsi"
arch/arm/boot/dts/omap446x-clocks.dtsi new file +27 -0
new file mode 100644
index 0000000..d5ba999
@@ -0,0 +1,27 @@
+/*
+ * Device Tree Source for OMAP4 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&prm {
+	div_ts_ck: div_ts_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&l4_wkup_clk_mux_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1888>;
+		ti,dividers = <8>, <16>, <32>;
+	};
+
+	bandgap_ts_fclk: bandgap_ts_fclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&div_ts_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1888>;
+	};
+};
arch/arm/boot/dts/omap44xx-clocks.dtsi new file +1664 -0

1,664 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#68 lore raw

PATCH v9 24/43 ARM: dts: omap5 clock data

In reply to Tero Kristo

This patch creates a unique node for each clock in the OMAP5 power, reset and clock manager (PRCM).

---
 arch/arm/boot/dts/omap5.dtsi           |    2 +
 arch/arm/boot/dts/omap54xx-clocks.dtsi | 1416 ++++++++++++++++++++++++++++++++
 2 files changed, 1418 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap54xx-clocks.dtsi
arch/arm/boot/dts/omap5.dtsi +2 -0
index eeaa5ed..8c9cee4 100644
@@ -107,6 +107,8 @@
 		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
+		/include/ "omap54xx-clocks.dtsi"
+
 		counter32k: counter at 4ae04000 {
 			compatible = "ti,omap-counter32k";
 			reg = <0x4ae04000 0x40>;
arch/arm/boot/dts/omap54xx-clocks.dtsi new file +1416 -0

1,416 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#69 lore raw

PATCH v9 25/43 ARM: dts: dra7 clock data

In reply to Tero Kristo

This patch creates a unique node for each clock in the DRA7 power, reset and clock manager (PRCM).

TODO: apll_pcie clock node is still a dummy in this version, and proper support for the APLL should be added.

---
 arch/arm/boot/dts/dra7xx-clocks.dtsi | 1998 ++++++++++++++++++++++++++++++++++
 1 file changed, 1998 insertions(+)
 create mode 100644 arch/arm/boot/dts/dra7xx-clocks.dtsi
arch/arm/boot/dts/dra7xx-clocks.dtsi new file +1998 -0
new file mode 100644
index 0000000..ba43e7d
@@ -0,0 +1,1998 @@
+/*
+ * Device Tree Source for DRA7xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+cm_core_aon: cm_core_aon at 4a005000 {
+	compatible = "ti,cm";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x4a005000 0x2000>;
+
+	atl_clkin0_ck: atl_clkin0_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	atl_clkin1_ck: atl_clkin1_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	atl_clkin2_ck: atl_clkin2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	atlclkin3_ck: atlclkin3_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	hdmi_clkin_ck: hdmi_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	mlb_clkin_ck: mlb_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	mlbp_clkin_ck: mlbp_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	pciesref_acs_clk_ck: pciesref_acs_clk_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <100000000>;
+	};
+
+	ref_clkin0_ck: ref_clkin0_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	ref_clkin1_ck: ref_clkin1_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	ref_clkin2_ck: ref_clkin2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	ref_clkin3_ck: ref_clkin3_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	rmii_clk_ck: rmii_clk_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	sdvenc_clkin_ck: sdvenc_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	secure_32k_clk_src_ck: secure_32k_clk_src_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	sys_32k_ck: sys_32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	virt_12000000_ck: virt_12000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+	};
+
+	virt_13000000_ck: virt_13000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <13000000>;
+	};
+
+	virt_16800000_ck: virt_16800000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <16800000>;
+	};
+
+	virt_19200000_ck: virt_19200000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+
+	virt_20000000_ck: virt_20000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <20000000>;
+	};
+
+	virt_26000000_ck: virt_26000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <26000000>;
+	};
+
+	virt_27000000_ck: virt_27000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <27000000>;
+	};
+
+	virt_38400000_ck: virt_38400000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <38400000>;
+	};
+
+	sys_clkin2: sys_clkin2 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <22579200>;
+	};
+
+	usb_otg_clkin_ck: usb_otg_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	video1_clkin_ck: video1_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	video1_m2_clkin_ck: video1_m2_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	video2_clkin_ck: video2_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	video2_m2_clkin_ck: video2_m2_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	dpll_abe_ck: dpll_abe_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-m4xen-clock";
+		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
+		reg = <0x01e0>, <0x01e4>, <0x01e8>, <0x01ec>;
+	};
+
+	dpll_abe_x2_ck: dpll_abe_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-x2-clock";
+		clocks = <&dpll_abe_ck>;
+	};
+
+	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x01f0>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	abe_clk: abe_clk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_m2x2_ck>;
+		ti,max-div = <4>;
+		reg = <0x0108>;
+		ti,index-power-of-two;
+	};
+
+	dpll_abe_m2_ck: dpll_abe_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x01f0>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x01f4>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_ck: dpll_core_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-core-clock";
+		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+		reg = <0x0120>, <0x0124>, <0x0128>, <0x012c>;
+	};
+
+	dpll_core_x2_ck: dpll_core_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-x2-clock";
+		clocks = <&dpll_core_ck>;
+	};
+
+	dpll_core_h12x2_ck: dpll_core_h12x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x013c>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	mpu_dpll_hs_clk_div: mpu_dpll_hs_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_h12x2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_mpu_ck: dpll_mpu_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>;
+		reg = <0x0160>, <0x0164>, <0x0168>, <0x016c>;
+	};
+
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_mpu_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0170>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	mpu_dclk_div: mpu_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_mpu_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dsp_dpll_hs_clk_div: dsp_dpll_hs_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_h12x2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_dsp_ck: dpll_dsp_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>;
+		reg = <0x0234>, <0x0238>, <0x023c>, <0x0240>;
+	};
+
+	dpll_dsp_m2_ck: dpll_dsp_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_dsp_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0244>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	iva_dpll_hs_clk_div: iva_dpll_hs_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_h12x2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_iva_ck: dpll_iva_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>;
+		reg = <0x01a0>, <0x01a4>, <0x01a8>, <0x01ac>;
+	};
+
+	dpll_iva_m2_ck: dpll_iva_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_iva_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x01b0>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	iva_dclk: iva_dclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_iva_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_gpu_ck: dpll_gpu_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+		reg = <0x02d8>, <0x02dc>, <0x02e0>, <0x02e4>;
+	};
+
+	dpll_gpu_m2_ck: dpll_gpu_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gpu_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x02e8>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_m2_ck: dpll_core_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0130>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	core_dpll_out_dclk_div: core_dpll_out_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_ddr_ck: dpll_ddr_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+		reg = <0x0210>, <0x0214>, <0x0218>, <0x021c>;
+	};
+
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0220>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_gmac_ck: dpll_gmac_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+		reg = <0x02a8>, <0x02ac>, <0x02b0>, <0x02b4>;
+	};
+
+	dpll_gmac_m2_ck: dpll_gmac_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x02b8>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	video2_dclk_div: video2_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&video2_m2_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	video1_dclk_div: video1_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&video1_m2_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	hdmi_dclk_div: hdmi_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&hdmi_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	per_dpll_hs_clk_div: per_dpll_hs_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_abe_m3x2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	usb_dpll_hs_clk_div: usb_dpll_hs_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_abe_m3x2_ck>;
+		clock-mult = <1>;
+		clock-div = <3>;
+	};
+
+	eve_dpll_hs_clk_div: eve_dpll_hs_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_h12x2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_eve_ck: dpll_eve_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>;
+		reg = <0x0284>, <0x0288>, <0x028c>, <0x0290>;
+	};
+
+	dpll_eve_m2_ck: dpll_eve_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_eve_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0294>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	eve_dclk_div: eve_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_eve_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_core_h13x2_ck: dpll_core_h13x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0140>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_h14x2_ck: dpll_core_h14x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0144>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_h22x2_ck: dpll_core_h22x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0154>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_h23x2_ck: dpll_core_h23x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0158>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_h24x2_ck: dpll_core_h24x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x015c>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_ddr_x2_ck: dpll_ddr_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-x2-clock";
+		clocks = <&dpll_ddr_ck>;
+	};
+
+	dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0228>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_dsp_x2_ck: dpll_dsp_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-x2-clock";
+		clocks = <&dpll_dsp_ck>;
+	};
+
+	dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_dsp_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0248>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_gmac_x2_ck: dpll_gmac_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-x2-clock";
+		clocks = <&dpll_gmac_ck>;
+	};
+
+	dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x02c0>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x02c4>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x02c8>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x02bc>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	gmii_m_clk_div: gmii_m_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_gmac_h11x2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	hdmi_clk2_div: hdmi_clk2_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&hdmi_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	hdmi_div_clk: hdmi_div_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&hdmi_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l3_iclk_div: l3_iclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_h12x2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l4_root_clk_div: l4_root_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&l3_iclk_div>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	video1_clk2_div: video1_clk2_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&video1_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	video1_div_clk: video1_div_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&video1_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	video2_clk2_div: video2_clk2_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&video2_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	video2_div_clk: video2_div_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&video2_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	ipu1_gfclk_mux: ipu1_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x0520>;
+	};
+
+	mcasp1_ahclkr_mux: mcasp1_ahclkr_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <28>;
+		reg = <0x0550>;
+	};
+
+	mcasp1_ahclkx_mux: mcasp1_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x0550>;
+	};
+
+	mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x0550>;
+	};
+
+	timer5_gfclk_mux: timer5_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+		ti,bit-shift = <24>;
+		reg = <0x0558>;
+	};
+
+	timer6_gfclk_mux: timer6_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+		ti,bit-shift = <24>;
+		reg = <0x0560>;
+	};
+
+	timer7_gfclk_mux: timer7_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+		ti,bit-shift = <24>;
+		reg = <0x0568>;
+	};
+
+	timer8_gfclk_mux: timer8_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+		ti,bit-shift = <24>;
+		reg = <0x0570>;
+	};
+
+	uart6_gfclk_mux: uart6_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x0580>;
+	};
+
+	dummy_ck: dummy_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+};
+prm: prm at 4ae06000 {
+	compatible = "ti,prm";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x4ae06000 0x3000>;
+
+	sys_clkin1: sys_clkin1 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&virt_12000000_ck>, <&virt_20000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
+		reg = <0x0110>;
+		ti,index-starts-at-one;
+	};
+
+	abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin2>;
+		reg = <0x0118>;
+	};
+
+	abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>;
+		reg = <0x0114>;
+	};
+
+	abe_dpll_clk_mux: abe_dpll_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>;
+		reg = <0x010c>;
+	};
+
+	abe_24m_fclk: abe_24m_fclk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_m2x2_ck>;
+		reg = <0x011c>;
+		ti,dividers = <8>, <16>;
+	};
+
+	aess_fclk: aess_fclk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&abe_clk>;
+		reg = <0x0178>;
+		ti,max-div = <2>;
+	};
+
+	abe_giclk_div: abe_giclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&aess_fclk>;
+		reg = <0x0174>;
+		ti,max-div = <2>;
+	};
+
+	abe_lp_clk_div: abe_lp_clk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_m2x2_ck>;
+		reg = <0x01d8>;
+		ti,dividers = <16>, <32>;
+	};
+
+	abe_sys_clk_div: abe_sys_clk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin1>;
+		reg = <0x0120>;
+		ti,max-div = <2>;
+	};
+
+	adc_gfclk_mux: adc_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin2>, <&sys_32k_ck>;
+		reg = <0x01dc>;
+	};
+
+	sys_clk1_dclk_div: sys_clk1_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin1>;
+		ti,max-div = <64>;
+		reg = <0x01c8>;
+		ti,index-power-of-two;
+	};
+
+	sys_clk2_dclk_div: sys_clk2_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin2>;
+		ti,max-div = <64>;
+		reg = <0x01cc>;
+		ti,index-power-of-two;
+	};
+
+	per_abe_x1_dclk_div: per_abe_x1_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x01bc>;
+		ti,index-power-of-two;
+	};
+
+	dsp_gclk_div: dsp_gclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_dsp_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x018c>;
+		ti,index-power-of-two;
+	};
+
+	gpu_dclk: gpu_dclk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gpu_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x01a0>;
+		ti,index-power-of-two;
+	};
+
+	emif_phy_dclk_div: emif_phy_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x0190>;
+		ti,index-power-of-two;
+	};
+
+	gmac_250m_dclk_div: gmac_250m_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x019c>;
+		ti,index-power-of-two;
+	};
+
+	l3init_480m_dclk_div: l3init_480m_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_usb_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x01ac>;
+		ti,index-power-of-two;
+	};
+
+	usb_otg_dclk_div: usb_otg_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&usb_otg_clkin_ck>;
+		ti,max-div = <64>;
+		reg = <0x0184>;
+		ti,index-power-of-two;
+	};
+
+	sata_dclk_div: sata_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin1>;
+		ti,max-div = <64>;
+		reg = <0x01c0>;
+		ti,index-power-of-two;
+	};
+
+	pcie2_dclk_div: pcie2_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_pcie_ref_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x01b8>;
+		ti,index-power-of-two;
+	};
+
+	pcie_dclk_div: pcie_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&apll_pcie_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x01b4>;
+		ti,index-power-of-two;
+	};
+
+	emu_dclk_div: emu_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin1>;
+		ti,max-div = <64>;
+		reg = <0x0194>;
+		ti,index-power-of-two;
+	};
+
+	secure_32k_dclk_div: secure_32k_dclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&secure_32k_clk_src_ck>;
+		ti,max-div = <64>;
+		reg = <0x01c4>;
+		ti,index-power-of-two;
+	};
+
+	clkoutmux0_clk_mux: clkoutmux0_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
+		reg = <0x0158>;
+	};
+
+	clkoutmux1_clk_mux: clkoutmux1_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
+		reg = <0x015c>;
+	};
+
+	clkoutmux2_clk_mux: clkoutmux2_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
+		reg = <0x0160>;
+	};
+
+	custefuse_sys_gfclk_div: custefuse_sys_gfclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin1>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	eve_clk: eve_clk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_eve_m2_ck>, <&dpll_dsp_m3x2_ck>;
+		reg = <0x0180>;
+	};
+
+	hdmi_dpll_clk_mux: hdmi_dpll_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin2>;
+		reg = <0x01a4>;
+	};
+
+	mlb_clk: mlb_clk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&mlb_clkin_ck>;
+		ti,max-div = <64>;
+		reg = <0x0134>;
+		ti,index-power-of-two;
+	};
+
+	mlbp_clk: mlbp_clk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&mlbp_clkin_ck>;
+		ti,max-div = <64>;
+		reg = <0x0130>;
+		ti,index-power-of-two;
+	};
+
+	per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_abe_m2_ck>;
+		ti,max-div = <64>;
+		reg = <0x0138>;
+		ti,index-power-of-two;
+	};
+
+	timer_sys_clk_div: timer_sys_clk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin1>;
+		reg = <0x0144>;
+		ti,max-div = <2>;
+	};
+
+	video1_dpll_clk_mux: video1_dpll_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin2>;
+		reg = <0x01d0>;
+	};
+
+	video2_dpll_clk_mux: video2_dpll_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin2>;
+		reg = <0x01d4>;
+	};
+
+	wkupaon_iclk_mux: wkupaon_iclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&abe_lp_clk_div>;
+		reg = <0x0108>;
+	};
+
+	gpio1_dbclk: gpio1_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1838>;
+	};
+
+	dcan1_sys_clk_mux: dcan1_sys_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin2>;
+		ti,bit-shift = <24>;
+		reg = <0x1888>;
+	};
+
+	timer1_gfclk_mux: timer1_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1840>;
+	};
+
+	uart10_gfclk_mux: uart10_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1880>;
+	};
+};
+cm_core: cm_core at 4a008000 {
+	compatible = "ti,cm2";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x4a008000 0x3000>;
+
+	dpll_pcie_ref_ck: dpll_pcie_ref_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&sys_clkin1>;
+		reg = <0x0200>, <0x0204>, <0x0208>, <0x020c>;
+	};
+
+	dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_pcie_ref_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0210>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	apll_pcie_ck: apll_pcie_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&dpll_pcie_ref_ck>, <&dpll_pcie_ref_ck>;
+		reg = <0x0200>, <0x0204>, <0x0208>, <0x020c>;
+	};
+
+	apll_pcie_clkvcoldo: apll_pcie_clkvcoldo {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&apll_pcie_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	apll_pcie_clkvcoldo_div: apll_pcie_clkvcoldo_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&apll_pcie_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	apll_pcie_m2_ck: apll_pcie_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&apll_pcie_ck>;
+		ti,max-div = <127>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0224>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_ck: dpll_per_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-clock";
+		clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>;
+		reg = <0x0140>, <0x0144>, <0x0148>, <0x014c>;
+	};
+
+	dpll_per_m2_ck: dpll_per_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0150>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	func_96m_aon_dclk_div: func_96m_aon_dclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_usb_ck: dpll_usb_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-j-type-clock";
+		clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>;
+		reg = <0x0180>, <0x0184>, <0x0188>, <0x018c>;
+	};
+
+	dpll_usb_m2_ck: dpll_usb_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_usb_ck>;
+		ti,max-div = <127>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0190>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_pcie_ref_ck>;
+		ti,max-div = <127>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0210>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_x2_ck: dpll_per_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-dpll-x2-clock";
+		clocks = <&dpll_per_ck>;
+	};
+
+	dpll_per_h11x2_ck: dpll_per_h11x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0158>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_h12x2_ck: dpll_per_h12x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x015c>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_h13x2_ck: dpll_per_h13x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0160>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_h14x2_ck: dpll_per_h14x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_x2_ck>;
+		ti,max-div = <63>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0164>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x0150>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_usb_clkdcoldo: dpll_usb_clkdcoldo {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_usb_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	func_128m_clk: func_128m_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_h11x2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	func_12m_fclk: func_12m_fclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2x2_ck>;
+		clock-mult = <1>;
+		clock-div = <16>;
+	};
+
+	func_24m_clk: func_24m_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	func_48m_fclk: func_48m_fclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2x2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	func_96m_fclk: func_96m_fclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2x2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	l3init_60m_fclk: l3init_60m_fclk {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_usb_m2_ck>;
+		reg = <0x0104>;
+		ti,dividers = <1>, <8>;
+	};
+
+	dss_32khz_clk: dss_32khz_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <11>;
+		reg = <0x1120>;
+	};
+
+	dss_48mhz_clk: dss_48mhz_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&func_48m_fclk>;
+		ti,bit-shift = <9>;
+		reg = <0x1120>;
+	};
+
+	dss_dss_clk: dss_dss_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_per_h12x2_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1120>;
+	};
+
+	dss_hdmi_clk: dss_hdmi_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&hdmi_dpll_clk_mux>;
+		ti,bit-shift = <10>;
+		reg = <0x1120>;
+	};
+
+	dss_video1_clk: dss_video1_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&video1_dpll_clk_mux>;
+		ti,bit-shift = <12>;
+		reg = <0x1120>;
+	};
+
+	dss_video2_clk: dss_video2_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&video2_dpll_clk_mux>;
+		ti,bit-shift = <13>;
+		reg = <0x1120>;
+	};
+
+	gpio2_dbclk: gpio2_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1760>;
+	};
+
+	gpio3_dbclk: gpio3_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1768>;
+	};
+
+	gpio4_dbclk: gpio4_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1770>;
+	};
+
+	gpio5_dbclk: gpio5_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1778>;
+	};
+
+	gpio6_dbclk: gpio6_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1780>;
+	};
+
+	gpio7_dbclk: gpio7_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1810>;
+	};
+
+	gpio8_dbclk: gpio8_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1818>;
+	};
+
+	mmc1_clk32k: mmc1_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1328>;
+	};
+
+	mmc2_clk32k: mmc2_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1330>;
+	};
+
+	mmc3_clk32k: mmc3_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1820>;
+	};
+
+	mmc4_clk32k: mmc4_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x1828>;
+	};
+
+	sata_ref_clk: sata_ref_clk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_clkin1>;
+		ti,bit-shift = <8>;
+		reg = <0x1388>;
+	};
+
+	usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_usb_clkdcoldo>;
+		ti,bit-shift = <8>;
+		reg = <0x13f0>;
+	};
+
+	usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_usb_clkdcoldo>;
+		ti,bit-shift = <8>;
+		reg = <0x1340>;
+	};
+
+	usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x0640>;
+	};
+
+	usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x0688>;
+	};
+
+	usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x0698>;
+	};
+
+	atl_dpll_clk_mux: atl_dpll_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_32k_ck>, <&video1_clkin_ck>, <&video2_clkin_ck>, <&hdmi_clkin_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x0c00>;
+	};
+
+	atl_gfclk_mux: atl_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&l3_iclk_div>, <&dpll_abe_m2_ck>, <&atl_dpll_clk_mux>;
+		ti,bit-shift = <26>;
+		reg = <0x0c00>;
+	};
+
+	gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_gmac_m2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x13d0>;
+		ti,dividers = <2>;
+	};
+
+	gmac_rft_clk_mux: gmac_rft_clk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&video1_clkin_ck>, <&video2_clkin_ck>, <&dpll_abe_m2_ck>, <&hdmi_clkin_ck>, <&l3_iclk_div>;
+		ti,bit-shift = <25>;
+		reg = <0x13d0>;
+	};
+
+	gpu_core_gclk_mux: gpu_core_gclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1220>;
+	};
+
+	gpu_hyd_gclk_mux: gpu_hyd_gclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>;
+		ti,bit-shift = <26>;
+		reg = <0x1220>;
+	};
+
+	l3instr_ts_gclk_div: l3instr_ts_gclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&wkupaon_iclk_mux>;
+		ti,bit-shift = <24>;
+		reg = <0x0e50>;
+		ti,dividers = <8>, <16>, <32>;
+	};
+
+	mcasp2_ahclkr_mux: mcasp2_ahclkr_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <28>;
+		reg = <0x1860>;
+	};
+
+	mcasp2_ahclkx_mux: mcasp2_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <28>;
+		reg = <0x1860>;
+	};
+
+	mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x1860>;
+	};
+
+	mcasp3_ahclkx_mux: mcasp3_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1868>;
+	};
+
+	mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x1868>;
+	};
+
+	mcasp4_ahclkx_mux: mcasp4_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1898>;
+	};
+
+	mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x1898>;
+	};
+
+	mcasp5_ahclkx_mux: mcasp5_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1878>;
+	};
+
+	mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x1878>;
+	};
+
+	mcasp6_ahclkx_mux: mcasp6_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1904>;
+	};
+
+	mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x1904>;
+	};
+
+	mcasp7_ahclkx_mux: mcasp7_ahclkx_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1908>;
+	};
+
+	mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <22>;
+		reg = <0x1908>;
+	};
+
+	mcasp8_ahclk_mux: mcasp8_ahclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+		ti,bit-shift = <22>;
+		reg = <0x1890>;
+	};
+
+	mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+		ti,bit-shift = <24>;
+		reg = <0x1890>;
+	};
+
+	mmc1_fclk_mux: mmc1_fclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1328>;
+	};
+
+	mmc1_fclk_div: mmc1_fclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&mmc1_fclk_mux>;
+		ti,bit-shift = <25>;
+		ti,max-div = <4>;
+		reg = <0x1328>;
+		ti,index-power-of-two;
+	};
+
+	mmc2_fclk_mux: mmc2_fclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1330>;
+	};
+
+	mmc2_fclk_div: mmc2_fclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&mmc2_fclk_mux>;
+		ti,bit-shift = <25>;
+		ti,max-div = <4>;
+		reg = <0x1330>;
+		ti,index-power-of-two;
+	};
+
+	mmc3_gfclk_mux: mmc3_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1820>;
+	};
+
+	mmc3_gfclk_div: mmc3_gfclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&mmc3_gfclk_mux>;
+		ti,bit-shift = <25>;
+		ti,max-div = <4>;
+		reg = <0x1820>;
+		ti,index-power-of-two;
+	};
+
+	mmc4_gfclk_mux: mmc4_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1828>;
+	};
+
+	mmc4_gfclk_div: mmc4_gfclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&mmc4_gfclk_mux>;
+		ti,bit-shift = <25>;
+		ti,max-div = <4>;
+		reg = <0x1828>;
+		ti,index-power-of-two;
+	};
+
+	qspi_gfclk_mux: qspi_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_128m_clk>, <&dpll_per_h13x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1838>;
+	};
+
+	qspi_gfclk_div: qspi_gfclk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&qspi_gfclk_mux>;
+		ti,bit-shift = <25>;
+		ti,max-div = <4>;
+		reg = <0x1838>;
+		ti,index-power-of-two;
+	};
+
+	timer10_gfclk_mux: timer10_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1728>;
+	};
+
+	timer11_gfclk_mux: timer11_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1730>;
+	};
+
+	timer13_gfclk_mux: timer13_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x17c8>;
+	};
+
+	timer14_gfclk_mux: timer14_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x17d0>;
+	};
+
+	timer15_gfclk_mux: timer15_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x17d8>;
+	};
+
+	timer16_gfclk_mux: timer16_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1830>;
+	};
+
+	timer2_gfclk_mux: timer2_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1738>;
+	};
+
+	timer3_gfclk_mux: timer3_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1740>;
+	};
+
+	timer4_gfclk_mux: timer4_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1748>;
+	};
+
+	timer9_gfclk_mux: timer9_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+		ti,bit-shift = <24>;
+		reg = <0x1750>;
+	};
+
+	uart1_gfclk_mux: uart1_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1840>;
+	};
+
+	uart2_gfclk_mux: uart2_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1848>;
+	};
+
+	uart3_gfclk_mux: uart3_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1850>;
+	};
+
+	uart4_gfclk_mux: uart4_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1858>;
+	};
+
+	uart5_gfclk_mux: uart5_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1870>;
+	};
+
+	uart7_gfclk_mux: uart7_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x18d0>;
+	};
+
+	uart8_gfclk_mux: uart8_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x18e0>;
+	};
+
+	uart9_gfclk_mux: uart9_gfclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x18e8>;
+	};
+
+	vip1_gclk_mux: vip1_gclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1020>;
+	};
+
+	vip2_gclk_mux: vip2_gclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1028>;
+	};
+
+	vip3_gclk_mux: vip3_gclk_mux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
+		ti,bit-shift = <24>;
+		reg = <0x1030>;
+	};
+
+	coreaon_clkdm: coreaon_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&dpll_usb_ck>;
+	};
+};
Signature · 1 line
1.7.9.5
#70 lore raw

PATCH v9 26/43 ARM: dts: clk: Add apll related clocks

In reply to Tero Kristo

From: J Keerthy <[email protected]>

The patch adds a mux node to choose the parent of apll_pcie_ck node.

---
 arch/arm/boot/dts/dra7xx-clocks.dtsi |   14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)
arch/arm/boot/dts/dra7xx-clocks.dtsi +11 -3
index ba43e7d..1226921 100644
@@ -1165,11 +1165,19 @@ cm_core: cm_core at 4a008000 {
 		ti,invert-autoidle-bit;
 	};
 
+	apll_pcie_in_clk_mux: apll_pcie_in_clk_mux at 4ae06118 {
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_pcie_ref_ck>, <&pciesref_acs_clk_ck>;
+		#clock-cells = <0>;
+		reg = <0x021c 0x4>;
+		ti,bit-shift = <7>;
+	};
+
 	apll_pcie_ck: apll_pcie_ck {
 		#clock-cells = <0>;
-		compatible = "ti,omap4-dpll-clock";
-		clocks = <&dpll_pcie_ref_ck>, <&dpll_pcie_ref_ck>;
-		reg = <0x0200>, <0x0204>, <0x0208>, <0x020c>;
+		compatible = "ti,dra7-apll-clock";
+		clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
+		reg = <0x021c>, <0x0220>;
 	};
 
 	apll_pcie_clkvcoldo: apll_pcie_clkvcoldo {
Signature · 1 line
1.7.9.5
#71 lore raw

PATCH v9 27/43 ARM: dts: DRA7: Change apll_pcie_m2_ck to fixed factor clock

In reply to Tero Kristo

From: J Keerthy <[email protected]>

This patch changes apll_pcie_m2_ck to fixed factor clock as there are no configurable divider associated to m2.

---
 arch/arm/boot/dts/dra7xx-clocks.dtsi |    9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)
arch/arm/boot/dts/dra7xx-clocks.dtsi +3 -6
index 1226921..76955c1 100644
@@ -1198,13 +1198,10 @@ cm_core: cm_core at 4a008000 {
 
 	apll_pcie_m2_ck: apll_pcie_m2_ck {
 		#clock-cells = <0>;
-		compatible = "ti,divider-clock";
+		compatible = "fixed-factor-clock";
 		clocks = <&apll_pcie_ck>;
-		ti,max-div = <127>;
-		ti,autoidle-shift = <8>;
-		reg = <0x0224>;
-		ti,index-starts-at-one;
-		ti,invert-autoidle-bit;
+		clock-mult = <1>;
+		clock-div = <1>;
 	};
 
 	dpll_per_ck: dpll_per_ck {
Signature · 1 line
1.7.9.5
#72 lore raw

PATCH v9 28/43 ARM: dts: DRA7: Add PCIe related clock nodes

In reply to Tero Kristo

From: J Keerthy <[email protected]>

This patch adds optfclk_pciephy_clk and optfclk_pciephy_div_clk which are used by PCIe phy. It also adds a mux clock to choose the source of optfclk_pciephy_div_clk clock.

---
 arch/arm/boot/dts/dra7xx-clocks.dtsi |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
arch/arm/boot/dts/dra7xx-clocks.dtsi +25 -0
index 76955c1..5b7efc3 100644
@@ -1180,6 +1180,31 @@ cm_core: cm_core at 4a008000 {
 		reg = <0x021c>, <0x0220>;
 	};
 
+	optfclk_pciephy_div: optfclk_pciephy_div at 4a00821c {
+		compatible = "ti,divider-clock";
+		clocks = <&apll_pcie_ck>;
+		#clock-cells = <0>;
+		reg = <0x021c>;
+		ti,bit-shift = <8>;
+		ti,max-div = <2>;
+	};
+
+	optfclk_pciephy_clk: optfclk_pciephy_clk at 4a0093b0 {
+		compatible = "ti,gate-clock";
+		clocks = <&apll_pcie_ck>;
+		#clock-cells = <0>;
+		reg = <0x13b0>;
+		ti,bit-shift = <9>;
+	};
+
+	optfclk_pciephy_div_clk: optfclk_pciephy_div_clk at 4a0093b0 {
+		compatible = "ti,gate-clock";
+		clocks = <&optfclk_pciephy_div>;
+		#clock-cells = <0>;
+		reg = <0x13b0>;
+		ti,bit-shift = <10>;
+	};
+
 	apll_pcie_clkvcoldo: apll_pcie_clkvcoldo {
 		#clock-cells = <0>;
 		compatible = "fixed-factor-clock";
Signature · 1 line
1.7.9.5
#73 lore raw

PATCH v9 29/43 ARM: dts: DRA7: link in clock DT data

In reply to Tero Kristo

Clock tree DT data is now included from base dra7.dtsi file.

---
 arch/arm/boot/dts/dra7.dtsi |    2 ++
 1 file changed, 2 insertions(+)
arch/arm/boot/dts/dra7.dtsi +2 -0
index d0df4c4..bf7797e 100644
@@ -104,6 +104,8 @@
 		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
+		/include/ "dra7xx-clocks.dtsi"
+
 		counter32k: counter at 4ae04000 {
 			compatible = "ti,omap-counter32k";
 			reg = <0x4ae04000 0x40>;
Signature · 1 line
1.7.9.5
#74 lore raw

PATCH v9 30/43 ARM: dts: am33xx clock data

In reply to Tero Kristo

This patch creates a unique node for each clock in the AM33xx power, reset and clock manager (PRCM).

---
 arch/arm/boot/dts/am33xx-clocks.dtsi |  672 ++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/am33xx.dtsi        |    2 +
 2 files changed, 674 insertions(+)
 create mode 100644 arch/arm/boot/dts/am33xx-clocks.dtsi
arch/arm/boot/dts/am33xx-clocks.dtsi new file +672 -0
new file mode 100644
index 0000000..4f70931
@@ -0,0 +1,672 @@
+/*
+ * Device Tree Source for AM33xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+scrm: scrm at 44e10000 {
+	compatible = "ti,scrm";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x44e10000 0x2000>;
+
+	sys_clkin_ck: sys_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
+		ti,bit-shift = <22>;
+		reg = <0x0040>;
+	};
+
+	adc_tsc_fck: adc_tsc_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dcan0_fck: dcan0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dcan1_fck: dcan1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	mcasp0_fck: mcasp0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	mcasp1_fck: mcasp1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	smartreflex0_fck: smartreflex0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	smartreflex1_fck: smartreflex1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	sha0_fck: sha0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	aes0_fck: aes0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	rng_fck: rng_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	ehrpwm0_gate_tbclk: ehrpwm0_gate_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,composite-no-wait-gate-clock";
+		clocks = <&dpll_per_m2_ck>;
+		ti,bit-shift = <0>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm0_tbclk: ehrpwm0_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,composite-clock";
+		clocks = <&ehrpwm0_gate_tbclk>;
+	};
+
+	ehrpwm1_gate_tbclk: ehrpwm1_gate_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,composite-no-wait-gate-clock";
+		clocks = <&dpll_per_m2_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm1_tbclk: ehrpwm1_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,composite-clock";
+		clocks = <&ehrpwm1_gate_tbclk>;
+	};
+
+	ehrpwm2_gate_tbclk: ehrpwm2_gate_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,composite-no-wait-gate-clock";
+		clocks = <&dpll_per_m2_ck>;
+		ti,bit-shift = <2>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm2_tbclk: ehrpwm2_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,composite-clock";
+		clocks = <&ehrpwm2_gate_tbclk>;
+	};
+};
+prcm: prcm at 44e00000 {
+	compatible = "ti,prcm";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x44e00000 0x4000>;
+
+	clk_32768_ck: clk_32768_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	clk_rc32k_ck: clk_rc32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32000>;
+	};
+
+	virt_19200000_ck: virt_19200000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+
+	virt_24000000_ck: virt_24000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	virt_25000000_ck: virt_25000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	virt_26000000_ck: virt_26000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <26000000>;
+	};
+
+	tclkin_ck: tclkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+	};
+
+	dpll_core_ck: dpll_core_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-core-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0490>, <0x045c>, <0x0468>;
+	};
+
+	dpll_core_x2_ck: dpll_core_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-x2-clock";
+		clocks = <&dpll_core_ck>;
+	};
+
+	dpll_core_m4_ck: dpll_core_m4_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		reg = <0x0480>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_core_m5_ck: dpll_core_m5_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		reg = <0x0484>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_core_m6_ck: dpll_core_m6_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		reg = <0x04d8>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_mpu_ck: dpll_mpu_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0488>, <0x0420>, <0x042c>;
+	};
+
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_mpu_ck>;
+		ti,max-div = <31>;
+		reg = <0x04a8>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_ddr_ck: dpll_ddr_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-no-gate-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0494>, <0x0434>, <0x0440>;
+	};
+
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_ck>;
+		ti,max-div = <31>;
+		reg = <0x04a0>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_ddr_m2_div2_ck: dpll_ddr_m2_div2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_ddr_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	dpll_disp_ck: dpll_disp_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-no-gate-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0498>, <0x0448>, <0x0454>;
+	};
+
+	dpll_disp_m2_ck: dpll_disp_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_disp_ck>;
+		ti,max-div = <31>;
+		reg = <0x04a4>;
+		ti,index-starts-at-one;
+		ti,set-rate-parent;
+	};
+
+	dpll_per_ck: dpll_per_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-no-gate-j-type-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x048c>, <0x0470>, <0x049c>;
+	};
+
+	dpll_per_m2_ck: dpll_per_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_ck>;
+		ti,max-div = <31>;
+		reg = <0x04ac>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	dpll_per_m2_div4_ck: dpll_per_m2_div4_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	cefuse_fck: cefuse_fck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_clkin_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x0a20>;
+	};
+
+	clk_24mhz: clk_24mhz {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <8>;
+	};
+
+	clkdiv32k_ck: clkdiv32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&clk_24mhz>;
+		clock-mult = <1>;
+		clock-div = <732>;
+	};
+
+	clkdiv32k_ick: clkdiv32k_ick {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x014c>;
+	};
+
+	l3_gclk: l3_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	pruss_ocp_gclk: pruss_ocp_gclk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&l3_gclk>, <&dpll_disp_m2_ck>;
+		reg = <0x0530>;
+	};
+
+	mmu_fck: mmu_fck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_core_m4_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x0914>;
+	};
+
+	timer1_fck: timer1_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>;
+		reg = <0x0528>;
+	};
+
+	timer2_fck: timer2_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x0508>;
+	};
+
+	timer3_fck: timer3_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x050c>;
+	};
+
+	timer4_fck: timer4_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x0510>;
+	};
+
+	timer5_fck: timer5_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x0518>;
+	};
+
+	timer6_fck: timer6_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x051c>;
+	};
+
+	timer7_fck: timer7_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x0504>;
+	};
+
+	usbotg_fck: usbotg_fck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_per_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x047c>;
+	};
+
+	dpll_core_m4_div2_ck: dpll_core_m4_div2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	ieee5000_fck: ieee5000_fck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x00e4>;
+	};
+
+	wdt1_fck: wdt1_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
+		reg = <0x0538>;
+	};
+
+	l4_rtc_gclk: l4_rtc_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	l4hs_gclk: l4hs_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l3s_gclk: l3s_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l4fw_gclk: l4fw_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l4ls_gclk: l4ls_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	sysclk_div_ck: sysclk_div_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	cpsw_125mhz_gclk: cpsw_125mhz_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m5_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>;
+		reg = <0x0520>;
+	};
+
+	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>;
+		reg = <0x053c>;
+	};
+
+	gpio0_dbclk: gpio0_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&gpio0_dbclk_mux_ck>;
+		ti,bit-shift = <18>;
+		reg = <0x0408>;
+	};
+
+	gpio1_dbclk: gpio1_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <18>;
+		reg = <0x00ac>;
+	};
+
+	gpio2_dbclk: gpio2_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <18>;
+		reg = <0x00b0>;
+	};
+
+	gpio3_dbclk: gpio3_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <18>;
+		reg = <0x00b4>;
+	};
+
+	lcd_gclk: lcd_gclk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
+		reg = <0x0534>;
+		ti,set-rate-parent;
+	};
+
+	mmc_clk: mmc_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x052c>;
+	};
+
+	gfx_fck_div_ck: gfx_fck_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&gfx_fclk_clksel_ck>;
+		reg = <0x052c>;
+		ti,dividers = <1>, <2>;
+	};
+
+	sysclkout_pre_ck: sysclkout_pre_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>;
+		reg = <0x0700>;
+	};
+
+	clkout2_div_ck: clkout2_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sysclkout_pre_ck>;
+		ti,bit-shift = <3>;
+		reg = <0x0700>;
+		ti,dividers = <1>, <2>, <3>, <4>, <5>, <6>, <7>, <8>;
+	};
+
+	dbg_sysclk_ck: dbg_sysclk_ck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_clkin_ck>;
+		ti,bit-shift = <19>;
+		reg = <0x0414>;
+	};
+
+	dbg_clka_ck: dbg_clka_ck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_core_m4_ck>;
+		ti,bit-shift = <30>;
+		reg = <0x0414>;
+	};
+
+	stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>;
+		ti,bit-shift = <22>;
+		reg = <0x0414>;
+	};
+
+	trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>;
+		ti,bit-shift = <20>;
+		reg = <0x0414>;
+	};
+
+	stm_clk_div_ck: stm_clk_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&stm_pmd_clock_mux_ck>;
+		ti,bit-shift = <27>;
+		ti,max-div = <64>;
+		reg = <0x0414>;
+		ti,index-power-of-two;
+	};
+
+	trace_clk_div_ck: trace_clk_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&trace_pmd_clk_mux_ck>;
+		ti,bit-shift = <24>;
+		ti,max-div = <64>;
+		reg = <0x0414>;
+		ti,index-power-of-two;
+	};
+
+	clkout2_ck: clkout2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkout2_div_ck>;
+		ti,bit-shift = <7>;
+		reg = <0x0700>;
+	};
+
+	clk_24mhz_clkdm: clk_24mhz_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&clkdiv32k_ick>;
+	};
+};
arch/arm/boot/dts/am33xx.dtsi +2 -0
index 0ca13ad..05ad544 100644
@@ -102,6 +102,8 @@
 		ranges;
 		ti,hwmods = "l3_main";
 
+		/include/ "am33xx-clocks.dtsi"
+
 		intc: interrupt-controller at 48200000 {
 			compatible = "ti,omap2-intc";
 			interrupt-controller;
Signature · 1 line
1.7.9.5
#75 lore raw

PATCH v9 30/43 ARM: dts: am33xx clock data

Quoted 5 lines · Tero Kristo
arch/arm/boot/dts/am33xx-clocks.dtsi new file +5 -0
+       mcasp0_fck: mcasp0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;

arch/arm/boot/dts/am33xx-clocks.dtsi line 62

Quoted 10 lines
arch/arm/boot/dts/am33xx-clocks.dtsi new file +10 -0
+               clock-div = <1>;
+       };
+
+       mcasp1_fck: mcasp1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };

What is you use case for these clocks with a fixed factor of 1? Wouldn't it be simpler to just use sys_clkin_ck from the devices?

Regards,
Jan

#76 lore raw

PATCH v9 30/43 ARM: dts: am33xx clock data

Quoted 17 lines · Jan L?bbe
Quoted 5 lines · Tero Kristo
arch/arm/boot/dts/am33xx-clocks.dtsi new file +5 -0
+       mcasp0_fck: mcasp0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;

arch/arm/boot/dts/am33xx-clocks.dtsi line 62

Quoted 10 lines
arch/arm/boot/dts/am33xx-clocks.dtsi new file +10 -0
+               clock-div = <1>;
+       };
+
+       mcasp1_fck: mcasp1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
Quoted 2 lines

What is you use case for these clocks with a fixed factor of 1? Wouldn't it be simpler to just use sys_clkin_ck from the devices?

This is just kind of a dummy clock node for the driver use, so that it is simpler for them to find their clocks. If these are dropped, the drivers need to know that instead of their old own mcaspX_fck, they now need to directly connect to sys_clkin_ck. This also allows to track usecounts for the clocks better, if you don't have the mcaspX_fck:s for example, you will just have a usecount of 25 for the sys_clkin_ck, but don't really know who is using it. Also, other SoCs most likely have the same name in use, so just to keep the clock data compatible across SoCs.

These files are also completely autogenerated from the existing clock data under mach-omap2, and these nodes exist there.

But yea, no hard requirement.

-Tero

#77 lore raw

PATCH v9 30/43 ARM: dts: am33xx clock data

Quoted 30 lines · Tero Kristo
Quoted 17 lines · Jan Lübbe
Quoted 5 lines · Tero Kristo
arch/arm/boot/dts/am33xx-clocks.dtsi new file +5 -0
+       mcasp0_fck: mcasp0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;

arch/arm/boot/dts/am33xx-clocks.dtsi line 62

Quoted 10 lines
arch/arm/boot/dts/am33xx-clocks.dtsi new file +10 -0
+               clock-div = <1>;
+       };
+
+       mcasp1_fck: mcasp1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
Quoted 2 lines

What is you use case for these clocks with a fixed factor of 1? Wouldn't it be simpler to just use sys_clkin_ck from the devices?

This is just kind of a dummy clock node for the driver use, so that it is simpler for them to find their clocks. If these are dropped, the drivers need to know that instead of their old own mcaspX_fck, they now need to directly connect to sys_clkin_ck. This also allows to track usecounts for the clocks better, if you don't have the mcaspX_fck:s for example, you will just have a usecount of 25 for the sys_clkin_ck, but don't really know who is using it. Also, other SoCs most likely have the same name in use, so just to keep the clock data compatible across SoCs.

Quoted 4 lines

These files are also completely autogenerated from the existing clock data under mach-omap2, and these nodes exist there.

But yea, no hard requirement.

We shouldn't add dummy clocks to simplify debugging, maybe we need some user tracking in the core clk code?

As there are only few of these factor 1 clocks, I'm fine with keeping them for consistency here.

Regards,
Jan

Signature · 9 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#78 lore raw

PATCH v9 30/43 ARM: dts: am33xx clock data

Quoted 31 lines · Jan L?bbe
Quoted 30 lines · Tero Kristo
Quoted 17 lines · Jan L?bbe
Quoted 5 lines · Tero Kristo
arch/arm/boot/dts/am33xx-clocks.dtsi new file +5 -0
+       mcasp0_fck: mcasp0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;

arch/arm/boot/dts/am33xx-clocks.dtsi line 62

Quoted 10 lines
arch/arm/boot/dts/am33xx-clocks.dtsi new file +10 -0
+               clock-div = <1>;
+       };
+
+       mcasp1_fck: mcasp1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
Quoted 2 lines

What is you use case for these clocks with a fixed factor of 1? Wouldn't it be simpler to just use sys_clkin_ck from the devices?

This is just kind of a dummy clock node for the driver use, so that it is simpler for them to find their clocks. If these are dropped, the drivers need to know that instead of their old own mcaspX_fck, they now need to directly connect to sys_clkin_ck. This also allows to track usecounts for the clocks better, if you don't have the mcaspX_fck:s for example, you will just have a usecount of 25 for the sys_clkin_ck, but don't really know who is using it. Also, other SoCs most likely have the same name in use, so just to keep the clock data compatible across SoCs.

Quoted 7 lines
Quoted 4 lines

These files are also completely autogenerated from the existing clock data under mach-omap2, and these nodes exist there.

But yea, no hard requirement.

We shouldn't add dummy clocks to simplify debugging, maybe we need some user tracking in the core clk code?

Yea might be good to have something like this as configurable option in the future, so you would know who has enabled a certain clock. Currently clock APIs don't really provide way to tell users apart from each other. Mike, any thoughts on this?

Quoted 3 lines

As there are only few of these factor 1 clocks, I'm fine with keeping them for consistency here.

Thanks. :)

-Tero

#79 lore raw

PATCH v9 31/43 ARM: dts: omap3 clock data

In reply to Tero Kristo

This patch creates a unique node for each clock in the OMAP3 power, reset and clock manager (PRCM).

---
 arch/arm/boot/dts/am35xx-clocks.dtsi               |  126 ++
 arch/arm/boot/dts/omap3.dtsi                       |    2 +
 arch/arm/boot/dts/omap3430es1-clocks.dtsi          |  205 +++
 arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi    |  266 ++++
 arch/arm/boot/dts/omap34xx.dtsi                    |    4 +
 .../omap36xx-am35xx-omap3430es2plus-clocks.dtsi    |  237 +++
 arch/arm/boot/dts/omap36xx-clocks.dtsi             |   88 +
 .../boot/dts/omap36xx-omap3430es2plus-clocks.dtsi  |  196 +++
 arch/arm/boot/dts/omap36xx.dtsi                    |    5 +
 arch/arm/boot/dts/omap3xxx-clocks.dtsi             | 1675 ++++++++++++++++++++
 10 files changed, 2804 insertions(+)
 create mode 100644 arch/arm/boot/dts/am35xx-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap3430es1-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap36xx-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/omap3xxx-clocks.dtsi
arch/arm/boot/dts/am35xx-clocks.dtsi new file +126 -0
new file mode 100644
index 0000000..53e9d61
@@ -0,0 +1,126 @@
+/*
+ * Device Tree Source for OMAP3 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&scrm {
+	emac_ick: emac_ick {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x059c>;
+		ti,bit-shift = <1>;
+	};
+
+	emac_fck: emac_fck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&rmii_ck>;
+		reg = <0x059c>;
+		ti,bit-shift = <9>;
+	};
+
+	vpfe_ick: vpfe_ick {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x059c>;
+		ti,bit-shift = <2>;
+	};
+
+	vpfe_fck: vpfe_fck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&pclk_ck>;
+		reg = <0x059c>;
+		ti,bit-shift = <10>;
+	};
+
+	hsotgusb_ick_am35xx: hsotgusb_ick_am35xx {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x059c>;
+		ti,bit-shift = <0>;
+	};
+
+	hsotgusb_fck_am35xx: hsotgusb_fck_am35xx {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_ck>;
+		reg = <0x059c>;
+		ti,bit-shift = <8>;
+	};
+
+	hecc_ck: hecc_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&sys_ck>;
+		reg = <0x059c>;
+		ti,bit-shift = <3>;
+	};
+};
+&cm {
+	ipss_ick: ipss_ick {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-interface-clock";
+		clocks = <&core_l3_ick>;
+		reg = <0x0a10>;
+		ti,bit-shift = <4>;
+	};
+
+	rmii_ck: rmii_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <50000000>;
+	};
+
+	pclk_ck: pclk_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <27000000>;
+	};
+
+	uart4_ick_am35xx: uart4_ick_am35xx {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-interface-clock";
+		clocks = <&core_l4_ick>;
+		reg = <0x0a10>;
+		ti,bit-shift = <23>;
+	};
+
+	uart4_fck_am35xx: uart4_fck_am35xx {
+		#clock-cells = <0>;
+		compatible = "ti,wait-gate-clock";
+		clocks = <&core_48m_fck>;
+		reg = <0x0a00>;
+		ti,bit-shift = <23>;
+	};
+
+	core_l3_clkdm: core_l3_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>,
+			 <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>,
+			 <&hecc_ck>;
+	};
+
+	core_l4_clkdm: core_l4_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+			 <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>,
+			 <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+			 <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+			 <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+			 <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+			 <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+			 <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+			 <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+			 <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+			 <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+			 <&uart4_ick_am35xx>, <&uart4_fck_am35xx>;
+	};
+};
arch/arm/boot/dts/omap3.dtsi +2 -0
index 4fd4229..67d26a7 100644
@@ -79,6 +79,8 @@
 		ranges;
 		ti,hwmods = "l3_main";
 
+		/include/ "omap3xxx-clocks.dtsi"
+
 		counter32k: counter at 48320000 {
 			compatible = "ti,omap-counter32k";
 			reg = <0x48320000 0x20>;
arch/arm/boot/dts/omap3430es1-clocks.dtsi new file +205 -0

205 lines not on this page · raw message

arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi new file +266 -0

266 lines not on this page · raw message

arch/arm/boot/dts/omap34xx.dtsi +4 -0
index 5355d61..d531abf 100644
@@ -26,3 +26,7 @@
 		};
 	};
 };
+
+/include/ "omap34xx-omap36xx-clocks.dtsi"
+/include/ "omap36xx-omap3430es2plus-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
\ No newline at end of file
arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi new file +237 -0

237 lines not on this page · raw message

arch/arm/boot/dts/omap36xx-clocks.dtsi new file +88 -0

88 lines not on this page · raw message

arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi new file +196 -0

196 lines not on this page · raw message

arch/arm/boot/dts/omap36xx.dtsi +5 -0
index f8b3765..4946f56 100644
@@ -36,3 +36,8 @@
 		};
 	};
 };
+
+/include/ "omap36xx-clocks.dtsi"
+/include/ "omap34xx-omap36xx-clocks.dtsi"
+/include/ "omap36xx-omap3430es2plus-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
\ No newline at end of file
arch/arm/boot/dts/omap3xxx-clocks.dtsi new file +1675 -0

1,675 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#80 lore raw

PATCH v9 32/43 ARM: dts: AM35xx: use DT clock data

In reply to Tero Kristo

AM35xx now uses the clock data from device tree. Most of the data is shared with OMAP3xxx, but as there is some delta, a new base .dtsi file is also created for the SoC.

---
 arch/arm/boot/dts/am3517-evm.dts        |    2 +-
 arch/arm/boot/dts/am3517.dtsi           |   31 +++++++++++++++++++++++++++++++
 arch/arm/boot/dts/am3517_mt_ventoux.dts |    2 +-
 3 files changed, 33 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/am3517.dtsi
arch/arm/boot/dts/am3517-evm.dts +1 -1
index e99dfaf..9ff51d7 100644
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "am3517.dtsi"
 
 / {
 	model = "TI AM3517 EVM (AM3517/05)";
arch/arm/boot/dts/am3517.dtsi new file +31 -0
new file mode 100644
index 0000000..c555443
@@ -0,0 +1,31 @@
+/*
+ * Device Tree Source for AM3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+	cpus {
+		cpu at 0 {
+			/* OMAP343x/OMAP35xx variants OPP1-5 */
+			operating-points = <
+				/* kHz    uV */
+				125000   975000
+				250000  1075000
+				500000  1200000
+				550000  1270000
+				600000  1350000
+			>;
+			clock-latency = <300000>; /* From legacy driver */
+		};
+	};
+};
+
+/include/ "am35xx-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
arch/arm/boot/dts/am3517_mt_ventoux.dts +1 -1
index fdf5ce6..d00e934 100644
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "am3517.dtsi"
 
 / {
 	model = "TeeJet Mt.Ventoux";
Signature · 1 line
1.7.9.5
#81 lore raw

PATCH v9 32/43 ARM: dts: AM35xx: use DT clock data

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 12 lines
arch/arm/boot/dts/am3517.dtsi new file +6 -0
new file mode 100644
index 0000000..c555443
@@ -0,0 +1,31 @@
+/*
+ * Device Tree Source for AM3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License

arch/arm/boot/dts/am3517.dtsi line 16

Quoted 10 lines
arch/arm/boot/dts/am3517.dtsi new file +10 -0
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+	cpus {
+		cpu at 0 {
+			/* OMAP343x/OMAP35xx variants OPP1-5 */

^^ you could fix the comment since this is OMAP35xx variant :)

Quoted 12 lines
arch/arm/boot/dts/am3517.dtsi new file +12 -0
+			operating-points = <
+				/* kHz    uV */
+				125000   975000
+				250000  1075000
+				500000  1200000
+				550000  1270000
+				600000  1350000
+			>;
+			clock-latency = <300000>; /* From legacy driver */
+		};
+	};
+};

[..]

Signature · 2 lines
Regards,
Nishanth Menon
#82 lore raw

PATCH v9 32/43 ARM: dts: AM35xx: use DT clock data

Quoted 19 lines · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 16 lines
arch/arm/boot/dts/am3517.dtsi new file +10 -0
new file mode 100644
index 0000000..c555443
@@ -0,0 +1,31 @@
+/*
+ * Device Tree Source for AM3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
Quoted 8 lines

arch/arm/boot/dts/am3517.dtsi line 16

Quoted 6 lines
arch/arm/boot/dts/am3517.dtsi new file +6 -0
+#include "omap3.dtsi"
+
+/ {
+	cpus {
+		cpu at 0 {
+			/* OMAP343x/OMAP35xx variants OPP1-5 */

^^ you could fix the comment since this is OMAP35xx variant :)

Ok. :)

Quoted 17 lines
Quoted 13 lines
arch/arm/boot/dts/am3517.dtsi new file +12 -0
+			operating-points = <
+				/* kHz    uV */
+				125000   975000
+				250000  1075000
+				500000  1200000
+				550000  1270000
+				600000  1350000
+			>;
+			clock-latency = <300000>; /* From legacy driver */
+		};
+	};
+};

[..]

#83 lore raw

PATCH v9 33/43 ARM: dts: am43xx clock data

In reply to Tero Kristo

This patch creates a unique node for each clock in the AM43xx power, reset and clock manager (PRCM).

---
 arch/arm/boot/dts/am4372.dtsi        |    2 +
 arch/arm/boot/dts/am43xx-clocks.dtsi |  666 ++++++++++++++++++++++++++++++++++
 2 files changed, 668 insertions(+)
 create mode 100644 arch/arm/boot/dts/am43xx-clocks.dtsi
arch/arm/boot/dts/am4372.dtsi +2 -0
index 974d103..1fb3ac2 100644
@@ -67,6 +67,8 @@
 		ranges;
 		ti,hwmods = "l3_main";
 
+		/include/ "am43xx-clocks.dtsi"
+
 		edma: edma at 49000000 {
 			compatible = "ti,edma3";
 			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
arch/arm/boot/dts/am43xx-clocks.dtsi new file +666 -0

666 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#84 lore raw

PATCH v9 33/43 ARM: dts: am43xx clock data

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 23 lines
arch/arm/boot/dts/am4372.dtsi +2 -0
index 974d103..1fb3ac2 100644
@@ -67,6 +67,8 @@
 		ranges;
 		ti,hwmods = "l3_main";
 
+		/include/ "am43xx-clocks.dtsi"
+
 		edma: edma at 49000000 {
 			compatible = "ti,edma3";
 			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
arch/arm/boot/dts/am43xx-clocks.dtsi new file +4 -0
new file mode 100644
index 0000000..1cc5071
@@ -0,0 +1,666 @@
+/*
+ * Device Tree Source for AM43xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.

arch/arm/boot/dts/am43xx-clocks.dtsi line 14

Quoted 10 lines
arch/arm/boot/dts/am43xx-clocks.dtsi new file +10 -0
+ *
+ * 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.
+ */
+scrm: scrm at 44e10000 {
+	compatible = "ti,scrm";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x44e10000 0x2000>;

here and other dts -> could we keep the scrm, prm, cm devices in SoC.dtsi? and clocks.dtsi just contains the clock nodes?

[...]

Signature · 2 lines
Regards,
Nishanth Menon
#85 lore raw

PATCH v9 33/43 ARM: dts: am43xx clock data

Quoted 30 lines · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 28 lines
arch/arm/boot/dts/am4372.dtsi +2 -0
index 974d103..1fb3ac2 100644
@@ -67,6 +67,8 @@
  		ranges;
  		ti,hwmods = "l3_main";
 
+		/include/ "am43xx-clocks.dtsi"
+
  		edma: edma at 49000000 {
  			compatible = "ti,edma3";
  			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
arch/arm/boot/dts/am43xx-clocks.dtsi new file +9 -0
new file mode 100644
index 0000000..1cc5071
@@ -0,0 +1,666 @@
+/*
+ * Device Tree Source for AM43xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
Quoted 8 lines

arch/arm/boot/dts/am43xx-clocks.dtsi line 14

Quoted 5 lines
arch/arm/boot/dts/am43xx-clocks.dtsi new file +5 -0
+scrm: scrm at 44e10000 {
+	compatible = "ti,scrm";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x44e10000 0x2000>;

here and other dts -> could we keep the scrm, prm, cm devices in SoC.dtsi? and clocks.dtsi just contains the clock nodes?

Could do that with some links yea, similar to how the clock data mods are done in this rev. Will check it out how it works.

-Tero

Quoted 3 lines

[...]

#86 lore raw

PATCH v9 34/43 ARM: OMAP2+: clock: add support for regmap

In reply to Tero Kristo

Using regmap is required for isolating the actual memory access from the clock code. Now, the driver providing the support for the clock IP block can provide a regmap for this purpose.

---
 arch/arm/mach-omap2/clock.c |   20 ++++++++++++++++++++
 arch/arm/mach-omap2/clock.h |    3 +++
 2 files changed, 23 insertions(+)
arch/arm/mach-omap2/clock.c +20 -0
index 223f432b..560c49b 100644
@@ -57,6 +57,26 @@ static bool clkdm_control = true;
 
 static LIST_HEAD(clk_hw_omap_clocks);
 
+void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
+{
+	if (clk->regmap)
+		regmap_write(clk->regmap, (u32)reg, val);
+	else
+		__raw_writel(val, reg);
+}
+
+u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
+{
+	u32 val;
+
+	if (clk->regmap)
+		regmap_read(clk->regmap, (u32)reg, &val);
+	else
+		val = __raw_readl(reg);
+
+	return val;
+}
+
 /*
  * Used for clocks that have the same value as the parent clock,
  * divided by some factor
arch/arm/mach-omap2/clock.h +3 -0
index d1b227e..a166683 100644
@@ -252,6 +252,9 @@ void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 			       const char *core_ck_name,
 			       const char *mpu_ck_name);
 
+u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg);
+void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
+
 extern u16 cpu_mask;
 
 extern const struct clkops clkops_omap2_dflt_wait;
Signature · 1 line
1.7.9.5
#87 lore raw

PATCH v9 35/43 ARM: OMAP2+: clock: use driver API instead of direct memory read/write

In reply to Tero Kristo

Clock nodes shall use the services provided by underlying drivers to access the hardware registers instead of direct memory read/write. Thus, change all the code to use the new omap2_clk_readl / omap2_clk_writel APIs for this.

---
 arch/arm/mach-omap2/clkt_clksel.c |   10 +++++-----
 arch/arm/mach-omap2/clkt_dpll.c   |    6 +++---
 arch/arm/mach-omap2/clkt_iclk.c   |   20 ++++++++++++--------
 arch/arm/mach-omap2/clock.c       |   24 ++++++++++++------------
 arch/arm/mach-omap2/clock36xx.c   |    7 ++++---
 arch/arm/mach-omap2/dpll3xxx.c    |   37 ++++++++++++++++++++-----------------
 arch/arm/mach-omap2/dpll44xx.c    |   12 ++++++------
 7 files changed, 62 insertions(+), 54 deletions(-)
arch/arm/mach-omap2/clkt_clksel.c +5 -5
index 0ec9f6f..7ee2610 100644
@@ -97,12 +97,12 @@ static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
 {
 	u32 v;
 
-	v = __raw_readl(clk->clksel_reg);
+	v = omap2_clk_readl(clk, clk->clksel_reg);
 	v &= ~clk->clksel_mask;
 	v |= field_val << __ffs(clk->clksel_mask);
-	__raw_writel(v, clk->clksel_reg);
+	omap2_clk_writel(v, clk, clk->clksel_reg);
 
-	v = __raw_readl(clk->clksel_reg); /* OCP barrier */
+	v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */
 }
 
 /**
@@ -204,7 +204,7 @@ static u32 _read_divisor(struct clk_hw_omap *clk)
 	if (!clk->clksel || !clk->clksel_mask)
 		return 0;
 
-	v = __raw_readl(clk->clksel_reg);
+	v = omap2_clk_readl(clk, clk->clksel_reg);
 	v &= clk->clksel_mask;
 	v >>= __ffs(clk->clksel_mask);
 
@@ -320,7 +320,7 @@ u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
 	WARN((!clk->clksel || !clk->clksel_mask),
 	     "clock: %s: attempt to call on a non-clksel clock", clk_name);
 
-	r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
+	r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask;
 	r >>= __ffs(clk->clksel_mask);
 
 	for (clks = clk->clksel; clks->parent && !found; clks++) {
arch/arm/mach-omap2/clkt_dpll.c +3 -3
index 924c230..47f9562 100644
@@ -196,7 +196,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
 	if (!dd)
 		return -EINVAL;
 
-	v = __raw_readl(dd->control_reg);
+	v = omap2_clk_readl(clk, dd->control_reg);
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
@@ -243,7 +243,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
 		return 0;
 
 	/* Return bypass rate if DPLL is bypassed */
-	v = __raw_readl(dd->control_reg);
+	v = omap2_clk_readl(clk, dd->control_reg);
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
@@ -262,7 +262,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
 			return __clk_get_rate(dd->clk_bypass);
 	}
 
-	v = __raw_readl(dd->mult_div1_reg);
+	v = omap2_clk_readl(clk, dd->mult_div1_reg);
 	dpll_mult = v & dd->mult_mask;
 	dpll_mult >>= __ffs(dd->mult_mask);
 	dpll_div = v & dd->div1_mask;
arch/arm/mach-omap2/clkt_iclk.c +12 -8
index f10eb03..333f0a6 100644
@@ -25,25 +25,29 @@
 /* XXX */
 void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
 {
-	u32 v, r;
+	u32 v;
+	void __iomem *r;
 
-	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+	r = (__force void __iomem *)
+		((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
 
-	v = __raw_readl((__force void __iomem *)r);
+	v = omap2_clk_readl(clk, r);
 	v |= (1 << clk->enable_bit);
-	__raw_writel(v, (__force void __iomem *)r);
+	omap2_clk_writel(v, clk, r);
 }
 
 /* XXX */
 void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
 {
-	u32 v, r;
+	u32 v;
+	void __iomem *r;
 
-	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+	r = (__force void __iomem *)
+		((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
 
-	v = __raw_readl((__force void __iomem *)r);
+	v = omap2_clk_readl(clk, r);
 	v &= ~(1 << clk->enable_bit);
-	__raw_writel(v, (__force void __iomem *)r);
+	omap2_clk_writel(v, clk, r);
 }
 
 /* Public data */
arch/arm/mach-omap2/clock.c +12 -12
index 560c49b..dd7a739 100644
@@ -118,14 +118,14 @@ unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
  * elapsed.  XXX Deprecated - should be moved into drivers for the
  * individual IP block that the IDLEST register exists in.
  */
-static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest,
-				const char *name)
+static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
+				u32 mask, u8 idlest, const char *name)
 {
 	int i = 0, ena = 0;
 
 	ena = (idlest) ? 0 : mask;
 
-	omap_test_timeout(((__raw_readl(reg) & mask) == ena),
+	omap_test_timeout(((omap2_clk_readl(clk, reg) & mask) == ena),
 			  MAX_MODULE_ENABLE_WAIT, i);
 
 	if (i < MAX_MODULE_ENABLE_WAIT)
@@ -158,7 +158,7 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
 	/* Not all modules have multiple clocks that their IDLEST depends on */
 	if (clk->ops->find_companion) {
 		clk->ops->find_companion(clk, &companion_reg, &other_bit);
-		if (!(__raw_readl(companion_reg) & (1 << other_bit)))
+		if (!(omap2_clk_readl(clk, companion_reg) & (1 << other_bit)))
 			return;
 	}
 
@@ -166,8 +166,8 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
 	r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
 	if (r) {
 		/* IDLEST register not in the CM module */
-		_wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val,
-				     __clk_get_name(clk->hw.clk));
+		_wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
+				     idlest_val, __clk_get_name(clk->hw.clk));
 	} else {
 		cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
 	};
@@ -329,13 +329,13 @@ int omap2_dflt_clk_enable(struct clk_hw *hw)
 	}
 
 	/* FIXME should not have INVERT_ENABLE bit here */
-	v = __raw_readl(clk->enable_reg);
+	v = omap2_clk_readl(clk, clk->enable_reg);
 	if (clk->flags & INVERT_ENABLE)
 		v &= ~(1 << clk->enable_bit);
 	else
 		v |= (1 << clk->enable_bit);
-	__raw_writel(v, clk->enable_reg);
-	v = __raw_readl(clk->enable_reg); /* OCP barrier */
+	omap2_clk_writel(v, clk, clk->enable_reg);
+	v = omap2_clk_readl(clk, clk->enable_reg); /* OCP barrier */
 
 	if (clk->ops && clk->ops->find_idlest)
 		_omap2_module_wait_ready(clk);
@@ -373,12 +373,12 @@ void omap2_dflt_clk_disable(struct clk_hw *hw)
 		return;
 	}
 
-	v = __raw_readl(clk->enable_reg);
+	v = omap2_clk_readl(clk, clk->enable_reg);
 	if (clk->flags & INVERT_ENABLE)
 		v |= (1 << clk->enable_bit);
 	else
 		v &= ~(1 << clk->enable_bit);
-	__raw_writel(v, clk->enable_reg);
+	omap2_clk_writel(v, clk, clk->enable_reg);
 	/* No OCP barrier needed here since it is a disable operation */
 
 	if (clkdm_control && clk->clkdm)
@@ -474,7 +474,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 v;
 
-	v = __raw_readl(clk->enable_reg);
+	v = omap2_clk_readl(clk, clk->enable_reg);
 
 	if (clk->flags & INVERT_ENABLE)
 		v ^= BIT(clk->enable_bit);
arch/arm/mach-omap2/clock36xx.c +4 -3
index bbd6a3f..91ccb96 100644
@@ -43,6 +43,7 @@ int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
 	struct clk_divider *parent;
 	struct clk_hw *parent_hw;
 	u32 dummy_v, orig_v;
+	struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
 	int ret;
 
 	/* Clear PWRDN bit of HSDIVIDER */
@@ -53,15 +54,15 @@ int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
 
 	/* Restore the dividers */
 	if (!ret) {
-		orig_v = __raw_readl(parent->reg);
+		orig_v = omap2_clk_readl(omap_clk, parent->reg);
 		dummy_v = orig_v;
 
 		/* Write any other value different from the Read value */
 		dummy_v ^= (1 << parent->shift);
-		__raw_writel(dummy_v, parent->reg);
+		omap2_clk_writel(dummy_v, omap_clk, parent->reg);
 
 		/* Write the original divider */
-		__raw_writel(orig_v, parent->reg);
+		omap2_clk_writel(orig_v, omap_clk, parent->reg);
 	}
 
 	return ret;
arch/arm/mach-omap2/dpll3xxx.c +20 -17
index 3a0296c..3185ced 100644
@@ -50,10 +50,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
 
 	dd = clk->dpll_data;
 
-	v = __raw_readl(dd->control_reg);
+	v = omap2_clk_readl(clk, dd->control_reg);
 	v &= ~dd->enable_mask;
 	v |= clken_bits << __ffs(dd->enable_mask);
-	__raw_writel(v, dd->control_reg);
+	omap2_clk_writel(v, clk, dd->control_reg);
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -69,8 +69,8 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
 
 	state <<= __ffs(dd->idlest_mask);
 
-	while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
-	       i < MAX_DPLL_WAIT_TRIES) {
+	while (((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask)
+		!= state) && i < MAX_DPLL_WAIT_TRIES) {
 		i++;
 		udelay(1);
 	}
@@ -147,7 +147,7 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
 	state <<= __ffs(dd->idlest_mask);
 
 	/* Check if already locked */
-	if ((__raw_readl(dd->idlest_reg) & dd->idlest_mask) == state)
+	if ((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) == state)
 		goto done;
 
 	ai = omap3_dpll_autoidle_read(clk);
@@ -311,14 +311,14 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 	 * only since freqsel field is no longer present on other devices.
 	 */
 	if (cpu_is_omap343x()) {
-		v = __raw_readl(dd->control_reg);
+		v = omap2_clk_readl(clk, dd->control_reg);
 		v &= ~dd->freqsel_mask;
 		v |= freqsel << __ffs(dd->freqsel_mask);
-		__raw_writel(v, dd->control_reg);
+		omap2_clk_writel(v, clk, dd->control_reg);
 	}
 
 	/* Set DPLL multiplier, divider */
-	v = __raw_readl(dd->mult_div1_reg);
+	v = omap2_clk_readl(clk, dd->mult_div1_reg);
 	v &= ~(dd->mult_mask | dd->div1_mask);
 	v |= dd->last_rounded_m << __ffs(dd->mult_mask);
 	v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
@@ -336,11 +336,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 		v |= sd_div << __ffs(dd->sddiv_mask);
 	}
 
-	__raw_writel(v, dd->mult_div1_reg);
+	omap2_clk_writel(v, clk, dd->mult_div1_reg);
 
 	/* Set 4X multiplier and low-power mode */
 	if (dd->m4xen_mask || dd->lpmode_mask) {
-		v = __raw_readl(dd->control_reg);
+		v = omap2_clk_readl(clk, dd->control_reg);
 
 		if (dd->m4xen_mask) {
 			if (dd->last_rounded_m4xen)
@@ -356,7 +356,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 				v &= ~dd->lpmode_mask;
 		}
 
-		__raw_writel(v, dd->control_reg);
+		omap2_clk_writel(v, clk, dd->control_reg);
 	}
 
 	/* We let the clock framework set the other output dividers later */
@@ -554,7 +554,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
 	if (!dd->autoidle_reg)
 		return -EINVAL;
 
-	v = __raw_readl(dd->autoidle_reg);
+	v = omap2_clk_readl(clk, dd->autoidle_reg);
 	v &= dd->autoidle_mask;
 	v >>= __ffs(dd->autoidle_mask);
 
@@ -588,10 +588,10 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
 	 * by writing 0x5 instead of 0x1.  Add some mechanism to
 	 * optionally enter this mode.
 	 */
-	v = __raw_readl(dd->autoidle_reg);
+	v = omap2_clk_readl(clk, dd->autoidle_reg);
 	v &= ~dd->autoidle_mask;
 	v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
-	__raw_writel(v, dd->autoidle_reg);
+	omap2_clk_writel(v, clk, dd->autoidle_reg);
 
 }
 
@@ -614,10 +614,10 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 	if (!dd->autoidle_reg)
 		return;
 
-	v = __raw_readl(dd->autoidle_reg);
+	v = omap2_clk_readl(clk, dd->autoidle_reg);
 	v &= ~dd->autoidle_mask;
 	v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
-	__raw_writel(v, dd->autoidle_reg);
+	omap2_clk_writel(v, clk, dd->autoidle_reg);
 
 }
 
@@ -639,6 +639,9 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 	struct clk_hw_omap *pclk = NULL;
 	struct clk *parent;
 
+	if (!parent_rate)
+		return 0;
+
 	/* Walk up the parents of clk, looking for a DPLL */
 	do {
 		do {
@@ -660,7 +663,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 
 	WARN_ON(!dd->enable_mask);
 
-	v = __raw_readl(dd->control_reg) & dd->enable_mask;
+	v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 	if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
 		rate = parent_rate;
arch/arm/mach-omap2/dpll44xx.c +6 -6
index d28b0f7..52f9438 100644
@@ -42,7 +42,7 @@ int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
 			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
 			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-	v = __raw_readl(clk->clksel_reg);
+	v = omap2_clk_readl(clk, clk->clksel_reg);
 	v &= mask;
 	v >>= __ffs(mask);
 
@@ -61,10 +61,10 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
 			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
 			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-	v = __raw_readl(clk->clksel_reg);
+	v = omap2_clk_readl(clk, clk->clksel_reg);
 	/* Clear the bit to allow gatectrl */
 	v &= ~mask;
-	__raw_writel(v, clk->clksel_reg);
+	omap2_clk_writel(v, clk, clk->clksel_reg);
 }
 
 void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
@@ -79,10 +79,10 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
 			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
 			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-	v = __raw_readl(clk->clksel_reg);
+	v = omap2_clk_readl(clk, clk->clksel_reg);
 	/* Set the bit to deny gatectrl */
 	v |= mask;
-	__raw_writel(v, clk->clksel_reg);
+	omap2_clk_writel(v, clk, clk->clksel_reg);
 }
 
 const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
@@ -140,7 +140,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
 	rate = omap2_get_dpll_rate(clk);
 
 	/* regm4xen adds a multiplier of 4 to DPLL calculations */
-	v = __raw_readl(dd->control_reg);
+	v = omap2_clk_readl(clk, dd->control_reg);
 	if (v & OMAP4430_DPLL_REGM4XEN_MASK)
 		rate *= OMAP4430_REGM4XEN_MULT;
 
Signature · 1 line
1.7.9.5
#88 lore raw

PATCH v9 36/43 ARM: OMAP: hwmod: fix an incorrect clk type cast with _get_clkdm

In reply to Tero Kristo

If the main clock for a hwmod is of basic clock type, it is illegal to type cast this to clk_hw_omap and will result in bogus data. Fixed by checking the clock flags before attempting the type cast.

---
 arch/arm/mach-omap2/omap_hwmod.c |    2 ++
 1 file changed, 2 insertions(+)
arch/arm/mach-omap2/omap_hwmod.c +2 -0
index d35145d..5f8f587 100644
@@ -656,6 +656,8 @@ static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
 	if (oh->clkdm) {
 		return oh->clkdm;
 	} else if (oh->_clk) {
+		if (__clk_get_flags(oh->_clk) & CLK_IS_BASIC)
+			return NULL;
 		clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
 		return  clk->clkdm;
 	}
Signature · 1 line
1.7.9.5
#89 lore raw

PATCH v9 37/43 ARM: OMAP3: hwmod: initialize clkdm from clkdm_name

In reply to Tero Kristo

DT clocks are mostly missing clkdm info now, and this causes an issue with counter32k which makes its slave idlemode wrong and prevents core idle.

Fixed by initializing the hwmod clkdm pointers for omap3 also which makes sure the clkdm flag matching logic works properly.

This patch also changes the return value for _init_clkdm to 0 for incorrect clkdm_name, as this a warning, not a fatal error.

---
 arch/arm/mach-omap2/omap_hwmod.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/omap_hwmod.c +2 -1
index 5f8f587..ae33fae 100644
@@ -1546,7 +1546,7 @@ static int _init_clkdm(struct omap_hwmod *oh)
 	if (!oh->clkdm) {
 		pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
 			oh->name, oh->clkdm_name);
-		return -EINVAL;
+		return 0;
 	}
 
 	pr_debug("omap_hwmod: %s: associated to clkdm %s\n",
@@ -4117,6 +4117,7 @@ void __init omap_hwmod_init(void)
 		soc_ops.assert_hardreset = _omap2_assert_hardreset;
 		soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
 		soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
+		soc_ops.init_clkdm = _init_clkdm;
 	} else if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx()) {
 		soc_ops.enable_module = _omap4_enable_module;
 		soc_ops.disable_module = _omap4_disable_module;
Signature · 1 line
1.7.9.5
#90 lore raw

PATCH v9 38/43 ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT

In reply to Tero Kristo

This patch provides top level functionality for the DT clock initialization. Clock tree is initialized hierarchically starting from IP modules (CM/PRM/PRCM) going down towards individual clock nodes, and finally initializing clockdomains once all the clocks are ready.

---
 arch/arm/mach-omap2/prm.h        |    1 +
 arch/arm/mach-omap2/prm_common.c |  133 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 134 insertions(+)
arch/arm/mach-omap2/prm.h +1 -0
index ac25ae6..623db40 100644
@@ -18,6 +18,7 @@
 # ifndef __ASSEMBLER__
 extern void __iomem *prm_base;
 extern void omap2_set_globals_prm(void __iomem *prm);
+int of_prcm_init(void);
 # endif
 
 
arch/arm/mach-omap2/prm_common.c +133 -0

148 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#91 lore raw

PATCH v9 38/43 ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
arch/arm/mach-omap2/prm_common.c +0 -0
index 228b850..6fa74c6 100644

[...]

Quoted 21 lines
arch/arm/mach-omap2/prm_common.c +21 -0
+/*
+ * XXX: implementation for the regmap read/write should be moved to
+ * individual PRCM IP drivers, once those are available.
+ */
+static int ti_clk_regmap_read(void *context, unsigned int reg,
+			      unsigned int *val)
+{
+	void __iomem *mem = context;
+	*val = __raw_readl(mem + reg);
+	return 0;
+}
+
+static int ti_clk_regmap_write(void *context, unsigned int reg,
+			       unsigned int val)
+{
+	void __iomem *mem = context;
+	__raw_writel(val, mem + reg);
+	return 0;
+}
+
+static struct regmap_config ti_clk_regmap_config = {

arch/arm/mach-omap2/prm_common.c int prm_unregister(struct prm_ll_data *pld) · line 503

Quoted 10 lines
arch/arm/mach-omap2/prm_common.c +10 -0
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.reg_read = ti_clk_regmap_read,
+	.reg_write = ti_clk_regmap_write,
+	.fast_io = true,
+	.cache_type = REGCACHE_NONE,
+	.reg_format_endian = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian = REGMAP_ENDIAN_NATIVE,
+};

why not use regmap_mmio?

[...]

Signature · 2 lines
Regards,
Nishanth Menon
#92 lore raw

PATCH v9 38/43 ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT

Quoted 33 lines · Nishanth Menon

On 10/25/2013 10:57 AM, Tero Kristo wrote:
[...]

Quoted 4 lines
arch/arm/mach-omap2/prm_common.c +0 -0
index 228b850..6fa74c6 100644

[...]

Quoted 25 lines
arch/arm/mach-omap2/prm_common.c +25 -0
+/*
+ * XXX: implementation for the regmap read/write should be moved to
+ * individual PRCM IP drivers, once those are available.
+ */
+static int ti_clk_regmap_read(void *context, unsigned int reg,
+			      unsigned int *val)
+{
+	void __iomem *mem = context;
+	*val = __raw_readl(mem + reg);
+	return 0;
+}
+
+static int ti_clk_regmap_write(void *context, unsigned int reg,
+			       unsigned int val)
+{
+	void __iomem *mem = context;
+	__raw_writel(val, mem + reg);
+	return 0;
+}
+
+static struct regmap_config ti_clk_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.reg_read = ti_clk_regmap_read,
Quoted 8 lines

arch/arm/mach-omap2/prm_common.c int prm_unregister(struct prm_ll_data *pld) · line 503

Quoted 6 lines
arch/arm/mach-omap2/prm_common.c +6 -0
+	.reg_write = ti_clk_regmap_write,
+	.fast_io = true,
+	.cache_type = REGCACHE_NONE,
+	.reg_format_endian = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian = REGMAP_ENDIAN_NATIVE,
+};

why not use regmap_mmio?

I was thinking about using it, however this will allow us to route everything to their individual driver APIs. Anyway, I guess that is rather moot point so I will look at this again.

-Tero

Quoted 4 lines

[...]

#93 lore raw

PATCH v9 39/43 ARM: OMAP2+: io: use new clock init API

In reply to Tero Kristo

clk_init is now separated to a common function which gets called for all SoC:s, which initializes the DT clocks and calls the SoC specific clock init.

---
 arch/arm/mach-omap2/common.h |    2 +-
 arch/arm/mach-omap2/io.c     |   32 +++++++++++++++++++++++---------
 arch/arm/mach-omap2/timer.c  |    6 ++----
 3 files changed, 26 insertions(+), 14 deletions(-)
arch/arm/mach-omap2/common.h +1 -1
index 4a5684b..513d17a 100644
@@ -299,7 +299,7 @@ struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
 /* SoC specific clock initializer */
-extern int (*omap_clk_init)(void);
+int omap_clk_init(void);
 
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
arch/arm/mach-omap2/io.c +23 -9
index e360ddf..2f90f38 100644
@@ -55,10 +55,10 @@
 #include "prm44xx.h"
 
 /*
- * omap_clk_init: points to a function that does the SoC-specific
+ * omap_clk_soc_init: points to a function that does the SoC-specific
  * clock initializations
  */
-int (*omap_clk_init)(void);
+int (*omap_clk_soc_init)(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -419,7 +419,7 @@ void __init omap2420_init_early(void)
 	omap242x_clockdomains_init();
 	omap2420_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = omap2420_clk_init;
+	omap_clk_soc_init = omap2420_clk_init;
 }
 
 void __init omap2420_init_late(void)
@@ -448,7 +448,7 @@ void __init omap2430_init_early(void)
 	omap243x_clockdomains_init();
 	omap2430_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = omap2430_clk_init;
+	omap_clk_soc_init = omap2430_clk_init;
 }
 
 void __init omap2430_init_late(void)
@@ -482,7 +482,7 @@ void __init omap3_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = omap3xxx_clk_init;
+	omap_clk_soc_init = omap3xxx_clk_init;
 }
 
 void __init omap3430_init_early(void)
@@ -520,7 +520,7 @@ void __init ti81xx_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = omap3xxx_clk_init;
+	omap_clk_soc_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
@@ -581,7 +581,7 @@ void __init am33xx_init_early(void)
 	am33xx_clockdomains_init();
 	am33xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = am33xx_clk_init;
+	omap_clk_soc_init = am33xx_clk_init;
 }
 #endif
 
@@ -619,7 +619,7 @@ void __init omap4430_init_early(void)
 	omap44xx_clockdomains_init();
 	omap44xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = omap4xxx_clk_init;
+	omap_clk_soc_init = omap4xxx_clk_init;
 }
 
 void __init omap4430_init_late(void)
@@ -650,7 +650,7 @@ void __init omap5_init_early(void)
 	omap54xx_clockdomains_init();
 	omap54xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_init = omap5xxx_dt_clk_init;
+	omap_clk_soc_init = omap5xxx_dt_clk_init;
 }
 #endif
 
@@ -685,3 +685,17 @@ void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 		_omap2_init_reprogram_sdrc();
 	}
 }
+
+int __init omap_clk_init(void)
+{
+	int ret = 0;
+
+	if (!omap_clk_soc_init)
+		return 0;
+
+	ret = of_prcm_init();
+	if (!ret)
+		ret = omap_clk_soc_init();
+
+	return ret;
+}
arch/arm/mach-omap2/timer.c +2 -4
index 87a42de..9812709 100644
@@ -558,8 +558,7 @@ static inline void __init realtime_counter_init(void)
 			       clksrc_nr, clksrc_src, clksrc_prop)	\
 void __init omap##name##_gptimer_timer_init(void)			\
 {									\
-	if (omap_clk_init)						\
-		omap_clk_init();					\
+	omap_clk_init();					\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src,		\
@@ -570,8 +569,7 @@ void __init omap##name##_gptimer_timer_init(void)			\
 				clksrc_nr, clksrc_src, clksrc_prop)	\
 void __init omap##name##_sync32k_timer_init(void)		\
 {									\
-	if (omap_clk_init)						\
-		omap_clk_init();					\
+	omap_clk_init();					\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	/* Enable the use of clocksource="gp_timer" kernel parameter */	\
Signature · 1 line
1.7.9.5
#94 lore raw

PATCH v9 40/43 ARM: OMAP4: remove old clock data and link in new clock init code

In reply to Tero Kristo

OMAP4 clocks have now been moved to DT, thus remove the old data file and use the new init code under drivers/clk/omap/clk-44xx.c.

---
 arch/arm/mach-omap2/Makefile          |    2 +-
 arch/arm/mach-omap2/cclock44xx_data.c | 1734 ---------------------------------
 arch/arm/mach-omap2/io.c              |    2 +-
 3 files changed, 2 insertions(+), 1736 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/cclock44xx_data.c
arch/arm/mach-omap2/Makefile +1 -1
index afb457c..f518360 100644
@@ -184,7 +184,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o clkt34xx_dpll3m2.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock3517.o clock36xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= dpll3xxx.o cclock3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clkt_iclk.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common) cclock44xx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_AM33XX)		+= $(clock-common) dpll3xxx.o
 obj-$(CONFIG_SOC_AM33XX)		+= cclock33xx_data.o
arch/arm/mach-omap2/cclock44xx_data.c deleted +0 -1734

1,734 lines not on this page · raw message

arch/arm/mach-omap2/io.c +1 -1
index 2f90f38..22e0689 100644
@@ -619,7 +619,7 @@ void __init omap4430_init_early(void)
 	omap44xx_clockdomains_init();
 	omap44xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_soc_init = omap4xxx_clk_init;
+	omap_clk_soc_init = omap4xxx_dt_clk_init;
 }
 
 void __init omap4430_init_late(void)
Signature · 1 line
1.7.9.5
#95 lore raw

PATCH v9 41/43 ARM: OMAP: DRA7: Enable clock init

In reply to Tero Kristo

Initializes clock data from device tree.

---
 arch/arm/mach-omap2/io.c |    1 +
 1 file changed, 1 insertion(+)
arch/arm/mach-omap2/io.c +1 -0
index 22e0689..dd8c37b 100644
@@ -671,6 +671,7 @@ void __init dra7xx_init_early(void)
 	dra7xx_clockdomains_init();
 	dra7xx_hwmod_init();
 	omap_hwmod_init_postsetup();
+	omap_clk_soc_init = dra7xx_dt_clk_init;
 }
 #endif
 
Signature · 1 line
1.7.9.5
#96 lore raw

PATCH v9 42/43 ARM: AM33xx: remove old clock data and link in new clock init code

In reply to Tero Kristo

AM33xx clocks have now been moved to DT, thus remove the old data file and use the new init code under OMAP clock driver.

---
 arch/arm/mach-omap2/Makefile          |    1 -
 arch/arm/mach-omap2/cclock33xx_data.c | 1064 ---------------------------------
 arch/arm/mach-omap2/io.c              |    2 +-
 3 files changed, 1 insertion(+), 1066 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/cclock33xx_data.c
arch/arm/mach-omap2/Makefile +0 -1
index f518360..020079e 100644
@@ -187,7 +187,6 @@ obj-$(CONFIG_ARCH_OMAP3)		+= clkt_iclk.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_AM33XX)		+= $(clock-common) dpll3xxx.o
-obj-$(CONFIG_SOC_AM33XX)		+= cclock33xx_data.o
 obj-$(CONFIG_SOC_OMAP5)			+= $(clock-common)
 obj-$(CONFIG_SOC_OMAP5)			+= dpll3xxx.o dpll44xx.o
 
arch/arm/mach-omap2/cclock33xx_data.c deleted +0 -1064

1,064 lines not on this page · raw message

arch/arm/mach-omap2/io.c +1 -1
index dd8c37b..d7afb58 100644
@@ -581,7 +581,7 @@ void __init am33xx_init_early(void)
 	am33xx_clockdomains_init();
 	am33xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_soc_init = am33xx_clk_init;
+	omap_clk_soc_init = am33xx_dt_clk_init;
 }
 #endif
 
Signature · 1 line
1.7.9.5
#97 lore raw

PATCH v9 43/43 ARM: OMAP3: use DT clock init if DT data is available

In reply to Tero Kristo

OMAP3 platforms support both DT and non-DT boot at the moment, make the clock init work according to the used setup.

---
 arch/arm/mach-omap2/io.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/io.c +12 -1
index d7afb58..962cc04 100644
@@ -488,21 +488,29 @@ void __init omap3_init_early(void)
 void __init omap3430_init_early(void)
 {
 	omap3_init_early();
+	if (of_have_populated_dt())
+		omap_clk_soc_init = omap3430_dt_clk_init;
 }
 
 void __init omap35xx_init_early(void)
 {
 	omap3_init_early();
+	if (of_have_populated_dt())
+		omap_clk_soc_init = omap3430_dt_clk_init;
 }
 
 void __init omap3630_init_early(void)
 {
 	omap3_init_early();
+	if (of_have_populated_dt())
+		omap_clk_soc_init = omap3630_dt_clk_init;
 }
 
 void __init am35xx_init_early(void)
 {
 	omap3_init_early();
+	if (of_have_populated_dt())
+		omap_clk_soc_init = am35xx_dt_clk_init;
 }
 
 void __init ti81xx_init_early(void)
@@ -520,7 +528,10 @@ void __init ti81xx_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_soc_init = omap3xxx_clk_init;
+	if (of_have_populated_dt())
+		omap_clk_soc_init = ti81xx_dt_clk_init;
+	else
+		omap_clk_soc_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
Signature · 1 line
1.7.9.5
#98 lore raw

v9 cover ARM: TI SoC clock DT conversion

In reply to Tero Kristo

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)
Panda-ES: http://pastebin.com/dWMp7D1z (bandgap_fclk not found)
OMAP5-UEVM: http://pastebin.com/pHEx6Yzg (omap-gpmc 50000000.gpmc:
error: clk_get)
DRA7-EVM: http://pastebin.com/uYNQ6Sss
BeagleBone-Black: http://pastebin.com/biGXS2vi
AM335x-evm: http://pastebin.com/K7qwJpCb

Signature · 2 lines
Regards,
Nishanth Menon
#99 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 11 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 9 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

Quoted 8 lines
Quoted 1 line

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

Quoted 3 lines

Panda-ES: http://pastebin.com/dWMp7D1z (bandgap_fclk not found)
OMAP5-UEVM: http://pastebin.com/pHEx6Yzg (omap-gpmc 50000000.gpmc:
error: clk_get)

Again, I don't think this is related to this series, but rather to missing/wrong hwmod data.

-Tero

Quoted 5 lines

DRA7-EVM: http://pastebin.com/uYNQ6Sss
BeagleBone-Black: http://pastebin.com/biGXS2vi
AM335x-evm: http://pastebin.com/K7qwJpCb

#100 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 17 lines · Tero Kristo
Quoted 16 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

Quoted 7 lines
Quoted 3 lines

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

it does bootup yes.

Quoted 7 lines

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

no-dt: http://pastebin.com/bYP9fTzH
dt: http://pastebin.com/xHup4L9Y

dpll5 warning seems to be only in dt-boot?

Quoted 7 lines
Quoted 4 lines

Panda-ES: http://pastebin.com/dWMp7D1z (bandgap_fclk not found)
OMAP5-UEVM: http://pastebin.com/pHEx6Yzg (omap-gpmc 50000000.gpmc:
error: clk_get)

Again, I don't think this is related to this series, but rather to missing/wrong hwmod data.

seems the bandgap_fclk stuff is generated from drivers/thermal/ti-soc-thermal/omap4-thermal-data.c

anyways..

Quoted 9 lines

-Tero

Quoted 5 lines

DRA7-EVM: http://pastebin.com/uYNQ6Sss
BeagleBone-Black: http://pastebin.com/biGXS2vi
AM335x-evm: http://pastebin.com/K7qwJpCb

Btw, I also noticed the following section mimatches:
WARNING: vmlinux.o(.text+0x2abd4): Section mismatch in reference from the function prcm_probe() to the (unknown reference) .init.data:(unknown) The function prcm_probe() references
the (unknown reference) __initdata (unknown).
This is often because prcm_probe lacks a __initdata annotation or the annotation of (unknown) is wrong.

WARNING: vmlinux.o(.data+0x3e30): Section mismatch in reference from the variable prcm_driver to the (unknown reference) .init.data:(unknown) The variable prcm_driver references
the (unknown reference) __initdata (unknown)
If the reference is valid then annotate the
variable with __init* or __refdata (see linux/init.h) or name the variable:
*_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console

Signature · 2 lines
Regards,
Nishanth Menon
#101 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 32 lines · Nishanth Menon
Quoted 17 lines · Tero Kristo
Quoted 16 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

Quoted 7 lines
Quoted 3 lines

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

it does bootup yes.

Quoted 5 lines

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

Quoted 8 lines
Quoted 2 lines

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

no-dt: http://pastebin.com/bYP9fTzH
dt: http://pastebin.com/xHup4L9Y

dpll5 warning seems to be only in dt-boot?

Tracked this down: you were missing the following - looks like the conversion script might be missing converting the flags clock data over to dts?

diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 7e37e3e..c9b77c8 100644

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +1 -0
@@ -30,6 +30,7 @@
                compatible = "ti,omap3-dpll-clock";
                clocks = <&sys_ck>, <&sys_ck>;
                reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
+               ti,low-power-stop;
        };
 
        dpll5_m2_ck: dpll5_m2_ck {
Signature · 2 lines
Regards,
Nishanth Menon
#102 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 56 lines · Nishanth Menon
Quoted 32 lines · Nishanth Menon
Quoted 17 lines · Tero Kristo
Quoted 16 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

Quoted 7 lines
Quoted 3 lines

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

it does bootup yes.

Quoted 5 lines

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

Quoted 8 lines
Quoted 2 lines

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

no-dt: http://pastebin.com/bYP9fTzH
dt: http://pastebin.com/xHup4L9Y

dpll5 warning seems to be only in dt-boot?

Tracked this down: you were missing the following - looks like the conversion script might be missing converting the flags clock data over to dts?

diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 7e37e3e..c9b77c8 100644

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi line 36

Quoted 7 lines
arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +1 -0
@@ -30,6 +30,7 @@
                 compatible = "ti,omap3-dpll-clock";
                 clocks = <&sys_ck>, <&sys_ck>;
                 reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
+               ti,low-power-stop;
         };
 
         dpll5_m2_ck: dpll5_m2_ck {

Yea, seems I introduced the problem with the conversion script changes. The valid fix for this is actually at the end of this mail (this fixes both of the problems introduced, and also completes the fix you did), I will add the fixes to the next rev. Question to Mike/Paul/Tony/Benoit, shall I resend the complete series or only the two patches that will be changed?

----

(quoted diff) +0 -0

a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 7e37e3e..08db6d8 100644

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +2 -0
@@ -30,6 +30,8 @@
                 compatible = "ti,omap3-dpll-clock";
                 clocks = <&sys_ck>, <&sys_ck>;
                 reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
+               ti,low-power-stop;
+               ti,lock;
         };
 
         dpll5_m2_ck: dpll5_m2_ck {
(quoted diff) +0 -0

b/arch/arm/boot/dts/omap3xxx-clocks.dtsi
index 417bb03..e834b1c 100644

arch/arm/boot/dts/omap3xxx-clocks.dtsi +0 -2
@@ -335,8 +335,6 @@ cm: cm at 48004000 {
                 compatible = "ti,omap3-dpll-clock";
                 clocks = <&sys_ck>, <&dpll1_fck>;
                 reg = <0x0904>, <0x0924>, <0x0934>, <0x0940>;
-               ti,lock;
-               ti,low-power-bypass;
         };
 
         dpll1_x2_ck: dpll1_x2_ck {
#103 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 60 lines · Tero Kristo
Quoted 59 lines · Nishanth Menon
Quoted 32 lines · Nishanth Menon
Quoted 17 lines · Tero Kristo
Quoted 16 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

Quoted 7 lines
Quoted 3 lines

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

it does bootup yes.

Quoted 5 lines

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

Quoted 8 lines
Quoted 2 lines

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

no-dt: http://pastebin.com/bYP9fTzH
dt: http://pastebin.com/xHup4L9Y

dpll5 warning seems to be only in dt-boot?

Tracked this down: you were missing the following - looks like the conversion script might be missing converting the flags clock data over to dts?

diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 7e37e3e..c9b77c8 100644

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +1 -0
@@ -30,6 +30,7 @@
                 compatible = "ti,omap3-dpll-clock";
                 clocks = <&sys_ck>, <&sys_ck>;
                 reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
+               ti,low-power-stop;
         };
 
Quoted 9 lines

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi line 37

Quoted 4 lines
arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +0 -0
         dpll5_m2_ck: dpll5_m2_ck {

Yea, seems I introduced the problem with the conversion script changes. The valid fix for this is actually at the end of this mail (this fixes both of the problems introduced, and also completes the fix you did), I will add the fixes to the next rev.

One debug feedback:
reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
clocks = <&sys_ck>, <&sys_ck>;

we used indexing for varied register and clocks. however the register meaning per index changes based on type of DPLL. This was one painful thing to track down when debugging. the only robust option to debug was to use prints as part of register write/reads to ensure that right sequence was being followed.

I understand based on review comments for dtb size, we have removed the names, but we lost sane debug capability as well with that.

Signature · 2 lines
Regards,
Nishanth Menon
#104 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 75 lines · Nishanth Menon
Quoted 60 lines · Tero Kristo
Quoted 59 lines · Nishanth Menon
Quoted 32 lines · Nishanth Menon
Quoted 17 lines · Tero Kristo
Quoted 16 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

Quoted 7 lines
Quoted 3 lines

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

it does bootup yes.

Quoted 5 lines

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

Quoted 8 lines
Quoted 2 lines

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

no-dt: http://pastebin.com/bYP9fTzH
dt: http://pastebin.com/xHup4L9Y

dpll5 warning seems to be only in dt-boot?

Tracked this down: you were missing the following - looks like the conversion script might be missing converting the flags clock data over to dts?

diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 7e37e3e..c9b77c8 100644

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +1 -0
@@ -30,6 +30,7 @@
                 compatible = "ti,omap3-dpll-clock";
                 clocks = <&sys_ck>, <&sys_ck>;
                 reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
+               ti,low-power-stop;
         };
 
Quoted 9 lines

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi line 37

Quoted 4 lines
arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +0 -0
         dpll5_m2_ck: dpll5_m2_ck {

Yea, seems I introduced the problem with the conversion script changes. The valid fix for this is actually at the end of this mail (this fixes both of the problems introduced, and also completes the fix you did), I will add the fixes to the next rev.

One debug feedback:
reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
clocks = <&sys_ck>, <&sys_ck>;

Quoted 9 lines

we used indexing for varied register and clocks. however the register meaning per index changes based on type of DPLL. This was one painful thing to track down when debugging. the only robust option to debug was to use prints as part of register write/reads to ensure that right sequence was being followed.

I understand based on review comments for dtb size, we have removed the names, but we lost sane debug capability as well with that.

I dont have any further feedback at this point beyond what is already shared and so far my minimal tests have been good..

I have the following warnings:
sparse build warnings: http://pastebin.com/HZ1TWzyh
kernel-doc warnings: http://pastebin.com/JQwFEuaC

Hopefully, the next rev will not introducing nothing newer that what we have in mainline.

Signature · 2 lines
Regards,
Nishanth Menon
#105 lore raw

v9 cover ARM: TI SoC clock DT conversion

Quoted 89 lines · Nishanth Menon
Quoted 75 lines · Nishanth Menon
Quoted 60 lines · Tero Kristo
Quoted 59 lines · Nishanth Menon
Quoted 32 lines · Nishanth Menon
Quoted 17 lines · Tero Kristo
Quoted 16 lines · Nishanth Menon

On 10/25/2013 10:56 AM, Tero Kristo wrote:
<snip>

Quoted 10 lines

Testing done:
- omap3-beagle: boot + suspend/resume (ret + off)
- omap4-panda-es: boot + suspend/resume
- omap5-uevm: boot
- dra7-evm: boot
- am335x-bone: boot

Test branches available:

tree: https://github.com/t-kristo/linux-pm.git

<snip>

Quoted 2 lines

Fully functioning test branch: 3.12-rc6-dt-clks-v9

Quoted 7 lines
Quoted 3 lines

^^ I tested this branch (boot testing):
Beagle-XM: http://pastebin.com/50A1qtFq (crashes + clkdm issues, dpll5 failed to transition)

I just sent you a private email with a patch to try out, should fix the boot crash at least hopefully. Basically I forgot to convert one part of the kernel to the new regmap stuff for omap36xx.

it does bootup yes.

Quoted 5 lines

clkdm issues are caused by wrong data in omap_hwmod_3xxx_data.c, USB nodes are listing l3_init_clkdm for them, but this only exists on omap4+. Seems like some copy paste bug introduced by someone.

Quoted 8 lines
Quoted 2 lines

dpll5 part I am not too sure, can you check if the same happens with non-dt boot?

no-dt: http://pastebin.com/bYP9fTzH
dt: http://pastebin.com/xHup4L9Y

dpll5 warning seems to be only in dt-boot?

Tracked this down: you were missing the following - looks like the conversion script might be missing converting the flags clock data over to dts?

diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 7e37e3e..c9b77c8 100644

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +1 -0
@@ -30,6 +30,7 @@
                  compatible = "ti,omap3-dpll-clock";
                  clocks = <&sys_ck>, <&sys_ck>;
                  reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
+               ti,low-power-stop;
          };
 
Quoted 9 lines

arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi line 37

Quoted 4 lines
arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +0 -0
          dpll5_m2_ck: dpll5_m2_ck {

Yea, seems I introduced the problem with the conversion script changes. The valid fix for this is actually at the end of this mail (this fixes both of the problems introduced, and also completes the fix you did), I will add the fixes to the next rev.

One debug feedback:
reg = <0x0d04>, <0x0d24>, <0x0d34>, <0x0d4c>;
clocks = <&sys_ck>, <&sys_ck>;

Quoted 9 lines

we used indexing for varied register and clocks. however the register meaning per index changes based on type of DPLL. This was one painful thing to track down when debugging. the only robust option to debug was to use prints as part of register write/reads to ensure that right sequence was being followed.

I understand based on review comments for dtb size, we have removed the names, but we lost sane debug capability as well with that.

I dont have any further feedback at this point beyond what is already shared and so far my minimal tests have been good..

Quoted 6 lines

I have the following warnings:
sparse build warnings: http://pastebin.com/HZ1TWzyh
kernel-doc warnings: http://pastebin.com/JQwFEuaC

Hopefully, the next rev will not introducing nothing newer that what we have in mainline.

I will have a look at those for the next rev, will most likely post next against 3.13-rc1, there's no much point posting before.

-Tero