All of lore.kernel.org
 help / color / mirror / Atom feed
* i.MX: Convert v4/v5 based SoCs to common clock framework
@ 2012-03-19 13:35 Sascha Hauer
  2012-03-19 13:35 ` [PATCH 1/8] clk: add a fixed factor clock Sascha Hauer
                   ` (8 more replies)
  0 siblings, 9 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:35 UTC (permalink / raw)
  To: linux-arm-kernel

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

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

* [PATCH 1/8] clk: add a fixed factor clock
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
@ 2012-03-19 13:35 ` Sascha Hauer
  2012-03-23  7:37   ` Philipp Zabel
  2012-03-23  7:41   ` Philipp Zabel
  2012-03-19 13:36 ` [PATCH 2/8] ARM i.MX: prepare for common clock framework Sascha Hauer
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:35 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 1f736bc..24aa714 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -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
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
new file mode 100644
index 0000000..7c5e1fc
--- /dev/null
+++ b/drivers/clk/clk-fixed-factor.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * 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.
+ *
+ * Standard functionality for the common clock API.
+ */
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#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];
+};
+
+#define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
+
+static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
+
+	return (parent_rate / fix->div) * fix->mult;
+}
+
+static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
+
+	if (prate) {
+		unsigned long best_parent;
+		best_parent = (rate / fix->mult) * fix->div;
+		*prate = __clk_round_rate(__clk_get_parent(hw->clk),
+				best_parent);
+		return (*prate / fix->div) * fix->mult;
+	} else {
+		return (__clk_get_rate(__clk_get_parent(hw->clk)) / fix->div) * fix->mult;
+	}
+}
+
+static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+	return 0;
+}
+
+struct clk_ops clk_fixed_factor_ops = {
+	.round_rate = clk_factor_round_rate,
+	.set_rate = clk_factor_set_rate,
+	.recalc_rate = clk_factor_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
+
+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)
+{
+	struct clk_fixed_factor *fix;
+	struct clk *clk;
+
+	fix = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+	if (!fix) {
+		pr_err("%s: could not allocate gated clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_gate assignments */
+	fix->mult = mult;
+	fix->div = div;
+
+	if (parent_name) {
+		fix->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+		if (!fix->parent[0])
+			goto out;
+	}
+
+	clk = clk_register(dev, name,
+			&clk_fixed_factor_ops, &fix->hw,
+			fix->parent,
+			(parent_name ? 1 : 0),
+			flags);
+	if (clk)
+		return clk;
+
+out:
+	kfree(fix->parent[0]);
+	kfree(fix);
+
+	return NULL;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5508897..21ca2f8 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -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
-- 
1.7.9.1

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

* [PATCH 2/8] ARM i.MX: prepare for common clock framework
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
  2012-03-19 13:35 ` [PATCH 1/8] clk: add a fixed factor clock Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 13:36 ` [PATCH 3/8] ARM i.MX timer: request correct clock Sascha Hauer
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
new file mode 100644
index 0000000..2f1a7b2
--- /dev/null
+++ b/arch/arm/mach-imx/clk.h
@@ -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
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 2ed3ab1..5079787 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -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
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..bd940c7 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -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);
 
-- 
1.7.9.1

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

* [PATCH 3/8] ARM i.MX timer: request correct clock
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
  2012-03-19 13:35 ` [PATCH 1/8] clk: add a fixed factor clock Sascha Hauer
  2012-03-19 13:36 ` [PATCH 2/8] ARM i.MX: prepare for common clock framework Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 13:36 ` [PATCH 4/8] ARM i.MX: Add common clock support for pllv1 Sascha Hauer
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/plat-mxc/time.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index 1c96cdb..462aecb 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -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;
 
-- 
1.7.9.1

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

* [PATCH 4/8] ARM i.MX: Add common clock support for pllv1
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
                   ` (2 preceding siblings ...)
  2012-03-19 13:36 ` [PATCH 3/8] ARM i.MX timer: request correct clock Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 13:36 ` [PATCH 5/8] ARM i.MX1: implement clocks using common clock framework Sascha Hauer
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 55db9c4..1f138ae 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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
 
diff --git a/arch/arm/mach-imx/clk-pllv1.c b/arch/arm/mach-imx/clk-pllv1.c
new file mode 100644
index 0000000..afbd95f
--- /dev/null
+++ b/arch/arm/mach-imx/clk-pllv1.c
@@ -0,0 +1,59 @@
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include "clk.h"
+
+/**
+ * pll v1
+ *
+ * @clk_hw	clock source
+ * @parent	the parent clock name
+ * @base	base address of pll registers
+ *
+ * PLL clock version 1, found on i.MX1/21/25/27/31/35
+ */
+struct clk_pllv1 {
+	struct clk_hw	hw;
+	void __iomem	*base;
+	char		*parent;
+};
+
+#define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
+
+static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_pllv1 *pll = to_clk_pllv1(hw);
+
+	return mxc_decode_pll(readl(pll->base), parent_rate);
+}
+
+struct clk_ops clk_pllv1_ops = {
+	.recalc_rate = clk_pllv1_recalc_rate,
+};
+
+struct clk *imx_clk_pllv1(const char *name, char *parent,
+		void __iomem *base)
+{
+	struct clk_pllv1 *pll;
+	struct clk *clk;
+
+	pll = kmalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return NULL;
+
+	pll->base = base;
+	pll->parent = parent;
+
+	clk = clk_register(NULL, name, &clk_pllv1_ops, &pll->hw, &pll->parent,
+			1, 0);
+	if (!clk)
+		kfree(pll);
+
+	return clk;
+}
-- 
1.7.9.1

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

* [PATCH 5/8] ARM i.MX1: implement clocks using common clock framework
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
                   ` (3 preceding siblings ...)
  2012-03-19 13:36 ` [PATCH 4/8] ARM i.MX: Add common clock support for pllv1 Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 13:36 ` [PATCH 6/8] ARM i.MX21: " Sascha Hauer
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4defb97..4cd86fb 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -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
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 1f138ae..cec4843 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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
diff --git a/arch/arm/mach-imx/clk-imx1.c b/arch/arm/mach-imx/clk-imx1.c
new file mode 100644
index 0000000..b9b8589
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx1.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, 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/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include "clk.h"
+
+/* CCM register addresses */
+#define IO_ADDR_CCM(off)	(MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
+
+#define CCM_CSCR	IO_ADDR_CCM(0x0)
+#define CCM_MPCTL0	IO_ADDR_CCM(0x4)
+#define CCM_SPCTL0	IO_ADDR_CCM(0xc)
+#define CCM_PCDR	IO_ADDR_CCM(0x20)
+
+/* SCM register addresses */
+#define IO_ADDR_SCM(off)	(MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
+
+#define SCM_GCCR	IO_ADDR_SCM(0xc)
+
+struct clkl {
+	struct clk_lookup lookup;
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+
+static struct clkl lookups[] = {
+	clkdev(NULL, "dma", "dma_gate")
+	clkdev("mx1-camera.0", NULL, "csi_gate")
+	clkdev(NULL, "mma", "mma_gate")
+	clkdev("imx_udc.0", NULL, "usbd_gate")
+	clkdev("imx-gpt.0", "per", "per1")
+	clkdev("imx1-uart.0", "per", "per1")
+	clkdev("imx1-uart.0", "ipg", "hclk")
+	clkdev("imx1-uart.1", "per", "per1")
+	clkdev("imx1-uart.1", "ipg", "hclk")
+	clkdev("imx1-uart.2", "per", "per1")
+	clkdev("imx1-uart.2", "ipg", "hclk")
+	clkdev("imx-i2c.0", NULL, "hclk")
+	clkdev("imx1-cspi.0", "per", "per2")
+	clkdev("imx1-cspi.0", "ipg", "dummy")
+	clkdev("imx1-cspi.1", "per", "per2")
+	clkdev("imx1-cspi.1", "ipg", "dummy")
+	clkdev("imx-mmc.0", NULL, "per2")
+	clkdev("imx-fb.0", "per", "per2")
+	clkdev("imx-fb.0", "ipg", "dummy")
+	clkdev("imx-fb.0", "ahb", "dummy")
+	clkdev(NULL, "mshc", "hclk")
+	clkdev(NULL, "ssi", "per3")
+	clkdev("mxc_rtc.0", NULL, "clk32")
+	clkdev(NULL, "clko", "clko")
+};
+
+static char *prem_sel_clks[] = { "clk32_premult", "clk16m", };
+static char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", "prem",
+				"fclk", };
+
+int __init mx1_clocks_init(unsigned long fref)
+{
+	int i;
+
+	imx_clk_fixed("dummy", 0);
+	imx_clk_fixed("clk32", fref);
+	imx_clk_fixed("clk16m_ext", 16000000);
+	imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
+	imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
+	imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks));
+	imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
+	imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
+	imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
+	imx_clk_divider("fclk", "mpll", CCM_CSCR, 15, 1);
+	imx_clk_divider("hclk", "spll", CCM_CSCR, 10, 4);
+	imx_clk_divider("clk48m", "spll", CCM_CSCR, 26, 3);
+	imx_clk_divider("per1", "spll", CCM_PCDR, 0, 4);
+	imx_clk_divider("per2", "spll", CCM_PCDR, 4, 4);
+	imx_clk_divider("per3", "spll", CCM_PCDR, 16, 7);
+	imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+	imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 4);
+	imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2);
+	imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1);
+	imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0);
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		struct clkl *l = &lookups[i];
+		l->lookup.clk = __clk_lookup(l->clkname);
+		clkdev_add(&l->lookup);
+	}
+
+	mxc_timer_init(NULL, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR),
+			MX1_TIM1_INT);
+
+	return 0;
+}
-- 
1.7.9.1

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

* [PATCH 6/8] ARM i.MX21: implement clocks using common clock framework
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
                   ` (4 preceding siblings ...)
  2012-03-19 13:36 ` [PATCH 5/8] ARM i.MX1: implement clocks using common clock framework Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 13:36 ` [PATCH 7/8] ARM i.MX25: " Sascha Hauer
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4cd86fb..8b4b4e3 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -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
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index cec4843..0a0bd05 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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
 
diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c
new file mode 100644
index 0000000..0807965
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx21.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include "clk.h"
+
+#define IO_ADDR_CCM(off)	(MX21_IO_ADDRESS(MX21_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)
+
+static char *mpll_sel_clks[] = { "fpm", "ckih", };
+static char *spll_sel_clks[] = { "fpm", "ckih", };
+
+struct clkl {
+	struct clk_lookup lookup;
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+
+static struct clkl lookups[] = {
+	clkdev("imx21-uart.0", "per", "per1")
+	clkdev("imx21-uart.0", "ipg", "uart1_ipg_gate")
+	clkdev("imx21-uart.1", "per", "per1")
+	clkdev("imx21-uart.1", "ipg", "uart2_ipg_gate")
+	clkdev("imx21-uart.2", "per", "per1")
+	clkdev("imx21-uart.2", "ipg", "uart3_ipg_gate")
+	clkdev("imx21-uart.3", "per", "per1")
+	clkdev("imx21-uart.3", "ipg", "uart4_ipg_gate")
+	clkdev("imx-gpt.0", "ipg", "gpt1_ipg_gate")
+	clkdev("imx-gpt.0", "per", "per1")
+	clkdev("imx-gpt.1", "ipg", "gpt2_ipg_gate")
+	clkdev("imx-gpt.1", "per", "per1")
+	clkdev("imx-gpt.2", "ipg", "gpt3_ipg_gate")
+	clkdev("imx-gpt.2", "per", "per1")
+	clkdev("mxc_pwm.0", "pwm", "pwm_ipg_gate")
+	clkdev("imx21-cspi.0", "per", "per2")
+	clkdev("imx21-cspi.0", "ipg", "cspi1_ipg_gate")
+	clkdev("imx21-cspi.1", "per", "per2")
+	clkdev("imx21-cspi.1", "ipg", "cspi2_ipg_gate")
+	clkdev("imx21-cspi.2", "per", "per2")
+	clkdev("imx21-cspi.2", "ipg", "cspi3_ipg_gate")
+	clkdev("imx-fb.0", "per", "per3")
+	clkdev("imx-fb.0", "ipg", "lcdc_ipg_gate")
+	clkdev("imx-fb.0", "ahb", "lcdc_hclk_gate")
+	clkdev("imx21-hcd.0", "per", "usb_gate")
+	clkdev("imx21-hcd.0", "ahb", "usb_hclk_gate")
+	clkdev("mxc_nand.0", NULL, "nfc_gate")
+	clkdev("imx-dma", "ahb", "dma_hclk_gate")
+	clkdev("imx-dma", "ipg", "dma_gate")
+	clkdev("imx2-wdt.0", NULL, "wdog_gate")
+	clkdev("imx-i2c.0", NULL, "i2c_gate")
+	clkdev("mxc-keypad", NULL, "kpp_gate")
+	clkdev("mxc_w1.0", NULL, "owire_gate")
+	clkdev(NULL, "brom", "brom_gate")
+	clkdev(NULL, "emma", "emma_gate")
+	clkdev(NULL, "slcdc", "slcdc_gate")
+	clkdev(NULL, "gpio", "gpio_gate")
+	clkdev(NULL, "rtc", "rtc_gate")
+	clkdev(NULL, "csi", "csi")
+	clkdev(NULL, "ssi1", "ssi1_gate")
+	clkdev(NULL, "ssi2", "ssi2_gate")
+	clkdev(NULL, "sdhc1", "sdhc1")
+	clkdev(NULL, "sdhc2", "sdhc2")
+};
+
+/*
+ * must be called very early to get information about the
+ * available clock rate when the timer framework starts
+ */
+int __init mx21_clocks_init(unsigned long lref, unsigned long href)
+{
+	int i;
+
+	imx_clk_fixed("ckil", lref);
+	imx_clk_fixed("ckih", href);
+	imx_clk_fixed_factor("fpm", "ckil", 512, 1);
+	imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
+	imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks, ARRAY_SIZE(spll_sel_clks));
+	imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
+	imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
+	imx_clk_divider("fclk", "mpll", CCM_CSCR, 29, 3);
+	imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
+	imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
+	imx_clk_divider("per1", "mpll", CCM_PCDR1, 0, 6);
+	imx_clk_divider("per2", "mpll", CCM_PCDR1, 8, 6);
+	imx_clk_divider("per3", "mpll", CCM_PCDR1, 16, 6);
+	imx_clk_divider("per4", "mpll", CCM_PCDR1, 24, 6);
+	imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
+	imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
+	imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
+	imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
+	imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
+	imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
+	imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
+	imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
+	imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
+	imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
+	imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
+	imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
+	imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
+	imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
+	imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
+	imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
+	imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
+	imx_clk_divider("usb_div", "spll", CCM_CSCR, 26, 3);
+	imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
+	imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
+	imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
+	imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
+	imx_clk_divider("nfc_div", "ipg", CCM_PCDR0, 12, 4);
+	imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
+	imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
+	imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
+	imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
+	imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
+	imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
+	imx_clk_gate("slcdc_gate", "ipg", CCM_PCCR0, 25);
+	imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
+	imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
+	imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
+	imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
+	imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
+	imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
+	imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		struct clkl *l = &lookups[i];
+		l->lookup.clk = __clk_lookup(l->clkname);
+		clkdev_add(&l->lookup);
+	}
+
+	mxc_timer_init(NULL, MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR),
+			MX21_INT_GPT1);
+	return 0;
+}
-- 
1.7.9.1

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

* [PATCH 7/8] ARM i.MX25: implement clocks using common clock framework
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
                   ` (5 preceding siblings ...)
  2012-03-19 13:36 ` [PATCH 6/8] ARM i.MX21: " Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 13:36 ` [PATCH 8/8] ARM i.MX27: " Sascha Hauer
  2012-03-19 14:44 ` i.MX: Convert v4/v5 based SoCs to " Rob Herring
  8 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 8b4b4e3..4623865 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -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
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0a0bd05..d96e2ce 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
new file mode 100644
index 0000000..d617b14
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/mx25.h>
+#include "clk.h"
+
+#define CRM_BASE	MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
+
+#define CCM_MPCTL	0x00
+#define CCM_UPCTL	0x04
+#define CCM_CCTL	0x08
+#define CCM_CGCR0	0x0C
+#define CCM_CGCR1	0x10
+#define CCM_CGCR2	0x14
+#define CCM_PCDR0	0x18
+#define CCM_PCDR1	0x1C
+#define CCM_PCDR2	0x20
+#define CCM_PCDR3	0x24
+#define CCM_RCSR	0x28
+#define CCM_CRDR	0x2C
+#define CCM_DCVR0	0x30
+#define CCM_DCVR1	0x34
+#define CCM_DCVR2	0x38
+#define CCM_DCVR3	0x3c
+#define CCM_LTR0	0x40
+#define CCM_LTR1	0x44
+#define CCM_LTR2	0x48
+#define CCM_LTR3	0x4c
+#define CCM_MCR		0x64
+
+#define ccm(x)	(CRM_BASE + (x))
+
+struct clkl {
+	struct clk_lookup lookup;
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+
+static struct clkl lookups[] = {
+	/* i.mx25 has the i.mx21 type uart */
+	clkdev("imx21-uart.0", "ipg", "uart1_ipg")
+	clkdev("imx21-uart.0", "per", "uart_ipg_per")
+	clkdev("imx21-uart.1", "ipg", "uart2_ipg")
+	clkdev("imx21-uart.1", "per", "uart_ipg_per")
+	clkdev("imx21-uart.2", "ipg", "uart3_ipg")
+	clkdev("imx21-uart.2", "per", "uart_ipg_per")
+	clkdev("imx21-uart.3", "ipg", "uart4_ipg")
+	clkdev("imx21-uart.3", "per", "uart_ipg_per")
+	clkdev("imx21-uart.4", "ipg", "uart5_ipg")
+	clkdev("imx21-uart.4", "per", "uart_ipg_per")
+	clkdev("imx-gpt.0", "ipg", "ipg")
+	clkdev("imx-gpt.0", "per", "gpt_ipg_per")
+	clkdev("mxc-ehci.0", NULL, "ipg")
+	clkdev("mxc-ehci.0", "ahb", "usbotg_ahb")
+	clkdev("mxc-ehci.0", "per", "usbdiv")
+	clkdev("mxc-ehci.1", NULL, "ipg")
+	clkdev("mxc-ehci.1", "ahb", "usbotg_ahb")
+	clkdev("mxc-ehci.1", "per", "usbdiv")
+	clkdev("mxc-ehci.2", NULL, "ipg")
+	clkdev("mxc-ehci.2", "ahb", "usbotg_ahb")
+	clkdev("mxc-ehci.2", "per", "usbdiv")
+	clkdev("fsl-usb2-udc", "ahb", "usbotg_ahb")
+	clkdev("fsl-usb2-udc", "per", "usbdiv")
+	clkdev("mxc_nand.0", NULL, "nfc_ipg_per")
+	/* i.mx25 has the i.mx35 type cspi */
+	clkdev("imx35-cspi.0", NULL, "cspi1_ipg")
+	clkdev("imx35-cspi.1", NULL, "cspi2_ipg")
+	clkdev("imx35-cspi.2", NULL, "cspi3_ipg")
+	clkdev("mxc_pwm.0", "ipg", "pwm1_ipg")
+	clkdev("mxc_pwm.0", "per", "per10")
+	clkdev("mxc_pwm.1", "ipg", "pwm1_ipg")
+	clkdev("mxc_pwm.1", "per", "per10")
+	clkdev("mxc_pwm.2", "ipg", "pwm1_ipg")
+	clkdev("mxc_pwm.2", "per", "per10")
+	clkdev("mxc_pwm.3", "ipg", "pwm1_ipg")
+	clkdev("mxc_pwm.3", "per", "per10")
+	clkdev("imx-keypad", NULL, "kpp_ipg")
+	clkdev("mx25-adc", NULL, "tsc_ipg")
+	clkdev("imx-i2c.0", NULL, "i2c_ipg_per")
+	clkdev("imx-i2c.1", NULL, "i2c_ipg_per")
+	clkdev("imx-i2c.2", NULL, "i2c_ipg_per")
+	clkdev("imx25-fec.0", "ipg", "fec_ipg")
+	clkdev("imx25-fec.0", "ahb", "fec_ahb")
+	clkdev("imxdi_rtc.0", NULL, "dryice_ipg")
+	clkdev("imx-fb.0", "per", "lcdc_ipg_per")
+	clkdev("imx-fb.0", "ipg", "lcdc_ipg")
+	clkdev("imx-fb.0", "ahb", "lcdc_ahb")
+	clkdev("imx2-wdt.0", NULL, "wdt_ipg")
+	clkdev("imx-ssi.0", "per", "ssi1_ipg_per")
+	clkdev("imx-ssi.0", "ipg", "ssi1_ipg")
+	clkdev("imx-ssi.1", "per", "ssi2_ipg_per")
+	clkdev("imx-ssi.1", "ipg", "ssi2_ipg")
+	clkdev("sdhci-esdhc-imx25.0", "per", "esdhc1_ipg_per")
+	clkdev("sdhci-esdhc-imx25.0", "ipg", "esdhc1_ipg")
+	clkdev("sdhci-esdhc-imx25.0", "ahb", "esdhc1_ahb")
+	clkdev("sdhci-esdhc-imx25.1", "per", "esdhc2_ipg_per")
+	clkdev("sdhci-esdhc-imx25.1", "ipg", "esdhc2_ipg")
+	clkdev("sdhci-esdhc-imx25.1", "ahb", "esdhc2_ahb")
+	clkdev("mx2-camera.0", "per", "csi_ipg_per")
+	clkdev("mx2-camera.0", "ipg", "csi_ipg")
+	clkdev("mx2-camera.0", "ahb", "csi_ahb")
+	clkdev(NULL, "audmux", "dummy")
+	clkdev("flexcan.0", NULL, "can1_ipg")
+	clkdev("flexcan.1", NULL, "can2_ipg")
+	/* i.mx25 has the i.mx35 type sdma */
+	clkdev("imx35-sdma", "ipg", "sdma_ipg")
+	clkdev("imx35-sdma", "ahb", "sdma_ahb")
+	clkdev(NULL, "iim", "iim_ipg")
+};
+
+static char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", };
+static char *per_sel_clks[] = { "ahb", "upll", };
+
+int __init mx25_clocks_init(void)
+{
+	int i;
+
+	imx_clk_fixed("dummy", 0);
+	imx_clk_fixed("osc", 24000000);
+	imx_clk_pllv1("mpll", "osc", ccm(CCM_MPCTL));
+	imx_clk_pllv1("upll", "osc", ccm(CCM_UPCTL));
+	imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
+	imx_clk_mux("cpu_sel", ccm(CCM_CCTL), 14, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
+	imx_clk_divider("cpu", "cpu_sel", ccm(CCM_CCTL), 30, 2);
+	imx_clk_divider("ahb", "cpu", ccm(CCM_CCTL), 28, 2);
+	imx_clk_fixed_factor("ipg", "ahb", 1, 2);
+	imx_clk_mux("per0_sel", ccm(CCM_MCR), 0, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per1_sel", ccm(CCM_MCR), 1, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per2_sel", ccm(CCM_MCR), 2, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per3_sel", ccm(CCM_MCR), 3, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per4_sel", ccm(CCM_MCR), 4, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per5_sel", ccm(CCM_MCR), 5, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per6_sel", ccm(CCM_MCR), 6, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per7_sel", ccm(CCM_MCR), 7, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per8_sel", ccm(CCM_MCR), 8, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per9_sel", ccm(CCM_MCR), 9, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per10_sel", ccm(CCM_MCR), 10, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per11_sel", ccm(CCM_MCR), 11, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per12_sel", ccm(CCM_MCR), 12, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per13_sel", ccm(CCM_MCR), 13, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per14_sel", ccm(CCM_MCR), 14, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_mux("per15_sel", ccm(CCM_MCR), 15, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	imx_clk_divider("per0", "per0_sel", ccm(CCM_PCDR0), 0, 6);
+	imx_clk_divider("per1", "per1_sel", ccm(CCM_PCDR0), 8, 6);
+	imx_clk_divider("per2", "per2_sel", ccm(CCM_PCDR0), 16, 6);
+	imx_clk_divider("per3", "per3_sel", ccm(CCM_PCDR0), 24, 6);
+	imx_clk_divider("per4", "per4_sel", ccm(CCM_PCDR1), 0, 6);
+	imx_clk_divider("per5", "per5_sel", ccm(CCM_PCDR1), 8, 6);
+	imx_clk_divider("per6", "per6_sel", ccm(CCM_PCDR1), 16, 6);
+	imx_clk_divider("per7", "per7_sel", ccm(CCM_PCDR1), 24, 6);
+	imx_clk_divider("per8", "per8_sel", ccm(CCM_PCDR2), 0, 6);
+	imx_clk_divider("per9", "per9_sel", ccm(CCM_PCDR2), 8, 6);
+	imx_clk_divider("per10", "per10_sel", ccm(CCM_PCDR2), 16, 6);
+	imx_clk_divider("per11", "per11_sel", ccm(CCM_PCDR2), 24, 6);
+	imx_clk_divider("per12", "per12_sel", ccm(CCM_PCDR3), 0, 6);
+	imx_clk_divider("per13", "per13_sel", ccm(CCM_PCDR3), 8, 6);
+	imx_clk_divider("per14", "per14_sel", ccm(CCM_PCDR3), 16, 6);
+	imx_clk_divider("per15", "per15_sel", ccm(CCM_PCDR3), 24, 6);
+	imx_clk_gate("csi_ipg_per", "per0", ccm(CCM_CGCR0), 0);
+	imx_clk_gate("esdhc1_ipg_per", "per3", ccm(CCM_CGCR0),  3);
+	imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);
+	imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);
+	imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6);
+	imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0),  7);
+	imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0),  8);
+	imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
+	imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
+	imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
+	imx_clk_gate("csi_ahb", "ahb", ccm(CCM_CGCR0), 18);
+	imx_clk_gate("esdhc1_ahb", "ahb", ccm(CCM_CGCR0), 21);
+	imx_clk_gate("esdhc2_ahb", "ahb", ccm(CCM_CGCR0), 22);
+	imx_clk_gate("fec_ahb", "ahb", ccm(CCM_CGCR0), 23);
+	imx_clk_gate("lcdc_ahb", "ahb", ccm(CCM_CGCR0), 24);
+	imx_clk_gate("sdma_ahb", "ahb", ccm(CCM_CGCR0), 26);
+	imx_clk_gate("usbotg_ahb", "ahb", ccm(CCM_CGCR0), 28);
+	imx_clk_gate("can1_ipg", "ipg", ccm(CCM_CGCR1),  2);
+	imx_clk_gate("can2_ipg", "ipg", ccm(CCM_CGCR1),  3);
+	imx_clk_gate("csi_ipg", "ipg", ccm(CCM_CGCR1),  4);
+	imx_clk_gate("cspi1_ipg", "ipg", ccm(CCM_CGCR1),  5);
+	imx_clk_gate("cspi2_ipg", "ipg", ccm(CCM_CGCR1),  6);
+	imx_clk_gate("cspi3_ipg", "ipg", ccm(CCM_CGCR1),  7);
+	imx_clk_gate("dryice_ipg", "ipg", ccm(CCM_CGCR1),  8);
+	imx_clk_gate("esdhc1_ipg", "ipg", ccm(CCM_CGCR1), 13);
+	imx_clk_gate("esdhc2_ipg", "ipg", ccm(CCM_CGCR1), 14);
+	imx_clk_gate("fec_ipg", "ipg", ccm(CCM_CGCR1), 15);
+	imx_clk_gate("iim_ipg", "ipg", ccm(CCM_CGCR1), 26);
+	imx_clk_gate("kpp_ipg", "ipg", ccm(CCM_CGCR1), 28);
+	imx_clk_gate("lcdc_ipg", "ipg", ccm(CCM_CGCR1), 29);
+	imx_clk_gate("pwm1_ipg", "ipg", ccm(CCM_CGCR1), 31);
+	imx_clk_gate("pwm2_ipg", "ipg", ccm(CCM_CGCR2),  0);
+	imx_clk_gate("pwm3_ipg", "ipg", ccm(CCM_CGCR2),  1);
+	imx_clk_gate("pwm4_ipg", "ipg", ccm(CCM_CGCR2),  2);
+	imx_clk_gate("sdma_ipg", "ipg", ccm(CCM_CGCR2),  6);
+	imx_clk_gate("ssi1_ipg", "ipg", ccm(CCM_CGCR2), 11);
+	imx_clk_gate("ssi2_ipg", "ipg", ccm(CCM_CGCR2), 12);
+	imx_clk_gate("tsc_ipg", "ipg", ccm(CCM_CGCR2), 13);
+	imx_clk_gate("uart1_ipg", "ipg", ccm(CCM_CGCR2), 14);
+	imx_clk_gate("uart2_ipg", "ipg", ccm(CCM_CGCR2), 15);
+	imx_clk_gate("uart3_ipg", "ipg", ccm(CCM_CGCR2), 16);
+	imx_clk_gate("uart4_ipg", "ipg", ccm(CCM_CGCR2), 17);
+	imx_clk_gate("uart5_ipg", "ipg", ccm(CCM_CGCR2), 18);
+	imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19);
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		struct clkl *l = &lookups[i];
+		l->lookup.clk = __clk_lookup(l->clkname);
+		clkdev_add(&l->lookup);
+	}
+
+	mxc_timer_init(NULL, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
+	return 0;
+}
-- 
1.7.9.1

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

* [PATCH 8/8] ARM i.MX27: implement clocks using common clock framework
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
                   ` (6 preceding siblings ...)
  2012-03-19 13:36 ` [PATCH 7/8] ARM i.MX25: " Sascha Hauer
@ 2012-03-19 13:36 ` Sascha Hauer
  2012-03-19 14:23   ` Shawn Guo
  2012-03-19 14:44 ` i.MX: Convert v4/v5 based SoCs to " Rob Herring
  8 siblings, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 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

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4623865..bbef3d0 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -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
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index d96e2ce..b39f2d6 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
new file mode 100644
index 0000000..e44e70e
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, 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;
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+
+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);
+	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);
+		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;
+}
-- 
1.7.9.1

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

* [PATCH 8/8] ARM i.MX27: implement clocks using common clock framework
  2012-03-19 13:36 ` [PATCH 8/8] ARM i.MX27: " Sascha Hauer
@ 2012-03-19 14:23   ` Shawn Guo
  2012-03-19 14:36     ` Sascha Hauer
  0 siblings, 1 reply; 18+ messages in thread
From: Shawn Guo @ 2012-03-19 14:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 19, 2012 at 02:36:06PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  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
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 4623865..bbef3d0 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -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
> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> index d96e2ce..b39f2d6 100644
> --- a/arch/arm/mach-imx/Makefile
> +++ b/arch/arm/mach-imx/Makefile
> @@ -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
> diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
> new file mode 100644
> index 0000000..e44e70e
> --- /dev/null
> +++ b/arch/arm/mach-imx/clk-imx27.c
> @@ -0,0 +1,277 @@
> +/*
> + * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, 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;
> +	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?

diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index d9a4fd0..2cde34e 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -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, ...);

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

> +		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;
> +}
> -- 
> 1.7.9.1
> 

-- 
Regards,
Shawn

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

* [PATCH 8/8] ARM i.MX27: implement clocks using common clock framework
  2012-03-19 14:23   ` Shawn Guo
@ 2012-03-19 14:36     ` Sascha Hauer
  2012-03-19 16:17       ` Arnd Bergmann
  0 siblings, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2012-03-19 14:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 19, 2012 at 10:23:29PM +0800, Shawn Guo wrote:
> > +
> > +struct clkl {
> > +	struct clk_lookup lookup;
> > +	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.

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

> 
> 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?
> 
> diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
> index d9a4fd0..2cde34e 100644
> --- a/include/linux/clkdev.h
> +++ b/include/linux/clkdev.h
> @@ -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, \
> +       }
> +

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

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

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

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

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

* i.MX: Convert v4/v5 based SoCs to common clock framework
  2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
                   ` (7 preceding siblings ...)
  2012-03-19 13:36 ` [PATCH 8/8] ARM i.MX27: " Sascha Hauer
@ 2012-03-19 14:44 ` Rob Herring
  2012-03-20 23:27   ` Turquette, Mike
  8 siblings, 1 reply; 18+ messages in thread
From: Rob Herring @ 2012-03-19 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/19/2012 08:35 AM, Sascha Hauer wrote:
> 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
> 

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

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

* [PATCH 8/8] ARM i.MX27: implement clocks using common clock framework
  2012-03-19 14:36     ` Sascha Hauer
@ 2012-03-19 16:17       ` Arnd Bergmann
  0 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2012-03-19 16:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 19 March 2012, Sascha Hauer wrote:
> > > +struct clkl {
> > > +   struct clk_lookup lookup;
> > > +   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.
> 
> 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

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

* i.MX: Convert v4/v5 based SoCs to common clock framework
  2012-03-19 14:44 ` i.MX: Convert v4/v5 based SoCs to " Rob Herring
@ 2012-03-20 23:27   ` Turquette, Mike
  0 siblings, 0 replies; 18+ messages in thread
From: Turquette, Mike @ 2012-03-20 23:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 19, 2012 at 7:44 AM, Rob Herring <robherring2@gmail.com> wrote:
> 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

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

* [PATCH 1/8] clk: add a fixed factor clock
  2012-03-19 13:35 ` [PATCH 1/8] clk: add a fixed factor clock Sascha Hauer
@ 2012-03-23  7:37   ` Philipp Zabel
  2012-03-23  8:40     ` Sascha Hauer
  2012-03-23  7:41   ` Philipp Zabel
  1 sibling, 1 reply; 18+ messages in thread
From: Philipp Zabel @ 2012-03-23  7:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha,

Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:
> Having fixed factors/dividers in hardware is a common pattern, so
> add a clock doing this. Currently no rate propagation is supported.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

Tested-by: Philipp Zabel <philipp.zabel@gmail.com>

Only a few clk-gateisms remain in clk_register_fixed_factor:

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index 7c5e1fc..d99b842 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -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

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

* [PATCH 1/8] clk: add a fixed factor clock
  2012-03-19 13:35 ` [PATCH 1/8] clk: add a fixed factor clock Sascha Hauer
  2012-03-23  7:37   ` Philipp Zabel
@ 2012-03-23  7:41   ` Philipp Zabel
  2012-03-23  8:42     ` Sascha Hauer
  1 sibling, 1 reply; 18+ messages in thread
From: Philipp Zabel @ 2012-03-23  7:41 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:
> 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(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index d99b842..8ca427a 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -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)
 
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 5e4312b..9501eab 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -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
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 21ca2f8..b58f846 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -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);
-- 
1.7.9.1

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

* [PATCH 1/8] clk: add a fixed factor clock
  2012-03-23  7:37   ` Philipp Zabel
@ 2012-03-23  8:40     ` Sascha Hauer
  0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-23  8:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Philipp,

On Fri, Mar 23, 2012 at 08:37:52AM +0100, Philipp Zabel wrote:
> Hi Sascha,
> 
> Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:
> > 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.

> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> 
> Tested-by: Philipp Zabel <philipp.zabel@gmail.com>
> 
> Only a few clk-gateisms remain in clk_register_fixed_factor:

Thanks, I'll integrate this.

Sascha

> diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
> index 7c5e1fc..d99b842 100644
> --- a/drivers/clk/clk-fixed-factor.c
> +++ b/drivers/clk/clk-fixed-factor.c
> @@ -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
> 
> 

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

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

* [PATCH 1/8] clk: add a fixed factor clock
  2012-03-23  7:41   ` Philipp Zabel
@ 2012-03-23  8:42     ` Sascha Hauer
  0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2012-03-23  8:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 23, 2012 at 08:41:29AM +0100, Philipp Zabel wrote:
> Am Montag, den 19.03.2012, 14:35 +0100 schrieb Sascha Hauer:
> > 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...

> 
> ---
>  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(-)
> 
> diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
> index d99b842..8ca427a 100644
> --- a/drivers/clk/clk-fixed-factor.c
> +++ b/drivers/clk/clk-fixed-factor.c
> @@ -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)
>  
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> index 5e4312b..9501eab 100644
> --- a/include/linux/clk-private.h
> +++ b/include/linux/clk-private.h
> @@ -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
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 21ca2f8..b58f846 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -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);
> -- 
> 1.7.9.1
> 
> 
> 

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

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

end of thread, other threads:[~2012-03-23  8:42 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-19 13:35 i.MX: Convert v4/v5 based SoCs to common clock framework Sascha Hauer
2012-03-19 13:35 ` [PATCH 1/8] clk: add a fixed factor clock Sascha Hauer
2012-03-23  7:37   ` Philipp Zabel
2012-03-23  8:40     ` Sascha Hauer
2012-03-23  7:41   ` Philipp Zabel
2012-03-23  8:42     ` Sascha Hauer
2012-03-19 13:36 ` [PATCH 2/8] ARM i.MX: prepare for common clock framework Sascha Hauer
2012-03-19 13:36 ` [PATCH 3/8] ARM i.MX timer: request correct clock Sascha Hauer
2012-03-19 13:36 ` [PATCH 4/8] ARM i.MX: Add common clock support for pllv1 Sascha Hauer
2012-03-19 13:36 ` [PATCH 5/8] ARM i.MX1: implement clocks using common clock framework Sascha Hauer
2012-03-19 13:36 ` [PATCH 6/8] ARM i.MX21: " Sascha Hauer
2012-03-19 13:36 ` [PATCH 7/8] ARM i.MX25: " Sascha Hauer
2012-03-19 13:36 ` [PATCH 8/8] ARM i.MX27: " Sascha Hauer
2012-03-19 14:23   ` Shawn Guo
2012-03-19 14:36     ` Sascha Hauer
2012-03-19 16:17       ` Arnd Bergmann
2012-03-19 14:44 ` i.MX: Convert v4/v5 based SoCs to " Rob Herring
2012-03-20 23:27   ` Turquette, Mike

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.