linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv12 00/49] ARM: TI SoC clock DT conversion
@ 2013-12-20 16:34 Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 01/49] clk: add support for registering clocks from description Tero Kristo
                   ` (18 more replies)
  0 siblings, 19 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Hopefully final post of this series. At least this is going to be the last
post this year as I will be going to x-mas vacation and won't be back before
Jan 2nd. This time I just sent the patches that have changes in them,
the missing ones are exactly the same as in v11.

Changes done:
 - most of the patches:
   * Some cosmetic documentation fixes
 - patch 06:
   * Changed register pointer types from 'u32 __iomem *' to 'void __iomem *'
 - patch 07,08,09:
   * Added check for clk->ll_ops being NULL (happens with statically built
     clock data), fixes the boot time crash issue noticed by Tony
 - patch 11:
   * Moved __clk_of_table extern declaration to clk-provider.h header file...
     Got flamed about this enough times now. :)
   * Type for the declaration changed also from array to single entry,
     and address for this used in code. This prevents compile time error:
     "array type has incomplete element type". Can't use pointer here either
     as this messes the address of the table.
   * ti_clk_retry_init() now has int return type, and checks for kzalloc
     failure
 - patch 12, 14, 23:
   * Added cleanup in case ti_clk_retry_init() fails
 - patch 17:
   * Fixed potential memory leak in failed init detected by sparse
 - patch 18:
   * Modified commit message to add some details about clockdomains
 - patch 43:
   * Changed register pointer types from 'u32 *' to 'void __iomem *'

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

Branches available at https://github.com/t-kristo/linux-pm.git:
- branch: 3.13-rc4-dt-clks-v12 : contains everything, shall me merged last
- branch: 3.13-rc4-dt-clks-v12-for-mike : drivers/clk changes
- branch: 3.13-rc4-dt-clks-v11-for-benoit : DT data only (from v11, no changes)

-Tero

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

* [PATCHv12 01/49] clk: add support for registering clocks from description
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 03/49] clk: divider: add support for registering divider clock from descriptor Tero Kristo
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mike Turquette <mturquette@linaro.org>

clk_register_desc is the primary interface for populating the clock tree
with new clock nodes. In time, this will replace the various hardware-specific
registration functions (e.g. clk_register_gate).

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk.c            |   71 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   22 +++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 2cf2ea6..29281f6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1905,6 +1905,77 @@ fail_out:
 EXPORT_SYMBOL_GPL(clk_register);
 
 /**
+ * clk_register_desc - register a new clock from its description
+ * @dev: device that is registering this clock
+ * @desc: description of the clock, may be __initdata or otherwise discarded
+ *
+ * clk_register_desc is the primary interface for populating the clock tree
+ * with new clock nodes. In time it will replace the various hardware-specific
+ * registration functions (e.g. clk_register_gate). clk_register_desc returns a
+ * pointer to the newly allocated struct clk which is an opaque cookie. Drivers
+ * must not dereference it except to check with IS_ERR.
+ */
+struct clk *clk_register_desc(struct device *dev, struct clk_desc *desc)
+{
+	int ret, i;
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	clk->hw = desc->register_func(dev, desc);
+	clk->hw->clk = clk;
+
+	/* _clk_register */
+	clk->name = kstrdup(desc->name, GFP_KERNEL);
+	if (!clk->name) {
+		ret = -ENOMEM;
+		goto fail_name;
+	}
+
+	clk->ops = desc->ops;
+	clk->flags = desc->flags;
+	clk->num_parents = desc->num_parents;
+
+	/* allocate local copy in case parent_names is __initdata */
+	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
+				    GFP_KERNEL);
+
+	if (!clk->parent_names) {
+		ret = -ENOMEM;
+		goto fail_parent_names;
+	}
+
+	/* copy each string name in case parent_names is __initdata */
+	for (i = 0; i < clk->num_parents; i++) {
+		clk->parent_names[i] = kstrdup(desc->parent_names[i],
+					       GFP_KERNEL);
+
+		if (!clk->parent_names[i]) {
+			ret = -ENOMEM;
+			goto fail_parent_names_copy;
+		}
+	}
+
+	ret = __clk_init(dev, clk);
+
+	if (!ret)
+		return clk;
+
+fail_parent_names_copy:
+	while (--i >= 0)
+		kfree(clk->parent_names[i]);
+	kfree(clk->parent_names);
+fail_parent_names:
+	kfree(clk->name);
+fail_name:
+	kfree(clk);
+	return ERR_PTR(ret);
+}
+
+/**
  * clk_unregister - unregister a currently registered clock
  * @clk: clock to unregister
  *
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7e59253..08a0da0 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -161,6 +161,27 @@ struct clk_init_data {
 };
 
 /**
+ * struct clk_desc - clock init descriptor for providing init time parameters
+ * for a clock.
+ * @name: clock name
+ * @ops: clock ops
+ * @parent_names: array of string names for all possible parents
+ * @num_parents: number of possible parents
+ * @flags: framework-level hints and quirks
+ * @register_func: function for parsing the clock descriptor and providing
+ *		   ready-to-register clk_hw
+ */
+struct clk_desc {
+	const char		*name;
+	const struct clk_ops	*ops;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	struct clk_hw *(*register_func)(struct device *dev,
+					struct clk_desc *desc);
+};
+
+/**
  * struct clk_hw - handle for traversing from a struct clk to its corresponding
  * hardware-specific structure.  struct clk_hw should be declared within struct
  * clk_foo and then referenced by the struct clk instance that uses struct
@@ -419,6 +440,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
  * error code; drivers must test for an error code after calling clk_register.
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk *clk_register_desc(struct device *dev, struct clk_desc *desc);
 struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
 void clk_unregister(struct clk *clk);
-- 
1.7.9.5

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

* [PATCHv12 03/49] clk: divider: add support for registering divider clock from descriptor
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 01/49] clk: add support for registering clocks from description Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 04/49] clk: mux: add support for registering mux " Tero Kristo
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

New clk_register_desc() call can be used to register this clock type now.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk-divider.c    |   34 ++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   22 ++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 8d3009e..8cfed5c 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -28,8 +28,12 @@
  * parent - fixed parent.  No clk_set_parent support
  */
 
+/* resolve struct clk_divider from inner struct clk_hw member */
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
+/* resolve struct clk_divider_desc from inner struct clk_desc member */
+#define to_hw_desc(_desc) container_of(_desc, struct clk_divider_desc, desc)
+
 #define div_mask(d)	((1 << ((d)->width)) - 1)
 
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
@@ -343,3 +347,33 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 			width, clk_divider_flags, table, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_divider_table);
+
+struct clk_hw *clk_register_divider_desc(struct device *dev,
+					 struct clk_desc *desc)
+{
+	struct clk_divider *divider;
+	struct clk_divider_desc *hw_desc;
+
+	hw_desc = to_hw_desc(desc);
+
+	/* allocate divider clock */
+	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
+	if (!divider)
+		return ERR_PTR(-ENOMEM);
+
+	/* populate struct clk_divider assignments */
+	divider->reg = hw_desc->reg;
+	divider->shift = hw_desc->shift;
+	divider->width = hw_desc->width;
+	divider->flags = hw_desc->flags;
+	divider->table = hw_desc->table;
+	divider->lock = hw_desc->lock;
+
+	if (!desc->ops)
+		desc->ops = &clk_divider_ops;
+
+	desc->flags |= CLK_IS_BASIC;
+
+	return &divider->hw;
+}
+EXPORT_SYMBOL_GPL(clk_register_divider_desc);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 232623d..bf89ab4 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -322,11 +322,33 @@ struct clk_divider {
 	spinlock_t	*lock;
 };
 
+/**
+ * struct clk_divider_desc - init descriptor for divider clock
+ * @desc:	handle between common and hardware-specific interfaces
+ * @reg:	register containing the divider
+ * @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
+ * @lock:	register lock
+ */
+struct clk_divider_desc {
+	struct clk_desc	desc;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u8		flags;
+	const struct clk_div_table	*table;
+	spinlock_t	*lock;
+};
+
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
 #define CLK_DIVIDER_ALLOW_ZERO		BIT(2)
 #define CLK_DIVIDER_HIWORD_MASK		BIT(3)
 
+struct clk_hw *clk_register_divider_desc(struct device *dev,
+					 struct clk_desc *desc);
+
 extern const struct clk_ops clk_divider_ops;
 struct clk *clk_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-- 
1.7.9.5

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

* [PATCHv12 04/49] clk: mux: add support for registering mux clock from descriptor
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 01/49] clk: add support for registering clocks from description Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 03/49] clk: divider: add support for registering divider clock from descriptor Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 05/49] clk: gate: add support for registering gate " Tero Kristo
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

New clk_register_desc() call can be used to register this clock type now.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk-mux.c        |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   20 ++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 4f96ff3..2cbed08 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -27,8 +27,12 @@
  * parent - parent is adjustable through clk_set_parent
  */
 
+/* resolve struct clk_mux from inner struct clk_hw member */
 #define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
 
+/* resolve struct clk_mux_desc from inner struct clk_desc member */
+#define to_hw_desc(_desc) container_of(_desc, struct clk_mux_desc, desc)
+
 static u8 clk_mux_get_parent(struct clk_hw *hw)
 {
 	struct clk_mux *mux = to_clk_mux(hw);
@@ -177,3 +181,36 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 				      NULL, lock);
 }
 EXPORT_SYMBOL_GPL(clk_register_mux);
+
+struct clk_hw *clk_register_mux_desc(struct device *dev, struct clk_desc *desc)
+{
+	struct clk_mux *mux;
+	struct clk_mux_desc *hw_desc;
+
+	hw_desc = to_hw_desc(desc);
+
+	/* allocate mux clock */
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return ERR_PTR(-ENOMEM);
+
+	/* populate struct clk_mux assignments */
+	mux->reg = hw_desc->reg;
+	mux->table = hw_desc->table;
+	mux->mask = hw_desc->mask;
+	mux->shift = hw_desc->shift;
+	mux->flags = hw_desc->flags;
+	mux->lock = hw_desc->lock;
+
+	if (!desc->ops) {
+		if (mux->flags & CLK_MUX_READ_ONLY)
+			desc->ops = &clk_mux_ro_ops;
+		else
+			desc->ops = &clk_mux_ops;
+	}
+
+	desc->flags |= CLK_IS_BASIC;
+
+	return &mux->hw;
+}
+EXPORT_SYMBOL_GPL(clk_register_mux_desc);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index bf89ab4..ea5281c 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -391,6 +391,25 @@ struct clk_mux {
 	spinlock_t	*lock;
 };
 
+/**
+ * struct clk_mux_desc - init descriptor for multiplexer clock
+ * @desc:	handle between common and hardware-specific interfaces
+ * @reg:	register controlling multiplexer
+ * @shift:	shift to multiplexer bit field
+ * @width:	width of multiplexer bit field
+ * @flags:	hardware-specific flags
+ * @lock:	register lock
+ */
+struct clk_mux_desc {
+	struct clk_desc	desc;
+	void __iomem	*reg;
+	u32		*table;
+	u32		mask;
+	u8		shift;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
 #define CLK_MUX_INDEX_ONE		BIT(0)
 #define CLK_MUX_INDEX_BIT		BIT(1)
 #define CLK_MUX_HIWORD_MASK		BIT(2)
@@ -399,6 +418,7 @@ struct clk_mux {
 extern const struct clk_ops clk_mux_ops;
 extern const struct clk_ops clk_mux_ro_ops;
 
+struct clk_hw *clk_register_mux_desc(struct device *dev, struct clk_desc *desc);
 struct clk *clk_register_mux(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
-- 
1.7.9.5

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

* [PATCHv12 05/49] clk: gate: add support for registering gate clock from descriptor
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (2 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 04/49] clk: mux: add support for registering mux " Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 06/49] clk: add support for low level register ops Tero Kristo
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

New clk_register_desc() call can be used to register this clock type now.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk-gate.c       |   31 +++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   18 ++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 4a58c55..3ec61d2 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -26,8 +26,12 @@
  * parent - fixed parent.  No clk_set_parent support
  */
 
+/* resolve struct clk_gate from inner struct clk_hw member */
 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
 
+/* resolve struct clk_gate_desc from inner struct clk_desc member */
+#define to_hw_desc(_desc) container_of(_desc, struct clk_gate_desc, desc)
+
 /*
  * It works on following logic:
  *
@@ -162,3 +166,30 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	return clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_gate);
+
+struct clk_hw *clk_register_gate_desc(struct device *dev, struct clk_desc *desc)
+{
+	struct clk_gate *gate;
+	struct clk_gate_desc *hw_desc;
+
+	hw_desc = to_hw_desc(desc);
+
+	/* allocate mux clock */
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	/* populate struct clk_gate assignments */
+	gate->reg = hw_desc->reg;
+	gate->bit_idx = hw_desc->bit_idx;
+	gate->flags = hw_desc->flags;
+	gate->lock = hw_desc->lock;
+
+	if (!desc->ops)
+		desc->ops = &clk_gate_ops;
+
+	desc->flags |= CLK_IS_BASIC;
+
+	return &gate->hw;
+}
+EXPORT_SYMBOL_GPL(clk_register_gate_desc);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index ea5281c..a4f14ae 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -268,10 +268,28 @@ struct clk_gate {
 	spinlock_t	*lock;
 };
 
+/**
+ * struct clk_gate_desc - init descriptor for gating clock
+ * @desc:	handle between common and hardware-specific interfaces
+ * @reg:	register controlling gate
+ * @bit_idx:	single bit controlling gate
+ * @flags:	hardware-specific flags
+ * @lock:	register lock
+ */
+struct clk_gate_desc {
+	struct clk_desc	desc;
+	void __iomem	*reg;
+	u8		bit_idx;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
 #define CLK_GATE_HIWORD_MASK		BIT(1)
 
 extern const struct clk_ops clk_gate_ops;
+struct clk_hw *clk_register_gate_desc(struct device *dev,
+				      struct clk_desc *desc);
 struct clk *clk_register_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
-- 
1.7.9.5

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

* [PATCHv12 06/49] clk: add support for low level register ops
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (3 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 05/49] clk: gate: add support for registering gate " Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-22 17:39   ` Gerhard Sittig
  2013-12-20 16:34 ` [PATCHv12 07/49] clk: divider: add support for low level ops Tero Kristo
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Low level register ops are needed for providing SoC or IP block specific
access routines to clock registers. Subsequent patches add support for
the low level ops for the individual clock drivers.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk.c            |   28 ++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   17 +++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 29281f6..8bcd1e0 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -34,6 +34,34 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+/**
+ * clk_readl_default - default clock register read support function
+ * @reg: register to read
+ *
+ * Default implementation for reading a clock register.
+ */
+static u32 clk_readl_default(void __iomem *reg)
+{
+	return readl(reg);
+}
+
+/**
+ * clk_writel_default - default clock register write support function
+ * @val: value to write
+ * @reg: register to write to
+ *
+ * Default implementation for writing a clock register.
+ */
+static void clk_writel_default(u32 val, void __iomem *reg)
+{
+	writel(val, reg);
+}
+
+struct clk_ll_ops clk_ll_ops_default = {
+	.clk_readl = clk_readl_default,
+	.clk_writel = clk_writel_default
+};
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a4f14ae..671dff4 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -198,6 +198,23 @@ struct clk_hw {
 	const struct clk_init_data *init;
 };
 
+/**
+ * struct clk_ll_ops - low-level register access ops for a clock
+ * @clk_readl: pointer to register read function
+ * @clk_writel: pointer to register write function
+ *
+ * Low-level register access ops are generally used by the basic clock types
+ * (clk-gate, clk-mux, clk-divider etc.) to provide support for various
+ * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be
+ * used by other hardware-specific clock drivers if needed.
+ */
+struct clk_ll_ops {
+	u32	(*clk_readl)(void __iomem *reg);
+	void	(*clk_writel)(u32 val, void __iomem *reg);
+};
+
+extern struct clk_ll_ops clk_ll_ops_default;
+
 /*
  * DOC: Basic clock implementations common to many platforms
  *
-- 
1.7.9.5

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

* [PATCHv12 07/49] clk: divider: add support for low level ops
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (4 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 06/49] clk: add support for low level register ops Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-22 17:52   ` Gerhard Sittig
  2013-12-20 16:34 ` [PATCHv12 08/49] clk: gate: " Tero Kristo
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Divider clock can now be registered to use low level register access ops.
Preferred initialization method is via clock description.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 8cfed5c..887e2d8 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -108,7 +108,12 @@ 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;
+	if (divider->ll_ops)
+		val = divider->ll_ops->clk_readl(divider->reg);
+	else
+		val = clk_readl(divider->reg);
+
+	val >>= divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -234,11 +239,17 @@ 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);
+		if (divider->ll_ops)
+			val = divider->ll_ops->clk_readl(divider->reg);
+		else
+			val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	clk_writel(val, divider->reg);
+	if (divider->ll_ops)
+		divider->ll_ops->clk_writel(val, divider->reg);
+	else
+		clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
@@ -291,6 +302,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	div->lock = lock;
 	div->hw.init = &init;
 	div->table = table;
+	div->ll_ops = &clk_ll_ops_default;
 
 	/* register the clock */
 	clk = clk_register(dev, &div->hw);
@@ -368,6 +380,10 @@ struct clk_hw *clk_register_divider_desc(struct device *dev,
 	divider->flags = hw_desc->flags;
 	divider->table = hw_desc->table;
 	divider->lock = hw_desc->lock;
+	divider->ll_ops = hw_desc->ll_ops;
+
+	if (!divider->ll_ops)
+		divider->ll_ops = &clk_ll_ops_default;
 
 	if (!desc->ops)
 		desc->ops = &clk_divider_ops;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 671dff4..f082a89 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -322,6 +322,7 @@ struct clk_div_table {
  *
  * @hw:		handle between common and hardware-specific interfaces
  * @reg:	register containing the divider
+ * @ll_ops:	low-level ops for accessing the register
  * @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
@@ -350,6 +351,7 @@ struct clk_div_table {
 struct clk_divider {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct clk_ll_ops	*ll_ops;
 	u8		shift;
 	u8		width;
 	u8		flags;
@@ -361,6 +363,7 @@ struct clk_divider {
  * struct clk_divider_desc - init descriptor for divider clock
  * @desc:	handle between common and hardware-specific interfaces
  * @reg:	register containing the divider
+ * @ll_ops:	low-level ops for accessing the register
  * @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
@@ -369,6 +372,7 @@ struct clk_divider {
 struct clk_divider_desc {
 	struct clk_desc	desc;
 	void __iomem	*reg;
+	struct clk_ll_ops	*ll_ops;
 	u8		shift;
 	u8		width;
 	u8		flags;
-- 
1.7.9.5

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

* [PATCHv12 08/49] clk: gate: add support for low level ops
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (5 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 07/49] clk: divider: add support for low level ops Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 09/49] clk: mux: " Tero Kristo
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Gate clock can now be registered to use low level register access ops.
Preferred initialization method is via clock description.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk-gate.c       |   20 +++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 3ec61d2..d4c94a7 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -62,7 +62,10 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = clk_readl(gate->reg);
+		if (gate->ll_ops)
+			reg = gate->ll_ops->clk_readl(gate->reg);
+		else
+			reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -70,7 +73,10 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	clk_writel(reg, gate->reg);
+	if (gate->ll_ops)
+		gate->ll_ops->clk_writel(reg, gate->reg);
+	else
+		clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -93,7 +99,10 @@ 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);
+	if (gate->ll_ops)
+		reg = gate->ll_ops->clk_readl(gate->reg);
+	else
+		reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
@@ -157,6 +166,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	gate->flags = clk_gate_flags;
 	gate->lock = lock;
 	gate->hw.init = &init;
+	gate->ll_ops = &clk_ll_ops_default;
 
 	clk = clk_register(dev, &gate->hw);
 
@@ -184,6 +194,10 @@ struct clk_hw *clk_register_gate_desc(struct device *dev, struct clk_desc *desc)
 	gate->bit_idx = hw_desc->bit_idx;
 	gate->flags = hw_desc->flags;
 	gate->lock = hw_desc->lock;
+	gate->ll_ops = hw_desc->ll_ops;
+
+	if (!gate->ll_ops)
+		gate->ll_ops = &clk_ll_ops_default;
 
 	if (!desc->ops)
 		desc->ops = &clk_gate_ops;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index f082a89..3923d46 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -262,6 +262,7 @@ void of_fixed_clk_setup(struct device_node *np);
  *
  * @hw:		handle between common and hardware-specific interfaces
  * @reg:	register controlling gate
+ * @ll_ops:	low-level ops for accessing the register
  * @bit_idx:	single bit controlling gate
  * @flags:	hardware-specific flags
  * @lock:	register lock
@@ -280,6 +281,7 @@ void of_fixed_clk_setup(struct device_node *np);
 struct clk_gate {
 	struct clk_hw hw;
 	void __iomem	*reg;
+	struct clk_ll_ops	*ll_ops;
 	u8		bit_idx;
 	u8		flags;
 	spinlock_t	*lock;
@@ -289,6 +291,7 @@ struct clk_gate {
  * struct clk_gate_desc - init descriptor for gating clock
  * @desc:	handle between common and hardware-specific interfaces
  * @reg:	register controlling gate
+ * @ll_ops:	low-level ops for accessing the register
  * @bit_idx:	single bit controlling gate
  * @flags:	hardware-specific flags
  * @lock:	register lock
@@ -296,6 +299,7 @@ struct clk_gate {
 struct clk_gate_desc {
 	struct clk_desc	desc;
 	void __iomem	*reg;
+	struct clk_ll_ops	*ll_ops;
 	u8		bit_idx;
 	u8		flags;
 	spinlock_t	*lock;
-- 
1.7.9.5

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

* [PATCHv12 09/49] clk: mux: add support for low level ops
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (6 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 08/49] clk: gate: " Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 11/49] CLK: ti: add init support for clock IP blocks Tero Kristo
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Multiplexer clock can now be registered to use low level register access ops.
Preferred initialization method is via clock description.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk-mux.c        |   24 +++++++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 2cbed08..ed3bc36 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -46,7 +46,12 @@ 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;
+	if (mux->ll_ops)
+		val = mux->ll_ops->clk_readl(mux->reg);
+	else
+		val = clk_readl(mux->reg);
+
+	val >>= mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -93,11 +98,19 @@ 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);
+		if (mux->ll_ops)
+			val = mux->ll_ops->clk_readl(mux->reg);
+		else
+			val = clk_readl(mux->reg);
+
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	clk_writel(val, mux->reg);
+
+	if (mux->ll_ops)
+		mux->ll_ops->clk_writel(val, mux->reg);
+	else
+		clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
@@ -159,6 +172,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 	mux->lock = lock;
 	mux->table = table;
 	mux->hw.init = &init;
+	mux->ll_ops = &clk_ll_ops_default;
 
 	clk = clk_register(dev, &mux->hw);
 
@@ -201,6 +215,10 @@ struct clk_hw *clk_register_mux_desc(struct device *dev, struct clk_desc *desc)
 	mux->shift = hw_desc->shift;
 	mux->flags = hw_desc->flags;
 	mux->lock = hw_desc->lock;
+	mux->ll_ops = hw_desc->ll_ops;
+
+	if (!mux->ll_ops)
+		mux->ll_ops = &clk_ll_ops_default;
 
 	if (!desc->ops) {
 		if (mux->flags & CLK_MUX_READ_ONLY)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 3923d46..629163c 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -408,6 +408,7 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
  *
  * @hw:		handle between common and hardware-specific interfaces
  * @reg:	register controlling multiplexer
+ * @ll_ops:	low-level ops for accessing the register
  * @shift:	shift to multiplexer bit field
  * @width:	width of mutliplexer bit field
  * @flags:	hardware-specific flags
@@ -427,6 +428,7 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 struct clk_mux {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct clk_ll_ops	*ll_ops;
 	u32		*table;
 	u32		mask;
 	u8		shift;
@@ -438,6 +440,7 @@ struct clk_mux {
  * struct clk_mux_desc - init descriptor for multiplexer clock
  * @desc:	handle between common and hardware-specific interfaces
  * @reg:	register controlling multiplexer
+ * @ll_ops:	low-level ops for accesing the register
  * @shift:	shift to multiplexer bit field
  * @width:	width of multiplexer bit field
  * @flags:	hardware-specific flags
@@ -446,6 +449,7 @@ struct clk_mux {
 struct clk_mux_desc {
 	struct clk_desc	desc;
 	void __iomem	*reg;
+	struct clk_ll_ops	*ll_ops;
 	u32		*table;
 	u32		mask;
 	u8		shift;
-- 
1.7.9.5

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

* [PATCHv12 11/49] CLK: ti: add init support for clock IP blocks
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (7 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 09/49] clk: mux: " Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 12/49] CLK: TI: Add DPLL clock support Tero Kristo
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

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.

This patch also introduces a helper function for the TI clock drivers
to get register info from DT and append the master IP info to this.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/clk.c            |    4 +-
 drivers/clk/ti/clk.c         |  112 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |    2 +
 include/linux/clk/ti.h       |   20 ++++++++
 4 files changed, 135 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8bcd1e0..c0521be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2203,8 +2203,6 @@ struct of_clk_provider {
 	void *data;
 };
 
-extern struct of_device_id __clk_of_table[];
-
 static const struct of_device_id __clk_of_table_sentinel
 	__used __section(__clk_of_table_end);
 
@@ -2344,7 +2342,7 @@ void __init of_clk_init(const struct of_device_id *matches)
 	struct device_node *np;
 
 	if (!matches)
-		matches = __clk_of_table;
+		matches = &__clk_of_table;
 
 	for_each_matching_node_and_match(np, matches, &match) {
 		of_clk_init_cb_t clk_init_cb = match->data;
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index ef1a7cd..e16da3a 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -19,10 +19,15 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/list.h>
 
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
+static int ti_dt_clk_memmap_index;
+struct clk_ll_ops *ti_clk_ll_ops;
+
 /**
  * ti_dt_clocks_register - register DT alias clocks during boot
  * @oclks: list of clocks to register
@@ -53,3 +58,110 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
 		}
 	}
 }
+
+struct clk_init_item {
+	struct device_node *node;
+	struct clk_hw *hw;
+	ti_of_clk_init_cb_t func;
+	struct list_head link;
+};
+
+static LIST_HEAD(retry_list);
+
+/**
+ * ti_clk_retry_init - retries a failed clock init at later phase
+ * @node: device not for the clock
+ * @hw: partially initialized clk_hw struct for the clock
+ * @func: init function to be called for the clock
+ *
+ * Adds a failed clock init to the retry list. The retry list is parsed
+ * once all the other clocks have been initialized.
+ */
+int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
+			      ti_of_clk_init_cb_t func)
+{
+	struct clk_init_item *retry;
+
+	pr_debug("%s: adding to retry list...\n", node->name);
+	retry = kzalloc(sizeof(*retry), GFP_KERNEL);
+	if (!retry)
+		return -ENOMEM;
+
+	retry->node = node;
+	retry->func = func;
+	retry->hw = hw;
+	list_add(&retry->link, &retry_list);
+
+	return 0;
+}
+
+/**
+ * ti_clk_get_reg_addr - get register address for a clock register
+ * @node: device node for the clock
+ * @index: register index from the clock node
+ *
+ * Builds clock register address from device tree information. This
+ * is a struct of type clk_omap_reg.
+ */
+void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
+{
+	struct clk_omap_reg *reg;
+	u32 val;
+	u32 tmp;
+
+	reg = (struct clk_omap_reg *)&tmp;
+	reg->index = ti_dt_clk_memmap_index;
+
+	if (of_property_read_u32_index(node, "reg", index, &val)) {
+		pr_err("%s must have reg[%d]!\n", node->name, index);
+		return NULL;
+	}
+
+	reg->offset = val;
+
+	return (void __iomem *)tmp;
+}
+
+/**
+ * ti_dt_clk_init_provider - init master clock provider
+ * @parent: master node
+ * @index: internal index for clk_reg_ops
+ *
+ * Initializes a master clock IP block and its child clock nodes.
+ * Regmap is provided for accessing the register space for the
+ * IP block and all the clocks under it.
+ */
+void ti_dt_clk_init_provider(struct device_node *parent, int index)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	struct device_node *clocks;
+	of_clk_init_cb_t clk_init_cb;
+	struct clk_init_item *retry;
+	struct clk_init_item *tmp;
+
+	ti_dt_clk_memmap_index = index;
+
+	/* get clocks for this parent */
+	clocks = of_get_child_by_name(parent, "clocks");
+	if (!clocks) {
+		pr_err("%s missing 'clocks' child node.\n", parent->name);
+		return;
+	}
+
+	for_each_child_of_node(clocks, np) {
+		match = of_match_node(&__clk_of_table, np);
+		if (!match)
+			continue;
+		clk_init_cb = (of_clk_init_cb_t)match->data;
+		pr_debug("%s: initializing: %s\n", __func__, np->name);
+		clk_init_cb(np);
+	}
+
+	list_for_each_entry_safe(retry, tmp, &retry_list, link) {
+		pr_debug("retry-init: %s\n", retry->node->name);
+		retry->func(retry->hw, retry->node);
+		list_del(&retry->link);
+		kfree(retry);
+	}
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 629163c..2d2c03d 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -584,6 +584,8 @@ struct clk_onecell_data {
 	unsigned int clk_num;
 };
 
+extern struct of_device_id __clk_of_table;
+
 #define CLK_OF_DECLARE(name, compat, fn)			\
 	static const struct of_device_id __clk_of_table_##name	\
 		__used __section(__clk_of_table)		\
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index df94c24..6750d25 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -36,7 +36,27 @@ struct ti_dt_clk {
 		.node_name = name,	\
 	}
 
+/* Maximum number of clock memmaps */
+#define CLK_MAX_MEMMAPS			4
 
+typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
+
+/**
+ * struct clk_omap_reg - OMAP register declaration
+ * @offset: offset from the master IP module base address
+ * @index: index of the master IP module
+ */
+struct clk_omap_reg {
+	u16 offset;
+	u16 index;
+};
+
+extern struct clk_ll_ops *ti_clk_ll_ops;
+
+void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+void ti_dt_clk_init_provider(struct device_node *np, int index);
+int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
+		      ti_of_clk_init_cb_t func);
 
 #endif
-- 
1.7.9.5

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

* [PATCHv12 12/49] CLK: TI: Add DPLL clock support
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (8 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 11/49] CLK: ti: add init support for clock IP blocks Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 14/49] clk: ti: add composite " Tero Kristo
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/ti/dpll.txt          |   75 +++
 arch/arm/mach-omap2/clock.h                        |  164 +-----
 arch/arm/mach-omap2/clock3xxx.h                    |    2 -
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/dpll.c                              |  558 ++++++++++++++++++++
 include/linux/clk/ti.h                             |  172 ++++++
 6 files changed, 807 insertions(+), 166 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/dpll.txt
 create mode 100644 drivers/clk/ti/dpll.c

diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt
new file mode 100644
index 0000000..30bfdb7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt
@@ -0,0 +1,75 @@
+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
+	"mult-div1" - contains the multiplier / divider register base address
+	"autoidle" - contains the autoidle register base address (optional)
+  ti,am3-* dpll types do not have autoidle register
+
+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>;
+	};
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 82916cc..b345f3e 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -21,6 +21,7 @@
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
 
 struct omap_clk {
 	u16				cpu;
@@ -37,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 = {				\
@@ -178,141 +178,6 @@ struct clksel {
 	const struct clksel_rate *rates;
 };
 
-/**
- * struct dpll_data - DPLL registers and integration data
- * @mult_div1_reg: register containing the DPLL M and N bitfields
- * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
- * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
- * @clk_bypass: struct clk pointer to the clock's bypass clock input
- * @clk_ref: struct clk pointer to the clock's reference clock input
- * @control_reg: register containing the DPLL mode bitfield
- * @enable_mask: mask of the DPLL mode bitfield in @control_reg
- * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
- * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
- * @last_rounded_m4xen: cache of the last M4X result of
- *			omap4_dpll_regm4xen_round_rate()
- * @last_rounded_lpmode: cache of the last lpmode result of
- *			 omap4_dpll_lpmode_recalc()
- * @max_multiplier: maximum valid non-bypass multiplier value (actual)
- * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
- * @min_divider: minimum valid non-bypass divider value (actual)
- * @max_divider: maximum valid non-bypass divider value (actual)
- * @modes: possible values of @enable_mask
- * @autoidle_reg: register containing the DPLL autoidle mode bitfield
- * @idlest_reg: register containing the DPLL idle status bitfield
- * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
- * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
- * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
- * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
- * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
- * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
- * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
- * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
- * @flags: DPLL type/features (see below)
- *
- * Possible values for @flags:
- * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
- *
- * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
- *
- * XXX Some DPLLs have multiple bypass inputs, so it's not technically
- * correct to only have one @clk_bypass pointer.
- *
- * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
- * @last_rounded_n) should be separated from the runtime-fixed fields
- * and placed into a different structure, so that the runtime-fixed data
- * can be placed into read-only space.
- */
-struct dpll_data {
-	void __iomem		*mult_div1_reg;
-	u32			mult_mask;
-	u32			div1_mask;
-	struct clk		*clk_bypass;
-	struct clk		*clk_ref;
-	void __iomem		*control_reg;
-	u32			enable_mask;
-	unsigned long		last_rounded_rate;
-	u16			last_rounded_m;
-	u8			last_rounded_m4xen;
-	u8			last_rounded_lpmode;
-	u16			max_multiplier;
-	u8			last_rounded_n;
-	u8			min_divider;
-	u16			max_divider;
-	u8			modes;
-	void __iomem		*autoidle_reg;
-	void __iomem		*idlest_reg;
-	u32			autoidle_mask;
-	u32			freqsel_mask;
-	u32			idlest_mask;
-	u32			dco_mask;
-	u32			sddiv_mask;
-	u32			lpmode_mask;
-	u32			m4xen_mask;
-	u8			auto_recal_bit;
-	u8			recal_en_bit;
-	u8			recal_st_bit;
-	u8			flags;
-};
-
-/*
- * 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 - OMAP struct clk
- * @node: list_head connecting this clock into the full clock list
- * @enable_reg: register to write to enable the clock (see @enable_bit)
- * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
- * @flags: see "struct clk.flags possibilities" above
- * @clksel_reg: for clksel clks, register va containing src/divisor select
- * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
- * @clksel: for clksel clks, pointer to struct clksel for this clock
- * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
- * @clkdm_name: clockdomain name that this clock is contained in
- * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
- * @rate_offset: bitshift for rate selection bitfield (OMAP1 only)
- * @src_offset: bitshift for source selection bitfield (OMAP1 only)
- *
- * XXX @rate_offset, @src_offset should probably be removed and OMAP1
- * clock code converted to use clksel.
- *
- */
-
-struct clk_hw_omap_ops;
-
-struct clk_hw_omap {
-	struct clk_hw		hw;
-	struct list_head	node;
-	unsigned long		fixed_rate;
-	u8			fixed_div;
-	void __iomem		*enable_reg;
-	u8			enable_bit;
-	u8			flags;
-	void __iomem		*clksel_reg;
-	u32			clksel_mask;
-	const struct clksel	*clksel;
-	struct dpll_data	*dpll_data;
-	const char		*clkdm_name;
-	struct clockdomain	*clkdm;
-	const struct clk_hw_omap_ops	*ops;
-};
-
 struct clk_hw_omap_ops {
 	void			(*find_idlest)(struct clk_hw_omap *oclk,
 					void __iomem **idlest_reg,
@@ -348,36 +213,13 @@ unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
 #define OMAP4XXX_EN_DPLL_FRBYPASS		0x6
 #define OMAP4XXX_EN_DPLL_LOCKED			0x7
 
-/* 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
-#define DPLL_LOCKED		0x7
-
-/* DPLL Type and DCO Selection Flags */
-#define DPLL_J_TYPE		0x1
-
-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-			unsigned long *parent_rate);
-unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
-int omap3_noncore_dpll_enable(struct clk_hw *hw);
-void omap3_noncore_dpll_disable(struct clk_hw *hw);
-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long parent_rate);
 u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
 void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
 void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
-unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
-				    unsigned long parent_rate);
 int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk);
 void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
 void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
-unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-				unsigned long parent_rate);
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-				    unsigned long target_rate,
-				    unsigned long *parent_rate);
 
-void omap2_init_clk_clkdm(struct clk_hw *clk);
 void __init omap2_clk_disable_clkdm_control(void);
 
 /* clkt_clksel.c public functions */
@@ -396,7 +238,6 @@ int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
 extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
 extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
 
-u8 omap2_init_dpll_parent(struct clk_hw *hw);
 unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
 
 int omap2_dflt_clk_enable(struct clk_hw *hw);
@@ -408,7 +249,6 @@ void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
 void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
 				void __iomem **idlest_reg,
 				u8 *idlest_bit, u8 *idlest_val);
-void omap2_init_clk_hw_omap_clocks(struct clk *clk);
 int omap2_clk_enable_autoidle_all(void);
 int omap2_clk_disable_autoidle_all(void);
 int omap2_clk_allow_idle(struct clk *clk);
@@ -433,10 +273,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_omap3_dpll;
 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_omap4_dpllmx;
 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;
diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
index 8cd4b0a..dab90e2 100644
--- a/arch/arm/mach-omap2/clock3xxx.h
+++ b/arch/arm/mach-omap2/clock3xxx.h
@@ -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);
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 1825f7f..05af5d8 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o
+obj-y					+= clk.o dpll.o
 endif
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
new file mode 100644
index 0000000..7e498a4
--- /dev/null
+++ b/drivers/clk/ti/dpll.c
@@ -0,0 +1,558 @@
+/*
+ * OMAP DPLL clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define DPLL_HAS_AUTOIDLE	0x1
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+	defined(CONFIG_SOC_DRA7XX)
+static const struct clk_ops dpll_m4xen_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.recalc_rate	= &omap4_dpll_regm4xen_recalc,
+	.round_rate	= &omap4_dpll_regm4xen_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+#endif
+
+static const struct clk_ops dpll_core_ck_ops = {
+	.recalc_rate	= &omap3_dpll_recalc,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+
+#ifdef CONFIG_ARCH_OMAP3
+static const struct clk_ops omap3_dpll_core_ck_ops = {
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+#endif
+
+static const struct clk_ops dpll_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+
+static const struct clk_ops dpll_no_gate_ck_ops = {
+	.recalc_rate	= &omap3_dpll_recalc,
+	.get_parent	= &omap2_init_dpll_parent,
+	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+};
+
+#ifdef CONFIG_ARCH_OMAP3
+static const struct clk_ops omap3_dpll_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+
+static const struct clk_ops omap3_dpll_per_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.set_rate	= &omap3_dpll4_set_rate,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+#endif
+
+static const struct clk_ops dpll_x2_ck_ops = {
+	.recalc_rate	= &omap3_clkoutx2_recalc,
+};
+
+/**
+ * ti_clk_register_dpll - low level registration of a DPLL clock
+ * @hw: hardware clock definition for the clock
+ * @node: device node for the clock
+ *
+ * Finalizes DPLL registration process. In case a failure (clk-ref or
+ * clk-bypass is missing), the clock is added to retry list and
+ * the initialization is retried on later stage.
+ */
+static void __init ti_clk_register_dpll(struct clk_hw *hw,
+					struct device_node *node)
+{
+	struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
+	struct dpll_data *dd = clk_hw->dpll_data;
+	struct clk *clk;
+
+	dd->clk_ref = of_clk_get(node, 0);
+	dd->clk_bypass = of_clk_get(node, 1);
+
+	if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) {
+		pr_debug("clk-ref or clk-bypass missing for %s, retry later\n",
+			 node->name);
+		if (!ti_clk_retry_init(node, hw, ti_clk_register_dpll))
+			return;
+
+		goto cleanup;
+	}
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (!IS_ERR(clk)) {
+		omap2_init_clk_hw_omap_clocks(clk);
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		kfree(clk_hw->hw.init->parent_names);
+		kfree(clk_hw->hw.init);
+		return;
+	}
+
+cleanup:
+	kfree(clk_hw->dpll_data);
+	kfree(clk_hw->hw.init->parent_names);
+	kfree(clk_hw->hw.init);
+	kfree(clk_hw);
+}
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+	defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX)
+/**
+ * ti_clk_register_dpll_x2 - Registers a DPLLx2 clock
+ * @node: device node for this clock
+ * @ops: clk_ops for this clock
+ * @hw_ops: clk_hw_ops for this clock
+ *
+ * Initializes a DPLL x 2 clock from device tree data.
+ */
+static void ti_clk_register_dpll_x2(struct device_node *node,
+				    const struct clk_ops *ops,
+				    const struct clk_hw_omap_ops *hw_ops)
+{
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+	struct clk_hw_omap *clk_hw;
+	const char *name = node->name;
+	const char *parent_name;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s must have parent\n", node->name);
+		return;
+	}
+
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	if (!clk_hw)
+		return;
+
+	clk_hw->ops = hw_ops;
+	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);
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	}
+}
+#endif
+
+/**
+ * of_ti_dpll_setup - Setup function for OMAP DPLL clocks
+ * @node: device node containing the DPLL info
+ * @ops: ops for the DPLL
+ * @ddt: DPLL data template to use
+ * @init_flags: flags for controlling init types
+ *
+ * Initializes a DPLL clock from device tree data.
+ */
+static void __init of_ti_dpll_setup(struct device_node *node,
+				    const struct clk_ops *ops,
+				    const struct dpll_data *ddt,
+				    u8 init_flags)
+{
+	struct clk_hw_omap *clk_hw = NULL;
+	struct clk_init_data *init = NULL;
+	const char **parent_names = NULL;
+	struct dpll_data *dd = NULL;
+	int i;
+	u8 dpll_mode = 0;
+
+	dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	init = kzalloc(sizeof(*init), GFP_KERNEL);
+	if (!dd || !clk_hw || !init)
+		goto cleanup;
+
+	memcpy(dd, ddt, sizeof(*dd));
+
+	clk_hw->dpll_data = dd;
+	clk_hw->ops = &clkhwops_omap3_dpll;
+	clk_hw->hw.init = init;
+	clk_hw->flags = MEMMAP_ADDRESSING;
+
+	init->name = node->name;
+	init->ops = ops;
+
+	init->num_parents = of_clk_get_parent_count(node);
+	if (init->num_parents < 1) {
+		pr_err("%s must have parent(s)\n", node->name);
+		goto cleanup;
+	}
+
+	parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
+	if (!parent_names)
+		goto cleanup;
+
+	for (i = 0; i < init->num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	init->parent_names = parent_names;
+
+	dd->control_reg = ti_clk_get_reg_addr(node, 0);
+	dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
+	dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
+
+	if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg)
+		goto cleanup;
+
+	if (init_flags & DPLL_HAS_AUTOIDLE) {
+		dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
+		if (!dd->autoidle_reg)
+			goto cleanup;
+	}
+
+	if (of_property_read_bool(node, "ti,low-power-stop"))
+		dpll_mode |= 1 << DPLL_LOW_POWER_STOP;
+
+	if (of_property_read_bool(node, "ti,low-power-bypass"))
+		dpll_mode |= 1 << DPLL_LOW_POWER_BYPASS;
+
+	if (of_property_read_bool(node, "ti,lock"))
+		dpll_mode |= 1 << DPLL_LOCKED;
+
+	if (dpll_mode)
+		dd->modes = dpll_mode;
+
+	ti_clk_register_dpll(&clk_hw->hw, node);
+	return;
+
+cleanup:
+	kfree(dd);
+	kfree(parent_names);
+	kfree(init);
+	kfree(clk_hw);
+}
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+	defined(CONFIG_SOC_DRA7XX)
+static void __init of_ti_omap4_dpll_x2_setup(struct device_node *node)
+{
+	ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx);
+}
+CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
+	       of_ti_omap4_dpll_x2_setup);
+#endif
+
+#ifdef CONFIG_SOC_AM33XX
+static void __init of_ti_am3_dpll_x2_setup(struct device_node *node)
+{
+	ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, NULL);
+}
+CLK_OF_DECLARE(ti_am3_dpll_x2_clock, "ti,am3-dpll-x2-clock",
+	       of_ti_am3_dpll_x2_setup);
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static void __init of_ti_omap3_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.freqsel_mask = 0xf0,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
+	       of_ti_omap3_dpll_setup);
+
+static void __init of_ti_omap3_core_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 16,
+		.div1_mask = 0x7f << 8,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.freqsel_mask = 0xf0,
+	};
+
+	of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock",
+	       of_ti_omap3_core_dpll_setup);
+
+static void __init of_ti_omap3_per_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1 << 1,
+		.enable_mask = 0x7 << 16,
+		.autoidle_mask = 0x7 << 3,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.freqsel_mask = 0xf00000,
+		.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock",
+	       of_ti_omap3_per_dpll_setup);
+
+static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1 << 1,
+		.enable_mask = 0x7 << 16,
+		.autoidle_mask = 0x7 << 3,
+		.mult_mask = 0xfff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 4095,
+		.max_divider = 128,
+		.min_divider = 1,
+		.sddiv_mask = 0xff << 24,
+		.dco_mask = 0xe << 20,
+		.flags = DPLL_J_TYPE,
+		.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock",
+	       of_ti_omap3_per_jtype_dpll_setup);
+#endif
+
+static void __init of_ti_omap4_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock",
+	       of_ti_omap4_dpll_setup);
+
+static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock",
+	       of_ti_omap4_core_dpll_setup);
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+	defined(CONFIG_SOC_DRA7XX)
+static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.m4xen_mask = 0x800,
+		.lpmode_mask = 1 << 10,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock",
+	       of_ti_omap4_m4xen_dpll_setup);
+
+static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0xfff << 8,
+		.div1_mask = 0xff,
+		.max_multiplier = 4095,
+		.max_divider = 256,
+		.min_divider = 1,
+		.sddiv_mask = 0xff << 24,
+		.flags = DPLL_J_TYPE,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock",
+	       of_ti_omap4_jtype_dpll_setup);
+#endif
+
+static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock",
+	       of_ti_am3_no_gate_dpll_setup);
+
+static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 4095,
+		.max_divider = 256,
+		.min_divider = 2,
+		.flags = DPLL_J_TYPE,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock",
+	       of_ti_am3_jtype_dpll_setup);
+
+static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.flags = DPLL_J_TYPE,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock,
+	       "ti,am3-dpll-no-gate-j-type-clock",
+	       of_ti_am3_no_gate_jtype_dpll_setup);
+
+static void __init of_ti_am3_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup);
+
+static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
+{
+	const struct dpll_data dd = {
+		.idlest_mask = 0x1,
+		.enable_mask = 0x7,
+		.autoidle_mask = 0x7,
+		.mult_mask = 0x7ff << 8,
+		.div1_mask = 0x7f,
+		.max_multiplier = 2047,
+		.max_divider = 128,
+		.min_divider = 1,
+		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	};
+
+	of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
+	       of_ti_am3_core_dpll_setup);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 6750d25..0ce1131 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -18,6 +18,153 @@
 #include <linux/clkdev.h>
 
 /**
+ * struct dpll_data - DPLL registers and integration data
+ * @mult_div1_reg: register containing the DPLL M and N bitfields
+ * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
+ * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
+ * @clk_bypass: struct clk pointer to the clock's bypass clock input
+ * @clk_ref: struct clk pointer to the clock's reference clock input
+ * @control_reg: register containing the DPLL mode bitfield
+ * @enable_mask: mask of the DPLL mode bitfield in @control_reg
+ * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
+ * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
+ * @last_rounded_m4xen: cache of the last M4X result of
+ *			omap4_dpll_regm4xen_round_rate()
+ * @last_rounded_lpmode: cache of the last lpmode result of
+ *			 omap4_dpll_lpmode_recalc()
+ * @max_multiplier: maximum valid non-bypass multiplier value (actual)
+ * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
+ * @min_divider: minimum valid non-bypass divider value (actual)
+ * @max_divider: maximum valid non-bypass divider value (actual)
+ * @modes: possible values of @enable_mask
+ * @autoidle_reg: register containing the DPLL autoidle mode bitfield
+ * @idlest_reg: register containing the DPLL idle status bitfield
+ * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
+ * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
+ * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
+ * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
+ * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
+ * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
+ * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
+ * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
+ * @flags: DPLL type/features (see below)
+ *
+ * Possible values for @flags:
+ * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
+ *
+ * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
+ *
+ * XXX Some DPLLs have multiple bypass inputs, so it's not technically
+ * correct to only have one @clk_bypass pointer.
+ *
+ * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
+ * @last_rounded_n) should be separated from the runtime-fixed fields
+ * and placed into a different structure, so that the runtime-fixed data
+ * can be placed into read-only space.
+ */
+struct dpll_data {
+	void __iomem		*mult_div1_reg;
+	u32			mult_mask;
+	u32			div1_mask;
+	struct clk		*clk_bypass;
+	struct clk		*clk_ref;
+	void __iomem		*control_reg;
+	u32			enable_mask;
+	unsigned long		last_rounded_rate;
+	u16			last_rounded_m;
+	u8			last_rounded_m4xen;
+	u8			last_rounded_lpmode;
+	u16			max_multiplier;
+	u8			last_rounded_n;
+	u8			min_divider;
+	u16			max_divider;
+	u8			modes;
+	void __iomem		*autoidle_reg;
+	void __iomem		*idlest_reg;
+	u32			autoidle_mask;
+	u32			freqsel_mask;
+	u32			idlest_mask;
+	u32			dco_mask;
+	u32			sddiv_mask;
+	u32			lpmode_mask;
+	u32			m4xen_mask;
+	u8			auto_recal_bit;
+	u8			recal_en_bit;
+	u8			recal_st_bit;
+	u8			flags;
+};
+
+struct clk_hw_omap_ops;
+
+/**
+ * struct clk_hw_omap - OMAP struct clk
+ * @node: list_head connecting this clock into the full clock list
+ * @enable_reg: register to write to enable the clock (see @enable_bit)
+ * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
+ * @flags: see "struct clk.flags possibilities" above
+ * @clksel_reg: for clksel clks, register va containing src/divisor select
+ * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
+ * @clksel: for clksel clks, pointer to struct clksel for this clock
+ * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
+ * @clkdm_name: clockdomain name that this clock is contained in
+ * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
+ * @ops: clock ops for this clock
+ */
+struct clk_hw_omap {
+	struct clk_hw		hw;
+	struct list_head	node;
+	unsigned long		fixed_rate;
+	u8			fixed_div;
+	void __iomem		*enable_reg;
+	u8			enable_bit;
+	u8			flags;
+	void __iomem		*clksel_reg;
+	u32			clksel_mask;
+	const struct clksel	*clksel;
+	struct dpll_data	*dpll_data;
+	const char		*clkdm_name;
+	struct clockdomain	*clkdm;
+	const struct clk_hw_omap_ops	*ops;
+};
+
+/*
+ * 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.
+ * MEMMAP_ADDRESSING: Use memmap addressing to access clock registers.
+ */
+#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)
+#define MEMMAP_ADDRESSING	(1 << 6)
+
+/* 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
+#define DPLL_LOCKED		0x7
+
+/* 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
@@ -53,10 +200,35 @@ struct clk_omap_reg {
 
 extern struct clk_ll_ops *ti_clk_ll_ops;
 
+#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);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+					 unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+				    unsigned long target_rate,
+				    unsigned long *parent_rate);
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+			   unsigned long *parent_rate);
+void omap2_init_clk_clkdm(struct clk_hw *clk);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+				    unsigned long parent_rate);
+int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
+			 unsigned long parent_rate);
+
 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, int index);
 int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
 		      ti_of_clk_init_cb_t func);
 
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+
 #endif
-- 
1.7.9.5

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

* [PATCHv12 14/49] clk: ti: add composite clock support
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (9 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 12/49] CLK: TI: Add DPLL clock support Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 17/49] CLK: TI: add support for gate clock Tero Kristo
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/ti/composite.txt     |   54 ++++
 arch/arm/mach-omap2/clock.h                        |    3 -
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/composite.c                         |  269 ++++++++++++++++++++
 include/linux/clk/ti.h                             |   12 +
 5 files changed, 336 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/composite.txt
 create mode 100644 drivers/clk/ti/composite.c

diff --git a/Documentation/devicetree/bindings/clock/ti/composite.txt b/Documentation/devicetree/bindings/clock/ti/composite.txt
new file mode 100644
index 0000000..5f43c47
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/composite.txt
@@ -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>;
+};
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index b345f3e..6bd72b5 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -240,9 +240,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);
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 533efb4..a4a7595 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -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
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
new file mode 100644
index 0000000..6539b65
--- /dev/null
+++ b/drivers/clk/ti/composite.c
@@ -0,0 +1,269 @@
+/*
+ * TI composite clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#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;
+	struct device_node *node;
+	int type;
+	struct clk_hw *hw;
+	struct list_head link;
+};
+
+static const char * __initconst component_clk_types[] = {
+	"gate", "divider", "mux"
+};
+
+static LIST_HEAD(component_clks);
+
+static struct device_node *_get_component_node(struct device_node *node, int i)
+{
+	int rc;
+	struct of_phandle_args clkspec;
+
+	rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i,
+					&clkspec);
+	if (rc)
+		return NULL;
+
+	return clkspec.np;
+}
+
+static struct component_clk *_lookup_component(struct device_node *node)
+{
+	struct component_clk *comp;
+
+	list_for_each_entry(comp, &component_clks, link) {
+		if (comp->node == node)
+			return comp;
+	}
+	return NULL;
+}
+
+struct clk_hw_omap_comp {
+	struct clk_hw hw;
+	struct device_node *comp_nodes[CLK_COMPONENT_TYPE_MAX];
+	struct component_clk *comp_clks[CLK_COMPONENT_TYPE_MAX];
+};
+
+static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx)
+{
+	if (!clk)
+		return NULL;
+
+	if (!clk->comp_clks[idx])
+		return NULL;
+
+	return clk->comp_clks[idx]->hw;
+}
+
+#define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw)
+
+static void __init ti_clk_register_composite(struct clk_hw *hw,
+					     struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw);
+	struct component_clk *comp;
+	int num_parents = 0;
+	const char **parent_names = NULL;
+	int i;
+
+	/* Check for presence of each component clock */
+	for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
+		if (!cclk->comp_nodes[i])
+			continue;
+
+		comp = _lookup_component(cclk->comp_nodes[i]);
+		if (!comp) {
+			pr_debug("component %s not ready for %s, retry\n",
+				 cclk->comp_nodes[i]->name, node->name);
+			if (!ti_clk_retry_init(node, hw,
+					       ti_clk_register_composite))
+				return;
+
+			goto cleanup;
+		}
+		if (cclk->comp_clks[comp->type] != NULL) {
+			pr_err("duplicate component types for %s (%s)!\n",
+			       node->name, component_clk_types[comp->type]);
+			goto cleanup;
+		}
+
+		cclk->comp_clks[comp->type] = comp;
+
+		/* Mark this node as found */
+		cclk->comp_nodes[i] = NULL;
+	}
+
+	/* All components exists, proceed with registration */
+	for (i = CLK_COMPONENT_TYPE_MAX - 1; i >= 0; i--) {
+		comp = cclk->comp_clks[i];
+		if (!comp)
+			continue;
+		if (comp->num_parents) {
+			num_parents = comp->num_parents;
+			parent_names = comp->parent_names;
+			break;
+		}
+	}
+
+	if (!num_parents) {
+		pr_err("%s: no parents found for %s!\n", __func__, node->name);
+		goto cleanup;
+	}
+
+	clk = clk_register_composite(NULL, node->name,
+				     parent_names, num_parents,
+				     _get_hw(cclk, CLK_COMPONENT_TYPE_MUX),
+				     &clk_mux_ops,
+				     _get_hw(cclk, CLK_COMPONENT_TYPE_DIVIDER),
+				     &ti_composite_divider_ops,
+				     _get_hw(cclk, CLK_COMPONENT_TYPE_GATE),
+				     &ti_composite_gate_ops, 0);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+cleanup:
+	/* Free component clock list entries */
+	for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
+		if (!cclk->comp_clks[i])
+			continue;
+		list_del(&cclk->comp_clks[i]->link);
+		kfree(cclk->comp_clks[i]);
+	}
+
+	kfree(cclk);
+}
+
+static void __init of_ti_composite_clk_setup(struct device_node *node)
+{
+	int num_clks;
+	int i;
+	struct clk_hw_omap_comp *cclk;
+
+	/* Number of component clocks to be put inside this clock */
+	num_clks = of_clk_get_parent_count(node);
+
+	if (num_clks < 1) {
+		pr_err("composite clk %s must have component(s)\n", node->name);
+		return;
+	}
+
+	cclk = kzalloc(sizeof(*cclk), GFP_KERNEL);
+	if (!cclk)
+		return;
+
+	/* Get device node pointers for each component clock */
+	for (i = 0; i < num_clks; i++)
+		cclk->comp_nodes[i] = _get_component_node(node, i);
+
+	ti_clk_register_composite(&cclk->hw, node);
+}
+CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
+	       of_ti_composite_clk_setup);
+
+/**
+ * ti_clk_add_component - add a component clock to the pool
+ * @node: device node of the component clock
+ * @hw: hardware clock definition for the component clock
+ * @type: type of the component clock
+ *
+ * Adds a component clock to the list of available components, so that
+ * it can be registered by a composite clock.
+ */
+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("component-clock %s must have parent(s)\n", 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;
+}
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 7036387..4d4ec49 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -164,6 +164,14 @@ struct clk_hw_omap {
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE		0x1
 
+/* Composite clock component types */
+enum {
+	CLK_COMPONENT_TYPE_GATE = 0,
+	CLK_COMPONENT_TYPE_DIVIDER,
+	CLK_COMPONENT_TYPE_MUX,
+	CLK_COMPONENT_TYPE_MAX,
+};
+
 /**
  * struct ti_dt_clk - OMAP DT clock alias declarations
  * @lk: clock lookup definition
@@ -221,6 +229,9 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
 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 __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
@@ -228,6 +239,7 @@ void ti_dt_clk_init_provider(struct device_node *np, int index);
 int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
 		      ti_of_clk_init_cb_t func);
 int of_ti_clk_autoidle_setup(struct device_node *node);
+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);
-- 
1.7.9.5

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

* [PATCHv12 17/49] CLK: TI: add support for gate clock
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (10 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 14/49] clk: ti: add composite " Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 18/49] CLK: TI: add support for clockdomain binding Tero Kristo
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/ti/gate.txt          |   85 +++++++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/gate.c                              |  247 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    6 +
 4 files changed, 339 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/gate.txt
 create mode 100644 drivers/clk/ti/gate.c

diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt
new file mode 100644
index 0000000..125281a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/gate.txt
@@ -0,0 +1,85 @@
+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
+
+Optional properties:
+- ti,bit-shift : bit shift for programming the clock gate, invalid for
+		 ti,clkdm-gate-clock type
+- 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>;
+	};
+
+	uart4_fck_am35xx: uart4_fck_am35xx {
+		#clock-cells = <0>;
+		compatible = "ti,wait-gate-clock";
+		clocks = <&core_48m_fck>;
+		reg = <0x0a00>;
+		ti,bit-shift = <23>;
+	};
+
+	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;
+	};
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index f57fc4b..7cba389 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -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
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
new file mode 100644
index 0000000..12ce4d3
--- /dev/null
+++ b/drivers/clk/ti/gate.c
@@ -0,0 +1,247 @@
+/*
+ * OMAP gate clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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>
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk);
+
+static const struct clk_ops omap_gate_clkdm_clk_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_clkops_enable_clkdm,
+	.disable	= &omap2_clkops_disable_clkdm,
+};
+
+static const struct clk_ops omap_gate_clk_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap36xx_gate_clk_enable_with_hsdiv_restore,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+/**
+ * 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 = ti_clk_ll_ops->clk_readl(parent->reg);
+		dummy_v = orig_v;
+
+		/* Write any other value different from the Read value */
+		dummy_v ^= (1 << parent->shift);
+		ti_clk_ll_ops->clk_writel(dummy_v, parent->reg);
+
+		/* Write the original divider */
+		ti_clk_ll_ops->clk_writel(orig_v, parent->reg);
+	}
+
+	return ret;
+}
+
+static void __init _of_ti_gate_clk_setup(struct device_node *node,
+					 const struct clk_ops *ops,
+					 const struct clk_hw_omap_ops *hw_ops)
+{
+	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)
+		return;
+
+	clk_hw->hw.init = &init;
+
+	init.name = clk_name;
+	init.ops = ops;
+
+	if (ops != &omap_gate_clkdm_clk_ops) {
+		clk_hw->enable_reg = ti_clk_get_reg_addr(node, 0);
+		if (!clk_hw->enable_reg)
+			goto cleanup;
+
+		if (!of_property_read_u32(node, "ti,bit-shift", &val))
+			clk_hw->enable_bit = val;
+	}
+
+	clk_hw->ops = hw_ops;
+
+	clk_hw->flags = MEMMAP_ADDRESSING;
+
+	if (of_clk_get_parent_count(node) != 1) {
+		pr_err("%s must have 1 parent\n", clk_name);
+		goto cleanup;
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	if (of_property_read_bool(node, "ti,set-rate-parent"))
+		init.flags |= CLK_SET_RATE_PARENT;
+
+	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;
+	}
+
+cleanup:
+	kfree(clk_hw);
+}
+
+static void __init
+_of_ti_composite_gate_clk_setup(struct device_node *node,
+				const struct clk_hw_omap_ops *hw_ops)
+{
+	struct clk_hw_omap *gate;
+	u32 val = 0;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return;
+
+	gate->enable_reg = ti_clk_get_reg_addr(node, 0);
+	if (!gate->enable_reg)
+		goto cleanup;
+
+	of_property_read_u32(node, "ti,bit-shift", &val);
+
+	gate->enable_bit = val;
+	gate->ops = hw_ops;
+	gate->flags = MEMMAP_ADDRESSING;
+
+	if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
+		return;
+
+cleanup:
+	kfree(gate);
+}
+
+static void __init
+of_ti_composite_no_wait_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_composite_gate_clk_setup(node, NULL);
+}
+CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock",
+	       of_ti_composite_no_wait_gate_clk_setup);
+
+static void __init of_ti_composite_interface_clk_setup(struct device_node *node)
+{
+	_of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait);
+}
+CLK_OF_DECLARE(ti_composite_interface_clk, "ti,composite-interface-clock",
+	       of_ti_composite_interface_clk_setup);
+
+static void __init of_ti_composite_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_composite_gate_clk_setup(node, &clkhwops_wait);
+}
+CLK_OF_DECLARE(ti_composite_gate_clk, "ti,composite-gate-clock",
+	       of_ti_composite_gate_clk_setup);
+
+
+static void __init of_ti_clkdm_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_gate_clk_setup(node, &omap_gate_clkdm_clk_ops, NULL);
+}
+CLK_OF_DECLARE(ti_clkdm_gate_clk, "ti,clkdm-gate-clock",
+	       of_ti_clkdm_gate_clk_setup);
+
+static void __init of_ti_hsdiv_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_gate_clk_setup(node, &omap_gate_clk_hsdiv_restore_ops,
+			      &clkhwops_wait);
+}
+CLK_OF_DECLARE(ti_hsdiv_gate_clk, "ti,hsdiv-gate-clock",
+	       of_ti_hsdiv_gate_clk_setup);
+
+static void __init of_ti_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_gate_clk_setup(node, &omap_gate_clk_ops, NULL);
+}
+CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup)
+
+static void __init of_ti_wait_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_gate_clk_setup(node, &omap_gate_clk_ops, &clkhwops_wait);
+}
+CLK_OF_DECLARE(ti_wait_gate_clk, "ti,wait-gate-clock",
+	       of_ti_wait_gate_clk_setup);
+
+#ifdef CONFIG_ARCH_OMAP3
+static void __init of_ti_am35xx_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_gate_clk_setup(node, &omap_gate_clk_ops,
+			      &clkhwops_am35xx_ipss_module_wait);
+}
+CLK_OF_DECLARE(ti_am35xx_gate_clk, "ti,am35xx-gate-clock",
+	       of_ti_am35xx_gate_clk_setup);
+
+static void __init of_ti_dss_gate_clk_setup(struct device_node *node)
+{
+	_of_ti_gate_clk_setup(node, &omap_gate_clk_ops,
+			      &clkhwops_omap3430es2_dss_usbhost_wait);
+}
+CLK_OF_DECLARE(ti_dss_gate_clk, "ti,dss-gate-clock",
+	       of_ti_dss_gate_clk_setup);
+#endif
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 4d4ec49..e38e9e1 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -227,6 +227,8 @@ 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);
@@ -251,5 +253,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
-- 
1.7.9.5

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

* [PATCHv12 18/49] CLK: TI: add support for clockdomain binding
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (11 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 17/49] CLK: TI: add support for gate clock Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 23/49] CLK: TI: DRA7: Add APLL support Tero Kristo
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

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. Clockdomain
itself is rather misleading name for the hardware functionality, as at
least on OMAP4 / OMAP5 / DRA7 the clockdomains can be collections of either
clocks and/or IP blocks, thus idle-domain or such might be more appropriate.
For most cases on these SoCs, the kernel doesn't even need the information
and the mappings can be ignored.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/ti/clockdomain.txt   |   24 +++++++
 drivers/clk/ti/Makefile                            |    3 +-
 drivers/clk/ti/clockdomain.c                       |   70 ++++++++++++++++++++
 include/linux/clk/ti.h                             |    1 +
 4 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/clockdomain.txt
 create mode 100644 drivers/clk/ti/clockdomain.c

diff --git a/Documentation/devicetree/bindings/clock/ti/clockdomain.txt b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt
new file mode 100644
index 0000000..cb76b3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt
@@ -0,0 +1,24 @@
+Binding for Texas Instruments clockdomain.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1] in consumer role.
+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. This binding doesn't define a new clock
+binding type, it is used to group existing clock nodes under
+hardware hierarchy.
+
+[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>;
+	};
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 7cba389..67056fb 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -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
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
new file mode 100644
index 0000000..f1e0038
--- /dev/null
+++ b/drivers/clk/ti/clockdomain.c
@@ -0,0 +1,70 @@
+/*
+ * OMAP clockdomain support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+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");
+
+	for (i = 0; i < num_clks; i++) {
+		clk = of_clk_get(node, i);
+		if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+			pr_warn("can't setup clkdm for basic clk %s\n",
+				__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);
+	}
+}
+
+static struct of_device_id ti_clkdm_match_table[] __initdata = {
+	{ .compatible = "ti,clockdomain" },
+	{ }
+};
+
+/**
+ * ti_dt_clockdomains_setup - setup device tree clockdomains
+ *
+ * Initializes clockdomain nodes for a SoC. This parses through all the
+ * nodes with compatible = "ti,clockdomain", and add the clockdomain
+ * info for all the clocks listed under these. This function shall be
+ * called after rest of the DT clock init has completed and all
+ * clock nodes have been registered.
+ */
+void __init ti_dt_clockdomains_setup(void)
+{
+	struct device_node *np;
+	for_each_matching_node(np, ti_clkdm_match_table) {
+		of_ti_clockdomain_setup(np);
+	}
+}
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index e38e9e1..9f2cedc 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -238,6 +238,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 void ti_dt_clk_init_provider(struct device_node *np, int index);
+void ti_dt_clockdomains_setup(void);
 int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
 		      ti_of_clk_init_cb_t func);
 int of_ti_clk_autoidle_setup(struct device_node *node);
-- 
1.7.9.5

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

* [PATCHv12 23/49] CLK: TI: DRA7: Add APLL support
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (12 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 18/49] CLK: TI: add support for clockdomain binding Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 16:34 ` [PATCHv12 43/49] ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT Tero Kristo
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

From: J Keerthy <j-keerthy@ti.com>

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.

Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/ti/apll.txt          |   31 +++
 drivers/clk/ti/Makefile                            |    2 +-
 drivers/clk/ti/apll.c                              |  221 ++++++++++++++++++++
 3 files changed, 253 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/apll.txt
 create mode 100644 drivers/clk/ti/apll.c

diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt
new file mode 100644
index 0000000..7faf5a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/apll.txt
@@ -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";
+	};
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 935e5d2..3d71e1e 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -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
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
new file mode 100644
index 0000000..79bcc34
--- /dev/null
+++ b/drivers/clk/ti/apll.c
@@ -0,0 +1,221 @@
+/*
+ * OMAP APLL clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * J Keerthy <j-keerthy@ti.com>
+ *
+ * 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/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/delay.h>
+
+#define APLL_FORCE_LOCK 0x1
+#define APLL_AUTO_IDLE	0x2
+#define MAX_APLL_WAIT_TRIES		1000000
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static int dra7_apll_enable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	int r = 0, i = 0;
+	struct dpll_data *ad;
+	const char *clk_name;
+	u8 state = 1;
+	u32 v;
+
+	ad = clk->dpll_data;
+	if (!ad)
+		return -EINVAL;
+
+	clk_name = __clk_get_name(clk->hw.clk);
+
+	state <<= __ffs(ad->idlest_mask);
+
+	/* Check is already locked */
+	v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+
+	if ((v & ad->idlest_mask) == state)
+		return r;
+
+	v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+	v &= ~ad->enable_mask;
+	v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask);
+	ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+
+	state <<= __ffs(ad->idlest_mask);
+
+	while (1) {
+		v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+		if ((v & ad->idlest_mask) == state)
+			break;
+		if (i > MAX_APLL_WAIT_TRIES)
+			break;
+		i++;
+		udelay(1);
+	}
+
+	if (i == MAX_APLL_WAIT_TRIES) {
+		pr_warn("clock: %s failed transition to '%s'\n",
+			clk_name, (state) ? "locked" : "bypassed");
+	} else {
+		pr_debug("clock: %s transition to '%s' in %d loops\n",
+			 clk_name, (state) ? "locked" : "bypassed", i);
+
+		r = 0;
+	}
+
+	return r;
+}
+
+static void dra7_apll_disable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct dpll_data *ad;
+	u8 state = 1;
+	u32 v;
+
+	ad = clk->dpll_data;
+
+	state <<= __ffs(ad->idlest_mask);
+
+	v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+	v &= ~ad->enable_mask;
+	v |= APLL_AUTO_IDLE << __ffs(ad->enable_mask);
+	ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+}
+
+static int dra7_apll_is_enabled(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct dpll_data *ad;
+	u32 v;
+
+	ad = clk->dpll_data;
+
+	v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+	v &= ad->enable_mask;
+
+	v >>= __ffs(ad->enable_mask);
+
+	return v == APLL_AUTO_IDLE ? 0 : 1;
+}
+
+static u8 dra7_init_apll_parent(struct clk_hw *hw)
+{
+	return 0;
+}
+
+static const struct clk_ops apll_ck_ops = {
+	.enable		= &dra7_apll_enable,
+	.disable	= &dra7_apll_disable,
+	.is_enabled	= &dra7_apll_is_enabled,
+	.get_parent	= &dra7_init_apll_parent,
+};
+
+static void __init omap_clk_register_apll(struct clk_hw *hw,
+					  struct device_node *node)
+{
+	struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
+	struct dpll_data *ad = clk_hw->dpll_data;
+	struct clk *clk;
+
+	ad->clk_ref = of_clk_get(node, 0);
+	ad->clk_bypass = of_clk_get(node, 1);
+
+	if (IS_ERR(ad->clk_ref) || IS_ERR(ad->clk_bypass)) {
+		pr_debug("clk-ref or clk-bypass for %s not ready, retry\n",
+			 node->name);
+		if (!ti_clk_retry_init(node, hw, omap_clk_register_apll))
+			return;
+
+		goto cleanup;
+	}
+
+	clk = clk_register(NULL, &clk_hw->hw);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		kfree(clk_hw->hw.init->parent_names);
+		kfree(clk_hw->hw.init);
+		return;
+	}
+
+cleanup:
+	kfree(clk_hw->dpll_data);
+	kfree(clk_hw->hw.init->parent_names);
+	kfree(clk_hw->hw.init);
+	kfree(clk_hw);
+}
+
+static void __init of_dra7_apll_setup(struct device_node *node)
+{
+	struct dpll_data *ad = NULL;
+	struct clk_hw_omap *clk_hw = NULL;
+	struct clk_init_data *init = NULL;
+	const char **parent_names = NULL;
+	int i;
+
+	ad = kzalloc(sizeof(*ad), GFP_KERNEL);
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+	init = kzalloc(sizeof(*init), GFP_KERNEL);
+	if (!ad || !clk_hw || !init)
+		goto cleanup;
+
+	clk_hw->dpll_data = ad;
+	clk_hw->hw.init = init;
+	clk_hw->flags = MEMMAP_ADDRESSING;
+
+	init->name = node->name;
+	init->ops = &apll_ck_ops;
+
+	init->num_parents = of_clk_get_parent_count(node);
+	if (init->num_parents < 1) {
+		pr_err("dra7 apll %s must have parent(s)\n", node->name);
+		goto cleanup;
+	}
+
+	parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
+
+	for (i = 0; i < init->num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	init->parent_names = parent_names;
+
+	ad->control_reg = ti_clk_get_reg_addr(node, 0);
+	ad->idlest_reg = ti_clk_get_reg_addr(node, 1);
+
+	if (!ad->control_reg || !ad->idlest_reg)
+		goto cleanup;
+
+	ad->idlest_mask = 0x1;
+	ad->enable_mask = 0x3;
+
+	omap_clk_register_apll(&clk_hw->hw, node);
+	return;
+
+cleanup:
+	kfree(parent_names);
+	kfree(ad);
+	kfree(clk_hw);
+	kfree(init);
+}
+CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup);
-- 
1.7.9.5

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

* [PATCHv12 43/49] ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (13 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 23/49] CLK: TI: DRA7: Add APLL support Tero Kristo
@ 2013-12-20 16:34 ` Tero Kristo
  2013-12-20 18:37 ` [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tony Lindgren
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2013-12-20 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/prm.h        |    1 +
 arch/arm/mach-omap2/prm_common.c |   66 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index ac25ae6..623db40 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -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
 
 
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index a2e1174..f568502 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -23,6 +23,10 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
 
 #include "soc.h"
 #include "prm2xxx_3xxx.h"
@@ -30,6 +34,7 @@
 #include "prm3xxx.h"
 #include "prm44xx.h"
 #include "common.h"
+#include "clock.h"
 
 /*
  * OMAP_PRCM_MAX_NR_PENDING_REG: maximum number of PRM_IRQ*_MPU regs
@@ -464,3 +469,64 @@ int prm_unregister(struct prm_ll_data *pld)
 
 	return 0;
 }
+
+static struct of_device_id omap_prcm_dt_match_table[] = {
+	{ .compatible = "ti,am3-prcm" },
+	{ .compatible = "ti,am3-scrm" },
+	{ .compatible = "ti,am4-prcm" },
+	{ .compatible = "ti,am4-scrm" },
+	{ .compatible = "ti,omap3-prm" },
+	{ .compatible = "ti,omap3-cm" },
+	{ .compatible = "ti,omap3-scrm" },
+	{ .compatible = "ti,omap4-cm1" },
+	{ .compatible = "ti,omap4-prm" },
+	{ .compatible = "ti,omap4-cm2" },
+	{ .compatible = "ti,omap4-scrm" },
+	{ .compatible = "ti,omap5-prm" },
+	{ .compatible = "ti,omap5-cm-core-aon" },
+	{ .compatible = "ti,omap5-scrm" },
+	{ .compatible = "ti,omap5-cm-core" },
+	{ .compatible = "ti,dra7-prm" },
+	{ .compatible = "ti,dra7-cm-core-aon" },
+	{ .compatible = "ti,dra7-cm-core" },
+	{ }
+};
+
+static struct clk_hw_omap memmap_dummy_ck = {
+	.flags = MEMMAP_ADDRESSING,
+};
+
+static u32 prm_clk_readl(void __iomem *reg)
+{
+	return omap2_clk_readl(&memmap_dummy_ck, reg);
+}
+
+static void prm_clk_writel(u32 val, void __iomem *reg)
+{
+	omap2_clk_writel(val, &memmap_dummy_ck, reg);
+}
+
+static struct clk_ll_ops omap_clk_ll_ops = {
+	.clk_readl = prm_clk_readl,
+	.clk_writel = prm_clk_writel,
+};
+
+int __init of_prcm_init(void)
+{
+	struct device_node *np;
+	void __iomem *mem;
+	int memmap_index = 0;
+
+	ti_clk_ll_ops = &omap_clk_ll_ops;
+
+	for_each_matching_node(np, omap_prcm_dt_match_table) {
+		mem = of_iomap(np, 0);
+		clk_memmaps[memmap_index] = mem;
+		ti_dt_clk_init_provider(np, memmap_index);
+		memmap_index++;
+	}
+
+	ti_dt_clockdomains_setup();
+
+	return 0;
+}
-- 
1.7.9.5

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

* [PATCHv12 00/49] ARM: TI SoC clock DT conversion
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (14 preceding siblings ...)
  2013-12-20 16:34 ` [PATCHv12 43/49] ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT Tero Kristo
@ 2013-12-20 18:37 ` Tony Lindgren
  2013-12-20 20:06 ` Felipe Balbi
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Tony Lindgren @ 2013-12-20 18:37 UTC (permalink / raw)
  To: linux-arm-kernel

* Tero Kristo <t-kristo@ti.com> [131220 08:36]:
> Hi,
> 
> Hopefully final post of this series. At least this is going to be the last
> post this year as I will be going to x-mas vacation and won't be back before
> Jan 2nd. This time I just sent the patches that have changes in them,
> the missing ones are exactly the same as in v11.
> 
> Changes done:
>  - most of the patches:
>    * Some cosmetic documentation fixes
>  - patch 06:
>    * Changed register pointer types from 'u32 __iomem *' to 'void __iomem *'
>  - patch 07,08,09:
>    * Added check for clk->ll_ops being NULL (happens with statically built
>      clock data), fixes the boot time crash issue noticed by Tony
>  - patch 11:
>    * Moved __clk_of_table extern declaration to clk-provider.h header file...
>      Got flamed about this enough times now. :)
>    * Type for the declaration changed also from array to single entry,
>      and address for this used in code. This prevents compile time error:
>      "array type has incomplete element type". Can't use pointer here either
>      as this messes the address of the table.
>    * ti_clk_retry_init() now has int return type, and checks for kzalloc
>      failure
>  - patch 12, 14, 23:
>    * Added cleanup in case ti_clk_retry_init() fails
>  - patch 17:
>    * Fixed potential memory leak in failed init detected by sparse
>  - patch 18:
>    * Modified commit message to add some details about clockdomains
>  - patch 43:
>    * Changed register pointer types from 'u32 *' to 'void __iomem *'
> 
> Testing done:
> - omap3-beagle: boot, suspend/resume (ret), suspend/resume (off)
> - omap4-panda-es: boot, suspend/resume (ret)
> - omap5-uevm: boot
> - am335x-bone: boot
> - dra7-evm: boot
> 
> Branches available at https://github.com/t-kristo/linux-pm.git:
> - branch: 3.13-rc4-dt-clks-v12 : contains everything, shall me merged last
> - branch: 3.13-rc4-dt-clks-v12-for-mike : drivers/clk changes
> - branch: 3.13-rc4-dt-clks-v11-for-benoit : DT data only (from v11, no changes)

Boots now for me on omap2/3/4, and off-idle works on omap3. So as far as
I'm concerned, please feel free to add my ack to the new and updated patches
still missing it:

Acked-by: Tony Lindgren <tony@atomide.com>

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

* [PATCHv12 00/49] ARM: TI SoC clock DT conversion
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (15 preceding siblings ...)
  2013-12-20 18:37 ` [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tony Lindgren
@ 2013-12-20 20:06 ` Felipe Balbi
  2013-12-20 20:10 ` Sebastian Reichel
  2014-01-07  3:21 ` Nishanth Menon
  18 siblings, 0 replies; 28+ messages in thread
From: Felipe Balbi @ 2013-12-20 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 20, 2013 at 06:34:19PM +0200, Tero Kristo wrote:
> Hi,
> 
> Hopefully final post of this series. At least this is going to be the last
> post this year as I will be going to x-mas vacation and won't be back before
> Jan 2nd. This time I just sent the patches that have changes in them,
> the missing ones are exactly the same as in v11.
> 
> Changes done:
>  - most of the patches:
>    * Some cosmetic documentation fixes
>  - patch 06:
>    * Changed register pointer types from 'u32 __iomem *' to 'void __iomem *'
>  - patch 07,08,09:
>    * Added check for clk->ll_ops being NULL (happens with statically built
>      clock data), fixes the boot time crash issue noticed by Tony
>  - patch 11:
>    * Moved __clk_of_table extern declaration to clk-provider.h header file...
>      Got flamed about this enough times now. :)
>    * Type for the declaration changed also from array to single entry,
>      and address for this used in code. This prevents compile time error:
>      "array type has incomplete element type". Can't use pointer here either
>      as this messes the address of the table.
>    * ti_clk_retry_init() now has int return type, and checks for kzalloc
>      failure
>  - patch 12, 14, 23:
>    * Added cleanup in case ti_clk_retry_init() fails
>  - patch 17:
>    * Fixed potential memory leak in failed init detected by sparse
>  - patch 18:
>    * Modified commit message to add some details about clockdomains
>  - patch 43:
>    * Changed register pointer types from 'u32 *' to 'void __iomem *'
> 
> Testing done:
> - omap3-beagle: boot, suspend/resume (ret), suspend/resume (off)
> - omap4-panda-es: boot, suspend/resume (ret)
> - omap5-uevm: boot
> - am335x-bone: boot
> - dra7-evm: boot
> 
> Branches available at https://github.com/t-kristo/linux-pm.git:
> - branch: 3.13-rc4-dt-clks-v12 : contains everything, shall me merged last
> - branch: 3.13-rc4-dt-clks-v12-for-mike : drivers/clk changes
> - branch: 3.13-rc4-dt-clks-v11-for-benoit : DT data only (from v11, no changes)

Still fails to build OMAP5-only defconfig:

drivers/built-in.o: In function `of_ti_composite_interface_clk_setup':
drivers/clk/ti/gate.c:190: undefined reference to `clkhwops_iclk_wait'
make: *** [vmlinux] Error 1

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131220/54f1fc8a/attachment-0001.sig>

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

* [PATCHv12 00/49] ARM: TI SoC clock DT conversion
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (16 preceding siblings ...)
  2013-12-20 20:06 ` Felipe Balbi
@ 2013-12-20 20:10 ` Sebastian Reichel
  2014-01-07  3:21 ` Nishanth Menon
  18 siblings, 0 replies; 28+ messages in thread
From: Sebastian Reichel @ 2013-12-20 20:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 20, 2013 at 06:34:19PM +0200, Tero Kristo wrote:
> Hopefully final post of this series. At least this is going to be the last
> post this year as I will be going to x-mas vacation and won't be back before
> Jan 2nd. This time I just sent the patches that have changes in them,
> the missing ones are exactly the same as in v11.

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

Booting the 3.13-rc4-dt-clks-v12 branch on my Nokia N900 works:

Tested-By: Sebastian Reichel <sre@debian.org>

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131220/95750d5b/attachment.sig>

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

* [PATCHv12 06/49] clk: add support for low level register ops
  2013-12-20 16:34 ` [PATCHv12 06/49] clk: add support for low level register ops Tero Kristo
@ 2013-12-22 17:39   ` Gerhard Sittig
  2014-01-03  9:13     ` Tero Kristo
  0 siblings, 1 reply; 28+ messages in thread
From: Gerhard Sittig @ 2013-12-22 17:39 UTC (permalink / raw)
  To: linux-arm-kernel

[ added agust@ for mpc5xxx, dropped devicetree ]

On Fri, Dec 20, 2013 at 18:34 +0200, Tero Kristo wrote:
> 
> Low level register ops are needed for providing SoC or IP block specific
> access routines to clock registers. Subsequent patches add support for
> the low level ops for the individual clock drivers.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  drivers/clk/clk.c            |   28 ++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |   17 +++++++++++++++++
>  2 files changed, 45 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 29281f6..8bcd1e0 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -34,6 +34,34 @@ static HLIST_HEAD(clk_root_list);
>  static HLIST_HEAD(clk_orphan_list);
>  static LIST_HEAD(clk_notifier_list);
>  
> +/**
> + * clk_readl_default - default clock register read support function
> + * @reg: register to read
> + *
> + * Default implementation for reading a clock register.
> + */
> +static u32 clk_readl_default(void __iomem *reg)
> +{
> +	return readl(reg);
> +}
> +
> +/**
> + * clk_writel_default - default clock register write support function
> + * @val: value to write
> + * @reg: register to write to
> + *
> + * Default implementation for writing a clock register.
> + */
> +static void clk_writel_default(u32 val, void __iomem *reg)
> +{
> +	writel(val, reg);
> +}
> +
> +struct clk_ll_ops clk_ll_ops_default = {
> +	.clk_readl = clk_readl_default,
> +	.clk_writel = clk_writel_default
> +};
> +
>  /***           locking             ***/
>  static void clk_prepare_lock(void)
>  {

Mike, Anatolij, this is a HEADS UP for the clock and mpc5xxx
maintainers:  This patch will break the recently introduced CCF
support for MPC512x (currently sitting in -next, to get merged
for 3.14), and requires some adjustment.

Either the clk_{read,write}l_default() routines' bodies need to
depend on the architecture, or the clk_ll_ops_default structure
needs to get preset differently depending on the architecture.

For least intrusive changes in future use, adding a routine which
allows to register a different ll_ops structure could be most
appropriate.  That would allow to pre-set the ll_ops structure
with the readl()/writel() implementation (current state of
mainline code, working for the ARM architecture and maybe other
little endian peripherals), and allows to register the
ioread32be()/iowrite32be() routines for PowerPC, or whatever
other platforms or architectures will require.

Expecting each individual clock item registration to specify a
differing set of ll_ops if readl()/writel() are not appropriate
would look weird to me.


Further I'd suggest to split this register access aspect out of
the TI clock series, and to prepare it already for regmap style
access to the hardware registers.  See the next comment below.

> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index a4f14ae..671dff4 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -198,6 +198,23 @@ struct clk_hw {
>  	const struct clk_init_data *init;
>  };
>  
> +/**
> + * struct clk_ll_ops - low-level register access ops for a clock
> + * @clk_readl: pointer to register read function
> + * @clk_writel: pointer to register write function
> + *
> + * Low-level register access ops are generally used by the basic clock types
> + * (clk-gate, clk-mux, clk-divider etc.) to provide support for various
> + * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be
> + * used by other hardware-specific clock drivers if needed.
> + */
> +struct clk_ll_ops {
> +	u32	(*clk_readl)(void __iomem *reg);
> +	void	(*clk_writel)(u32 val, void __iomem *reg);
> +};
> +
> +extern struct clk_ll_ops clk_ll_ops_default;
> +

I'd suggest to add a "strct clk_ll_ops" pointer to the routines'
list of arguments, and to add some "user data" pointer to the
struct.

This would provide more than the "reg" pointer to the routine,
e.g. to determine an offset within a register set, and/or to hold
a regmap handle.

Not adding this extension now would lead to our queueing several
patches which will result in potential conflicts, or requiring
more cycles than necessary to achieve a working state for
currently pending changes.


There is another issue with this series:  It introduces
"alternative" _default() routines (which are verbatim copies of
the static inlines from the header), then adjusts the basic clock
types (div, gate, mux), but does not remove the then obsolete
static inlines from the header.

Tero, can you please verify whether the clk_readl() and
clk_writel() routines from <linux/clock-provider.h> become
obsolete with your patch, or whether any unchanged users remain?


Are other parts of v12 still stuck?  I only saw 15 of 49 patches.


virtually yours
Gerhard Sittig
-- 
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

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

* [PATCHv12 07/49] clk: divider: add support for low level ops
  2013-12-20 16:34 ` [PATCHv12 07/49] clk: divider: add support for low level ops Tero Kristo
@ 2013-12-22 17:52   ` Gerhard Sittig
  2014-01-03  9:17     ` Tero Kristo
  0 siblings, 1 reply; 28+ messages in thread
From: Gerhard Sittig @ 2013-12-22 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

[ dropped devicetree, we're clock specific here ]

On Fri, Dec 20, 2013 at 18:34 +0200, Tero Kristo wrote:
> 
> Divider clock can now be registered to use low level register access ops.
> Preferred initialization method is via clock description.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
>  include/linux/clk-provider.h |    4 ++++
>  2 files changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 8cfed5c..887e2d8 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -108,7 +108,12 @@ 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;
> +	if (divider->ll_ops)
> +		val = divider->ll_ops->clk_readl(divider->reg);
> +	else
> +		val = clk_readl(divider->reg);

Should this not better always use an ll_ops structure, which
either is individual to the clock item, or is "global" for a
platform, yet can get re-registered at runtime (see the comment
on 06/49)?  And why are you referencing clk_readl() instead of
clk_readl_default() which you specifically have introduced in the
previous patch?  Adding a copy of the routine and using both the
copy and the original doesn't look right.


virtually yours
Gerhard Sittig
-- 
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

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

* [PATCHv12 06/49] clk: add support for low level register ops
  2013-12-22 17:39   ` Gerhard Sittig
@ 2014-01-03  9:13     ` Tero Kristo
  2014-01-03 19:48       ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Tero Kristo @ 2014-01-03  9:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/22/2013 07:39 PM, Gerhard Sittig wrote:
> [ added agust@ for mpc5xxx, dropped devicetree ]
>
> On Fri, Dec 20, 2013 at 18:34 +0200, Tero Kristo wrote:
>>
>> Low level register ops are needed for providing SoC or IP block specific
>> access routines to clock registers. Subsequent patches add support for
>> the low level ops for the individual clock drivers.
>>
>> Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> ---
>>   drivers/clk/clk.c            |   28 ++++++++++++++++++++++++++++
>>   include/linux/clk-provider.h |   17 +++++++++++++++++
>>   2 files changed, 45 insertions(+)
>>
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 29281f6..8bcd1e0 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -34,6 +34,34 @@ static HLIST_HEAD(clk_root_list);
>>   static HLIST_HEAD(clk_orphan_list);
>>   static LIST_HEAD(clk_notifier_list);
>>
>> +/**
>> + * clk_readl_default - default clock register read support function
>> + * @reg: register to read
>> + *
>> + * Default implementation for reading a clock register.
>> + */
>> +static u32 clk_readl_default(void __iomem *reg)
>> +{
>> +	return readl(reg);
>> +}
>> +
>> +/**
>> + * clk_writel_default - default clock register write support function
>> + * @val: value to write
>> + * @reg: register to write to
>> + *
>> + * Default implementation for writing a clock register.
>> + */
>> +static void clk_writel_default(u32 val, void __iomem *reg)
>> +{
>> +	writel(val, reg);
>> +}
>> +
>> +struct clk_ll_ops clk_ll_ops_default = {
>> +	.clk_readl = clk_readl_default,
>> +	.clk_writel = clk_writel_default
>> +};
>> +
>>   /***           locking             ***/
>>   static void clk_prepare_lock(void)
>>   {
>
> Mike, Anatolij, this is a HEADS UP for the clock and mpc5xxx
> maintainers:  This patch will break the recently introduced CCF
> support for MPC512x (currently sitting in -next, to get merged
> for 3.14), and requires some adjustment.
>
> Either the clk_{read,write}l_default() routines' bodies need to
> depend on the architecture, or the clk_ll_ops_default structure
> needs to get preset differently depending on the architecture.
>
> For least intrusive changes in future use, adding a routine which
> allows to register a different ll_ops structure could be most
> appropriate.  That would allow to pre-set the ll_ops structure
> with the readl()/writel() implementation (current state of
> mainline code, working for the ARM architecture and maybe other
> little endian peripherals), and allows to register the
> ioread32be()/iowrite32be() routines for PowerPC, or whatever
> other platforms or architectures will require.
>
> Expecting each individual clock item registration to specify a
> differing set of ll_ops if readl()/writel() are not appropriate
> would look weird to me.
>
>
> Further I'd suggest to split this register access aspect out of
> the TI clock series, and to prepare it already for regmap style
> access to the hardware registers.  See the next comment below.

This sounds like a good idea to me, seeing it is blocking lots of other 
things.

>> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
>> index a4f14ae..671dff4 100644
>> --- a/include/linux/clk-provider.h
>> +++ b/include/linux/clk-provider.h
>> @@ -198,6 +198,23 @@ struct clk_hw {
>>   	const struct clk_init_data *init;
>>   };
>>
>> +/**
>> + * struct clk_ll_ops - low-level register access ops for a clock
>> + * @clk_readl: pointer to register read function
>> + * @clk_writel: pointer to register write function
>> + *
>> + * Low-level register access ops are generally used by the basic clock types
>> + * (clk-gate, clk-mux, clk-divider etc.) to provide support for various
>> + * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be
>> + * used by other hardware-specific clock drivers if needed.
>> + */
>> +struct clk_ll_ops {
>> +	u32	(*clk_readl)(void __iomem *reg);
>> +	void	(*clk_writel)(u32 val, void __iomem *reg);
>> +};
>> +
>> +extern struct clk_ll_ops clk_ll_ops_default;
>> +
>
> I'd suggest to add a "strct clk_ll_ops" pointer to the routines'
> list of arguments, and to add some "user data" pointer to the
> struct.
>
> This would provide more than the "reg" pointer to the routine,
> e.g. to determine an offset within a register set, and/or to hold
> a regmap handle.
>
> Not adding this extension now would lead to our queueing several
> patches which will result in potential conflicts, or requiring
> more cycles than necessary to achieve a working state for
> currently pending changes.

Yea I think this sounds like a good idea.

>
>
> There is another issue with this series:  It introduces
> "alternative" _default() routines (which are verbatim copies of
> the static inlines from the header), then adjusts the basic clock
> types (div, gate, mux), but does not remove the then obsolete
> static inlines from the header.
>
> Tero, can you please verify whether the clk_readl() and
> clk_writel() routines from <linux/clock-provider.h> become
> obsolete with your patch, or whether any unchanged users remain?

Just did a quick grep and it seems you are right, the routines become 
obsolete and could be removed (or alternatively just rename the 
clk_readl/writel_default to clk_readl/writel.)

>
>
> Are other parts of v12 still stuck?  I only saw 15 of 49 patches.

Rest of v12 was identical copy of v11, so I didn't repost them.

-Tero

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

* [PATCHv12 07/49] clk: divider: add support for low level ops
  2013-12-22 17:52   ` Gerhard Sittig
@ 2014-01-03  9:17     ` Tero Kristo
  2014-01-04 16:48       ` Gerhard Sittig
  0 siblings, 1 reply; 28+ messages in thread
From: Tero Kristo @ 2014-01-03  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/22/2013 07:52 PM, Gerhard Sittig wrote:
> [ dropped devicetree, we're clock specific here ]
>
> On Fri, Dec 20, 2013 at 18:34 +0200, Tero Kristo wrote:
>>
>> Divider clock can now be registered to use low level register access ops.
>> Preferred initialization method is via clock description.
>>
>> Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> ---
>>   drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
>>   include/linux/clk-provider.h |    4 ++++
>>   2 files changed, 23 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
>> index 8cfed5c..887e2d8 100644
>> --- a/drivers/clk/clk-divider.c
>> +++ b/drivers/clk/clk-divider.c
>> @@ -108,7 +108,12 @@ 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;
>> +	if (divider->ll_ops)
>> +		val = divider->ll_ops->clk_readl(divider->reg);
>> +	else
>> +		val = clk_readl(divider->reg);
>
> Should this not better always use an ll_ops structure, which
> either is individual to the clock item, or is "global" for a
> platform, yet can get re-registered at runtime (see the comment
> on 06/49)?  And why are you referencing clk_readl() instead of
> clk_readl_default() which you specifically have introduced in the
> previous patch?  Adding a copy of the routine and using both the
> copy and the original doesn't look right.

In some cases, the clock data is defined statically during compile time 
and here, ll_ops can be (and for OMAP cases at least is) NULL. I had 
kind of a global ll_ops definition in some of the earlier versions of 
this series, but it was frowned upon by some of the maintainers thus I 
dropped it.

-Tero

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

* [PATCHv12 06/49] clk: add support for low level register ops
  2014-01-03  9:13     ` Tero Kristo
@ 2014-01-03 19:48       ` Stephen Boyd
  2014-01-07  7:44         ` Tero Kristo
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2014-01-03 19:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/03/14 01:13, Tero Kristo wrote:
> On 12/22/2013 07:39 PM, Gerhard Sittig wrote:
>>
>>
>> Further I'd suggest to split this register access aspect out of
>> the TI clock series, and to prepare it already for regmap style
>> access to the hardware registers.  See the next comment below.
>
> This sounds like a good idea to me, seeing it is blocking lots of
> other things.

This ll_ops struct looks like a simplified regmap. Have you seen my
series that adds regmap support to the common clock framework[1]? Is
there any reason why you can't use those patches and layer some patches
on top to add support for regmap to the basic clock types?

[1] https://lkml.org/lkml/2013/12/23/461

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCHv12 07/49] clk: divider: add support for low level ops
  2014-01-03  9:17     ` Tero Kristo
@ 2014-01-04 16:48       ` Gerhard Sittig
  0 siblings, 0 replies; 28+ messages in thread
From: Gerhard Sittig @ 2014-01-04 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 03, 2014 at 11:17 +0200, Tero Kristo wrote:
> 
> On 12/22/2013 07:52 PM, Gerhard Sittig wrote:
> >[ dropped devicetree, we're clock specific here ]
> >
> >On Fri, Dec 20, 2013 at 18:34 +0200, Tero Kristo wrote:
> >>
> >>Divider clock can now be registered to use low level register access ops.
> >>Preferred initialization method is via clock description.
> >>
> >>Signed-off-by: Tero Kristo <t-kristo@ti.com>
> >>---
> >>  drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
> >>  include/linux/clk-provider.h |    4 ++++
> >>  2 files changed, 23 insertions(+), 3 deletions(-)
> >>
> >>diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> >>index 8cfed5c..887e2d8 100644
> >>--- a/drivers/clk/clk-divider.c
> >>+++ b/drivers/clk/clk-divider.c
> >>@@ -108,7 +108,12 @@ 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;
> >>+	if (divider->ll_ops)
> >>+		val = divider->ll_ops->clk_readl(divider->reg);
> >>+	else
> >>+		val = clk_readl(divider->reg);
> >
> >Should this not better always use an ll_ops structure, which
> >either is individual to the clock item, or is "global" for a
> >platform, yet can get re-registered at runtime (see the comment
> >on 06/49)?  And why are you referencing clk_readl() instead of
> >clk_readl_default() which you specifically have introduced in the
> >previous patch?  Adding a copy of the routine and using both the
> >copy and the original doesn't look right.
> 
> In some cases, the clock data is defined statically during compile
> time and here, ll_ops can be (and for OMAP cases at least is) NULL.
> I had kind of a global ll_ops definition in some of the earlier
> versions of this series, but it was frowned upon by some of the
> maintainers thus I dropped it.

Well, admittedly v11 was the first version that I have
seen/noticed.  But the static declaration you talk about and the
ll_ops potentially being NULL was discussed there.  My response
was about replacing the above clk_readl() call with some ll_ops
dereference while the ll_ops to use gets determined before, as
'divider' need not have one.

Consider something like this
- have default routines which do readl() and writel(), and have a
  default ll_ops struct which references the default routines
- have a default ll_ops struct _pointer_ that by default
  references the default readl/writel struct, yet can get changed
  to something else for a whole platform or architecture
- never use routines directly upon hardware access, but instead
  always dereference an ll_ops struct that gets determined so:
  - start with the clock item's ll_ops reference
  - use the global ll_ops pointer if the above is NULL
  - use the pointer to the default ll_ops struct if still NULL
    (this protects against NULL platform specs, which should not
    happen yet are possible, and the test is cheap)

In pseudo code, this would then be

  init:
    default_struct = { default_read, default_write, NULL, };
    default_ops = &default_struct;

  setup:
    /* allow platforms to optionally change default_ops */
    /* allow clk items to have individual clk->ll_ops */

  use:
    ops = divider->ll_ops;
    if (!ops)
      ops = default_ops;
    if (!ops)
      ops = &default_struct;
    val = ops->clk_readl(ops, ...);

This way
- you always end up with an ll_ops reference which leads to
  routines (and potential additional data that can be specific to
  a clock item, like regmap data), for both "dynamically"
  registered clock items as well as "static" declarations
- one initialization step can apply different accessors for a
  whole platform, while the default behaviour equals the current
  implementation
- individual clock items can specify their accessor routine and
  data, or may go with the builtin or the preset defaults

The biggest change in cost here is the indirect routine call in
contrast to the static inline of the current implementation,
while this additional cost of calling a real wrapper routine
can't get avoided in the first place.  Comparing pointers and
falling back in the absence of individual overrides should not
outweight the above additional cost of calling the routine.  The
always identical logic to determine which routine to call can get
implemented in a static inline and then won't clutter the actual
clock handling logic.

If regmap access is rather popular a method, and requires only
little additional information, it might receive more explicit
support such that users need not hand-roll the same logic over
and over again, yet not too much waste occurs to non-regmap
items.  But available information suggests that currently there
is only one user for regmap style access to clock related
hardware (Steven's).  This could change in the future.


virtually yours
Gerhard Sittig
-- 
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

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

* [PATCHv12 00/49] ARM: TI SoC clock DT conversion
  2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
                   ` (17 preceding siblings ...)
  2013-12-20 20:10 ` Sebastian Reichel
@ 2014-01-07  3:21 ` Nishanth Menon
  2014-01-07 16:36   ` Nishanth Menon
  18 siblings, 1 reply; 28+ messages in thread
From: Nishanth Menon @ 2014-01-07  3:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tero,
On 12/20/2013 10:34 AM, Tero Kristo wrote:
> Hopefully final post of this series. At least this is going to be the last
> post this year as I will be going to x-mas vacation and won't be back before
> Jan 2nd. This time I just sent the patches that have changes in them,
> the missing ones are exactly the same as in v11.
> 

There are still a few issues that I see
[...]

> Branches available at https://github.com/t-kristo/linux-pm.git:
> - branch: 3.13-rc4-dt-clks-v12 : contains everything, shall me merged last
> - branch: 3.13-rc4-dt-clks-v12-for-mike : drivers/clk changes
> - branch: 3.13-rc4-dt-clks-v11-for-benoit : DT data only (from v11, no changes)

For easy maintainer merging, you may want to make this as three branches:

1. for-mike based on
git://git.linaro.org/people/mturquette/linux.git clk-next

2. for-benoit based on
git://git.kernel.org/pub/scm/linux/kernel/git/bcousson/linux-omap-dt.git
for_3.14/dts

3. for-tony based on
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
omap-for-v3.14/board-removal or on a clean k.org tag

4. A testing branch for the rest of us which consolidates all of these
together.

Testing with a rebase of 3.13-rc4-dt-clks-v12 to v3.13-rc7:

Here is my test platforms and logs (boot only - omap2plus_defconfig +
common_clk_debug - all boots to sd card based filesystem):

AM335x Family:

AM335x-EVMSK:
        http://pastebin.mozilla.org/3955459
AM335x-EVM:
        http://pastebin.mozilla.org/3955460
AM335x-BeagleBone Black:
        http://pastebin.mozilla.org/3955476

OMAP3 family:
OMAP3430: SDP3430:
        http://pastebin.mozilla.org/3955475
AM3517-evm: (requires a bootargs fix - remote board - no regressions seen)
        http://pastebin.mozilla.org/3955461
AM3517-CraneBoard:
        http://pastebin.mozilla.org/3955477
OMAP3630/DM3730 BeagleBoard-XM:
        http://pastebin.mozilla.org/3955474
AM37xx-evm:
        http://pastebin.mozilla.org/3955472

OMAP4 Family:
OMAP4460: PandaBoard-ES:
        http://pastebin.mozilla.org/3955478
	NOTE: trace_clk_div_ck seems orphan clock here?

OMAP5 Family:
OMAP5432: OMAP5uEVM:
        http://pastebin.mozilla.org/3955479

DRA7 Family:

DRA7: DRA7-evm:
        http://pastebin.mozilla.org/3955480


Patch autoverification report: http://pastebin.mozilla.org/3955695

The following issues need fixes I suppose:
* CHECK: spinlock_t definition without comment
	[PATCH 03/49] clk: divider: add support for registering divider
	[PATCH 04/49] clk: mux: add support for registering mux clock from
	[PATCH 05/49] clk: gate: add support for registering gate clock from

* [PATCH 23/49] CLK: TI: DRA7: Add APLL support
	"parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);"
	* kzalloc without check for NULL
	* will also be good to add some kerneldoc documentation (same with
interface.c)
* WARNING: static const char * array should probably be static const
char * const
	[PATCH 25/49] CLK: TI: add am33xx clock init file
	[PATCH 27/49] CLK: TI: add omap3 clock init file
* [PATCH 40/49] ARM: OMAP2+: clock: use driver API instead of direct
	adds a new kernel doc warning "Warning(arch/arm/mach-omap2/clock.c:
No description found for parameter 'clk'"
* [PATCH 44/49] ARM: OMAP2+: io: use new clock init API
	introduces warning for
		"arch/arm/mach-omap2/io.c: warning: symbol 'omap_clk_soc_init' was
not declared. Should it be static?"
	which seems squashed with "[PATCH 45/49] ARM: OMAP4: remove old clock
data and link in new"
	will be good to have it not appear in patch 44 itself.


Also pending is OMAP5 only build failure that Felipe reported and does
not seem fixed in V12 as well:
http://marc.info/?l=linux-arm-kernel&m=138757010619274&w=2
and
http://marc.info/?l=linux-arm-kernel&m=138755595914796&w=2

-- 
Regards,
Nishanth Menon

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

* [PATCHv12 06/49] clk: add support for low level register ops
  2014-01-03 19:48       ` Stephen Boyd
@ 2014-01-07  7:44         ` Tero Kristo
  0 siblings, 0 replies; 28+ messages in thread
From: Tero Kristo @ 2014-01-07  7:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/03/2014 09:48 PM, Stephen Boyd wrote:
> On 01/03/14 01:13, Tero Kristo wrote:
>> On 12/22/2013 07:39 PM, Gerhard Sittig wrote:
>>>
>>>
>>> Further I'd suggest to split this register access aspect out of
>>> the TI clock series, and to prepare it already for regmap style
>>> access to the hardware registers.  See the next comment below.
>>
>> This sounds like a good idea to me, seeing it is blocking lots of
>> other things.
>
> This ll_ops struct looks like a simplified regmap. Have you seen my
> series that adds regmap support to the common clock framework[1]? Is
> there any reason why you can't use those patches and layer some patches
> on top to add support for regmap to the basic clock types?
>
> [1] https://lkml.org/lkml/2013/12/23/461

Yea I've seen that. I also used regmap myself on some earlier rev, but 
it is rather an overkill solution to my purposes, and it also adds 
additional latencies to the register access.

-Tero

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

* [PATCHv12 00/49] ARM: TI SoC clock DT conversion
  2014-01-07  3:21 ` Nishanth Menon
@ 2014-01-07 16:36   ` Nishanth Menon
  0 siblings, 0 replies; 28+ messages in thread
From: Nishanth Menon @ 2014-01-07 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/06/2014 09:21 PM, Nishanth Menon wrote:
> Hi Tero,
> On 12/20/2013 10:34 AM, Tero Kristo wrote:
>> Hopefully final post of this series. At least this is going to be the last
>> post this year as I will be going to x-mas vacation and won't be back before
>> Jan 2nd. This time I just sent the patches that have changes in them,
>> the missing ones are exactly the same as in v11.
>>
> 
> There are still a few issues that I see
> [...]
> 
>> Branches available at https://github.com/t-kristo/linux-pm.git:
>> - branch: 3.13-rc4-dt-clks-v12 : contains everything, shall me merged last
>> - branch: 3.13-rc4-dt-clks-v12-for-mike : drivers/clk changes
>> - branch: 3.13-rc4-dt-clks-v11-for-benoit : DT data only (from v11, no changes)
> 
> For easy maintainer merging, you may want to make this as three branches:
> 
> 1. for-mike based on
> git://git.linaro.org/people/mturquette/linux.git clk-next
> 
> 2. for-benoit based on
> git://git.kernel.org/pub/scm/linux/kernel/git/bcousson/linux-omap-dt.git
> for_3.14/dts
> 
> 3. for-tony based on
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
> omap-for-v3.14/board-removal or on a clean k.org tag
> 
> 4. A testing branch for the rest of us which consolidates all of these
> together.
> 
> Testing with a rebase of 3.13-rc4-dt-clks-v12 to v3.13-rc7:
> 
> Here is my test platforms and logs (boot only - omap2plus_defconfig +
> common_clk_debug - all boots to sd card based filesystem):
> 
> AM335x Family:
> 
> AM335x-EVMSK:
>         http://pastebin.mozilla.org/3955459
> AM335x-EVM:
>         http://pastebin.mozilla.org/3955460
> AM335x-BeagleBone Black:
>         http://pastebin.mozilla.org/3955476
> 
> OMAP3 family:
> OMAP3430: SDP3430:
>         http://pastebin.mozilla.org/3955475
> AM3517-evm: (requires a bootargs fix - remote board - no regressions seen)
>         http://pastebin.mozilla.org/3955461
> AM3517-CraneBoard:
>         http://pastebin.mozilla.org/3955477
> OMAP3630/DM3730 BeagleBoard-XM:
>         http://pastebin.mozilla.org/3955474
> AM37xx-evm:
>         http://pastebin.mozilla.org/3955472
> 
> OMAP4 Family:
> OMAP4460: PandaBoard-ES:
>         http://pastebin.mozilla.org/3955478
> 	NOTE: trace_clk_div_ck seems orphan clock here?
> 
> OMAP5 Family:
> OMAP5432: OMAP5uEVM:
>         http://pastebin.mozilla.org/3955479
> 
> DRA7 Family:
> 
> DRA7: DRA7-evm:
>         http://pastebin.mozilla.org/3955480

one more missing test platform:

AM43xx-epos platform: (needed a few out of tree patches to test on TI
internal engineering samples):
	http://pastebin.mozilla.org/3960056


> 
> 
> Patch autoverification report: http://pastebin.mozilla.org/3955695
> 
> The following issues need fixes I suppose:
> * CHECK: spinlock_t definition without comment
> 	[PATCH 03/49] clk: divider: add support for registering divider
> 	[PATCH 04/49] clk: mux: add support for registering mux clock from
> 	[PATCH 05/49] clk: gate: add support for registering gate clock from
> 
> * [PATCH 23/49] CLK: TI: DRA7: Add APLL support
> 	"parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);"
> 	* kzalloc without check for NULL
> 	* will also be good to add some kerneldoc documentation (same with
> interface.c)
> * WARNING: static const char * array should probably be static const
> char * const
> 	[PATCH 25/49] CLK: TI: add am33xx clock init file
> 	[PATCH 27/49] CLK: TI: add omap3 clock init file
> * [PATCH 40/49] ARM: OMAP2+: clock: use driver API instead of direct
> 	adds a new kernel doc warning "Warning(arch/arm/mach-omap2/clock.c:
> No description found for parameter 'clk'"
> * [PATCH 44/49] ARM: OMAP2+: io: use new clock init API
> 	introduces warning for
> 		"arch/arm/mach-omap2/io.c: warning: symbol 'omap_clk_soc_init' was
> not declared. Should it be static?"
> 	which seems squashed with "[PATCH 45/49] ARM: OMAP4: remove old clock
> data and link in new"
> 	will be good to have it not appear in patch 44 itself.
> 
> 
> Also pending is OMAP5 only build failure that Felipe reported and does
> not seem fixed in V12 as well:
> http://marc.info/?l=linux-arm-kernel&m=138757010619274&w=2
> and
> http://marc.info/?l=linux-arm-kernel&m=138755595914796&w=2
> 


-- 
Regards,
Nishanth Menon

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

end of thread, other threads:[~2014-01-07 16:36 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-20 16:34 [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tero Kristo
2013-12-20 16:34 ` [PATCHv12 01/49] clk: add support for registering clocks from description Tero Kristo
2013-12-20 16:34 ` [PATCHv12 03/49] clk: divider: add support for registering divider clock from descriptor Tero Kristo
2013-12-20 16:34 ` [PATCHv12 04/49] clk: mux: add support for registering mux " Tero Kristo
2013-12-20 16:34 ` [PATCHv12 05/49] clk: gate: add support for registering gate " Tero Kristo
2013-12-20 16:34 ` [PATCHv12 06/49] clk: add support for low level register ops Tero Kristo
2013-12-22 17:39   ` Gerhard Sittig
2014-01-03  9:13     ` Tero Kristo
2014-01-03 19:48       ` Stephen Boyd
2014-01-07  7:44         ` Tero Kristo
2013-12-20 16:34 ` [PATCHv12 07/49] clk: divider: add support for low level ops Tero Kristo
2013-12-22 17:52   ` Gerhard Sittig
2014-01-03  9:17     ` Tero Kristo
2014-01-04 16:48       ` Gerhard Sittig
2013-12-20 16:34 ` [PATCHv12 08/49] clk: gate: " Tero Kristo
2013-12-20 16:34 ` [PATCHv12 09/49] clk: mux: " Tero Kristo
2013-12-20 16:34 ` [PATCHv12 11/49] CLK: ti: add init support for clock IP blocks Tero Kristo
2013-12-20 16:34 ` [PATCHv12 12/49] CLK: TI: Add DPLL clock support Tero Kristo
2013-12-20 16:34 ` [PATCHv12 14/49] clk: ti: add composite " Tero Kristo
2013-12-20 16:34 ` [PATCHv12 17/49] CLK: TI: add support for gate clock Tero Kristo
2013-12-20 16:34 ` [PATCHv12 18/49] CLK: TI: add support for clockdomain binding Tero Kristo
2013-12-20 16:34 ` [PATCHv12 23/49] CLK: TI: DRA7: Add APLL support Tero Kristo
2013-12-20 16:34 ` [PATCHv12 43/49] ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT Tero Kristo
2013-12-20 18:37 ` [PATCHv12 00/49] ARM: TI SoC clock DT conversion Tony Lindgren
2013-12-20 20:06 ` Felipe Balbi
2013-12-20 20:10 ` Sebastian Reichel
2014-01-07  3:21 ` Nishanth Menon
2014-01-07 16:36   ` Nishanth Menon

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