Skip to contentSkip to conversation

i.MX: Convert v4/v5 based SoCs to common clock framework

PATCH Superseded Sascha Hauer 6 participants 18 messages Mar 19, 2012 – Mar 23, 2012

Subsystems (4)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Sascha Hauer

author maintainer
#0 lore raw

Hi All,

The following patches convert the i.MX v4/v5 based SoCs to the common clock framework. They may not be completely ready, I am posting it now because I'd like to show that the function based clock initializers are indeed usable in real life and that the end result does not look too bad.

This series depends on another series not yet posted which convert the i.MX drivers to not depend on grouped clocks. I will follow up on this after the merge window. My plan for these patches is to put them into the arm-soc staging area after the merge window to let them stabilize until hopefully before the next merge window there are no regressions left.

Except the i.MX21 port all SoCs are runtime tested with the basic devices (at least uart and network; I tested more, but not systematically). Testers for these patches are very welcome, I will happily integrate fixups into this series. A branch containing Mikes latest clock patches, the driver fixups and this series can be found here:

git://git.pengutronix.de/git/imx/linux-2.6.git work/imx-clk-v4-v5

As a side note, we currently compile all i.MX v4/v5 based SoCs in a single defconfig. Since a kernel can only be built with or without the common clock framework this series is not fully bisectable, you have to disable the not yet converted SoCs in between.

The patch for removing the old clock support is not included in this post, but with the removal the overall diffstat looks like this:

 arch/arm/mach-imx/clock-imx1.c           |  636 ---------------
 arch/arm/mach-imx/clock-imx21.c          | 1239 -------------------------------
 arch/arm/mach-imx/clock-imx25.c          |  346 --------
 arch/arm/mach-imx/clock-imx27.c          |  766 -------------------
 b/arch/arm/mach-imx/Kconfig              |    4 
 b/arch/arm/mach-imx/Makefile             |   10 
 b/arch/arm/mach-imx/clk-imx1.c           |  118 ++
 b/arch/arm/mach-imx/clk-imx21.c          |  177 ++++
 b/arch/arm/mach-imx/clk-imx25.c          |  242 ++++++
 b/arch/arm/mach-imx/clk-imx27.c          |  277 ++++++
 b/arch/arm/mach-imx/clk-pllv1.c          |   59 +
 b/arch/arm/mach-imx/clk.h                |   44 +
 b/arch/arm/plat-mxc/clock.c              |   11 
 b/arch/arm/plat-mxc/include/mach/clock.h |    4 
 b/arch/arm/plat-mxc/time.c               |    5 
 15 files changed, 946 insertions(+), 2992 deletions(-)

----------------------------------------------------------------
Sascha Hauer (7):
ARM i.MX: prepare for common clock framework ARM i.MX timer: request correct clock
ARM i.MX: Add common clock support for pllv1 ARM i.MX1: implement clocks using common clock framework ARM i.MX21: implement clocks using common clock framework ARM i.MX25: implement clocks using common clock framework ARM i.MX27: implement clocks using common clock framework

 arch/arm/mach-imx/Kconfig              |    4 +
 arch/arm/mach-imx/Makefile             |   10 +-
 arch/arm/mach-imx/clk-imx1.c           |  118 ++++++++++++++
 arch/arm/mach-imx/clk-imx21.c          |  177 ++++++++++++++++++++
 arch/arm/mach-imx/clk-imx25.c          |  242 ++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk-imx27.c          |  277 ++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk-pllv1.c          |   59 +++++++
 arch/arm/mach-imx/clk.h                |   44 +++++
 arch/arm/plat-mxc/clock.c              |   11 ++
 arch/arm/plat-mxc/include/mach/clock.h |    4 +
 arch/arm/plat-mxc/time.c               |    5 +-
 11 files changed, 946 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx1.c
 create mode 100644 arch/arm/mach-imx/clk-imx21.c
 create mode 100644 arch/arm/mach-imx/clk-imx25.c
 create mode 100644 arch/arm/mach-imx/clk-imx27.c
 create mode 100644 arch/arm/mach-imx/clk-pllv1.c
 create mode 100644 arch/arm/mach-imx/clk.h
author maintainer
#1 lore raw

PATCH 1/8 clk: add a fixed factor clock

Having fixed factors/dividers in hardware is a common pattern, so add a clock doing this. Currently no rate propagation is supported.

---
 drivers/clk/Makefile           |    2 +-
 drivers/clk/clk-fixed-factor.c |   97 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |    4 ++
 3 files changed, 102 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/clk-fixed-factor.c
drivers/clk/Makefile +1 -1
index 1f736bc..24aa714 100644
@@ -1,4 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
-				   clk-mux.o clk-divider.o
+				   clk-mux.o clk-divider.o clk-fixed-factor.o
drivers/clk/clk-fixed-factor.c new file +97 -0

97 lines not on this page · raw message

include/linux/clk-provider.h +4 -0
index 5508897..21ca2f8 100644
@@ -257,6 +257,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
+struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned int mult, unsigned int div);
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
Signature · 1 line
1.7.9.1
#2 lore raw

PATCH 1/8 clk: add a fixed factor clock

Hi Sascha,

Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:

Quoted 4 lines

Having fixed factors/dividers in hardware is a common pattern, so add a clock doing this. Currently no rate propagation is supported.

Only a few clk-gateisms remain in clk_register_fixed_factor:

drivers/clk/clk-fixed-factor.c +3 -3
index 7c5e1fc..d99b842 100644
@@ -64,14 +64,14 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 	struct clk_fixed_factor *fix;
 	struct clk *clk;
 
-	fix = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
+	fix = kmalloc(sizeof(struct clk_fixed_factor), GFP_KERNEL);
 
 	if (!fix) {
-		pr_err("%s: could not allocate gated clk\n", __func__);
+		pr_err("%s: could not allocate fixed factor clk\n", __func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	/* struct clk_gate assignments */
+	/* struct clk_fixed_factor assignments */
 	fix->mult = mult;
 	fix->div = div;
 

--
1.7.9.1

regards
Philipp

author maintainer
#3 lore raw

PATCH 1/8 clk: add a fixed factor clock

Hi Philipp,

Quoted 5 lines · Philipp Zabel

Hi Sascha,

Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:

Quoted 2 lines

Having fixed factors/dividers in hardware is a common pattern, so add a clock doing this. Currently no rate propagation is supported.

Also this is not true anymore, rate propagation now is supported.

Quoted 6 lines
Quoted 2 lines

Only a few clk-gateisms remain in clk_register_fixed_factor:

Thanks, I'll integrate this.

Sascha

Quoted 29 lines
drivers/clk/clk-fixed-factor.c +3 -4
index 7c5e1fc..d99b842 100644
@@ -64,14 +64,14 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 	struct clk_fixed_factor *fix;
 	struct clk *clk;
 
-	fix = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
+	fix = kmalloc(sizeof(struct clk_fixed_factor), GFP_KERNEL);
 
 	if (!fix) {
-		pr_err("%s: could not allocate gated clk\n", __func__);
+		pr_err("%s: could not allocate fixed factor clk\n", __func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	/* struct clk_gate assignments */
+	/* struct clk_fixed_factor assignments */
 	fix->mult = mult;
 	fix->div = div;
 
--

1.7.9.1

regards
Philipp

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#4 lore raw

PATCH 1/8 clk: add a fixed factor clock

In reply to Sascha Hauer

Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:

Quoted 2 lines

Having fixed factors/dividers in hardware is a common pattern, so add a clock doing this. Currently no rate propagation is supported.

Also, could I convince you to move struct clk_fixed_factor into clk-provider.h and provide a DEFINE_CLK_FIXED_FACTOR macro to align with the other basic clocks?

---
 drivers/clk/clk-fixed-factor.c |   15 +++++++++------
 include/linux/clk-private.h    |   28 ++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |   19 +++++++++++++++++++
 3 files changed, 56 insertions(+), 6 deletions(-)
drivers/clk/clk-fixed-factor.c +9 -6
index d99b842..8ca427a 100644
@@ -12,12 +12,15 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 
-struct clk_fixed_factor {
-	struct clk_hw	hw;
-	unsigned int	mult;
-	unsigned int	div;
-	char		*parent[1];
-};
+/*
+ * DOC: basic fixed multiplier and divider clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is fixed.  clk->rate = parent->rate / div * mult
+ * parent - fixed parent.  No clk_set_parent support
+ */
 
 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
 
include/linux/clk-private.h +28 -0
index 5e4312b..9501eab 100644
@@ -170,6 +170,34 @@ extern struct clk_ops clk_mux_ops;
 		.flags = _flags,				\
 	};
 
+extern struct clk_ops clk_fixed_factor_ops;
+
+#define DEFINE_CLK_FIXED_FACTOR(_name, _parent_name,		\
+				_parent_ptr, _flags,		\
+				_mult, _div)			\
+	static struct clk _name;				\
+	static struct clk *_name##_parents[] = {		\
+		_parent_ptr,					\
+	};							\
+	static struct clk_fixed_factor _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.mult = _mult,					\
+		.div = _div,					\
+		.parent[0] = _parent_name,			\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_fixed_factor_ops,			\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_hw.parent,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##_hw.parent),		\
+		.parents = _name##_parents,			\
+		.flags = _flags,				\
+	};
+
 /**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
include/linux/clk-provider.h +19 -0
index 21ca2f8..b58f846 100644
@@ -257,6 +257,25 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
+/**
+ * struct clk_fixed_factor - fixed multiplier and divider clock
+ *
+ * @hw:         handle between common and hardware-specific interfaces
+ * @mult:	multiplier
+ * @div:        divider
+ *
+ * Clock with a fixed multiplier and divider. The output frequency is the
+ * parent clock rate divided by div and multiplied by mult.
+ * Implements .recalc_rate, .set_rate and .round_rate
+ */
+
+struct clk_fixed_factor {
+        struct clk_hw   hw;
+        unsigned int    mult;
+        unsigned int    div;
+        char            *parent[1];
+};
+
 struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div);
Signature · 1 line
1.7.9.1
author maintainer
#5 lore raw

PATCH 1/8 clk: add a fixed factor clock

Quoted 7 lines · Philipp Zabel

Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:

Quoted 2 lines

Having fixed factors/dividers in hardware is a common pattern, so add a clock doing this. Currently no rate propagation is supported.

Also, could I convince you to move struct clk_fixed_factor into clk-provider.h and provide a DEFINE_CLK_FIXED_FACTOR macro to align with the other basic clocks?

Given that this is the current way to statically initialize clocks, yes I'll integrate it, but not without grumbling about these macros in general...

Quoted 107 lines
---
 drivers/clk/clk-fixed-factor.c |   15 +++++++++------
 include/linux/clk-private.h    |   28 ++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |   19 +++++++++++++++++++
 3 files changed, 56 insertions(+), 6 deletions(-)
drivers/clk/clk-fixed-factor.c +9 -6
index d99b842..8ca427a 100644
@@ -12,12 +12,15 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 
-struct clk_fixed_factor {
-	struct clk_hw	hw;
-	unsigned int	mult;
-	unsigned int	div;
-	char		*parent[1];
-};
+/*
+ * DOC: basic fixed multiplier and divider clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is fixed.  clk->rate = parent->rate / div * mult
+ * parent - fixed parent.  No clk_set_parent support
+ */
 
 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
 
include/linux/clk-private.h +28 -0
index 5e4312b..9501eab 100644
@@ -170,6 +170,34 @@ extern struct clk_ops clk_mux_ops;
 		.flags = _flags,				\
 	};
 
+extern struct clk_ops clk_fixed_factor_ops;
+
+#define DEFINE_CLK_FIXED_FACTOR(_name, _parent_name,		\
+				_parent_ptr, _flags,		\
+				_mult, _div)			\
+	static struct clk _name;				\
+	static struct clk *_name##_parents[] = {		\
+		_parent_ptr,					\
+	};							\
+	static struct clk_fixed_factor _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.mult = _mult,					\
+		.div = _div,					\
+		.parent[0] = _parent_name,			\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_fixed_factor_ops,			\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_hw.parent,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##_hw.parent),		\
+		.parents = _name##_parents,			\
+		.flags = _flags,				\
+	};
+
 /**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
include/linux/clk-provider.h +19 -0
index 21ca2f8..b58f846 100644
@@ -257,6 +257,25 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
+/**
+ * struct clk_fixed_factor - fixed multiplier and divider clock
+ *
+ * @hw:         handle between common and hardware-specific interfaces
+ * @mult:	multiplier
+ * @div:        divider
+ *
+ * Clock with a fixed multiplier and divider. The output frequency is the
+ * parent clock rate divided by div and multiplied by mult.
+ * Implements .recalc_rate, .set_rate and .round_rate
+ */
+
+struct clk_fixed_factor {
+        struct clk_hw   hw;
+        unsigned int    mult;
+        unsigned int    div;
+        char            *parent[1];
+};
+
 struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div);
Signature · 1 line
1.7.9.1
Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#6 lore raw

PATCH 2/8 ARM i.MX: prepare for common clock framework

In reply to Sascha Hauer

- Add necessary #ifdefs for CONFIG_COMMON_CLOCK
- Add a global spinlock to protect the CCM registers

---
 arch/arm/mach-imx/clk.h                |   44 ++++++++++++++++++++++++++++++++
 arch/arm/plat-mxc/clock.c              |   11 ++++++++
 arch/arm/plat-mxc/include/mach/clock.h |    4 +++
 3 files changed, 59 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk.h
arch/arm/mach-imx/clk.h new file +44 -0
new file mode 100644
index 0000000..2f1a7b2
@@ -0,0 +1,44 @@
+#ifndef __MACH_IMX_CLK_H
+#define __MACH_IMX_CLK_H
+
+#include <linux/spinlock.h>
+#include <linux/clk-provider.h>
+#include <mach/clock.h>
+
+struct clk *imx_clk_pllv1(const char *name, char *parent,
+		void __iomem *base);
+
+static inline struct clk *imx_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *imx_clk_divider(const char *name, const char *parent,
+		void __iomem *reg, u8 shift, u8 width)
+{
+	return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
+			reg, shift, width, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_gate(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
+		u8 shift, u8 width, char **parents, int num_parents)
+{
+	return clk_register_mux(NULL, name, parents, num_parents, 0, reg, shift,
+			width, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_fixed_factor(const char *name,
+		const char *parent, unsigned int mult, unsigned int div)
+{
+	return clk_register_fixed_factor(NULL, name, parent,
+			CLK_SET_RATE_PARENT, mult, div);
+}
+
+#endif
arch/arm/plat-mxc/clock.c +11 -0
index 2ed3ab1..5079787 100644
@@ -41,6 +41,7 @@
 #include <mach/clock.h>
 #include <mach/hardware.h>
 
+#ifndef CONFIG_COMMON_CLK
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
@@ -200,6 +201,16 @@ struct clk *clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+#else
+
+/*
+ * Lock to protect the clock module (ccm) registers. Used
+ * on all i.MXs
+ */
+DEFINE_SPINLOCK(imx_ccm_lock);
+
+#endif /* CONFIG_COMMON_CLK */
+
 /*
  * Get the resulting clock rate from a PLL register value and the input
  * frequency. PLLs with this register layout can at least be found on
arch/arm/plat-mxc/include/mach/clock.h +4 -0
index 753a598..bd940c7 100644
@@ -23,6 +23,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/list.h>
 
+#ifndef CONFIG_COMMON_CLK
 struct module;
 
 struct clk {
@@ -59,6 +60,9 @@ struct clk {
 
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);
+#endif /* CONFIG_COMMON_CLK */
+
+extern spinlock_t imx_ccm_lock;
 
 unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
 
Signature · 1 line
1.7.9.1
author maintainer
#7 lore raw

PATCH 3/8 ARM i.MX timer: request correct clock

In reply to Sascha Hauer

We used to pass the timer clock directly to mxc_timer_init. We should instead request the correct clock. This is an intermediate
step: For now we request the clock in the timer code when NULL is passed as clock.

---
 arch/arm/plat-mxc/time.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
arch/arm/plat-mxc/time.c +4 -1
index 1c96cdb..462aecb 100644
@@ -283,7 +283,10 @@ void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
 {
 	uint32_t tctl_val;
 
-	clk_enable(timer_clk);
+	if (!timer_clk)
+		timer_clk = clk_get_sys("imx-gpt.0", "per");
+
+	clk_prepare_enable(timer_clk);
 
 	timer_base = base;
 
Signature · 1 line
1.7.9.1
author maintainer
#8 lore raw

PATCH 4/8 ARM i.MX: Add common clock support for pllv1

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Makefile    |    2 +
 arch/arm/mach-imx/clk-pllv1.c |   59 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-pllv1.c
arch/arm/mach-imx/Makefile +2 -0
index 55db9c4..1f138ae 100644
@@ -13,6 +13,8 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o
+
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
arch/arm/mach-imx/clk-pllv1.c new file +59 -0

59 lines not on this page · raw message

Signature · 1 line
1.7.9.1
author maintainer
#9 lore raw

PATCH 5/8 ARM i.MX1: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig    |    1 +
 arch/arm/mach-imx/Makefile   |    2 +-
 arch/arm/mach-imx/clk-imx1.c |  118 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx1.c
arch/arm/mach-imx/Kconfig +1 -0
index 4defb97..4cd86fb 100644
@@ -37,6 +37,7 @@ config ARCH_MX53
 config SOC_IMX1
 	bool
 	select ARCH_MX1
+	select COMMON_CLK
 	select CPU_ARM920T
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
arch/arm/mach-imx/Makefile +1 -1
index 1f138ae..cec4843 100644
@@ -1,6 +1,6 @@
 obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 
-obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
 obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
arch/arm/mach-imx/clk-imx1.c new file +118 -0

118 lines not on this page · raw message

Signature · 1 line
1.7.9.1
author maintainer
#10 lore raw

PATCH 6/8 ARM i.MX21: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx21.c |  177 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx21.c
arch/arm/mach-imx/Kconfig +1 -0
index 4cd86fb..8b4b4e3 100644
@@ -46,6 +46,7 @@ config SOC_IMX1
 config SOC_IMX21
 	bool
 	select MACH_MX21
+	select COMMON_CLK
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
arch/arm/mach-imx/Makefile +1 -1
index cec4843..0a0bd05 100644
@@ -1,7 +1,7 @@
 obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 
 obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
-obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
+obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 
 obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
arch/arm/mach-imx/clk-imx21.c new file +177 -0

177 lines not on this page · raw message

Signature · 1 line
1.7.9.1
author maintainer
#11 lore raw

PATCH 7/8 ARM i.MX25: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx25.c |  242 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 244 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/Kconfig +1 -0
index 8b4b4e3..4623865 100644
@@ -59,6 +59,7 @@ config SOC_IMX25
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_MXC_IOMUX_V3
+	select COMMON_CLK
 	select MXC_AVIC
 
 config SOC_IMX27
arch/arm/mach-imx/Makefile +1 -1
index 0a0bd05..d96e2ce 100644
@@ -3,7 +3,7 @@ obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 
-obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
 obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
arch/arm/mach-imx/clk-imx25.c new file +242 -0

242 lines not on this page · raw message

Signature · 1 line
1.7.9.1
author maintainer
#12 lore raw

PATCH 8/8 ARM i.MX27: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx27.c |  277 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 279 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/Kconfig +1 -0
index 4623865..bbef3d0 100644
@@ -65,6 +65,7 @@ config SOC_IMX25
 config SOC_IMX27
 	bool
 	select MACH_MX27
+	select COMMON_CLK
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
arch/arm/mach-imx/Makefile +1 -1
index d96e2ce..b39f2d6 100644
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
arch/arm/mach-imx/clk-imx27.c new file +277 -0

277 lines not on this page · raw message

Signature · 1 line
1.7.9.1
#13 lore raw

PATCH 8/8 ARM i.MX27: implement clocks using common clock framework

Quoted 107 lines · Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx27.c |  277 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 279 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/Kconfig +1 -0
index 4623865..bbef3d0 100644
@@ -65,6 +65,7 @@ config SOC_IMX25
 config SOC_IMX27
 	bool
 	select MACH_MX27
+	select COMMON_CLK
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
arch/arm/mach-imx/Makefile +1 -1
index d96e2ce..b39f2d6 100644
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
arch/arm/mach-imx/clk-imx27.c new file +68 -0
new file mode 100644
index 0000000..e44e70e
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012 Sascha Hauer <[email protected]>, Pengutronix
+ *
+ * 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 in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#include "clk.h"
+
+#define IO_ADDR_CCM(off)	(MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
+
+/* Register offsets */
+#define CCM_CSCR		IO_ADDR_CCM(0x0)
+#define CCM_MPCTL0		IO_ADDR_CCM(0x4)
+#define CCM_MPCTL1		IO_ADDR_CCM(0x8)
+#define CCM_SPCTL0		IO_ADDR_CCM(0xc)
+#define CCM_SPCTL1		IO_ADDR_CCM(0x10)
+#define CCM_OSC26MCTL		IO_ADDR_CCM(0x14)
+#define CCM_PCDR0		IO_ADDR_CCM(0x18)
+#define CCM_PCDR1		IO_ADDR_CCM(0x1c)
+#define CCM_PCCR0		IO_ADDR_CCM(0x20)
+#define CCM_PCCR1		IO_ADDR_CCM(0x24)
+#define CCM_CCSR		IO_ADDR_CCM(0x28)
+#define CCM_PMCTL		IO_ADDR_CCM(0x2c)
+#define CCM_PMCOUNT		IO_ADDR_CCM(0x30)
+#define CCM_WKGDCTL		IO_ADDR_CCM(0x34)
+
+#define CCM_CSCR_UPDATE_DIS	(1 << 31)
+#define CCM_CSCR_SSI2		(1 << 23)
+#define CCM_CSCR_SSI1		(1 << 22)
+#define CCM_CSCR_VPU		(1 << 21)
+#define CCM_CSCR_MSHC           (1 << 20)
+#define CCM_CSCR_SPLLRES        (1 << 19)
+#define CCM_CSCR_MPLLRES        (1 << 18)
+#define CCM_CSCR_SP             (1 << 17)
+#define CCM_CSCR_MCU            (1 << 16)
+#define CCM_CSCR_OSC26MDIV      (1 << 4)
+#define CCM_CSCR_OSC26M         (1 << 3)
+#define CCM_CSCR_FPM            (1 << 2)
+#define CCM_CSCR_SPEN           (1 << 1)
+#define CCM_CSCR_MPEN           (1 << 0)
+
+/* i.MX27 TO 2+ */
+#define CCM_CSCR_ARM_SRC        (1 << 15)
+
+#define CCM_SPCTL1_LF           (1 << 15)
+#define CCM_SPCTL1_BRMO         (1 << 6)
+
+struct clkl {
+	struct clk_lookup lookup;

arch/arm/mach-imx/clk-imx27.c line 78

Quoted 10 lines
arch/arm/mach-imx/clk-imx27.c new file +10 -0
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+

They should at least be defined in arch/arm/mach-imx/clk.h to avoid the duplication in every single imx clock driver.

If using registration function becomes the common way that clock driver registers clks, they will be needed by other platforms too. Then, we should probably do something like below instead?

include/linux/clkdev.h +8 -0
index d9a4fd0..2cde34e 100644
@@ -21,6 +21,7 @@ struct clk_lookup {
        struct list_head        node;
        const char              *dev_id;
        const char              *con_id;
+       const char              *clk_name;
        struct clk              *clk;
 };
 
@@ -31,6 +32,13 @@ struct clk_lookup {
                .clk = c,       \
        }
 
+#define CLKDEV_INIT_N(d, n, cn)        \
+       {                       \
+               .dev_id = d,    \
+               .con_id = n,    \
+               .clk_name = cn, \
+       }
+
 struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
        const char *dev_fmt, ...);
 
Quoted 179 lines
arch/arm/mach-imx/clk-imx27.c new file +179 -0
+static struct clkl lookups[] = {
+	clkdev("imx21-uart.0", "ipg", "uart1_ipg_gate")
+	clkdev("imx21-uart.0", "per", "per1_gate")
+	clkdev("imx21-uart.1", "ipg", "uart2_ipg_gate")
+	clkdev("imx21-uart.1", "per", "per1_gate")
+	clkdev("imx21-uart.2", "ipg", "uart3_ipg_gate")
+	clkdev("imx21-uart.2", "per", "per1_gate")
+	clkdev("imx21-uart.3", "ipg", "uart4_ipg_gate")
+	clkdev("imx21-uart.3", "per", "per1_gate")
+	clkdev("imx21-uart.4", "ipg", "uart5_ipg_gate")
+	clkdev("imx21-uart.4", "per", "per1_gate")
+	clkdev("imx21-uart.5", "ipg", "uart6_ipg_gate")
+	clkdev("imx21-uart.5", "per", "per1_gate")
+	clkdev("imx-gpt.0", "ipg", "gpt1_ipg_gate")
+	clkdev("imx-gpt.0", "per", "per1_gate")
+	clkdev("imx-gpt.1", "ipg", "gpt2_ipg_gate")
+	clkdev("imx-gpt.1", "per", "per1_gate")
+	clkdev("imx-gpt.2", "ipg", "gpt3_ipg_gate")
+	clkdev("imx-gpt.2", "per", "per1_gate")
+	clkdev("imx-gpt.3", "ipg", "gpt4_ipg_gate")
+	clkdev("imx-gpt.3", "per", "per1_gate")
+	clkdev("imx-gpt.4", "ipg", "gpt5_ipg_gate")
+	clkdev("imx-gpt.4", "per", "per1_gate")
+	clkdev("imx-gpt.5", "ipg", "gpt6_ipg_gate")
+	clkdev("imx-gpt.5", "per", "per1_gate")
+	clkdev("mxc_pwm.0", NULL, "pwm")
+	clkdev("mxc-mmc.0", "per", "per2_gate")
+	clkdev("mxc-mmc.0", "ipg", "sdhc1_ipg_gate")
+	clkdev("mxc-mmc.1", "per", "per2_gate")
+	clkdev("mxc-mmc.1", "ipg", "sdhc2_ipg_gate")
+	clkdev("mxc-mmc.2", "per", "per2_gate")
+	clkdev("mxc-mmc.2", "ipg", "sdhc2_ipg_gate")
+	clkdev("imx27-cspi.0", NULL, "cspi1")
+	clkdev("imx27-cspi.1", NULL, "cspi2")
+	clkdev("imx27-cspi.2", NULL, "cspi3")
+	clkdev("imx-fb.0", "per", "per3_gate")
+	clkdev("imx-fb.0", "ipg", "lcdc_ipg_gate")
+	clkdev("imx-fb.0", "ahb", "lcdc_ahb_gate")
+	clkdev("mx2-camera.0", NULL, "csi")
+	clkdev("fsl-usb2-udc", "usb", "usb")
+	clkdev("fsl-usb2-udc", "usb_ahb", "usb_ahb_gate")
+	clkdev("mxc-ehci.0", "usb", "usb")
+	clkdev("mxc-ehci.0", "usb_ahb", "usb_ahb_gate")
+	clkdev("mxc-ehci.1", "usb", "usb")
+	clkdev("mxc-ehci.1", "usb_ahb", "usb_ahb_gate")
+	clkdev("mxc-ehci.2", "usb", "usb")
+	clkdev("mxc-ehci.2", "usb_ahb", "usb_ahb_gate")
+	clkdev("imx-ssi.0", NULL, "ssi1_ipg_gate")
+	clkdev("imx-ssi.1", NULL, "ssi2_ipg_gate")
+	clkdev("mxc_nand.0", NULL, "nfc_baud_gate")
+	clkdev("imx-vpu", "per", "vpu_baud_gate")
+	clkdev("imx-vpu", "ahb", "vpu_ahb_gate")
+	clkdev("imx-dma", "ahb", "dma_ahb_gate")
+	clkdev("imx-dma", "ipg", "dma_ipg_gate")
+	clkdev("imx27-fec.0", "ipg", "fec_ipg_gate")
+	clkdev("imx27-fec.0", "ahb", "fec_ahb_gate")
+	clkdev("imx2-wdt.0", NULL, "wdog_ipg_gate")
+	clkdev("imx-i2c.0", NULL, "i2c1_ipg_gate")
+	clkdev("imx-i2c.1", NULL, "i2c2_ipg_gate")
+	clkdev("mxc_w1.0", NULL, "owire_ipg_gate")
+	clkdev("imx-keypad", NULL, "kpp_ipg_gate")
+	clkdev("imx-emma", "ahb", "emma_ahb_gate")
+	clkdev("imx-emma", "ipg", "emma_ipg_gate")
+	clkdev(NULL, "iim", "iim_ipg_gate")
+	clkdev(NULL, "gpio", "gpio_ipg_gate")
+	clkdev(NULL, "brom", "brom_ahb_gate")
+	clkdev(NULL, "ata", "ata_ahb_gate")
+	clkdev(NULL, "rtc", "rtc_ipg_gate")
+	clkdev(NULL, "scc", "scc_ipg_gate")
+	clkdev(NULL, "cpu", "cpu_div")
+	clkdev(NULL, "emi_ahb" , "emi_ahb_gate")
+	clkdev("imx-ssi.0", "bitrate" , "ssi1_baud_gate")
+	clkdev("imx-ssi.1", "bitrate" , "ssi2_baud_gate")
+};
+
+static char *vpu_sel_clks[] = { "spll", "mpll_main2", };
+static char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
+static char *clko_sel_clks[] = {
+	"ckil", "prem", "ckih", "ckih",
+	"ckih", "mpll", "spll", "cpu_div",
+	"ahb", "ipg", "per1_div", "per2_div",
+	"per3_div", "per4_div", "ssi1_div", "ssi2_div",
+	"nfc_div", "mshc_div", "vpu_div", "60m",
+	"32k", "usb_div", "dptc",
+};
+
+static char *ssi_sel_clks[] = { "spll", "mpll", };
+
+int __init mx27_clocks_init(unsigned long fref)
+{
+	int i;
+	struct clk *emi_ahb;
+
+	imx_clk_fixed("dummy", 0);
+	imx_clk_fixed("ckih", fref);
+	imx_clk_fixed("ckil", 32768);
+	imx_clk_pllv1("mpll", "ckih", CCM_MPCTL0);
+	imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
+	imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
+
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
+		imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
+		imx_clk_fixed_factor("ipg", "ahb", 1, 2);
+	} else {
+		imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4);
+		imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1);
+	}
+
+	imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
+	imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
+	imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
+	imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
+	imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
+	imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
+	imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3);
+	imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
+	imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
+	imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
+		imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
+	else
+		imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3);
+	imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3);
+	imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+	imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+	imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
+	imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3);
+	imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
+	imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
+	imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
+	imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
+	imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
+	imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
+	imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
+	imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
+	imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
+	imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
+	imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
+	imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
+	imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
+	imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
+	imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
+	imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
+	imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
+	imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
+	imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
+	imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
+	imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
+	imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
+	imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
+	imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
+	imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
+	imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
+	imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
+	imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
+	imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
+	imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
+	imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1,  3);
+	imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1,  4);
+	imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1,  5);
+	imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1,  6);
+	imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1,  7);
+	imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1,  8);
+	imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1,  9);
+	imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
+	imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
+	imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
+	imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
+	imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
+	imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
+	imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
+	imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
+	emi_ahb = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
+	imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
+	imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
+	imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
+	imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
+	imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
+	imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);

arch/arm/mach-imx/clk-imx27.c line 267

Quoted 10 lines
arch/arm/mach-imx/clk-imx27.c new file +10 -0
+	imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
+	imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
+	imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
+	imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
+	imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
+	imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		struct clkl *l = &lookups[i];
+		l->lookup.clk = __clk_lookup(l->clkname);

That's somehow unfortunate this expensive function needs to be called to retrieve these clks, while those registration functions should ever have them returned.

Quoted 13 lines
arch/arm/mach-imx/clk-imx27.c new file +10 -0
+		clkdev_add(&l->lookup);
+	}
+
+	mxc_timer_init(NULL, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+			MX27_INT_GPT1);
+
+	clk_prepare_enable(emi_ahb);
+
+	return 0;
+}
Signature · 1 line
1.7.9.1
Signature · 2 lines
Regards,
Shawn
author maintainer
#14 lore raw

PATCH 8/8 ARM i.MX27: implement clocks using common clock framework

Quoted 8 lines · Shawn Guo
Quoted 8 lines
(quoted diff) +8 -0
+
+struct clkl {
+	struct clk_lookup lookup;
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+

They should at least be defined in arch/arm/mach-imx/clk.h to avoid the duplication in every single imx clock driver.

Yes, right. See it as a quick-n-dirty solution...

Quoted 18 lines

If using registration function becomes the common way that clock driver registers clks, they will be needed by other platforms too. Then, we should probably do something like below instead?

include/linux/clkdev.h +1 -0
index d9a4fd0..2cde34e 100644
@@ -21,6 +21,7 @@ struct clk_lookup {
        struct list_head        node;
        const char              *dev_id;
        const char              *con_id;
+       const char              *clk_name;
        struct clk              *clk;
 };
 

include/linux/clkdev.h struct clk_lookup { · line 41

Quoted 10 lines
include/linux/clkdev.h +7 -0
@@ -31,6 +32,13 @@ struct clk_lookup {
                .clk = c,       \
        }
 
+#define CLKDEV_INIT_N(d, n, cn)        \
+       {                       \
+               .dev_id = d,    \
+               .con_id = n,    \
+               .clk_name = cn, \
+       }
+

...until something better is found. Adding the clock name to clk_lookup seems like a good start.

Quoted 11 lines
include/linux/clkdev.h +0 -0
 > +	imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
 > +	imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
 > +	imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);

Review

Quoted 4 lines
(quoted diff) +4 -0
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		struct clkl *l = &lookups[i];
+		l->lookup.clk = __clk_lookup(l->clkname);

That's somehow unfortunate this expensive function needs to be called to retrieve these clks, while those registration functions should ever have them returned.

I wanted to avoid having 'clkbla =' before every initializer. Maybe we can skip struct clk from struct clk_lookup and only keep the name. __clk_lookup could then be called in clk_get. This way looking up the clock would be done when a clock is requested and we wouldn't do it all at once and wouldn't add delays to the boot process.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#15 lore raw

PATCH 8/8 ARM i.MX27: implement clocks using common clock framework

Quoted 16 lines · Sascha Hauer
Quoted 7 lines
Quoted 7 lines
(quoted diff) +7 -0
+struct clkl {
+   struct clk_lookup lookup;
+   const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+   { \
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+           .lookup.dev_id = d, \
+           .lookup.con_id = n, \
+           .clkname = c, \
+   },
+

They should at least be defined in arch/arm/mach-imx/clk.h to avoid the duplication in every single imx clock driver.

Quoted 2 lines

Yes, right. See it as a quick-n-dirty solution...

Or maybe just remove the macro. Open-coding seems to take little more space, and I actually find it more readable:

static struct clkl lookups[] = {
	{ { .dev_id = "imx21-uart.0", .con_id = "ipg" }, "uart1_ipg_gate" },
	{ { .dev_id = "imx21-uart.0", .con_id = "per" }, "per1_gate" },
	{ { .dev_id = "imx21-uart.1", .con_id = "ipg" }, "uart2_ipg_gate" },
	{ ... },
};

Arnd

#16 lore raw
In reply to Sascha Hauer
Quoted 69 lines · Sascha Hauer

Hi All,

The following patches convert the i.MX v4/v5 based SoCs to the common clock framework. They may not be completely ready, I am posting it now because I'd like to show that the function based clock initializers are indeed usable in real life and that the end result does not look too bad.

This series depends on another series not yet posted which convert the i.MX drivers to not depend on grouped clocks. I will follow up on this after the merge window. My plan for these patches is to put them into the arm-soc staging area after the merge window to let them stabilize until hopefully before the next merge window there are no regressions left.

Except the i.MX21 port all SoCs are runtime tested with the basic devices (at least uart and network; I tested more, but not systematically). Testers for these patches are very welcome, I will happily integrate fixups into this series. A branch containing Mikes latest clock patches, the driver fixups and this series can be found here:

git://git.pengutronix.de/git/imx/linux-2.6.git work/imx-clk-v4-v5

As a side note, we currently compile all i.MX v4/v5 based SoCs in a single defconfig. Since a kernel can only be built with or without the common clock framework this series is not fully bisectable, you have to disable the not yet converted SoCs in between.

The patch for removing the old clock support is not included in this post, but with the removal the overall diffstat looks like this:

 arch/arm/mach-imx/clock-imx1.c           |  636 ---------------
 arch/arm/mach-imx/clock-imx21.c          | 1239 -------------------------------
 arch/arm/mach-imx/clock-imx25.c          |  346 --------
 arch/arm/mach-imx/clock-imx27.c          |  766 -------------------
 b/arch/arm/mach-imx/Kconfig              |    4 
 b/arch/arm/mach-imx/Makefile             |   10 
 b/arch/arm/mach-imx/clk-imx1.c           |  118 ++
 b/arch/arm/mach-imx/clk-imx21.c          |  177 ++++
 b/arch/arm/mach-imx/clk-imx25.c          |  242 ++++++
 b/arch/arm/mach-imx/clk-imx27.c          |  277 ++++++
 b/arch/arm/mach-imx/clk-pllv1.c          |   59 +
 b/arch/arm/mach-imx/clk.h                |   44 +
 b/arch/arm/plat-mxc/clock.c              |   11 
 b/arch/arm/plat-mxc/include/mach/clock.h |    4 
 b/arch/arm/plat-mxc/time.c               |    5 
 15 files changed, 946 insertions(+), 2992 deletions(-)

----------------------------------------------------------------
Sascha Hauer (7):
ARM i.MX: prepare for common clock framework ARM i.MX timer: request correct clock
ARM i.MX: Add common clock support for pllv1 ARM i.MX1: implement clocks using common clock framework ARM i.MX21: implement clocks using common clock framework ARM i.MX25: implement clocks using common clock framework ARM i.MX27: implement clocks using common clock framework

 arch/arm/mach-imx/Kconfig              |    4 +
 arch/arm/mach-imx/Makefile             |   10 +-
 arch/arm/mach-imx/clk-imx1.c           |  118 ++++++++++++++
 arch/arm/mach-imx/clk-imx21.c          |  177 ++++++++++++++++++++
 arch/arm/mach-imx/clk-imx25.c          |  242 ++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk-imx27.c          |  277 ++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk-pllv1.c          |   59 +++++++
 arch/arm/mach-imx/clk.h                |   44 +++++
 arch/arm/plat-mxc/clock.c              |   11 ++
 arch/arm/plat-mxc/include/mach/clock.h |    4 +
Quoted 9 lines
 arch/arm/plat-mxc/time.c               |    5 +-
 11 files changed, 946 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx1.c
 create mode 100644 arch/arm/mach-imx/clk-imx21.c
 create mode 100644 arch/arm/mach-imx/clk-imx25.c
 create mode 100644 arch/arm/mach-imx/clk-imx27.c
 create mode 100644 arch/arm/mach-imx/clk-pllv1.c
 create mode 100644 arch/arm/mach-imx/clk.h

Do we want to move all clock code to drivers/clk? I'm not saying it has to be done now, but is that a goal?

Rob

#17 lore raw
Quoted 2 lines · Rob Herring

Do we want to move all clock code to drivers/clk? I'm not saying it has to be done now, but is that a goal?

My knee jerk response is to say "no". Back in January a similar topic came up for the AT91 CPUidle driver migrating to drivers/cpuidle/. See Russell's reply here:
http://article.gmane.org/gmane.linux.ports.arm.kernel/147849

If a platform's clock code lives in a silo and is nicely walled off from other platform-specific bits then migration to drivers/clk/ is possible. In practice I think that more complex clock code and data will have a hard time doing so. Even the simple task of sharing a header which exposes commonly used register addresses, offsets and widths starts to get complicated when some of the code/data that uses it lives in arch/* and some of it lives in drivers/*

Regards,
Mike