Skip to contentSkip to conversation

ARM: TI SoC clock DT conversion

PATCH Superseded Tero Kristo 7 participants 28 messages Dec 20, 2013 – Jan 7, 2014

Subsystems (8)

v12 of 13 Superseded Latest is v13 →

lore
Share & tools
lore
#0 lore raw

v12 cover ARM: TI SoC clock DT conversion

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

#1 lore raw

PATCH v12 1/49 clk: add support for registering clocks from description

From: Mike Turquette <[email protected]>

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).

---
 drivers/clk/clk.c            |   71 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   22 +++++++++++++
 2 files changed, 93 insertions(+)
drivers/clk/clk.c +71 -0
index 2cf2ea6..29281f6 100644
@@ -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
  *
include/linux/clk-provider.h +22 -0
index 7e59253..08a0da0 100644
@@ -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);
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH v12 3/49 clk: divider: add support for registering divider clock from descriptor

In reply to Tero Kristo

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

---
 drivers/clk/clk-divider.c    |   34 ++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   22 ++++++++++++++++++++++
 2 files changed, 56 insertions(+)
drivers/clk/clk-divider.c +34 -0
index 8d3009e..8cfed5c 100644
@@ -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);
include/linux/clk-provider.h +22 -0
index 232623d..bf89ab4 100644
@@ -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,
Signature · 1 line
1.7.9.5
#3 lore raw

PATCH v12 4/49 clk: mux: add support for registering mux clock from descriptor

In reply to Tero Kristo

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

---
 drivers/clk/clk-mux.c        |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   20 ++++++++++++++++++++
 2 files changed, 57 insertions(+)
drivers/clk/clk-mux.c +37 -0
index 4f96ff3..2cbed08 100644
@@ -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);
include/linux/clk-provider.h +20 -0
index bf89ab4..ea5281c 100644
@@ -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,
Signature · 1 line
1.7.9.5
#4 lore raw

PATCH v12 5/49 clk: gate: add support for registering gate clock from descriptor

In reply to Tero Kristo

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

---
 drivers/clk/clk-gate.c       |   31 +++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   18 ++++++++++++++++++
 2 files changed, 49 insertions(+)
drivers/clk/clk-gate.c +31 -0
index 4a58c55..3ec61d2 100644
@@ -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);
include/linux/clk-provider.h +18 -0
index ea5281c..a4f14ae 100644
@@ -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,
Signature · 1 line
1.7.9.5
#5 lore raw

PATCH v12 6/49 clk: add support for low level register ops

In reply to Tero Kristo

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.

---
 drivers/clk/clk.c            |   28 ++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   17 +++++++++++++++++
 2 files changed, 45 insertions(+)
drivers/clk/clk.c +28 -0
index 29281f6..8bcd1e0 100644
@@ -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)
 {
include/linux/clk-provider.h +17 -0
index a4f14ae..671dff4 100644
@@ -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
  *
Signature · 1 line
1.7.9.5
#6 lore raw

PATCH v12 6/49 clk: add support for low level register ops

[ added agust@ for mpc5xxx, dropped devicetree ]

Quoted 40 lines · Tero Kristo

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.

---
 drivers/clk/clk.c            |   28 ++++++++++++++++++++++++++++
 include/linux/clk-provider.h |   17 +++++++++++++++++
 2 files changed, 45 insertions(+)
drivers/clk/clk.c +21 -0
index 29281f6..8bcd1e0 100644
@@ -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);

drivers/clk/clk.c static HLIST_HEAD(clk_root_list); · line 67

Quoted 10 lines
drivers/clk/clk.c +7 -0
+}
+
+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.

Quoted 15 lines
include/linux/clk-provider.h +7 -0
index a4f14ae..671dff4 100644
@@ -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

include/linux/clk-provider.h struct clk_hw { · line 217

Quoted 10 lines
include/linux/clk-provider.h +10 -0
+ * 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

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

PATCH v12 6/49 clk: add support for low level register ops

Quoted 72 lines · Gerhard Sittig

[ added agust@ for mpc5xxx, dropped devicetree ]

Quoted 40 lines · Tero Kristo

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.

---
  drivers/clk/clk.c            |   28 ++++++++++++++++++++++++++++
  include/linux/clk-provider.h |   17 +++++++++++++++++
  2 files changed, 45 insertions(+)
drivers/clk/clk.c +21 -0
index 29281f6..8bcd1e0 100644
@@ -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);

drivers/clk/clk.c static HLIST_HEAD(clk_root_list); · line 67

Quoted 10 lines
drivers/clk/clk.c +7 -0
+}
+
+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.

Quoted 8 lines

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.

Quoted 30 lines
Quoted 15 lines
include/linux/clk-provider.h +7 -0
index a4f14ae..671dff4 100644
@@ -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

include/linux/clk-provider.h struct clk_hw { · line 217

Quoted 10 lines
include/linux/clk-provider.h +10 -0
+ * 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.

Quoted 8 lines

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.

Quoted 11 lines

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.)

Quoted 3 lines

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

#8 lore raw

PATCH v12 6/49 clk: add support for low level register ops

Quoted 9 lines · Tero Kristo
Quoted 5 lines · Gerhard Sittig

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

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#9 lore raw

PATCH v12 6/49 clk: add support for low level register ops

Quoted 11 lines · Stephen Boyd
Quoted 9 lines · Tero Kristo
Quoted 5 lines · Gerhard Sittig

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.

Quoted 6 lines

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

#10 lore raw

PATCH v12 7/49 clk: divider: add support for low level ops

In reply to Tero Kristo

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

---
 drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 23 insertions(+), 3 deletions(-)
drivers/clk/clk-divider.c +19 -3
index 8cfed5c..887e2d8 100644
@@ -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;
include/linux/clk-provider.h +4 -0
index 671dff4..f082a89 100644
@@ -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;
Signature · 1 line
1.7.9.5
#11 lore raw

PATCH v12 7/49 clk: divider: add support for low level ops

[ dropped devicetree, we're clock specific here ]

Quoted 15 lines · Tero Kristo

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

---
 drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 23 insertions(+), 3 deletions(-)
drivers/clk/clk-divider.c +0 -0
index 8cfed5c..887e2d8 100644

drivers/clk/clk-divider.c static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, · line 114

Quoted 8 lines
drivers/clk/clk-divider.c +4 -1
@@ -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

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

PATCH v12 7/49 clk: divider: add support for low level ops

Quoted 21 lines · Gerhard Sittig

[ dropped devicetree, we're clock specific here ]

Quoted 18 lines · Tero Kristo

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

---
  drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
  include/linux/clk-provider.h |    4 ++++
  2 files changed, 23 insertions(+), 3 deletions(-)
drivers/clk/clk-divider.c +0 -0
index 8cfed5c..887e2d8 100644
@@ -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;
 
Quoted 13 lines

drivers/clk/clk-divider.c static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, · line 114

Quoted 5 lines
drivers/clk/clk-divider.c +4 -1
-	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

#13 lore raw

PATCH v12 7/49 clk: divider: add support for low level ops

Quoted 37 lines · Tero Kristo
Quoted 21 lines · Gerhard Sittig

[ dropped devicetree, we're clock specific here ]

Quoted 18 lines · Tero Kristo

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

---
 drivers/clk/clk-divider.c    |   22 +++++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 23 insertions(+), 3 deletions(-)
drivers/clk/clk-divider.c +0 -0
index 8cfed5c..887e2d8 100644
@@ -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;
 
Quoted 13 lines

drivers/clk/clk-divider.c static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, · line 114

Quoted 5 lines
drivers/clk/clk-divider.c +4 -1
-	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.

Quoted 5 lines

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

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

PATCH v12 8/49 clk: gate: add support for low level ops

In reply to Tero Kristo

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

---
 drivers/clk/clk-gate.c       |   20 +++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 21 insertions(+), 3 deletions(-)
drivers/clk/clk-gate.c +17 -3
index 3ec61d2..d4c94a7 100644
@@ -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;
include/linux/clk-provider.h +4 -0
index f082a89..3923d46 100644
@@ -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;
Signature · 1 line
1.7.9.5
#15 lore raw

PATCH v12 9/49 clk: mux: add support for low level ops

In reply to Tero Kristo

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

---
 drivers/clk/clk-mux.c        |   24 +++++++++++++++++++++---
 include/linux/clk-provider.h |    4 ++++
 2 files changed, 25 insertions(+), 3 deletions(-)
drivers/clk/clk-mux.c +21 -3
index 2cbed08..ed3bc36 100644
@@ -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)
include/linux/clk-provider.h +4 -0
index 3923d46..629163c 100644
@@ -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;
Signature · 1 line
1.7.9.5
#16 lore raw

PATCH v12 11/49 CLK: ti: add init support for clock IP blocks

In reply to Tero Kristo

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

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.

---
 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(-)
drivers/clk/clk.c +1 -3
index 8bcd1e0..c0521be 100644
@@ -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;
drivers/clk/ti/clk.c +112 -0

125 lines not on this page · raw message

include/linux/clk-provider.h +2 -0
index 629163c..2d2c03d 100644
@@ -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)		\
include/linux/clk/ti.h +20 -0
index df94c24..6750d25 100644
@@ -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
Signature · 1 line
1.7.9.5
#17 lore raw

PATCH v12 12/49 CLK: TI: Add DPLL clock support

In reply to Tero Kristo

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

---
 .../devicetree/bindings/clock/ti/dpll.txt          |   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
Documentation/devicetree/bindings/clock/ti/dpll.txt new file +75 -0
new file mode 100644
index 0000000..30bfdb7
@@ -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>;
+	};
arch/arm/mach-omap2/clock.h +1 -163

215 lines not on this page · raw message

arch/arm/mach-omap2/clock3xxx.h +0 -2
index 8cd4b0a..dab90e2 100644
@@ -9,8 +9,6 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H
 
 int omap3xxx_clk_init(void);
-int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
-					unsigned long parent_rate);
 int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
 					unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
drivers/clk/ti/Makefile +1 -1
index 1825f7f..05af5d8 100644
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y					+= clk.o
+obj-y					+= clk.o dpll.o
 endif
drivers/clk/ti/dpll.c new file +558 -0

558 lines not on this page · raw message

include/linux/clk/ti.h +172 -0

188 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#18 lore raw

PATCH v12 14/49 clk: ti: add composite clock support

In reply to Tero Kristo

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

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

269 lines not on this page · raw message

include/linux/clk/ti.h +12 -0
index 7036387..4d4ec49 100644
@@ -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);
Signature · 1 line
1.7.9.5
#19 lore raw

PATCH v12 17/49 CLK: TI: add support for gate clock

In reply to Tero Kristo

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

---
 .../devicetree/bindings/clock/ti/gate.txt          |   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
Documentation/devicetree/bindings/clock/ti/gate.txt new file +85 -0
new file mode 100644
index 0000000..125281a
@@ -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;
+	};
drivers/clk/ti/Makefile +1 -1
index f57fc4b..7cba389 100644
@@ -1,4 +1,4 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   fixed-factor.o composite.o
+					   fixed-factor.o gate.o composite.o
 endif
drivers/clk/ti/gate.c new file +247 -0

247 lines not on this page · raw message

include/linux/clk/ti.h +6 -0
index 4d4ec49..e38e9e1 100644
@@ -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
Signature · 1 line
1.7.9.5
#20 lore raw

PATCH v12 18/49 CLK: TI: add support for clockdomain binding

In reply to Tero Kristo

Some OMAP clocks require knowledge about their parent clockdomain for book keeping purposes. This patch creates a new DT binding for TI clockdomains, which act as a collection of device clocks. 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.

---
 .../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
Documentation/devicetree/bindings/clock/ti/clockdomain.txt new file +24 -0
new file mode 100644
index 0000000..cb76b3f
@@ -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>;
+	};
drivers/clk/ti/Makefile +2 -1
index 7cba389..67056fb 100644
@@ -1,4 +1,5 @@
 ifneq ($(CONFIG_OF),)
 obj-y					+= clk.o dpll.o autoidle.o divider.o \
-					   fixed-factor.o gate.o composite.o
+					   fixed-factor.o gate.o clockdomain.o \
+					   composite.o
 endif
drivers/clk/ti/clockdomain.c new file +70 -0

70 lines not on this page · raw message

include/linux/clk/ti.h +1 -0
index e38e9e1..9f2cedc 100644
@@ -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);
Signature · 1 line
1.7.9.5
#21 lore raw

PATCH v12 23/49 CLK: TI: DRA7: Add APLL support

In reply to Tero Kristo

From: J Keerthy <[email protected]>

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

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

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

221 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#22 lore raw

PATCH v12 43/49 ARM: OMAP2+: PRM: add support for initializing PRCM clock modules from DT

In reply to Tero Kristo

This patch provides top level functionality for the DT clock initialization. Clock tree is initialized hierarchically starting from IP modules (CM/PRM/PRCM) going down towards individual clock nodes, and finally initializing clockdomains once all the clocks are ready.

---
 arch/arm/mach-omap2/prm.h        |    1 +
 arch/arm/mach-omap2/prm_common.c |   66 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)
arch/arm/mach-omap2/prm.h +1 -0
index ac25ae6..623db40 100644
@@ -18,6 +18,7 @@
 # ifndef __ASSEMBLER__
 extern void __iomem *prm_base;
 extern void omap2_set_globals_prm(void __iomem *prm);
+int of_prcm_init(void);
 # endif
 
 
arch/arm/mach-omap2/prm_common.c +66 -0

81 lines not on this page · raw message

Signature · 1 line
1.7.9.5
maintainer
#23 lore raw

v12 cover ARM: TI SoC clock DT conversion

In reply to Tero Kristo
Quoted 40 lines · Tero Kristo

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

Quoted 4 lines

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:

#24 lore raw

v12 cover ARM: TI SoC clock DT conversion

In reply to Tero Kristo
Quoted 40 lines · Tero Kristo

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

Quoted 4 lines

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

Signature · 8 lines
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>
#25 lore raw

v12 cover ARM: TI SoC clock DT conversion

In reply to Tero Kristo
Quoted 11 lines · Tero Kristo

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:

-- 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>

#26 lore raw

v12 cover ARM: TI SoC clock DT conversion

In reply to Tero Kristo

Hi Tero,

Quoted 5 lines · Tero Kristo

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
[...]

Quoted 4 lines

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

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

v12 cover ARM: TI SoC clock DT conversion

Quoted 63 lines · Nishanth Menon

Hi Tero,

Quoted 5 lines · Tero Kristo

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
[...]

Quoted 4 lines

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?

Quoted 8 lines

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
Quoted 37 lines

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

Signature · 2 lines
Regards,
Nishanth Menon