devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] clk: mmp: clock device tree support
@ 2014-06-10  1:27 Chao Xie
  2014-06-10  1:27 ` [PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac Chao Xie
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

The patch set focuses at support device tree for clock.

The first part of the patches
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
It enhances the clk-frac.

The second part of the patches
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add clock type composite for mix
It add three new types of clocks.

The third part of the patches
  clk: mmp: add clock type master
  clk: mmp: add spin lock automatic detection from device tree
  clk: mmp: add device tree support for composite type clock
  clk: mmp: add device tree support for clocks.
It add the device tree support. The whole clock tree is not
defined in .c file, but be parsed from the device tree file.

The final part of the patches
  arm: mmp: support clock device tree for mmp platforms
Change the mmp platform to use device tree to parse the clocks.

Chao Xie (12):
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add clock type composite for mix
  clk: mmp: add clock type master
  clk: mmp: add spin lock automatic detection from device tree
  clk: mmp: add device tree support for composite type clock
  clk: mmp: add device tree support for clocks.
  arm: mmp: support clock device tree for mmp platforms

 .../devicetree/bindings/clock/mmp/clk-composite    |  58 ++
 .../devicetree/bindings/clock/mmp/clk-div          |  28 +
 .../devicetree/bindings/clock/mmp/clk-factor       |  28 +
 .../devicetree/bindings/clock/mmp/clk-gate         |  41 ++
 .../devicetree/bindings/clock/mmp/clk-master       |  47 ++
 .../devicetree/bindings/clock/mmp/clk-mix          |  38 ++
 .../devicetree/bindings/clock/mmp/clk-mux          |  20 +
 Documentation/devicetree/bindings/clock/mmp/lock   |  44 ++
 arch/arm/boot/dts/mmp2-clock.dtsi                  | 575 +++++++++++++++++
 arch/arm/boot/dts/mmp2.dtsi                        |  11 +
 arch/arm/boot/dts/pxa168-clock.dtsi                | 443 +++++++++++++
 arch/arm/boot/dts/pxa168.dtsi                      |  10 +
 arch/arm/boot/dts/pxa910-clock.dtsi                | 388 ++++++++++++
 arch/arm/boot/dts/pxa910.dtsi                      |  10 +
 arch/arm/mach-mmp/Kconfig                          |   7 +-
 arch/arm/mach-mmp/Makefile                         |   2 +-
 arch/arm/mach-mmp/common.h                         |   1 +
 arch/arm/mach-mmp/mmp-dt.c                         |  57 +-
 arch/arm/mach-mmp/mmp2-dt.c                        |  50 --
 drivers/clk/mmp/Makefile                           |   7 +-
 drivers/clk/mmp/clk-frac.c                         |  74 ++-
 drivers/clk/mmp/clk-gate.c                         | 133 ++++
 drivers/clk/mmp/clk-master-node.c                  | 195 ++++++
 drivers/clk/mmp/clk-mix-composite.c                | 195 ++++++
 drivers/clk/mmp/clk-mix.c                          | 419 +++++++++++++
 drivers/clk/mmp/clk-mmp2.c                         |   6 +-
 drivers/clk/mmp/clk-of-composite.c                 | 253 ++++++++
 drivers/clk/mmp/clk-of.c                           | 689 +++++++++++++++++++++
 drivers/clk/mmp/clk-pxa168.c                       |   6 +-
 drivers/clk/mmp/clk-pxa910.c                       |   6 +-
 drivers/clk/mmp/clk.h                              | 164 ++++-
 drivers/clk/mmp/lock.c                             | 159 +++++
 32 files changed, 4035 insertions(+), 129 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-composite
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-div
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-factor
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-gate
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-master
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mix
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mux
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/lock
 create mode 100644 arch/arm/boot/dts/mmp2-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa168-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa910-clock.dtsi
 delete mode 100644 arch/arm/mach-mmp/mmp2-dt.c
 create mode 100644 drivers/clk/mmp/clk-gate.c
 create mode 100644 drivers/clk/mmp/clk-master-node.c
 create mode 100644 drivers/clk/mmp/clk-mix-composite.c
 create mode 100644 drivers/clk/mmp/clk-mix.c
 create mode 100644 drivers/clk/mmp/clk-of-composite.c
 create mode 100644 drivers/clk/mmp/clk-of.c
 create mode 100644 drivers/clk/mmp/lock.c

-- 
1.8.3.2

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

* [PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 02/12] clk: mmp: add spin lock " Chao Xie
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

The structures defined for clk-frac will be used out side
of clk-frac.c.
To avoid conflicts, add prefix "mmp" for these structures'
name.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/clk-frac.c   | 23 ++++++++++++-----------
 drivers/clk/mmp/clk-mmp2.c   |  4 ++--
 drivers/clk/mmp/clk-pxa168.c |  4 ++--
 drivers/clk/mmp/clk-pxa910.c |  4 ++--
 drivers/clk/mmp/clk.h        |  8 ++++----
 5 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 23a56f5..3fbc9ca 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -22,19 +22,19 @@
  * numerator/denominator = Fin / (Fout * factor)
  */
 
-#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
-struct clk_factor {
+#define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
+struct mmp_clk_factor {
 	struct clk_hw		hw;
 	void __iomem		*base;
-	struct clk_factor_masks	*masks;
-	struct clk_factor_tbl	*ftbl;
+	struct mmp_clk_factor_masks	*masks;
+	struct mmp_clk_factor_tbl	*ftbl;
 	unsigned int		ftbl_cnt;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
 		unsigned long *prate)
 {
-	struct clk_factor *factor = to_clk_factor(hw);
+	struct mmp_clk_factor *factor = to_clk_factor(hw);
 	unsigned long rate = 0, prev_rate;
 	int i;
 
@@ -58,8 +58,8 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
-	struct clk_factor *factor = to_clk_factor(hw);
-	struct clk_factor_masks *masks = factor->masks;
+	struct mmp_clk_factor *factor = to_clk_factor(hw);
+	struct mmp_clk_factor_masks *masks = factor->masks;
 	unsigned int val, num, den;
 
 	val = readl_relaxed(factor->base);
@@ -81,8 +81,8 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 				unsigned long prate)
 {
-	struct clk_factor *factor = to_clk_factor(hw);
-	struct clk_factor_masks *masks = factor->masks;
+	struct mmp_clk_factor *factor = to_clk_factor(hw);
+	struct mmp_clk_factor_masks *masks = factor->masks;
 	int i;
 	unsigned long val;
 	unsigned long prev_rate, rate = 0;
@@ -118,10 +118,11 @@ static struct clk_ops clk_factor_ops = {
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
 		unsigned long flags, void __iomem *base,
-		struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
+		struct mmp_clk_factor_masks *masks,
+		struct mmp_clk_factor_tbl *ftbl,
 		unsigned int ftbl_cnt)
 {
-	struct clk_factor *factor;
+	struct mmp_clk_factor *factor;
 	struct clk_init_data init;
 	struct clk *clk;
 
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index b2721ca..7083f12 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -54,7 +54,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
 	.factor = 2,
 	.num_mask = 0x1fff,
 	.den_mask = 0x1fff,
@@ -62,7 +62,7 @@ static struct clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
 	{.num = 14634, .den = 2165},	/*14.745MHZ */
 	{.num = 3521, .den = 689},	/*19.23MHZ */
 	{.num = 9679, .den = 5728},	/*58.9824MHZ */
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 014396b..75266ac 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -47,7 +47,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
 	.factor = 2,
 	.num_mask = 0x1fff,
 	.den_mask = 0x1fff,
@@ -55,7 +55,7 @@ static struct clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
 	{.num = 8125, .den = 1536},	/*14.745MHZ */
 };
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index 9efc6a4..f817999 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -45,7 +45,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
 	.factor = 2,
 	.num_mask = 0x1fff,
 	.den_mask = 0x1fff,
@@ -53,7 +53,7 @@ static struct clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
 	{.num = 8125, .den = 1536},	/*14.745MHZ */
 };
 
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index ab86dd4..3fe92be 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -7,7 +7,7 @@
 #define APBC_NO_BUS_CTRL	BIT(0)
 #define APBC_POWER_CTRL		BIT(1)
 
-struct clk_factor_masks {
+struct mmp_clk_factor_masks {
 	unsigned int	factor;
 	unsigned int	num_mask;
 	unsigned int	den_mask;
@@ -15,7 +15,7 @@ struct clk_factor_masks {
 	unsigned int	den_shift;
 };
 
-struct clk_factor_tbl {
+struct mmp_clk_factor_tbl {
 	unsigned int num;
 	unsigned int den;
 };
@@ -30,6 +30,6 @@ extern struct clk *mmp_clk_register_apmu(const char *name,
 		spinlock_t *lock);
 extern struct clk *mmp_clk_register_factor(const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *base, struct clk_factor_masks *masks,
-		struct clk_factor_tbl *ftbl, unsigned int ftbl_cnt);
+		void __iomem *base, struct mmp_clk_factor_masks *masks,
+		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt);
 #endif
-- 
1.8.3.2

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

* [PATCH 02/12] clk: mmp: add spin lock for clk-frac
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
  2014-06-10  1:27 ` [PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
       [not found] ` <1402363668-25806-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

The register used by clk-frac may be shared with
other clocks.
So it needs to use spin lock to protect the register
access.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/clk-frac.c   | 11 ++++++++++-
 drivers/clk/mmp/clk-mmp2.c   |  2 +-
 drivers/clk/mmp/clk-pxa168.c |  2 +-
 drivers/clk/mmp/clk-pxa910.c |  2 +-
 drivers/clk/mmp/clk.h        |  3 ++-
 5 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 3fbc9ca..e29d006 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -29,6 +29,7 @@ struct mmp_clk_factor {
 	struct mmp_clk_factor_masks	*masks;
 	struct mmp_clk_factor_tbl	*ftbl;
 	unsigned int		ftbl_cnt;
+	spinlock_t *lock;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
@@ -86,6 +87,7 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 	int i;
 	unsigned long val;
 	unsigned long prev_rate, rate = 0;
+	unsigned long flags = 0;
 
 	for (i = 0; i < factor->ftbl_cnt; i++) {
 		prev_rate = rate;
@@ -97,6 +99,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 	if (i > 0)
 		i--;
 
+	if (factor->lock)
+		spin_lock_irqsave(factor->lock, flags);
+
 	val = readl_relaxed(factor->base);
 
 	val &= ~(masks->num_mask << masks->num_shift);
@@ -107,6 +112,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 
 	writel_relaxed(val, factor->base);
 
+	if (factor->lock)
+		spin_unlock_irqrestore(factor->lock, flags);
+
 	return 0;
 }
 
@@ -120,7 +128,7 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
 		unsigned long flags, void __iomem *base,
 		struct mmp_clk_factor_masks *masks,
 		struct mmp_clk_factor_tbl *ftbl,
-		unsigned int ftbl_cnt)
+		unsigned int ftbl_cnt, spinlock_t *lock)
 {
 	struct mmp_clk_factor *factor;
 	struct clk_init_data init;
@@ -143,6 +151,7 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
 	factor->ftbl = ftbl;
 	factor->ftbl_cnt = ftbl_cnt;
 	factor->hw.init = &init;
+	factor->lock = lock;
 
 	init.name = name;
 	init.ops = &clk_factor_ops;
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 7083f12..5c90a42 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -191,7 +191,7 @@ void __init mmp2_clk_init(void)
 	clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
 				mpmu_base + MPMU_UART_PLL,
 				&uart_factor_masks, uart_factor_tbl,
-				ARRAY_SIZE(uart_factor_tbl));
+				ARRAY_SIZE(uart_factor_tbl), &clk_lock);
 	clk_set_rate(clk, 14745600);
 	clk_register_clkdev(clk, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 75266ac..93e967c 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -158,7 +158,7 @@ void __init pxa168_clk_init(void)
 	uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
 				mpmu_base + MPMU_UART_PLL,
 				&uart_factor_masks, uart_factor_tbl,
-				ARRAY_SIZE(uart_factor_tbl));
+				ARRAY_SIZE(uart_factor_tbl), &clk_lock);
 	clk_set_rate(uart_pll, 14745600);
 	clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index f817999..993abcd 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -163,7 +163,7 @@ void __init pxa910_clk_init(void)
 	uart_pll =  mmp_clk_register_factor("uart_pll", "pll1_4", 0,
 				mpmu_base + MPMU_UART_PLL,
 				&uart_factor_masks, uart_factor_tbl,
-				ARRAY_SIZE(uart_factor_tbl));
+				ARRAY_SIZE(uart_factor_tbl), &clk_lock);
 	clk_set_rate(uart_pll, 14745600);
 	clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 3fe92be..b71b717 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -31,5 +31,6 @@ extern struct clk *mmp_clk_register_apmu(const char *name,
 extern struct clk *mmp_clk_register_factor(const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *base, struct mmp_clk_factor_masks *masks,
-		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt);
+		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+		spinlock_t *lock);
 #endif
-- 
1.8.3.2

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

* [PATCH 03/12] clk: mmp: add init callback for clk-frac
       [not found] ` <1402363668-25806-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
@ 2014-06-10  1:27   ` Chao Xie
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang-Re5JQEeQqe8AvxtiuMwx3w,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	chao.xie-eYqpPyKDWXRBDgjK7y7TUQ, xiechao_mail-9Onoh4P/yGk,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

From: Chao Xie <chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>

For the clk-frac, if it has table, we need to make
sure that the initial clock rate is one item of the
table.
If it is not, we use the first item in the table by default.

Signed-off-by: Chao Xie <chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
---
 drivers/clk/mmp/clk-frac.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index e29d006..1876d2c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -118,10 +118,50 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 	return 0;
 }
 
+void clk_factor_init(struct clk_hw *hw)
+{
+	struct mmp_clk_factor *factor = to_clk_factor(hw);
+	struct mmp_clk_factor_masks *masks = factor->masks;
+	u32 val, num, den;
+	int i;
+	unsigned long flags = 0;
+
+	if (factor->lock)
+		spin_lock_irqsave(factor->lock, flags);
+
+	val = readl(factor->base);
+
+	/* calculate numerator */
+	num = (val >> masks->num_shift) & masks->num_mask;
+
+	/* calculate denominator */
+	den = (val >> masks->den_shift) & masks->den_mask;
+
+	for (i = 0; i < factor->ftbl_cnt; i++)
+		if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+			break;
+
+	if (i >= factor->ftbl_cnt) {
+		val &= ~(masks->num_mask << masks->num_shift);
+		val |= (factor->ftbl[0].num & masks->num_mask) <<
+			masks->num_shift;
+
+		val &= ~(masks->den_mask << masks->den_shift);
+		val |= (factor->ftbl[0].den & masks->den_mask) <<
+			masks->den_shift;
+
+		writel(val, factor->base);
+	}
+
+	if (factor->lock)
+		spin_unlock_irqrestore(factor->lock, flags);
+}
+
 static struct clk_ops clk_factor_ops = {
 	.recalc_rate = clk_factor_recalc_rate,
 	.round_rate = clk_factor_round_rate,
 	.set_rate = clk_factor_set_rate,
+	.init = clk_factor_init,
 };
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 04/12] clk: mmp: move definiton of mmp_clk_frac to clk.h
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (2 preceding siblings ...)
       [not found] ` <1402363668-25806-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 05/12] clk: mmp: add clock type mix Chao Xie
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

Move the definition of structure of mmp_clk_frac to
clk.h.
So device tree support can use this structure.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/clk-frac.c |  8 --------
 drivers/clk/mmp/clk.h      | 32 ++++++++++++++++++++++----------
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 1876d2c..eeba52c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -23,14 +23,6 @@
  */
 
 #define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
-struct mmp_clk_factor {
-	struct clk_hw		hw;
-	void __iomem		*base;
-	struct mmp_clk_factor_masks	*masks;
-	struct mmp_clk_factor_tbl	*ftbl;
-	unsigned int		ftbl_cnt;
-	spinlock_t *lock;
-};
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
 		unsigned long *prate)
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index b71b717..d267639 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -7,12 +7,14 @@
 #define APBC_NO_BUS_CTRL	BIT(0)
 #define APBC_POWER_CTRL		BIT(1)
 
+
+/* Clock type "factor" */
 struct mmp_clk_factor_masks {
-	unsigned int	factor;
-	unsigned int	num_mask;
-	unsigned int	den_mask;
-	unsigned int	num_shift;
-	unsigned int	den_shift;
+	unsigned int factor;
+	unsigned int num_mask;
+	unsigned int den_mask;
+	unsigned int num_shift;
+	unsigned int den_shift;
 };
 
 struct mmp_clk_factor_tbl {
@@ -20,6 +22,21 @@ struct mmp_clk_factor_tbl {
 	unsigned int den;
 };
 
+struct mmp_clk_factor {
+	struct clk_hw hw;
+	void __iomem *base;
+	struct mmp_clk_factor_masks *masks;
+	struct mmp_clk_factor_tbl *ftbl;
+	unsigned int ftbl_cnt;
+	spinlock_t *lock;
+};
+
+extern struct clk *mmp_clk_register_factor(const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *base, struct mmp_clk_factor_masks *masks,
+		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+		spinlock_t *lock);
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
@@ -28,9 +45,4 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
 extern struct clk *mmp_clk_register_apmu(const char *name,
 		const char *parent_name, void __iomem *base, u32 enable_mask,
 		spinlock_t *lock);
-extern struct clk *mmp_clk_register_factor(const char *name,
-		const char *parent_name, unsigned long flags,
-		void __iomem *base, struct mmp_clk_factor_masks *masks,
-		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
-		spinlock_t *lock);
 #endif
-- 
1.8.3.2

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

* [PATCH 05/12] clk: mmp: add clock type mix
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (3 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 04/12] clk: mmp: move definiton of mmp_clk_frac to clk.h Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 06/12] clk: mmp: add mmp private gate clock Chao Xie
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

The clock type mix is a kind of clock combines "div" and "mux".
This kind of clock can not allow to change div first then
mux or change mux first or div.
The reason is
1. Some clock has frequency change bit. Each time want to change
   the frequency, there are some operations based on this bit, and
   these operations are time-cost.
   Seperating div and mux change will make the process longer, and
   waste more time.
2. Seperting the div and mux may generate middle clock that the
   peripharals do not support. It may make the peripharals hang.

There are three kinds of this type of clock in all SOCes.
1. The clock has bit to trigger the frequency change.
2. Same as #1, but the operations for the bit is different
3. Do not have frequency change bit.

So this type of clock has implemented the callbacks
->determine_rate
->set_rate_and_parent
These callbacks can help to change the div and mux together.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/Makefile  |   2 +-
 drivers/clk/mmp/clk-mix.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/mmp/clk.h     |  62 +++++++
 3 files changed, 482 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 392d780..8bfee860 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
new file mode 100644
index 0000000..d2f6406
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix.c
@@ -0,0 +1,419 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+/*
+ * The mix clock is a clock combined mux and div type clock.
+ * Because the div field and mux field need to be set at same
+ * time, we can not divide it into 2 types of clock
+ */
+
+#define to_clk_mix(hw)	container_of(hw, struct mmp_clk_mix, hw)
+
+static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
+{
+	if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+		return val;
+	if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+		return 1 << val;
+	return val + 1;
+}
+
+static unsigned int _get_val(struct mmp_clk_mix *mix, unsigned int div)
+{
+	if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+		return div;
+	if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+		return __ffs(div);
+	return div - 1;
+}
+
+static void _filter_clk_table(struct mmp_clk_mix *mix,
+				struct mmp_clk_mix_clk_table *table,
+				unsigned int table_size)
+{
+	int i;
+	struct mmp_clk_mix_clk_table *item;
+	struct clk *parent, *clk;
+	unsigned long parent_rate;
+
+	clk = mix->hw.clk;
+
+	for (i = 0; i < table_size; i++) {
+		item = &table[i];
+		parent = clk_get_parent_by_index(clk, item->parent_index);
+		parent_rate = __clk_get_rate(parent);
+		if (parent_rate % item->rate) {
+			item->valid = 0;
+		} else {
+			item->divisor = parent_rate / item->rate;
+			item->valid = 1;
+		}
+	}
+}
+
+static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val,
+			unsigned int change_mux, unsigned int change_div)
+{
+	struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
+	u8 width, shift;
+	u32 mux_div, fc_req;
+	int ret, timeout = 50;
+	unsigned long flags = 0;
+
+	if (!change_mux && !change_div)
+		return -EINVAL;
+
+	if (mix->lock)
+		spin_lock_irqsave(mix->lock, flags);
+
+	if (mix->type == MMP_CLK_MIX_TYPE_V1
+		|| mix->type == MMP_CLK_MIX_TYPE_V2)
+		mux_div = readl(ri->reg_clk_ctrl);
+	else
+		mux_div = readl(ri->reg_clk_sel);
+
+	if (change_div) {
+		width = ri->width_div;
+		shift = ri->shift_div;
+		mux_div &= ~MMP_CLK_BITS_MASK(width, shift);
+		mux_div |= MMP_CLK_BITS_SET_VAL(div_val, width, shift);
+	}
+
+	if (change_mux) {
+		width = ri->width_mux;
+		shift = ri->shift_mux;
+		mux_div &= ~MMP_CLK_BITS_MASK(width, shift);
+		mux_div |= MMP_CLK_BITS_SET_VAL(mux_val, width, shift);
+	}
+
+	if (mix->type == MMP_CLK_MIX_TYPE_V1) {
+		writel(mux_div, ri->reg_clk_ctrl);
+	} else if (mix->type == MMP_CLK_MIX_TYPE_V2) {
+		writel(mux_div, ri->reg_clk_ctrl);
+
+		do {
+			fc_req = readl(ri->reg_clk_ctrl);
+			timeout--;
+			if (fc_req & (1 << ri->bit_fc))
+				break;
+		} while (timeout);
+
+		if (timeout == 0) {
+			pr_err("%s:%s cannot do frequency change\n",
+				__func__, __clk_get_name(mix->hw.clk));
+			ret = -EBUSY;
+			goto error;
+		}
+	} else {
+		fc_req = readl(ri->reg_clk_ctrl);
+		fc_req |= 1 << ri->bit_fc;
+		writel(fc_req, ri->reg_clk_ctrl);
+		writel(mux_div, ri->reg_clk_sel);
+		fc_req &= ~(1 << ri->bit_fc);
+	}
+
+	ret = 0;
+error:
+	if (mix->lock)
+		spin_unlock_irqrestore(mix->lock, flags);
+
+	return ret;
+}
+
+static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+	struct mmp_clk_mix_clk_table *item;
+	struct clk *parent, *parent_best, *mix_clk;
+	unsigned long parent_rate, mix_rate, mix_rate_best, parent_rate_best;
+	unsigned long gap, gap_best;
+	u32 div_val_max;
+	unsigned int div;
+	int i, j;
+
+	mix_clk = hw->clk;
+
+	parent = NULL;
+	mix_rate_best = 0;
+	parent_rate_best = 0;
+	gap_best = rate;
+	parent_best = NULL;
+
+	if (mix->table) {
+		for (i = 0; i < mix->table_size; i++) {
+			item = &mix->table[i];
+			if (item->valid == 0)
+				continue;
+			parent = clk_get_parent_by_index(mix_clk,
+							item->parent_index);
+			parent_rate = __clk_get_rate(parent);
+			mix_rate = parent_rate / item->divisor;
+			gap = abs(mix_rate - rate);
+			if (parent_best == NULL || gap < gap_best) {
+				parent_best = parent;
+				parent_rate_best = parent_rate;
+				mix_rate_best = mix_rate;
+				gap_best = gap;
+				if (gap_best == 0)
+					goto found;
+			}
+		}
+	} else {
+		for (i = 0; i < __clk_get_num_parents(mix_clk); i++) {
+			parent = clk_get_parent_by_index(mix_clk, i);
+			parent_rate = __clk_get_rate(parent);
+			div_val_max = (1 << mix->reg_info.width_div) - 1;
+			for (j = 0; j < div_val_max; j++) {
+				div = _get_div(mix, j);
+				mix_rate = parent_rate / div;
+				gap = abs(mix_rate - rate);
+				if (parent_best == NULL || gap < gap_best) {
+					parent_best = parent;
+					parent_rate_best = parent_rate;
+					mix_rate_best = mix_rate;
+					gap_best = gap;
+					if (gap_best == 0)
+						goto found;
+				}
+			}
+		}
+	}
+
+found:
+	*best_parent_rate = parent_rate_best;
+	*best_parent_clk = parent_best;
+
+	return mix_rate_best;
+}
+
+static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
+						unsigned long rate,
+						unsigned long parent_rate,
+						u8 index)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+	unsigned int div;
+	u32 div_val, mux_val;
+
+	div = parent_rate / rate;
+	div_val = _get_val(mix, div);
+	mux_val = index;
+
+	return _set_rate(mix, mux_val, div_val, 1, 1);
+}
+
+static u8 mmp_clk_mix_get_parent(struct clk_hw *hw)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+	struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
+	unsigned long flags = 0;
+	u32 mux_div = 0;
+	u8 width, shift;
+
+	if (mix->lock)
+		spin_lock_irqsave(mix->lock, flags);
+
+	if (mix->type == MMP_CLK_MIX_TYPE_V1
+		|| mix->type == MMP_CLK_MIX_TYPE_V2)
+		mux_div = readl(ri->reg_clk_ctrl);
+	else
+		mux_div = readl(ri->reg_clk_sel);
+
+	if (mix->lock)
+		spin_unlock_irqrestore(mix->lock, flags);
+
+	width = mix->reg_info.width_mux;
+	shift = mix->reg_info.shift_mux;
+
+	return MMP_CLK_BITS_GET_VAL(mux_div, width, shift);
+}
+
+static unsigned long mmp_clk_mix_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+	struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
+	unsigned long flags = 0;
+	u32 mux_div = 0;
+	u8 width, shift;
+	unsigned int div;
+
+	if (mix->lock)
+		spin_lock_irqsave(mix->lock, flags);
+
+	if (mix->type == MMP_CLK_MIX_TYPE_V1
+		|| mix->type == MMP_CLK_MIX_TYPE_V2)
+		mux_div = readl(ri->reg_clk_ctrl);
+	else
+		mux_div = readl(ri->reg_clk_sel);
+
+	if (mix->lock)
+		spin_unlock_irqrestore(mix->lock, flags);
+
+	width = mix->reg_info.width_div;
+	shift = mix->reg_info.shift_div;
+
+	div = _get_div(mix, MMP_CLK_BITS_GET_VAL(mux_div, width, shift));
+
+	return parent_rate / div;
+}
+
+static int mmp_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+	struct mmp_clk_mix_clk_table *item;
+	int i;
+
+	if (mix->table) {
+		for (i = 0; i < mix->table_size; i++) {
+			item = &mix->table[i];
+			if (item->valid == 0)
+				continue;
+			if (item->parent_index == index)
+				break;
+		}
+		if (i < mix->table_size)
+			return _set_rate(mix, index,
+					_get_val(mix, item->divisor), 1, 1);
+		else
+			return -EINVAL;
+	} else
+		return _set_rate(mix, index, 0, 1, 0);
+}
+
+static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long best_parent_rate)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+	struct mmp_clk_mix_clk_table *item;
+	unsigned long parent_rate;
+	unsigned int best_divisor;
+	struct clk *mix_clk, *parent;
+	int i;
+
+	best_divisor = best_parent_rate / rate;
+
+	mix_clk = hw->clk;
+	if (mix->table) {
+		for (i = 0; i < mix->table_size; i++) {
+			item = &mix->table[i];
+			if (item->valid == 0)
+				continue;
+			parent = clk_get_parent_by_index(mix_clk,
+							item->parent_index);
+			parent_rate = __clk_get_rate(parent);
+			if (parent_rate == best_parent_rate
+				&& item->divisor == best_divisor)
+				break;
+		}
+		if (i < mix->table_size)
+			return _set_rate(mix, item->parent_index,
+					item->divisor, 1, 1);
+		else
+			return -EINVAL;
+	} else {
+		for (i = 0; i < __clk_get_num_parents(mix_clk); i++) {
+			parent = clk_get_parent_by_index(mix_clk, i);
+			parent_rate = __clk_get_rate(parent);
+			if (parent_rate == best_parent_rate)
+				break;
+		}
+		if (i < mix->table_size)
+			return _set_rate(mix, i, best_divisor, 1, 1);
+		else
+			return -EINVAL;
+	}
+}
+
+static void mmp_clk_mix_init(struct clk_hw *hw)
+{
+	struct mmp_clk_mix *mix = to_clk_mix(hw);
+
+	if (mix->table)
+		_filter_clk_table(mix, mix->table, mix->table_size);
+}
+
+const struct clk_ops mmp_clk_mix_ops = {
+	.determine_rate = mmp_clk_mix_determine_rate,
+	.set_rate_and_parent = mmp_clk_mix_set_rate_and_parent,
+	.set_rate = mmp_clk_set_rate,
+	.set_parent = mmp_clk_set_parent,
+	.get_parent = mmp_clk_mix_get_parent,
+	.recalc_rate = mmp_clk_mix_recalc_rate,
+	.init = mmp_clk_mix_init,
+};
+
+struct clk *mmp_clk_register_mix(struct device *dev,
+					const char *name,
+					u8 num_parents,
+					const char **parent_names,
+					unsigned long flags,
+					struct mmp_clk_mix_config *config,
+					spinlock_t *lock)
+{
+	struct mmp_clk_mix *mix;
+	struct clk *clk;
+	struct clk_init_data init;
+	size_t table_bytes;
+
+	if (config->table)
+		table_bytes = sizeof(config->table) * config->table_size;
+	else
+		table_bytes = 0;
+
+	mix = kzalloc(sizeof(*mix) + table_bytes, GFP_KERNEL);
+	if (!mix) {
+		pr_err("%s:%s: could not allocate mmp mix clk\n",
+			__func__, name);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.flags = flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.ops = &mmp_clk_mix_ops;
+
+	memcpy(&mix->reg_info, &config->reg_info, sizeof(config->reg_info));
+	if (config->table) {
+		mix->table = (struct mmp_clk_mix_clk_table *)(mix + 1);
+		memcpy(mix->table, config->table, table_bytes);
+		mix->table_size = config->table_size;
+	}
+	mix->div_flags = config->div_flags;
+	mix->mux_flags = config->mux_flags;
+	mix->lock = lock;
+	mix->hw.init = &init;
+
+	if (config->reg_info.bit_fc >= 32)
+		mix->type = MMP_CLK_MIX_TYPE_V1;
+	else if (config->reg_info.reg_clk_sel)
+		mix->type = MMP_CLK_MIX_TYPE_V3;
+	else
+		mix->type = MMP_CLK_MIX_TYPE_V2;
+	clk = clk_register(dev, &mix->hw);
+
+	if (IS_ERR(clk)) {
+		kfree(mix->table);
+		kfree(mix);
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index d267639..426616b 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -37,6 +37,68 @@ extern struct clk *mmp_clk_register_factor(const char *name,
 		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
 		spinlock_t *lock);
 
+/* Clock type "mix" */
+#define MMP_CLK_BITS_MASK(width, shift)			\
+		(((1 << (width)) - 1) << (shift))
+#define MMP_CLK_BITS_GET_VAL(data, width, shift)	\
+		((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift))
+#define MMP_CLK_BITS_SET_VAL(val, width, shift)		\
+		(((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift))
+
+enum {
+	MMP_CLK_MIX_TYPE_V1,
+	MMP_CLK_MIX_TYPE_V2,
+	MMP_CLK_MIX_TYPE_V3,
+};
+
+/* The register layout */
+struct mmp_clk_mix_reg_info {
+	void __iomem *reg_clk_ctrl;
+	void __iomem *reg_clk_sel;
+	u8 width_div;
+	u8 shift_div;
+	u8 width_mux;
+	u8 shift_mux;
+	u8 bit_fc;
+};
+
+/* The suggested clock table from user. */
+struct mmp_clk_mix_clk_table {
+	unsigned long rate;
+	u8 parent_index;
+	unsigned int divisor;
+	unsigned int valid;
+};
+
+struct mmp_clk_mix_config {
+	struct mmp_clk_mix_reg_info reg_info;
+	struct mmp_clk_mix_clk_table *table;
+	unsigned int table_size;
+	u8 div_flags;
+	u8 mux_flags;
+};
+
+struct mmp_clk_mix {
+	struct clk_hw hw;
+	struct mmp_clk_mix_reg_info reg_info;
+	struct mmp_clk_mix_clk_table *table;
+	unsigned int table_size;
+	u8 div_flags;
+	u8 mux_flags;
+	unsigned int type;
+	spinlock_t *lock;
+};
+
+extern const struct clk_ops mmp_clk_mix_ops;
+extern struct clk *mmp_clk_register_mix(struct device *dev,
+					const char *name,
+					u8 num_parents,
+					const char **parent_names,
+					unsigned long flags,
+					struct mmp_clk_mix_config *config,
+					spinlock_t *lock);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
-- 
1.8.3.2

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

* [PATCH 06/12] clk: mmp: add mmp private gate clock
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (4 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 05/12] clk: mmp: add clock type mix Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 07/12] clk: mmp: add clock type composite for mix Chao Xie
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

Some SOCes have this kind of the gate clock
1. There are some bits to control the gate not only one bit.
2. Some clocks has operations of "out of reset" and "enable".
   To enable clock, we need do "out of reset" and "enable".
   To disable clock, we may not need "set to reset". It depends
   on the SOCes' design.
3. It is not always that "1" is to enable while "0" is to disable
   when write register.

So we have to define the "mask", "enable_val", "disable_val" for
this kind of gate clock.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-gate.c | 133 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/mmp/clk.h      |  21 +++++++
 3 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-gate.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 8bfee860..2855f7b 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c
new file mode 100644
index 0000000..adbd9d6
--- /dev/null
+++ b/drivers/clk/mmp/clk-gate.c
@@ -0,0 +1,133 @@
+/*
+ * mmp gate clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include "clk.h"
+
+/*
+ * Some clocks will have mutiple bits to enable the clocks, and
+ * the bits to disable the clock is not same as enabling bits.
+ */
+
+#define to_clk_mmp_gate(hw)	container_of(hw, struct mmp_clk_gate, hw)
+
+static int mmp_clk_gate_enable(struct clk_hw *hw)
+{
+	struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+	struct clk *clk = hw->clk;
+	unsigned long flags = 0;
+	unsigned long rate;
+	u32 tmp;
+
+	if (gate->lock)
+		spin_lock_irqsave(gate->lock, flags);
+
+	tmp = readl(gate->reg);
+	tmp &= ~gate->mask;
+	tmp |= gate->val_enable;
+	writel(tmp, gate->reg);
+
+	if (gate->lock)
+		spin_unlock_irqrestore(gate->lock, flags);
+
+	if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
+		rate = __clk_get_rate(clk);
+		/* Need delay 2 cycles. */
+		udelay(2000000/rate);
+	}
+
+	return 0;
+}
+
+static void mmp_clk_gate_disable(struct clk_hw *hw)
+{
+	struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+	unsigned long flags = 0;
+	u32 tmp;
+
+	if (gate->lock)
+		spin_lock_irqsave(gate->lock, flags);
+
+	tmp = readl(gate->reg);
+	tmp &= ~gate->mask;
+	tmp |= gate->val_disable;
+	writel(tmp, gate->reg);
+
+	if (gate->lock)
+		spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int mmp_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+	unsigned long flags = 0;
+	u32 tmp;
+
+	if (gate->lock)
+		spin_lock_irqsave(gate->lock, flags);
+
+	tmp = readl(gate->reg);
+
+	if (gate->lock)
+		spin_unlock_irqrestore(gate->lock, flags);
+
+	return (tmp & gate->mask) == gate->val_enable;
+}
+
+const struct clk_ops mmp_clk_gate_ops = {
+	.enable = mmp_clk_gate_enable,
+	.disable = mmp_clk_gate_disable,
+	.is_enabled = mmp_clk_gate_is_enabled,
+};
+
+struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,
+		unsigned int gate_flags, spinlock_t *lock)
+{
+	struct mmp_clk_gate *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the gate */
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate) {
+		pr_err("%s:%s could not allocate gate clk\n", __func__, name);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &mmp_clk_gate_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_gate assignments */
+	gate->reg = reg;
+	gate->mask = mask;
+	gate->val_enable = val_enable;
+	gate->val_disable = val_disable;
+	gate->flags = gate_flags;
+	gate->lock = lock;
+	gate->hw.init = &init;
+
+	clk = clk_register(dev, &gate->hw);
+
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 426616b..9096f0a 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -99,6 +99,27 @@ extern struct clk *mmp_clk_register_mix(struct device *dev,
 					spinlock_t *lock);
 
 
+/* Clock type "gate". MMP private gate */
+#define MMP_CLK_GATE_NEED_DELAY		BIT(0)
+
+struct mmp_clk_gate {
+	struct clk_hw hw;
+	void __iomem *reg;
+	u32 mask;
+	u32 val_enable;
+	u32 val_disable;
+	unsigned int flags;
+	spinlock_t *lock;
+};
+
+extern const struct clk_ops mmp_clk_gate_ops;
+extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
+			const char *parent_name, unsigned long flags,
+			void __iomem *reg, u32 mask, u32 val_enable,
+			u32 val_disable, unsigned int gate_flags,
+			spinlock_t *lock);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
-- 
1.8.3.2

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

* [PATCH 07/12] clk: mmp: add clock type composite for mix
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (5 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 06/12] clk: mmp: add mmp private gate clock Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 08/12] clk: mmp: add clock type master Chao Xie
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

The general composite clock supports div/mux/gate.
marvell SOCes have many clocks that need change
div and mux together. So it need the composite
clock that supports mix/gate.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/Makefile            |   3 +-
 drivers/clk/mmp/clk-mix-composite.c | 195 ++++++++++++++++++++++++++++++++++++
 drivers/clk/mmp/clk.h               |  20 ++++
 3 files changed, 217 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix-composite.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2855f7b..2cd7d94 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,8 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o	\
+	 clk-mix-composite.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix-composite.c b/drivers/clk/mmp/clk-mix-composite.c
new file mode 100644
index 0000000..79d5286
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix-composite.c
@@ -0,0 +1,195 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define to_clk_composite(_hw) container_of(_hw, struct mmp_clk_composite, hw)
+
+static u8 mmp_clk_composite_get_parent(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->get_parent(mix_hw);
+}
+
+static int mmp_clk_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->set_parent(mix_hw, index);
+}
+
+static int mmp_clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->set_rate(mix_hw, rate, parent_rate);
+}
+
+static unsigned long mmp_clk_composite_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->recalc_rate(mix_hw, parent_rate);
+}
+
+static long mmp_clk_composite_determine_rate(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_p)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->determine_rate(mix_hw, rate, best_parent_rate,
+					best_parent_p);
+}
+
+static int mmp_clk_composite_set_rate_and_parent(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long parent_rate, u8 index)
+
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->set_rate_and_parent(mix_hw, rate, parent_rate, index);
+}
+
+static int mmp_clk_composite_is_enabled(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->is_enabled(gate_hw);
+}
+
+static int mmp_clk_composite_enable(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->enable(gate_hw);
+}
+
+static void mmp_clk_composite_disable(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	gate_ops->disable(gate_hw);
+}
+
+static void mmp_clk_composite_init(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+	gate_hw->clk = hw->clk;
+
+	if (mix_ops->init)
+		mix_ops->init(mix_hw);
+	if (gate_ops->init)
+		gate_ops->init(gate_hw);
+}
+
+static struct clk_ops mmp_clk_composite_ops = {
+	.enable = mmp_clk_composite_enable,
+	.disable = mmp_clk_composite_disable,
+	.is_enabled = mmp_clk_composite_is_enabled,
+	.determine_rate = mmp_clk_composite_determine_rate,
+	.set_rate_and_parent = mmp_clk_composite_set_rate_and_parent,
+	.set_rate = mmp_clk_composite_set_rate,
+	.recalc_rate = mmp_clk_composite_recalc_rate,
+	.get_parent = mmp_clk_composite_get_parent,
+	.set_parent = mmp_clk_composite_set_parent,
+	.init = mmp_clk_composite_init,
+};
+
+struct clk *mmp_clk_register_composite(struct device *dev, const char *name,
+			const char **parent_names, int num_parents,
+			struct clk_hw *mix_hw, const struct clk_ops *mix_ops,
+			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+			unsigned long flags)
+{
+	struct clk *clk;
+	struct clk_init_data init;
+	struct mmp_clk_composite *composite;
+
+	if (!mix_hw || !gate_hw)
+		return ERR_PTR(-EINVAL);
+
+	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
+	if (!composite) {
+		pr_err("%s: could not allocate mmp composite clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.flags = flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.ops = &mmp_clk_composite_ops;
+
+	composite->mix_hw = mix_hw;
+	composite->mix_ops = mix_ops;
+	composite->gate_hw = gate_hw;
+	composite->gate_ops = gate_ops;
+	composite->hw.init = &init;
+
+	clk = clk_register(dev, &composite->hw);
+	if (IS_ERR(clk))
+		kfree(composite);
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 9096f0a..9827a4f 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -120,6 +120,26 @@ extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
 			spinlock_t *lock);
 
 
+/* Clock type "composite" for mix clock */
+struct mmp_clk_composite {
+	struct clk_hw hw;
+	struct clk_ops ops;
+
+	struct clk_hw *mix_hw;
+	struct clk_hw *gate_hw;
+
+	const struct clk_ops *mix_ops;
+	const struct clk_ops *gate_ops;
+};
+
+extern struct clk *mmp_clk_register_composite(struct device *dev,
+			const char *name,
+			const char **parent_names, int num_parents,
+			struct clk_hw *mix_hw, const struct clk_ops *mix_ops,
+			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+			unsigned long flags);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
-- 
1.8.3.2

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

* [PATCH 08/12] clk: mmp: add clock type master
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (6 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 07/12] clk: mmp: add clock type composite for mix Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 09/12] clk: mmp: add spin lock automatic detection from device tree Chao Xie
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

To support device tree for clock, we need pass the register
base and range to the clock.
There are many clock share same range of registers.
For example, clk1 has register as 0xd4210010 while clk2
has 0xd42100c0. If we map the register seperately. There
will waste some space. If there are many clocks like that,
the waste will be huge.
clock type "master node" will map the register for all clocks
that listed as its child in DT file. Each clock will invoke
the APIs provided by "master node" to get its register base.
The following is a exmaple of master clock usage in DT file

apmu_clocks {
	compatible = "marvell,mmp-clk-master";
	reg = <0xd4210000 0x1000>;

	ck1 {
		marvell,reg-offset = <0 0x10>;
	};

	clk2 {
		marvell,reg-offset = <0 0xc0>;
	};
}

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 .../devicetree/bindings/clock/mmp/clk-master       |  47 +++++
 drivers/clk/mmp/Makefile                           |   4 +
 drivers/clk/mmp/clk-master-node.c                  | 195 +++++++++++++++++++++
 drivers/clk/mmp/clk.h                              |   7 +
 4 files changed, 253 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-master
 create mode 100644 drivers/clk/mmp/clk-master-node.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-master b/Documentation/devicetree/bindings/clock/mmp/clk-master
new file mode 100644
index 0000000..b6acde1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-master
@@ -0,0 +1,47 @@
+Binding for Marvell MMP series master clock.
+
+The MMP related device tree support for clock based on the clock type not clock
+controller. So specific SOC, user need define the DT file for the clock such as
+pxa910-clock.dtsi.
+
+Almost all types of clock will need parameter as "register", and it will map the
+"register" before access it. If every clock map the "register" seperately, there
+will be a lot of waste.
+
+A master clock is defined for this kind of situation. It will be responsible for
+map the registers for all clocks that lists as its children in DT file.
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-master".
+
+
+Optional properties:
+- reg : The register start and range the master clock covered.
+
+Optional properties for child node:
+- marvell,reg-offset : It is a two-values item - <register_index regiser_offset>.
+                   Master node will map the registers for all its children. So
+                   for the child it need to pass the information about register
+                   index and offset. "register_index" indicates which register space
+                   it from because master clock can have mutiple register space in
+                   "reg". "register_offset" indicates the offset in the register
+                   space.
+
+Examples
+There are two clocks, clk1 has register at 0xd4210010, and clk2 has register at
+0xd42100c0.
+
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4210000 0x1000>;
+
+	clk1 {
+		...
+		marvell,reg-offset = <0 0x10>;
+	};
+
+	clk2 {
+		...
+		marvell,reg-offset = <0 0xc0>;
+	};
+};
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2cd7d94..518931e 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -5,6 +5,10 @@
 obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o	\
 	 clk-mix-composite.o
 
+ifneq ($(CONFIG_OF),)
+obj-y += clk-master-node.o
+endif
+
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/clk-master-node.c b/drivers/clk/mmp/clk-master-node.c
new file mode 100644
index 0000000..584f72f
--- /dev/null
+++ b/drivers/clk/mmp/clk-master-node.c
@@ -0,0 +1,195 @@
+/*
+ * mmp master clock source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/ioport.h>
+
+#include "clk.h"
+
+#define MAX_REG		8
+
+struct mmp_clk_master_node {
+	unsigned int reg_base[MAX_REG];
+	void __iomem *reg[MAX_REG];
+	struct device_node *np;
+	struct list_head node;
+};
+
+static LIST_HEAD(master_list);
+static DEFINE_MUTEX(master_mutex);
+
+static void mmp_clk_master_setup(struct device_node *np)
+{
+	struct mmp_clk_master_node *node;
+	struct resource res;
+	int i, ret;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node) {
+		pr_err("%s:%s failed to allocate master node.\n",
+			__func__, np->name);
+		return;
+	}
+
+	for (i = 0; i < MAX_REG; i++) {
+		ret = of_address_to_resource(np, i, &res);
+		if (ret)
+			break;
+		node->reg_base[i] = res.start;
+		node->reg[i] = ioremap(res.start, resource_size(&res));
+		if (!node->reg[i]) {
+			pr_err("%s:%s failed to map register.\n",
+				__func__, np->name);
+			goto error;
+		}
+	}
+
+	node->np = np;
+	INIT_LIST_HEAD(&node->node);
+
+	mutex_lock(&master_mutex);
+
+	list_add(&node->node, &master_list);
+
+	mutex_unlock(&master_mutex);
+
+	return;
+error:
+	for (i--; i >= 0; i--)
+		iounmap(node->reg[i]);
+
+	kfree(node);
+}
+
+struct of_device_id mmp_clk_master_of_id[] = {
+	{
+		.compatible = "marvell,mmp-clk-master",
+		.data = mmp_clk_master_setup,
+	},
+	{ },
+};
+
+static struct mmp_clk_master_node *get_master_node(struct device_node *child)
+{
+	struct device_node *master;
+	struct mmp_clk_master_node *node;
+
+	/* Find the master device node */
+	master = child;
+	do {
+		master = of_get_next_parent(master);
+	} while (!of_match_node(mmp_clk_master_of_id, master));
+
+	mutex_lock(&master_mutex);
+
+	list_for_each_entry(node, &master_list, node) {
+		if (node->np == master) {
+			mutex_unlock(&master_mutex);
+			return node;
+		}
+	}
+
+	mutex_unlock(&master_mutex);
+
+	return NULL;
+}
+
+static void __iomem *get_child_reg(struct device_node *child,
+				unsigned int reg_index,
+				unsigned int *reg_base)
+{
+	struct mmp_clk_master_node *node;
+
+	if (reg_index >= MAX_REG) {
+		pr_err("%s:%s reg_index too big.\n", __func__, child->name);
+		return NULL;
+	}
+
+	node = get_master_node(child);
+	if (!node) {
+		pr_err("%s:%s failed to get master node\n",
+			__func__, child->name);
+		return NULL;
+	}
+
+	*reg_base = node->reg_base[reg_index];
+
+	return node->reg[reg_index];
+}
+
+void __iomem *of_mmp_clk_get_reg(struct device_node *np,
+					unsigned int index,
+					unsigned int *reg_phys)
+{
+	const __be32 *prop;
+	unsigned int proplen, size;
+	u32 reg_index, reg_offset;
+	unsigned int reg_base;
+	void __iomem *reg;
+
+	prop = of_get_property(np, "marvell,reg-offset", &proplen);
+	if (!prop) {
+		pr_err("%s:%s can not find marvell,reg-offset\n",
+			__func__, np->name);
+		return NULL;
+	}
+
+	size = proplen / sizeof(u32);
+
+	if ((proplen % sizeof(u32)) || (size <= (index * 2))) {
+		pr_err("%s:%s prop len is not correct\n",
+			__func__, np->name);
+		return NULL;
+	}
+
+	reg_index = be32_to_cpup(prop + index * 2);
+	reg_offset = be32_to_cpup(prop + index * 2 + 1);
+	reg = get_child_reg(np, reg_index, &reg_base);
+	if (!reg) {
+		pr_err("%s:%s failed to get reg\n",
+			__func__, np->name);
+		return NULL;
+	}
+
+	*reg_phys = reg_base + reg_offset;
+
+	return reg + reg_offset;
+}
+
+struct device_node *of_mmp_clk_master_init(struct device_node *from)
+{
+	struct device_node *parent, *child;
+	const struct of_device_id *match;
+	of_clk_init_cb_t clk_init_cb;
+
+	parent = from;
+	parent = of_find_matching_node_and_match(from, mmp_clk_master_of_id,
+						&match);
+	if (parent) {
+		clk_init_cb = (of_clk_init_cb_t)match->data;
+		clk_init_cb(parent);
+		for_each_child_of_node(parent, child) {
+			match = of_match_node(&__clk_of_table, child);
+			if (!match)
+				continue;
+			clk_init_cb = (of_clk_init_cb_t)match->data;
+			clk_init_cb(child);
+		}
+	}
+
+	return parent;
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 9827a4f..6d8c3b3 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -140,6 +140,13 @@ extern struct clk *mmp_clk_register_composite(struct device *dev,
 			unsigned long flags);
 
 
+/* Master clock exported APIs and data. */
+extern void __iomem *of_mmp_clk_get_reg(struct device_node *np,
+					unsigned int reg_index,
+					unsigned int *reg_phys);
+struct device_node *of_mmp_clk_master_init(struct device_node *from);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
-- 
1.8.3.2

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

* [PATCH 09/12] clk: mmp: add spin lock automatic detection from device tree
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (7 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 08/12] clk: mmp: add clock type master Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 10/12] clk: mmp: add device tree support for composite type clock Chao Xie
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

For Marvell MMP series SOC, many clocks share same register.
In the operations of these clock, a spin lock is needed to avoid
confilicts.
When parse the clock from the device tree and register the clock,
we do not know whether it share the register with others.
So a common API is provided to get the spin lock for the clock based
on device tree support.
The general idea is record the node (clock device node, regsiter),
and before register a new clock, search the node list based on
register. If a node is found, return the shared spin lock, or create
a new.

Signed-off-by: Chao Xie <chao.xie@marvell.com>

Conflicts:
	drivers/clk/mmp/Makefile
---
 Documentation/devicetree/bindings/clock/mmp/lock |  44 +++++++
 drivers/clk/mmp/Makefile                         |   2 +-
 drivers/clk/mmp/clk.h                            |   5 +
 drivers/clk/mmp/lock.c                           | 159 +++++++++++++++++++++++
 4 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/lock
 create mode 100644 drivers/clk/mmp/lock.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/lock b/Documentation/devicetree/bindings/clock/mmp/lock
new file mode 100644
index 0000000..7e7b5bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/lock
@@ -0,0 +1,44 @@
+Binding of spin lock support for Marvell MMP series clock
+
+Because some clocks share same register, spinlock need to be used to avoid
+conflicts.
+
+The spin lock sharing detection is based on regsiter address, and it is
+automatically. To support some clocks, the spin lock is not based on
+register address, some properies are provided.
+The properites are used as part of clock's properties in clock device tree
+files.
+
+Optional properties:
+marvell,mmp-clk-spinlock-new : Skip the automatic detection based on
+			       register address. Direclty create a new
+			       spin lock.
+marvell,mmp-clk-spinlock : It is handle. It points to the clock that share
+			   same spin lock.
+
+Examples:
+
+Assume that clk1, clk2, clk3 share same spin lock.
+
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	...
+
+	clk1 {
+		...
+		marvell,mmp-clk-spinlock-new;
+		...
+	};
+
+	clk2 {
+		...
+		mmp-clk-spinlock = <&clk1>;
+		...
+	};
+
+	clk3 {
+		...
+		mmp-clk-spinlock = <&clk1>;
+		...
+	};
+};
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 518931e..e8810b6 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o	\
 	 clk-mix-composite.o
 
 ifneq ($(CONFIG_OF),)
-obj-y += clk-master-node.o
+obj-y += clk-master-node.o lock.o
 endif
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 6d8c3b3..e06a228 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -147,6 +147,11 @@ extern void __iomem *of_mmp_clk_get_reg(struct device_node *np,
 struct device_node *of_mmp_clk_master_init(struct device_node *from);
 
 
+/* spin lock sharing support. */
+extern spinlock_t *of_mmp_clk_get_spinlock(struct device_node *np,
+					   unsigned int reg_base);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
diff --git a/drivers/clk/mmp/lock.c b/drivers/clk/mmp/lock.c
new file mode 100644
index 0000000..e2e246c
--- /dev/null
+++ b/drivers/clk/mmp/lock.c
@@ -0,0 +1,159 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/of.h>
+
+struct mmp_clk_spinlock_node {
+	struct device_node *share;
+	struct list_head node;
+};
+
+struct mmp_clk_spinlock {
+	spinlock_t lock;
+	struct device_node *owner;
+	unsigned int reg_base;
+	struct list_head share_list;
+	struct list_head node;
+};
+
+static LIST_HEAD(lock_list);
+
+static DEFINE_MUTEX(lock_mutex);
+
+static struct mmp_clk_spinlock_node *create_lock_node(struct device_node *np)
+{
+	struct mmp_clk_spinlock_node *node;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node) {
+		pr_err("%s:%s failed to allocate spinlock node.\n",
+			__func__, np->name);
+		return NULL;
+	}
+
+	node->share = np;
+
+	return node;
+}
+
+static struct mmp_clk_spinlock *create_lock(struct device_node *np,
+					    unsigned int reg_base)
+{
+	struct mmp_clk_spinlock *lock;
+
+	lock = kzalloc(sizeof(*lock), GFP_KERNEL);
+	if (!lock) {
+		pr_err("%s:%s failed to allocate spinlock.\n",
+			__func__, np->name);
+		return NULL;
+	}
+
+	lock->owner = np;
+	lock->reg_base = reg_base;
+	INIT_LIST_HEAD(&lock->node);
+	INIT_LIST_HEAD(&lock->share_list);
+	spin_lock_init(&lock->lock);
+
+	return lock;
+}
+
+static struct mmp_clk_spinlock *find_lock_by_np(struct device_node *np)
+{
+	struct mmp_clk_spinlock *lock;
+
+	list_for_each_entry(lock, &lock_list, node) {
+		if (lock->owner == np)
+			return lock;
+	}
+
+	return NULL;
+}
+
+static struct mmp_clk_spinlock *find_lock_by_reg_base(unsigned int reg_base)
+{
+	struct mmp_clk_spinlock *lock;
+
+	list_for_each_entry(lock, &lock_list, node) {
+		if (lock->reg_base == reg_base)
+			return lock;
+	}
+
+	return NULL;
+}
+
+spinlock_t *of_mmp_clk_get_spinlock(struct device_node *np,
+					unsigned int reg_base)
+{
+	struct mmp_clk_spinlock *lock;
+	struct mmp_clk_spinlock_node *node;
+	struct device_node *owner;
+
+	if (of_property_read_bool(np, "marvell,mmp-clk-spinlock-new")) {
+
+		mutex_lock(&lock_mutex);
+
+		lock = find_lock_by_np(np);
+		if (!lock) {
+			lock = create_lock(np, reg_base);
+			if (lock)
+				list_add(&lock->node, &lock_list);
+		}
+
+		mutex_unlock(&lock_mutex);
+
+		return &lock->lock;
+	}
+
+	if (of_find_property(np, "marvell,mmp-clk-spinlock", NULL)) {
+
+		mutex_lock(&lock_mutex);
+
+		owner = of_parse_phandle(np, "marvell,mmp-clk-spinlock", 0);
+		lock = find_lock_by_np(owner);
+	} else {
+
+		mutex_lock(&lock_mutex);
+
+		lock = find_lock_by_reg_base(reg_base);
+	}
+
+	if (!lock) {
+		lock = create_lock(np, reg_base);
+		if (lock)
+			list_add(&lock->node, &lock_list);
+	}
+
+	if (!lock) {
+		mutex_unlock(&lock_mutex);
+		pr_err("%s:%s failed to get spinlock\n", __func__, np->name);
+		return NULL;
+	}
+
+	node = create_lock_node(np);
+	if (!node) {
+		mutex_unlock(&lock_mutex);
+		pr_err("%s:%s failed to create spinlock node\n",
+			__func__, np->name);
+		return NULL;
+	}
+	node->share = np;
+	list_add(&node->node, &lock->share_list);
+
+	mutex_unlock(&lock_mutex);
+
+	return &lock->lock;
+}
+
-- 
1.8.3.2

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

* [PATCH 10/12] clk: mmp: add device tree support for composite type clock
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (8 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 09/12] clk: mmp: add spin lock automatic detection from device tree Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 11/12] clk: mmp: add device tree support for clocks Chao Xie
  2014-06-10  1:27 ` [PATCH 12/12] arm: mmp: support clock device tree for mmp platforms Chao Xie
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

To parse composite clock from device tree file, there are some
rules.
The clock to be composited will be the child of the composite
clock in device tree file.
It can support the composition of (mux,div,gate) clock defined
as common clock and (mix,gate) defined only for MMP series.

Signed-off-by: Chao Xie <chao.xie@marvell.com>

Conflicts:
	drivers/clk/mmp/Makefile
---
 .../devicetree/bindings/clock/mmp/clk-composite    |  58 +++++
 drivers/clk/mmp/Makefile                           |   2 +-
 drivers/clk/mmp/clk-of-composite.c                 | 253 +++++++++++++++++++++
 drivers/clk/mmp/clk.h                              |  14 ++
 4 files changed, 326 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-composite
 create mode 100644 drivers/clk/mmp/clk-of-composite.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-composite b/Documentation/devicetree/bindings/clock/mmp/clk-composite
new file mode 100644
index 0000000..224968c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-composite
@@ -0,0 +1,58 @@
+Binding for Marvell MMP series composite clock
+
+The common clock defines a general composite clock with div/mux/gate.
+Because MMP series has clock need combines the div/mux together, so
+there is a new type of clock "mix". The "mix" clock can also be
+composited with gate clock. In fact, many mix clocks and gate clocks
+share same registers.
+
+In the device tree file, the clock to be composited should be child
+of the composite clock.
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-composite" for (mix, gate)
+               composition, or "marvell,mmp-clk-general-composite" for
+               (mux, div, gate) composition.
+
+
+Examples
+1. There are three clocks mux1, div1, gate1.
+
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xde210000 0x1000>;
+
+	general_composite_clk {
+		compatible = "marvell,mmp-clk-general-composite";
+
+		mux1 {
+			...
+		};
+		div1 {
+			...
+		};
+		gate1 {
+			...
+		};
+	};
+};
+
+2. There are two clocks mix1, gate2
+
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xde210000 0x1000>;
+
+	composite_clk {
+		compatible = "marvell,mmp-clk-composite";
+
+		mix1 {
+			...
+		};
+		gate2 {
+			...
+		};
+	};
+};
+
+
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index e8810b6..84dce78 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o	\
 	 clk-mix-composite.o
 
 ifneq ($(CONFIG_OF),)
-obj-y += clk-master-node.o lock.o
+obj-y += clk-master-node.o lock.o clk-of-composite.o
 endif
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
diff --git a/drivers/clk/mmp/clk-of-composite.c b/drivers/clk/mmp/clk-of-composite.c
new file mode 100644
index 0000000..403ebe2
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-composite.c
@@ -0,0 +1,253 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+struct mmp_clk_composite_member {
+	struct device_node *np;
+	struct clk_hw *hw;
+	const struct clk_ops *ops;
+	int num_parents;
+	const char **parent_names;
+};
+
+struct mmp_clk_composite_node {
+	struct device_node *np;
+	struct mmp_clk_composite_member *members[MMP_CLK_COMPOSITE_TYPE_MAX];
+	struct list_head node;
+};
+
+static LIST_HEAD(composite_list);
+static DEFINE_MUTEX(composite_mutex);
+
+int of_mmp_clk_composite_add_member(struct device_node *np, struct clk_hw *hw,
+				const struct clk_ops *ops, int type)
+{
+	struct device_node *parent_np;
+	struct mmp_clk_composite_node *node;
+	struct mmp_clk_composite_member *member;
+	unsigned int found = 0;
+	size_t size;
+	int i, ret;
+
+	mutex_lock(&composite_mutex);
+
+	parent_np = of_get_next_parent(np);
+
+	list_for_each_entry(node, &composite_list, node) {
+		if (node->np == parent_np) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		pr_err("%s:%s can not find member %s\n",
+			__func__, parent_np->name, np->name);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	if (node->members[type]) {
+		pr_err("%s:%s already has type %d,when add member %s\n",
+			__func__, parent_np->name, type, np->name);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	member = kzalloc(sizeof(*member), GFP_KERNEL);
+	if (!member) {
+		pr_err("%s:%s failed to allocate member.\n",
+			__func__, parent_np->name);
+		ret = -ENOMEM;
+		goto out;
+	}
+	member->np = np;
+	member->hw = hw;
+	member->ops = ops;
+
+	ret = of_clk_get_parent_count(np);
+	if (ret >= 1) {
+		member->num_parents = ret;
+		size = sizeof(*member->parent_names) * member->num_parents;
+		member->parent_names = kzalloc(size, GFP_KERNEL);
+		if (!member->parent_names) {
+			pr_err("%s:%s failed to allocate parent_names.\n",
+				__func__, parent_np->name);
+			ret = -ENOMEM;
+			goto member_free;
+		}
+		for (i = 0; i < member->num_parents; i++)
+			member->parent_names[i] =
+					of_clk_get_parent_name(np, i);
+	} else {
+		member->num_parents = 0;
+		member->parent_names = NULL;
+	}
+
+	node->members[type] = member;
+
+	ret = 0;
+	goto out;
+
+member_free:
+	kfree(member);
+out:
+	mutex_unlock(&composite_mutex);
+
+	return ret;
+}
+
+static void of_mmp_clk_composite_setup(struct device_node *np)
+{
+	struct mmp_clk_composite_node *node;
+	struct mmp_clk_composite_member *mix, *gate;
+	struct device_node *child;
+	struct clk *clk;
+	const struct of_device_id *match;
+	of_clk_init_cb_t clk_init_cb;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node) {
+		pr_err("%s:%s failed to allocate node\n", __func__, np->name);
+		return;
+	}
+
+	INIT_LIST_HEAD(&node->node);
+	node->np = np;
+
+	mutex_lock(&composite_mutex);
+	list_add(&node->node, &composite_list);
+	mutex_unlock(&composite_mutex);
+
+	for_each_child_of_node(np, child) {
+		match = of_match_node(&__clk_of_table, child);
+		clk_init_cb = (of_clk_init_cb_t)match->data;
+		clk_init_cb(child);
+	}
+
+	mix = node->members[MMP_CLK_COMPOSITE_TYPE_MUXMIX];
+	gate = node->members[MMP_CLK_COMPOSITE_TYPE_GATE];
+	if (!mix || !gate) {
+		pr_err("%s:%s failed to parse members.\n", __func__, np->name);
+		goto error;
+	}
+
+	clk = mmp_clk_register_composite(NULL, np->name,
+				mix->parent_names, mix->num_parents,
+				mix->hw, mix->ops,
+				gate->hw, gate->ops, 0);
+	if (!IS_ERR(clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+	return;
+
+error:
+	mutex_lock(&composite_mutex);
+	list_del(&node->node);
+	mutex_unlock(&composite_mutex);
+	kfree(node);
+}
+
+static void of_mmp_clk_general_composite_setup(struct device_node *np)
+{
+	struct mmp_clk_composite_node *node;
+	struct mmp_clk_composite_member *mux, *gate, *div;
+	struct device_node *child;
+	struct clk *clk;
+	const char **parent_names;
+	int num_parents;
+	const struct of_device_id *match;
+	of_clk_init_cb_t clk_init_cb;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node) {
+		pr_err("%s:%s failed to allocate node\n", __func__, np->name);
+		return;
+	}
+
+	INIT_LIST_HEAD(&node->node);
+	node->np = np;
+
+	mutex_lock(&composite_mutex);
+	list_add(&node->node, &composite_list);
+	mutex_unlock(&composite_mutex);
+
+	for_each_child_of_node(np, child) {
+		match = of_match_node(&__clk_of_table, child);
+		clk_init_cb = (of_clk_init_cb_t)match->data;
+		clk_init_cb(child);
+	}
+
+	mux = node->members[MMP_CLK_COMPOSITE_TYPE_MUXMIX];
+	gate = node->members[MMP_CLK_COMPOSITE_TYPE_GATE];
+	div = node->members[MMP_CLK_COMPOSITE_TYPE_DIV];
+
+	if ((!mux && !div) || (!mux && !gate) || (!gate && !div)) {
+		pr_err("%s:%s failed to parse members.\n", __func__, np->name);
+		goto error;
+	}
+
+	if (mux) {
+		parent_names = mux->parent_names;
+		num_parents = mux->num_parents;
+	} else {
+		parent_names = div->parent_names;
+		num_parents = div->num_parents;
+	}
+
+	clk = clk_register_composite(NULL, np->name,
+				parent_names, num_parents,
+				mux ? mux->hw : NULL, mux ? mux->ops : NULL,
+				div ? div->hw : NULL, div ? div->ops : NULL,
+				gate ? gate->hw : NULL,
+				gate ? gate->ops : NULL, 0);
+	if (!IS_ERR(clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+	return;
+
+error:
+	mutex_lock(&composite_mutex);
+	list_del(&node->node);
+	mutex_unlock(&composite_mutex);
+	kfree(node);
+}
+
+CLK_OF_DECLARE(mmp_clk_composite, "marvell,mmp-clk-composite",
+		of_mmp_clk_composite_setup);
+CLK_OF_DECLARE(mmp_clk_general_composite, "marvell,mmp-clk-general-composite",
+		of_mmp_clk_general_composite_setup);
+
+int of_mmp_clk_is_composite(struct device_node *np)
+{
+	struct device_node *parent_np;
+	struct mmp_clk_composite_node *node;
+
+	parent_np = of_get_next_parent(np);
+	mutex_lock(&composite_mutex);
+	list_for_each_entry(node, &composite_list, node) {
+		if (node->np == parent_np) {
+			mutex_unlock(&composite_mutex);
+			return 1;
+		}
+	}
+	mutex_unlock(&composite_mutex);
+
+	return 0;
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index e06a228..66d0fd4 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -152,6 +152,20 @@ extern spinlock_t *of_mmp_clk_get_spinlock(struct device_node *np,
 					   unsigned int reg_base);
 
 
+/* DT support for composiste type clock. */
+enum {
+	MMP_CLK_COMPOSITE_TYPE_MUXMIX,
+	MMP_CLK_COMPOSITE_TYPE_DIV,
+	MMP_CLK_COMPOSITE_TYPE_GATE,
+	MMP_CLK_COMPOSITE_TYPE_MAX,
+};
+
+extern int of_mmp_clk_composite_add_member(struct device_node *np,
+				struct clk_hw *hw,
+				const struct clk_ops *ops, int type);
+extern int of_mmp_clk_is_composite(struct device_node *np);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
-- 
1.8.3.2

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

* [PATCH 11/12] clk: mmp: add device tree support for clocks.
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (9 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 10/12] clk: mmp: add device tree support for composite type clock Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  2014-06-10  1:27 ` [PATCH 12/12] arm: mmp: support clock device tree for mmp platforms Chao Xie
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

For MMP series SOC, it will use some types of clock.
Add the device tree support for these kind of clocks.
It includes mux/div/mix/gate/factor clock.

Signed-off-by: Chao Xie <chao.xie@marvell.com>

Conflicts:
	drivers/clk/mmp/Makefile
---
 .../devicetree/bindings/clock/mmp/clk-div          |  28 +
 .../devicetree/bindings/clock/mmp/clk-factor       |  28 +
 .../devicetree/bindings/clock/mmp/clk-gate         |  41 ++
 .../devicetree/bindings/clock/mmp/clk-mix          |  38 ++
 .../devicetree/bindings/clock/mmp/clk-mux          |  20 +
 drivers/clk/mmp/Makefile                           |   2 +-
 drivers/clk/mmp/clk-of.c                           | 689 +++++++++++++++++++++
 7 files changed, 845 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-div
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-factor
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-gate
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mix
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mux
 create mode 100644 drivers/clk/mmp/clk-of.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-div b/Documentation/devicetree/bindings/clock/mmp/clk-div
new file mode 100644
index 0000000..62eb7d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-div
@@ -0,0 +1,28 @@
+Binding for div type clock
+
+The div clock is defined as common clock.
+
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-div".
+- clocks : The parents of the clock.
+- marvell,mmp-clk-bits-div : The width and shift of divider bits.
+
+Optional properties:
+- marvell,mmp-clk-div-power-of-two : The value of divider is a power of two.
+- marvell,mmp-clk-div-one-based : The value of divider starts from 1.
+- marvell,mmp-clk-div-table : The value of divider is not continous, and need
+                              a table to record it.
+
+
+Examples
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4282800 0x1000>;
+	dsi_phy_slow_div: dsi_phy_slow_div {
+		compatible = "marvell,mmp-clk-div";
+		marvell,reg-offset = <0 0x44>;
+		clocks = <&vctcxo>;
+		marvell,mmp-clk-bits-div = <5 6>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-factor b/Documentation/devicetree/bindings/clock/mmp/clk-factor
new file mode 100644
index 0000000..9e1816c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-factor
@@ -0,0 +1,28 @@
+Binding for Marvell MMP series factor clock
+
+The factor clock is calculated by
+  Fout = (Fin * (den / num)) / factor;
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-factor";
+- clock: The parent of the clock.
+- marvell,mmp-clk-factor-factor : The "factor" of the clock.
+- marvell,mmp-clk-factor-bits-num : The width and shift of bits for "num".
+- marvell,mmp-clk-factor-bits-den : The width and shift of bits for "dev".
+- marvell,mmp-clk-factor-table : The table of (num, den) for the clock.
+
+Examples
+mpmu_clocks: mpmu_clocks {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4050000 0x1000>;
+	uart_pll: uart_pll {
+		compatible = "marvell,mmp-clk-factor";
+		clocks = <&pll1_4>;
+		marvell,reg-offset = <0 0x14>;
+		marvell,mmp-clk-factor-factor = <2>;
+		marvell,mmp-clk-factor-bits-den = <13 0>;
+		marvell,mmp-clk-factor-bits-num = <13 16>;
+		marvell,mmp-clk-factor-table = <8125 1536>;
+	};
+};
++
diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-gate b/Documentation/devicetree/bindings/clock/mmp/clk-gate
new file mode 100644
index 0000000..5da6c63
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-gate
@@ -0,0 +1,41 @@
+Binding for Marvell MMP series gate clock and common gate clock
+
+There two type of gate clock used by Marvell MMP series SOC.
+The common gate clock and the gate clock defined for MMP series SOC.
+
+For common gate clock
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-general-gate";
+- clock : The parent of the clock.
+- marvell,mmp-clk-bit-gate : The offset of the bit control the gate.
+
+Examples
+apmu_clocks: apmu_clocks {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4282800 0x1000>;
+	pll1_416_gate: pll1_416_gate {
+		compatible = "marvell,mmp-clk-general-gate";
+		clocks = <&pll1_416m>;
+		marvell,reg-offset = <0 0x40>;
+		marvell,mmp-clk-bit-gate = <27>;
+	};
+};
+
+For MMP series gate clock
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-gate";
+- clock : The parent of the clock.
+- marvell,mmp-clk-mask : The (mask, val_enable, val_disable) for the clock.
+
+Examples
+apmu_clocks: apmu_clocks {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4282800 0x1000>;
+	usb_clock: usb_clock {
+		compatible = "marvell,mmp-clk-gate";
+		marvell,reg-offset = <0 0x5c>;
+		marvell,mmp-clk-mask = <0x9 0x9 0x1>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-mix b/Documentation/devicetree/bindings/clock/mmp/clk-mix
new file mode 100644
index 0000000..8cf9b38
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-mix
@@ -0,0 +1,38 @@
+Binding for Marvell MMP series mix clock
+
+The mix clock is a combination of mux and div clock. It need to
+change the bits of mux and div together.
+
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-mix".
+- clocks : The parents of the clock.
+- marvell,mmp-clk-bits-div : The width and shift of divider bits.
+- marvell,mmp-clk-bits-mux : The width and shift of divider bits.
+- marvell,mmp-clk-bit-fc : The offset of the frequency change bit.
+- marvell,mmp-clk-mix-table : The array of (rate, parent_index). The rate
+                              means the clock's rate, and parent_index means
+                              the suggested parent index from user.
+
+Optional properties:
+- marvell,mmp-clk-div-power-of-two : The value of divider is a power of two.
+- marvell,mmp-clk-div-one-based : The value of divider starts from 1.
+- marvell,mmp-clk-div-table : The value of divider is not continous, and need
+                              a table to record it.
+
+
+Exampels
+
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4282800 0x1000>;
+	lcd_clk {
+		compatible = "marvell,mmp-clk-mix";
+		clocks = <&pll1_416m &pll1_624 &pll2 &pll2p>;
+		marvell,reg-offset = <0 0x4c>;
+		marvell,mmp-clk-bits-mux = <2 17>;
+		marvell,mmp-clk-bits-div = <3 19>;
+		marvell,mmp-clk-bit-fc = <22>;
+	};
+};
+
diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-mux b/Documentation/devicetree/bindings/clock/mmp/clk-mux
new file mode 100644
index 0000000..f5bb4dd
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-mux
@@ -0,0 +1,20 @@
+Binding for mux type clock
+
+The mux clock is defined as common clock.
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-mux".
+- clocks : The parents of the clock.
+- marvell,mmp-clk-bits-mux : The width and shift of mux bits.
+
+Examples
+apmu_clk {
+	compatible = "marvell,mmp-clk-master";
+	reg = <0xd4282800 0x1000>;
+	dsi_phy_esc_mux: dsi_phy_esc_mux {
+		compatible = "marvell,mmp-clk-mux";
+		marvell,reg-offset = <0 0x44>;
+		clocks = <&pll1_12 &pll1_13 &vctcxo &pll1_8>;
+		marvell,mmp-clk-bits-mux = <2 0>;
+	};
+};
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 84dce78..e29c6f1 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o	\
 	 clk-mix-composite.o
 
 ifneq ($(CONFIG_OF),)
-obj-y += clk-master-node.o lock.o clk-of-composite.o
+obj-y += clk-master-node.o lock.o clk-of-composite.o clk-of.o
 endif
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
diff --git a/drivers/clk/mmp/clk-of.c b/drivers/clk/mmp/clk-of.c
new file mode 100644
index 0000000..2bba7ee
--- /dev/null
+++ b/drivers/clk/mmp/clk-of.c
@@ -0,0 +1,689 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+static int of_mmp_clk_get_flags(struct device_node *np,
+				unsigned long *flags)
+{
+	*flags = 0;
+
+	return 0;
+}
+
+static int of_mmp_clk_get_bits(struct device_node *np, const char *name,
+				u8 *width, u8 *shift)
+{
+	int ret;
+	u32 tmp[2];
+
+	ret = of_property_read_u32_array(np, name, tmp, 2);
+	if (ret) {
+		pr_err("%s:%s failed to read bits %s\n",
+			__func__, np->name, name);
+		return -EINVAL;
+	}
+
+	*width = tmp[0];
+	*shift = tmp[1];
+
+	return 0;
+}
+
+static int of_mmp_clk_div_dt_parse(struct device_node *np, u8 *shift,
+					u8 *width,
+					struct clk_div_table **ptable,
+					u8 *div_flags)
+{
+	int i, ret;
+	const __be32 *prop;
+	unsigned int proplen;
+	struct clk_div_table *table;
+	unsigned int size;
+
+	ret = of_mmp_clk_get_bits(np, "marvell,mmp-clk-bits-div",
+				width, shift);
+	if (ret)
+		return ret;
+
+	*div_flags = 0;
+	if (of_property_read_bool(np, "marvell,mmp-clk-div-power-of-two"))
+		*div_flags |= CLK_DIVIDER_POWER_OF_TWO;
+	else if (of_property_read_bool(np, "marvell,mmp-clk-div-one-based"))
+		*div_flags |= CLK_DIVIDER_ONE_BASED;
+
+	if (ptable)
+		*ptable = NULL;
+
+	prop = of_get_property(np, "marvell,mmp-clk-div-table", &proplen);
+	if (prop) {
+		if (!ptable)
+			return -EINVAL;
+
+		size = proplen / sizeof(u32);
+		if ((proplen % sizeof(u32)) || size % 2) {
+			pr_err("%s:%s marvell,mmp-clk-mix-table wrong value\n",
+				__func__, np->name);
+			return -EINVAL;
+		}
+		table = kzalloc(sizeof(*table) * (size / 2 + 1), GFP_KERNEL);
+		if (!table) {
+			pr_err("%s:%s failed to allocate table\n",
+				__func__, np->name);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < size; i += 2) {
+			table[i / 2].val = be32_to_cpup(prop + i);
+			table[i / 2].div = be32_to_cpup(prop + i + 1);
+		}
+		/* For safe. */
+		table[i / 2].val = 0;
+		table[i / 2].div = 0;
+
+		*ptable = table;
+	}
+
+	return 0;
+}
+
+static int of_mmp_clk_mux_dt_parse(struct device_node *np, u8 *shift,
+					u8 *width, u8 *mux_flags)
+{
+	int ret;
+
+	ret = of_mmp_clk_get_bits(np, "marvell,mmp-clk-bits-mux",
+				width, shift);
+	if (ret)
+		return ret;
+
+	*mux_flags = 0;
+
+	return 0;
+}
+
+static int of_mmp_clk_general_gate_dt_parse(struct device_node *np,
+					u8 *bit_idx, u8 *gate_flags)
+{
+	int ret;
+	u32 tmp;
+
+	ret = of_property_read_u32(np, "marvell,mmp-clk-bit-gate", &tmp);
+	if (ret) {
+		pr_err("%s:%s can not find marvell,mmp-clk-bit-gate\n",
+			__func__, np->name);
+		return -EINVAL;
+	}
+	*bit_idx = tmp;
+
+	*gate_flags = 0;
+
+	return 0;
+}
+
+static int of_mmp_clk_gate_dt_parse(struct device_node *np,
+				u32 *mask, u32 *val_enable, u32 *val_disable,
+				unsigned int *gate_flags)
+{
+	int ret;
+	u32 tmp[3];
+
+	ret = of_property_read_u32_array(np, "marvell,mmp-clk-mask", tmp, 3);
+	if (ret) {
+		pr_err("%s:%s can not find marvell,mmp-clk-mask\n",
+			__func__, np->name);
+		return -EINVAL;
+	}
+	*mask = tmp[0];
+	*val_enable = tmp[1];
+	*val_disable = tmp[2];
+
+	*gate_flags = 0;
+	if (of_property_read_bool(np, "marvell,mmp-clk-gate-need-delay"))
+		*gate_flags |= MMP_CLK_GATE_NEED_DELAY;
+
+	return 0;
+}
+
+
+static int of_mmp_clk_mix_dt_parse(struct device_node *np,
+					struct mmp_clk_mix_config *config,
+					spinlock_t **plock)
+{
+	struct mmp_clk_mix_reg_info *ri;
+	struct mmp_clk_mix_clk_table *table;
+	int i, ret, size;
+	u32 tmp;
+	spinlock_t *lock;
+	void __iomem *reg;
+	unsigned int reg_phys;
+	const __be32 *prop;
+	unsigned int proplen;
+
+	ri = &config->reg_info;
+	ret = of_mmp_clk_div_dt_parse(np, &ri->shift_div, &ri->width_div,
+					NULL, &config->div_flags);
+	if (ret)
+		return ret;
+
+	ret = of_mmp_clk_mux_dt_parse(np, &ri->shift_mux, &ri->width_mux,
+					&config->mux_flags);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(np, "marvell,mmp-clk-bit-fc", &tmp);
+	if (ret)
+		ri->bit_fc = (u8)-1;
+	else
+		ri->bit_fc = tmp;
+
+	reg = of_mmp_clk_get_reg(np, 0, &reg_phys);
+	if (!reg)
+		return -EINVAL;
+	ri->reg_clk_ctrl = reg;
+
+	lock = of_mmp_clk_get_spinlock(np, reg_phys);
+	if (!lock)
+		return -EINVAL;
+
+	*plock = lock;
+	reg = of_mmp_clk_get_reg(np, 1, &reg_phys);
+	if (reg)
+		ri->reg_clk_sel = reg;
+
+	prop = of_get_property(np, "marvell,mmp-clk-mix-table", &proplen);
+	if (prop) {
+		size = proplen / sizeof(u32);
+		if ((proplen % sizeof(u32)) || size % 2) {
+			pr_err("%s:%s marvell,mmp-clk-mix-table wrong value\n",
+				__func__, np->name);
+			return -EINVAL;
+		}
+		table = kzalloc(sizeof(*table) * (size / 2), GFP_KERNEL);
+		if (!table) {
+			pr_err("%s:%s failed to allocate table\n",
+				__func__, np->name);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < size; i += 2) {
+			table[i / 2].rate = be32_to_cpup(prop + i);
+			table[i / 2].parent_index = be32_to_cpup(prop + i + 1);
+		}
+		config->table = table;
+		config->table_size = size / 2;
+	} else {
+		config->table = NULL;
+		config->table_size = 0;
+	}
+
+	return 0;
+}
+
+static int of_mmp_clk_factor_dt_parse(struct device_node *np,
+					struct mmp_clk_factor_masks **pmasks,
+					struct mmp_clk_factor_tbl **pftbl,
+					unsigned int *pftbl_cnt)
+{
+	struct mmp_clk_factor_masks *masks;
+	struct mmp_clk_factor_tbl *table;
+	u8 width, shift;
+	int i, ret, size;
+	u32 tmp;
+	const __be32 *prop;
+	unsigned int proplen;
+
+	masks = kzalloc(sizeof(*masks), GFP_KERNEL);
+	if (!masks) {
+		pr_err("%s:%s failed to allocate factor masks\n",
+			__func__, np->name);
+		return -ENOMEM;
+	}
+
+	ret = of_property_read_u32(np, "marvell,mmp-clk-factor-factor", &tmp);
+	if (ret) {
+		pr_err("%s:%s can not find marvell,mmp-clk-factor-num\n",
+			__func__, np->name);
+		return -EINVAL;
+	}
+	masks->factor = tmp;
+
+	ret = of_mmp_clk_get_bits(np, "marvell,mmp-clk-factor-bits-num",
+				&width, &shift);
+	if (ret)
+		return ret;
+	masks->num_mask = BIT(width) - 1;
+	masks->num_shift = shift;
+
+	ret = of_mmp_clk_get_bits(np, "marvell,mmp-clk-factor-bits-den",
+				&width, &shift);
+	if (ret)
+		return ret;
+	masks->den_mask = BIT(width) - 1;
+	masks->den_shift = shift;
+	*pmasks = masks;
+
+	prop = of_get_property(np, "marvell,mmp-clk-factor-table", &proplen);
+	if (!prop) {
+		pr_err("%s:%s failed to get marvell,mmp-clk-factor-table\n",
+			__func__, np->name);
+		return -EINVAL;
+	}
+
+	size = proplen / sizeof(u32);
+	if ((proplen % sizeof(u32)) || size % 2) {
+		pr_err("%s:%s marvell,mmp-clk-factor-table wrong value\n",
+			__func__, np->name);
+		return -EINVAL;
+	}
+	table = kzalloc(sizeof(*table) * (size / 2), GFP_KERNEL);
+	if (!table) {
+		pr_err("%s:%s failed to allocate table\n",
+			__func__, np->name);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i += 2) {
+		table[i / 2].num = be32_to_cpup(prop + i);
+		table[i / 2].den = be32_to_cpup(prop + i + 1);
+	}
+	*pftbl = table;
+	*pftbl_cnt = size / 2;
+
+	return 0;
+}
+
+static void of_mmp_clk_mix_setup(struct device_node *np)
+{
+	struct mmp_clk_mix *mix;
+	struct mmp_clk_mix_config config;
+	struct clk *clk;
+	spinlock_t *lock;
+	unsigned int num_parents;
+	const char **parent_names;
+	int i, ret;
+
+	ret = of_mmp_clk_mix_dt_parse(np, &config, &lock);
+	if (ret)
+		return;
+
+	if (of_mmp_clk_is_composite(np)) {
+		mix = kzalloc(sizeof(*mix), GFP_KERNEL);
+		if (!mix) {
+			pr_err("%s:%s failed to allocate clk\n",
+				__func__, np->name);
+			return;
+		}
+		memcpy(&mix->reg_info, &config.reg_info,
+			sizeof(config.reg_info));
+		mix->div_flags = config.div_flags;
+		mix->mux_flags = config.mux_flags;
+		mix->lock = lock;
+		if (config.table) {
+			mix->table = config.table;
+			mix->table_size = config.table_size;
+		}
+
+		of_mmp_clk_composite_add_member(np, &mix->hw, &mmp_clk_mix_ops,
+					MMP_CLK_COMPOSITE_TYPE_MUXMIX);
+	} else {
+		num_parents = of_clk_get_parent_count(np);
+		parent_names = kcalloc(num_parents, sizeof(char *),
+					GFP_KERNEL);
+		if (!parent_names) {
+			pr_err("%s:%s failed to allocate parent_names\n",
+				__func__, np->name);
+			return;
+		}
+		for (i = 0; i < num_parents; i++)
+			parent_names[i] = of_clk_get_parent_name(np, i);
+
+		clk = mmp_clk_register_mix(NULL, np->name, num_parents,
+					parent_names, 0, &config, lock);
+
+		if (IS_ERR(clk)) {
+			kfree(parent_names);
+
+			pr_err("%s:%s failed to register clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	}
+}
+CLK_OF_DECLARE(mmp_clk_mix, "marvell,mmp-clk-mix",
+		of_mmp_clk_mix_setup);
+
+static void of_mmp_clk_div_setup(struct device_node *np)
+{
+	struct clk_divider *div;
+	void __iomem *reg;
+	u8 width, shift, div_flags;
+	struct clk_div_table *table;
+	unsigned long flags;
+	const char *parent_name;
+	struct clk *clk;
+	unsigned int reg_phys;
+	spinlock_t *lock;
+	int ret;
+
+	reg = of_mmp_clk_get_reg(np, 0, &reg_phys);
+	if (!reg)
+		return;
+
+	ret = of_mmp_clk_div_dt_parse(np, &shift, &width, &table, &div_flags);
+	if (ret)
+		return;
+
+	ret = of_mmp_clk_get_flags(np, &flags);
+	if (ret)
+		return;
+
+	lock = of_mmp_clk_get_spinlock(np, reg_phys);
+	if (!lock)
+		return;
+
+	if (of_mmp_clk_is_composite(np)) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			pr_err("%s:%s failed to allocate clk\n",
+				__func__, np->name);
+			return;
+		}
+		div->shift = shift;
+		div->width = width;
+		div->table = table;
+		div->flags = div_flags;
+		div->lock = lock;
+		div->reg = reg;
+
+		of_mmp_clk_composite_add_member(np, &div->hw, &clk_divider_ops,
+					MMP_CLK_COMPOSITE_TYPE_DIV);
+	} else {
+		parent_name = of_clk_get_parent_name(np, 0);
+
+		if (!table)
+			clk = clk_register_divider(NULL, np->name, parent_name,
+					flags, reg, shift, width, div_flags,
+					lock);
+		else
+			clk = clk_register_divider_table(NULL, np->name,
+					parent_name, flags, reg, shift, width,
+					div_flags, table, lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s:%s failed to register clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	}
+}
+CLK_OF_DECLARE(mmp_clk_div, "marvell,mmp-clk-div",
+		of_mmp_clk_div_setup);
+
+static void of_mmp_clk_mux_setup(struct device_node *np)
+{
+	struct clk_mux *mux;
+	void __iomem *reg;
+	u8 width, shift, mux_flags;
+	unsigned long flags;
+	spinlock_t *lock;
+	unsigned int num_parents;
+	const char **parent_names;
+	struct clk *clk;
+	unsigned int reg_phys;
+	int i, ret;
+
+	reg = of_mmp_clk_get_reg(np, 0, &reg_phys);
+	if (!reg)
+		return;
+
+	ret = of_mmp_clk_mux_dt_parse(np, &shift, &width, &mux_flags);
+	if (ret)
+		return;
+
+	ret = of_mmp_clk_get_flags(np, &flags);
+	if (ret)
+		return;
+
+	lock = of_mmp_clk_get_spinlock(np, reg_phys);
+	if (!lock)
+		return;
+
+	if (of_mmp_clk_is_composite(np)) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux) {
+			pr_err("%s:%s failed to allocate clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		mux->reg = reg;
+		mux->mask = BIT(width) - 1;
+		mux->shift = shift;
+		mux->lock = lock;
+		mux->flags = mux_flags;
+		of_mmp_clk_composite_add_member(np, &mux->hw, &clk_mux_ops,
+					MMP_CLK_COMPOSITE_TYPE_MUXMIX);
+	} else {
+		num_parents = of_clk_get_parent_count(np);
+		parent_names = kcalloc(num_parents, sizeof(char *),
+					GFP_KERNEL);
+		if (!parent_names) {
+			pr_err("%s:%s failed to allocate parent_names\n",
+				__func__, np->name);
+			return;
+		}
+		for (i = 0; i < num_parents; i++)
+			parent_names[i] = of_clk_get_parent_name(np, i);
+
+		clk = clk_register_mux(NULL, np->name, parent_names,
+					num_parents, flags,
+					reg, shift, width, mux_flags, lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s:%s failed to register clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	}
+}
+CLK_OF_DECLARE(mmp_clk_mux, "marvell,mmp-clk-mux",
+		of_mmp_clk_mux_setup);
+
+static void of_mmp_clk_general_gate_setup(struct device_node *np)
+{
+	struct clk_gate *gate;
+	void __iomem *reg;
+	u8 bit_idx, gate_flags;
+	unsigned long flags;
+	spinlock_t *lock;
+	const char *parent_name;
+	struct clk *clk;
+	unsigned int reg_phys;
+	int ret;
+
+	reg = of_mmp_clk_get_reg(np, 0, &reg_phys);
+	if (!reg)
+		return;
+
+	ret = of_mmp_clk_general_gate_dt_parse(np, &bit_idx, &gate_flags);
+	if (ret)
+		return;
+
+	ret = of_mmp_clk_get_flags(np, &flags);
+	if (ret)
+		return;
+
+	lock = of_mmp_clk_get_spinlock(np, reg_phys);
+	if (!lock)
+		return;
+
+	if (of_mmp_clk_is_composite(np)) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			pr_err("%s:%s failed to allocate clk\n",
+				__func__, np->name);
+			return;
+		}
+		gate->bit_idx = bit_idx;
+		gate->flags = gate_flags;
+		gate->reg = reg;
+		gate->lock = lock;
+		of_mmp_clk_composite_add_member(np, &gate->hw, &clk_gate_ops,
+					MMP_CLK_COMPOSITE_TYPE_GATE);
+	} else {
+		parent_name = of_clk_get_parent_name(np, 0);
+
+		clk = clk_register_gate(NULL, np->name, parent_name, flags,
+					reg, bit_idx, gate_flags, lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s:%s failed to register clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	}
+}
+CLK_OF_DECLARE(mmp_clk_general_gate, "marvell,mmp-clk-general-gate",
+		of_mmp_clk_general_gate_setup);
+
+static void of_mmp_clk_gate_setup(struct device_node *np)
+{
+	struct mmp_clk_gate *gate;
+	void __iomem *reg;
+	u32 mask, val_enable, val_disable;
+	unsigned int gate_flags;
+	unsigned long flags;
+	spinlock_t *lock;
+	const char *parent_name;
+	struct clk *clk;
+	unsigned int reg_phys;
+	int ret;
+
+	reg = of_mmp_clk_get_reg(np, 0, &reg_phys);
+	if (!reg)
+		return;
+
+	ret = of_mmp_clk_gate_dt_parse(np, &mask, &val_enable, &val_disable,
+					&gate_flags);
+	if (ret)
+		return;
+
+	ret = of_mmp_clk_get_flags(np, &flags);
+	if (ret)
+		return;
+
+	lock = of_mmp_clk_get_spinlock(np, reg_phys);
+	if (!lock)
+		return;
+
+	if (of_mmp_clk_is_composite(np)) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			pr_err("%s:%s failed to allocate clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		gate->flags = gate_flags;
+		gate->mask = mask;
+		gate->val_enable = val_enable;
+		gate->val_disable = val_disable;
+		gate->reg = reg;
+		gate->lock = lock;
+		of_mmp_clk_composite_add_member(np, &gate->hw,
+				&mmp_clk_gate_ops,
+				MMP_CLK_COMPOSITE_TYPE_GATE);
+	} else {
+		parent_name = of_clk_get_parent_name(np, 0);
+
+		clk = mmp_clk_register_gate(NULL, np->name, parent_name, flags,
+					reg, mask, val_enable, val_disable,
+					gate_flags, lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s:%s failed to register clk\n",
+				__func__, np->name);
+			return;
+		}
+
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	}
+}
+CLK_OF_DECLARE(mmp_clk_gate, "marvell,mmp-clk-gate",
+		of_mmp_clk_gate_setup);
+
+static void of_mmp_clk_factor_setup(struct device_node *np)
+{
+	void __iomem *reg;
+	struct mmp_clk_factor_masks *masks;
+	struct mmp_clk_factor_tbl *table;
+	unsigned int table_size;
+	unsigned long flags;
+	spinlock_t *lock;
+	const char *parent_name;
+	struct clk *clk;
+	unsigned int reg_phys;
+	int ret;
+
+	reg = of_mmp_clk_get_reg(np, 0, &reg_phys);
+	if (!reg)
+		return;
+
+	ret = of_mmp_clk_factor_dt_parse(np, &masks, &table, &table_size);
+	if (ret)
+		return;
+
+	ret = of_mmp_clk_get_flags(np, &flags);
+	if (ret)
+		return;
+
+	lock = of_mmp_clk_get_spinlock(np, reg_phys);
+	if (!lock)
+		return;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+
+	clk = mmp_clk_register_factor(np->name, parent_name, flags,
+					reg, masks, table, table_size,
+					lock);
+	if (IS_ERR(clk)) {
+		pr_err("%s:%s failed to register clk\n", __func__, np->name);
+		return;
+	}
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+}
+CLK_OF_DECLARE(mmp_clk_factor,
+		"marvell,mmp-clk-factor",
+		of_mmp_clk_factor_setup);
+
+void mmp_clk_of_init(void)
+{
+	struct device_node *next;
+
+	next = NULL;
+	do {
+		next = of_mmp_clk_master_init(next);
+	} while (next);
+}
-- 
1.8.3.2

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

* [PATCH 12/12] arm: mmp: support clock device tree for mmp platforms
  2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
                   ` (10 preceding siblings ...)
  2014-06-10  1:27 ` [PATCH 11/12] clk: mmp: add device tree support for clocks Chao Xie
@ 2014-06-10  1:27 ` Chao Xie
  11 siblings, 0 replies; 15+ messages in thread
From: Chao Xie @ 2014-06-10  1:27 UTC (permalink / raw)
  To: haojian.zhuang, mturquette, chao.xie, xiechao_mail,
	linux-arm-kernel, devicetree, linux-kernel

From: Chao Xie <chao.xie@marvell.com>

The platforms including pxa168/pxa910/mmp2.

After add clock device tree support. There is no need
to maintain mmp2-dt.c because it is same as mmp-dt.c now.
The file will be removed.

Compiling test for pxa168 because of lacking of platform.
The platform is too old.

Functonality test for pxa910 and mmp2.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 arch/arm/boot/dts/mmp2-clock.dtsi   | 575 ++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/mmp2.dtsi         |  11 +
 arch/arm/boot/dts/pxa168-clock.dtsi | 443 +++++++++++++++++++++++++++
 arch/arm/boot/dts/pxa168.dtsi       |  10 +
 arch/arm/boot/dts/pxa910-clock.dtsi | 388 ++++++++++++++++++++++++
 arch/arm/boot/dts/pxa910.dtsi       |  10 +
 arch/arm/mach-mmp/Kconfig           |   7 +-
 arch/arm/mach-mmp/Makefile          |   2 +-
 arch/arm/mach-mmp/common.h          |   1 +
 arch/arm/mach-mmp/mmp-dt.c          |  57 ++--
 arch/arm/mach-mmp/mmp2-dt.c         |  50 ----
 11 files changed, 1462 insertions(+), 92 deletions(-)
 create mode 100644 arch/arm/boot/dts/mmp2-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa168-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa910-clock.dtsi
 delete mode 100644 arch/arm/mach-mmp/mmp2-dt.c

diff --git a/arch/arm/boot/dts/mmp2-clock.dtsi b/arch/arm/boot/dts/mmp2-clock.dtsi
new file mode 100644
index 0000000..89f2279
--- /dev/null
+++ b/arch/arm/boot/dts/mmp2-clock.dtsi
@@ -0,0 +1,575 @@
+&soc_clocks {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	fixed_clocks: fixed_clocks {
+		compatible = "marvell,mmp-clk-master";
+		clk32: clk32 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+		vctcxo: vctcxo {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+		vctcxo_2: vctcxo_2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&vctcxo>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		vctcxo_4: vctcxo_4 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&vctcxo_2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		usb_pll: usb_pll {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <480000000>;
+		};
+		pll1: pll1 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <624000000>;
+		};
+		pll1_2: pll1_2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_4: pll1_4 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_8: pll1_8 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_4>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_16: pll1_16 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_8>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_20: pll1_20 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_4>;
+			clock-div = <5>;
+			clock-mult = <1>;
+		};
+		pll1_3: pll1_3 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		pll1_6: pll1_6 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_3>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		pll1_12: pll1_12 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_6>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll2: pll2 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <960000000>;
+		};
+		pll2_2: pll2_2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll2_4: pll2_4 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2_2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll2_8: pll2_8 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2_4>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll2_16: pll2_16 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2_8>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll2_20: pll2_20 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2_4>;
+			clock-div = <5>;
+			clock-mult = <1>;
+		};
+		pll2_3: pll2_3 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		pll2_6: pll2_6 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2_3>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		pll2_12: pll2_12 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll2_6>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+	};
+	mpmu_clocks: mpmu_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4050000 0x1000>;
+		uart_pll: uart_pll {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-factor";
+			clocks = <&pll1_4>;
+			marvell,reg-offset = <0 0x14>;
+			marvell,mmp-clk-factor-factor = <2>;
+			marvell,mmp-clk-factor-bits-den = <13 0>;
+			marvell,mmp-clk-factor-bits-num = <13 16>;
+			marvell,mmp-clk-factor-table = <14634 2165>,
+						       <3521 689>,
+						       <9679 5728>,
+						       <15859 9451>;
+		};
+	};
+	apbc_clocks: apbc_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4015000 0x1000>;
+		twsi0_clock: twsi0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x4>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		twsi1_clock: twsi1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x8>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		twsi2_clock: twsi2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0xc>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		twsi3_clock: twsi3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x10>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		twsi4_clock: twsi4_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x7c>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		twsi5_clock: twsi5_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x80>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		gpio_clock: gpio_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x38>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		kpc_clock: kpc_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&clk32>;
+			marvell,reg-offset = <0 0x18>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			marvell,mmp-clk-gate-need-delay;
+		};
+		rtc_clock: rtc_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&clk32>;
+			marvell,reg-offset = <0 0x0>;
+			marvell,mmp-clk-mask = <0x87 0x83 0x4>;
+			marvell,mmp-clk-gate-need-delay;
+		};
+		pwm0_clock: pwm0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x3c>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm1_clock: pwm1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x40>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm2_clock: pwm2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x44>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm3_clock: pwm3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x48>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		uart0_clock: uart0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart0_mux: uart0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&uart_pll &vctcxo>;
+				marvell,reg-offset = <0 0x2c>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart0_gate: uart0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x2c>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		uart1_clock: uart1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart1_mux: uart1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&uart_pll &vctcxo>;
+				marvell,reg-offset = <0 0x30>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart1_gate: uart1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x30>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		uart2_clock: uart2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart2_mux: uart2_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&uart_pll &vctcxo>;
+				marvell,reg-offset = <0 0x34>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart2_gate: uart2_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x34>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		uart3_clock: uart3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart3_mux: uart3_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&uart_pll &vctcxo>;
+				marvell,reg-offset = <0 0x88>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart3_gate: uart3_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x88>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+
+		ssp0_clock: ssp0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp0_mux: ssp0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&vctcxo_4 &vctcxo_2 &vctcxo &pll1_16>;
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp0_gate: ssp0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp1_clock: ssp1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp1_mux: ssp1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&vctcxo_4 &vctcxo_2 &vctcxo &pll1_16>;
+				marvell,reg-offset = <0 0x54>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp1_gate: ssp1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x54>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp2_clock: ssp2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp2_mux: ssp2_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&vctcxo_4 &vctcxo_2 &vctcxo &pll1_16>;
+				marvell,reg-offset = <0 0x58>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp2_gate: ssp2_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x58>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp3_clock: ssp3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp3_mux: ssp3_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&vctcxo_4 &vctcxo_2 &vctcxo &pll1_16>;
+				marvell,reg-offset = <0 0x5c>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp3_gate: ssp3_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x5c>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+	};
+	apmu_clocks: apmu_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4282800 0x1000>;
+		sdh_mix: sdh_mix {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-mix";
+			clocks = <&pll1_4 &pll2 &usb_pll &pll1>;
+			marvell,reg-offset = <0 0x54>;
+			marvell,mmp-clk-bits-mux = <2 8>;
+			marvell,mmp-clk-bits-div = <4 10>;
+			marvell,mmp-clk-div-one-based;
+		};
+		sdh0_clock: sdh0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&sdh_mix>;
+			marvell,reg-offset = <0 0x54>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		sdh1_clock: sdh1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&sdh_mix>;
+			marvell,reg-offset = <0 0x58>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		sdh2_clock: sdh2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&sdh_mix>;
+			marvell,reg-offset = <0 0xe8>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		sdh3_clock: sdh3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&sdh_mix>;
+			marvell,reg-offset = <0 0xec>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		usb_clock: usb_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			marvell,reg-offset = <0 0x5c>;
+			marvell,mmp-clk-mask = <0x9 0x9 0x0>;
+		};
+		disp0_mux: disp0_mux {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-mux";
+			marvell,reg-offset = <0 0x4c>;
+			clocks = <&pll1 &pll1_16 &pll2 &vctcxo>;
+			marvell,mmp-clk-bits-mux = <2 6>;
+		};
+		disp0_clock: disp0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			disp0_div: disp0_div {
+				compatible = "marvell,mmp-clk-div";
+				marvell,reg-offset = <0 0x4c>;
+				clocks = <&disp0_mux>;
+				marvell,mmp-clk-bits-div = <4 8>;
+				marvell,mmp-clk-div-one-based;
+			};
+			disp0_gate: disp0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4c>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		disp1_clock: disp1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			disp1_mix: disp1_mix {
+				compatible = "marvell,mmp-clk-mix";
+				marvell,reg-offset = <0 0x110>;
+				clocks = <&pll1 &pll1_16 &pll2 &vctcxo>;
+				marvell,mmp-clk-bits-mux = <2 6>;
+				marvell,mmp-clk-bits-div = <4 8>;
+				marvell,mmp-clk-div-one-based;
+			};
+			disp1_gate: disp1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x110>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		ccic_arbiter: ccic_arbiter {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-mask = <0x1800 0x1800 0x0>;
+		};
+		ccic0_mix: ccic0_mix {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-mux";
+			clocks = <&pll1_2 &pll1_16 &vctcxo>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-bits-mux = <2 6>;
+			marvell,mmp-clk-bits-div = <4 17>;
+			marvell,mmp-clk-div-one-based;
+		};
+		ccic0_clock: ccic0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&ccic0_mix>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		ccic0_phy_clock: ccic0_phy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&ccic0_mix>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-mask = <0x24 0x24 0x0>;
+		};
+		ccic0_sphy_clock: ccic0_sphy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ccic0_sphy_div: ccic0_sphy_div {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-div";
+				clocks = <&ccic0_mix>;
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-bits-div = <5 10>;
+			};
+			ccic0_sphy_gate: ccic0_sphy_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-mask = <0x300 0x300 0x0>;
+			};
+		};
+		ccic1_mix: ccic1_mix {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-mux";
+			clocks = <&pll1_2 &pll1_16 &vctcxo>;
+			marvell,reg-offset = <0 0xf4>;
+			marvell,mmp-clk-bits-mux = <2 6>;
+			marvell,mmp-clk-bits-div = <4 16>;
+			marvell,mmp-clk-div-one-based;
+		};
+		ccic1_clock: ccic1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&ccic1_mix>;
+			marvell,reg-offset = <0 0xf4>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		ccic1_phy_clock: ccic1_phy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&ccic1_mix>;
+			marvell,reg-offset = <0 0xf4>;
+			marvell,mmp-clk-mask = <0x24 0x24 0x0>;
+		};
+		ccic1_sphy_clock: ccic1_sphy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ccic1_sphy_div: ccic1_sphy_div {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-div";
+				clocks = <&ccic1_mix>;
+				marvell,reg-offset = <0 0xf4>;
+				marvell,mmp-clk-bits-div = <5 10>;
+			};
+			ccic1_sphy_gate: ccic1_sphy_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0xf4>;
+				marvell,mmp-clk-mask = <0x300 0x300 0x0>;
+			};
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index 4e8b08c..66bc8db 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -135,6 +135,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4030000 0x1000>;
 				interrupts = <27>;
+				clocks = <&uart0_clock>;
 				status = "disabled";
 			};
 
@@ -142,6 +143,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4017000 0x1000>;
 				interrupts = <28>;
+				clocks = <&uart1_clock>;
 				status = "disabled";
 			};
 
@@ -149,6 +151,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4018000 0x1000>;
 				interrupts = <24>;
+				clocks = <&uart2_clock>;
 				status = "disabled";
 			};
 
@@ -156,6 +159,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4016000 0x1000>;
 				interrupts = <46>;
+				clocks = <&uart3_clock>;
 				status = "disabled";
 			};
 
@@ -164,6 +168,7 @@
 				#address-cells = <1>;
 				#size-cells = <1>;
 				reg = <0xd4019000 0x1000>;
+				clocks = <&gpio_clock>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupts = <49>;
@@ -201,6 +206,7 @@
 				compatible = "mrvl,mmp-twsi";
 				reg = <0xd4011000 0x1000>;
 				interrupts = <7>;
+				clocks = <&twsi0_clock>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				mrvl,i2c-fast-mode;
@@ -211,6 +217,7 @@
 				compatible = "mrvl,mmp-twsi";
 				reg = <0xd4025000 0x1000>;
 				interrupts = <58>;
+				clocks = <&twsi1_clock>;
 				status = "disabled";
 			};
 
@@ -220,8 +227,12 @@
 				interrupts = <1 0>;
 				interrupt-names = "rtc 1Hz", "rtc alarm";
 				interrupt-parent = <&intcmux5>;
+				clocks = <&rtc_clock>;
 				status = "disabled";
 			};
 		};
+		soc_clocks: clocks{
+		};
 	};
 };
+/include/ "mmp2-clock.dtsi"
diff --git a/arch/arm/boot/dts/pxa168-clock.dtsi b/arch/arm/boot/dts/pxa168-clock.dtsi
new file mode 100644
index 0000000..8bd331e
--- /dev/null
+++ b/arch/arm/boot/dts/pxa168-clock.dtsi
@@ -0,0 +1,443 @@
+&soc_clocks {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	fixed_clocks: fixed_clocks {
+		compatible = "marvell,mmp-clk-master";
+		clk32: clk32 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+		vctcxo: vctcxo {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+		pll1: pll1 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <624000000>;
+		};
+		pll1_2: pll1_2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_4: pll1_4 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_8: pll1_8 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_4>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_16: pll1_16 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_8>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_6: pll1_6 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_2>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		pll1_12: pll1_12 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_6>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_24: pll1_24 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_12>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_48: pll1_48 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_24>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_96: pll1_96 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_48>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_13: pll1_13 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <13>;
+			clock-mult = <1>;
+		};
+		pll1_13_1_5: pll1_13_1_5 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_13>;
+			clock-div = <3>;
+			clock-mult = <2>;
+		};
+		pll1_2_1_5: pll1_2_1_5 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <3>;
+			clock-mult = <2>;
+		};
+		pll1_3_16: pll1_3_16 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <16>;
+			clock-mult = <3>;
+		};
+	};
+	mpmu_clocks: mpmu_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4050000 0x1000>;
+		uart_pll: uart_pll {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-factor";
+			clocks = <&pll1_4>;
+			marvell,reg-offset = <0 0x14>;
+			marvell,mmp-clk-factor-factor = <2>;
+			marvell,mmp-clk-factor-bits-den = <13 0>;
+			marvell,mmp-clk-factor-bits-num = <13 16>;
+			marvell,mmp-clk-factor-table = <8125 1536>;
+		};
+	};
+	apbc_clocks: apbc_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4015000 0x1000>;
+		twsi0_clock: twsi0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_13_1_5>;
+			marvell,reg-offset = <0 0x2c>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		twsi1_clock: twsi1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_13_1_5>;
+			marvell,reg-offset = <0 0x6c>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		gpio_clock: gpio_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x8>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		kpc_clock: kpc_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&clk32>;
+			marvell,reg-offset = <0 0x30>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			marvell,mmp-clk-gate-need-delay;
+		};
+		rtc_clock: rtc_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&clk32>;
+			marvell,reg-offset = <0 0x28>;
+			marvell,mmp-clk-mask = <0x87 0x83 0x4>;
+			marvell,mmp-clk-gate-need-delay;
+		};
+		pwm0_clock: pwm0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0xc>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm1_clock: pwm1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0x10>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm2_clock: pwm2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0x14>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm3_clock: pwm3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0x18>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		uart0_clock: uart0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart0_mux: uart0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_3_16 &uart_pll>;
+				marvell,reg-offset = <0 0x0>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart0_gate: uart0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x0>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		uart1_clock: uart1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart1_mux: uart1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_3_16 &uart_pll>;
+				marvell,reg-offset = <0 0x4>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart1_gate: uart1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		uart2_clock: uart2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart2_mux: uart2_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_3_16 &uart_pll>;
+				marvell,reg-offset = <0 0x70>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart2_gate: uart2_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		ssp0_clock: ssp0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp0_mux: ssp0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x81c>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp0_gate: ssp0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x81c>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp1_clock: ssp1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp1_mux: ssp1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x820>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp1_gate: ssp1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x820>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp2_clock: ssp2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp2_mux: ssp2_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x84c>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp2_gate: ssp2_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x84c>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp3_clock: ssp3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp3_mux: ssp3_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x858>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp3_gate: ssp3_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x858>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp4_clock: ssp4_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp4_mux: ssp4_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x85c>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp4_gate: ssp4_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x85c>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+	};
+	apmu_clocks: apmu_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4282800 0x1000>;
+		dfc_clock: dfc_clock {
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_4>;
+			marvell,reg-offset = <0 0x60>;
+			marvell,mmp-clk-mask = <0x19b 0x19b 0x0>;
+		};
+		sdh0_clock: sdh0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			sdh0_mux: sdh0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_12 &pll1_13>;
+				marvell,reg-offset = <0 0x54>;
+				marvell,mmp-clk-bits-mux = <1 6>;
+			};
+			sdh0_gate: sdh0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x54>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		sdh1_clock: sdh1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			sdh1_mux: sdh1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_12 &pll1_13>;
+				marvell,reg-offset = <0 0x58>;
+				marvell,mmp-clk-bits-mux = <1 6>;
+			};
+			sdh1_gate: sdh1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x58>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		usb_clock: usb_clock {
+			compatible = "marvell,mmp-clk-gate";
+			marvell,reg-offset = <0 0x5c>;
+			marvell,mmp-clk-mask = <0x9 0x9 0x0>;
+		};
+		sph_clock: sph_clock {
+			compatible = "marvell,mmp-clk-gate";
+			marvell,reg-offset = <0 0x5c>;
+			marvell,mmp-clk-mask = <0x12 0x12 0x0>;
+		};
+		disp0_clock: disp0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			disp0_mux: disp0_mux {
+				compatible = "marvell,mmp-clk-mux";
+				marvell,reg-offset = <0 0x4c>;
+				clocks = <&pll1_2 &pll1_12>;
+				marvell,mmp-clk-bits-mux = <1 6>;
+			};
+			disp0_gate: disp0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4c>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		disp0_h_clock: disp0_h_clock {
+			compatible = "marvell,mmp-clk-gate";
+			marvell,reg-offset = <0 0x4c>;
+			marvell,mmp-clk-mask = <0x24 0x24 0x0>;
+		};
+		ccic0_mux: ccic0_mux {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-mux";
+			clocks = <&pll1_2 &pll1_12>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-bits-mux = <1 6>;
+		};
+		ccic0_clock: ccic0_clock {
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&ccic0_mux>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		ccic0_phy_clock: ccic0_phy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-composite";
+			ccic0_phy_mux: ccic0_phy_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_2 &pll1_12>;
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-bits-mux = <1 7>;
+			};
+			ccic0_phy_gate: ccic0_phy_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-mask = <0x24 0x24 0x0>;
+			};
+		};
+		ccic0_sphy_clock: ccic0_sphy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-composite";
+			ccic0_sphy_div: ccic0_sphy_div {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-div";
+				clocks = <&ccic0_mux>;
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-bits-div = <5 10>;
+			};
+			ccic0_sphy_gate: ccic0_sphy_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-mask = <0x300 0x300 0x0>;
+			};
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index 975dad2..d16aa1b 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -59,6 +59,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4017000 0x1000>;
 				interrupts = <27>;
+				clocks = <&uart0_clock>;
 				status = "disabled";
 			};
 
@@ -66,6 +67,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4018000 0x1000>;
 				interrupts = <28>;
+				clocks = <&uart1_clock>;
 				status = "disabled";
 			};
 
@@ -73,6 +75,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4026000 0x1000>;
 				interrupts = <29>;
+				clocks = <&uart2_clock>;
 				status = "disabled";
 			};
 
@@ -81,6 +84,7 @@
 				#address-cells = <1>;
 				#size-cells = <1>;
 				reg = <0xd4019000 0x1000>;
+				clocks = <&gpio_clock>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupts = <49>;
@@ -110,6 +114,7 @@
 				compatible = "mrvl,mmp-twsi";
 				reg = <0xd4011000 0x1000>;
 				interrupts = <7>;
+				clocks = <&twsi0_clock>;
 				mrvl,i2c-fast-mode;
 				status = "disabled";
 			};
@@ -118,6 +123,7 @@
 				compatible = "mrvl,mmp-twsi";
 				reg = <0xd4025000 0x1000>;
 				interrupts = <58>;
+				clocks = <&twsi1_clock>;
 				status = "disabled";
 			};
 
@@ -126,8 +132,12 @@
 				reg = <0xd4010000 0x1000>;
 				interrupts = <5 6>;
 				interrupt-names = "rtc 1Hz", "rtc alarm";
+				clocks = <&rtc_clock>;
 				status = "disabled";
 			};
 		};
+		soc_clocks: clocks{
+		};
 	};
 };
+/include/ "pxa168-clock.dtsi"
diff --git a/arch/arm/boot/dts/pxa910-clock.dtsi b/arch/arm/boot/dts/pxa910-clock.dtsi
new file mode 100644
index 0000000..e9c58e2
--- /dev/null
+++ b/arch/arm/boot/dts/pxa910-clock.dtsi
@@ -0,0 +1,388 @@
+&soc_clocks {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	fixed_clocks: fixed_clocks {
+		compatible = "marvell,mmp-clk-master";
+		clk32: clk32 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+		vctcxo: vctcxo {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+		pll1: pll1 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <624000000>;
+		};
+		pll1_2: pll1_2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_4: pll1_4 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_8: pll1_8 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_4>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_16: pll1_16 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_8>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_6: pll1_6 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_2>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		pll1_12: pll1_12 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_6>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_24: pll1_24 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_12>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_48: pll1_48 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_24>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_96: pll1_96 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_48>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		pll1_13: pll1_13 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <13>;
+			clock-mult = <1>;
+		};
+		pll1_13_1_5: pll1_13_1_5 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_13>;
+			clock-div = <3>;
+			clock-mult = <2>;
+		};
+		pll1_2_1_5: pll1_2_1_5 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <3>;
+			clock-mult = <2>;
+		};
+		pll1_3_16: pll1_3_16 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1>;
+			clock-div = <16>;
+			clock-mult = <3>;
+		};
+	};
+	mpmu_clocks: mpmu_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4050000 0x1000>;
+		uart_pll: uart_pll {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-factor";
+			clocks = <&pll1_4>;
+			marvell,reg-offset = <0 0x14>;
+			marvell,mmp-clk-factor-factor = <2>;
+			marvell,mmp-clk-factor-bits-den = <13 0>;
+			marvell,mmp-clk-factor-bits-num = <13 16>;
+			marvell,mmp-clk-factor-table = <8125 1536>;
+		};
+	};
+	apbc_clocks: apbc_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4015000 0x1000>;
+		twsi0_clock: twsi0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_13_1_5>;
+			marvell,reg-offset = <0 0x2c>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		gpio_clock: gpio_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&vctcxo>;
+			marvell,reg-offset = <0 0x8>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		kpc_clock: kpc_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&clk32>;
+			marvell,reg-offset = <0 0x30>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			marvell,mmp-clk-gate-need-delay;
+		};
+		rtc_clock: rtc_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&clk32>;
+			marvell,reg-offset = <0 0x28>;
+			marvell,mmp-clk-mask = <0x87 0x83 0x4>;
+			marvell,mmp-clk-gate-need-delay;
+		};
+		pwm0_clock: pwm0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0xc>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm1_clock: pwm1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0x10>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm2_clock: pwm2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0x14>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		pwm3_clock: pwm3_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_48>;
+			marvell,reg-offset = <0 0x18>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+		uart0_clock: uart0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart0_mux: uart0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_3_16 &uart_pll>;
+				marvell,reg-offset = <0 0x0>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart0_gate: uart0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x0>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		uart1_clock: uart1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart1_mux: uart1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_3_16 &uart_pll>;
+				marvell,reg-offset = <0 0x4>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart1_gate: uart1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		ssp0_clock: ssp0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp0_mux: ssp0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x81c>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp0_gate: ssp0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x81c>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+		ssp1_clock: ssp1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ssp1_mux: ssp1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_96 &pll1_48 &pll1_24 &pll1_12>;
+				marvell,reg-offset = <0 0x820>;
+				marvell,mmp-clk-bits-mux = <3 4>;
+			};
+			ssp1_gate: ssp1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x820>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+			};
+		};
+	};
+	apbcp_clock: apbcp_clock {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd403b000 0x1000>;
+		uart2_clock: uart2_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			uart2_mux: uart2_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_3_16 &uart_pll>;
+				marvell,reg-offset = <0 0x70>;
+				marvell,mmp-clk-bits-mux = <1 4>;
+			};
+			uart2_gate: uart2_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4>;
+				marvell,mmp-clk-mask = <0x7 0x3 0x0>;
+			};
+		};
+		twsi1_clock: twsi1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&pll1_13_1_5>;
+			marvell,reg-offset = <0 0x28>;
+			marvell,mmp-clk-mask = <0x7 0x3 0x4>;
+		};
+	};
+	apmu_clocks: apmu_clocks {
+		compatible = "marvell,mmp-clk-master";
+		reg = <0xd4282800 0x1000>;
+		sdh0_clock: sdh0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			sdh0_mux: sdh0_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_12 &pll1_13>;
+				marvell,reg-offset = <0 0x54>;
+				marvell,mmp-clk-bits-mux = <1 6>;
+			};
+			sdh0_gate: sdh0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x54>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		sdh1_clock: sdh1_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			sdh1_mux: sdh1_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_12 &pll1_13>;
+				marvell,reg-offset = <0 0x58>;
+				marvell,mmp-clk-bits-mux = <1 6>;
+			};
+			sdh1_gate: sdh1_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x58>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		usb_clock: usb_clock {
+			compatible = "marvell,mmp-clk-gate";
+			marvell,reg-offset = <0 0x5c>;
+			marvell,mmp-clk-mask = <0x9 0x9 0x0>;
+		};
+		sph_clock: sph_clock {
+			compatible = "marvell,mmp-clk-gate";
+			marvell,reg-offset = <0 0x5c>;
+			marvell,mmp-clk-mask = <0x12 0x12 0x0>;
+		};
+		disp0_clock: disp0_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			disp0_mux: disp0_mux {
+				compatible = "marvell,mmp-clk-mux";
+				marvell,reg-offset = <0 0x4c>;
+				clocks = <&pll1_2 &pll1_12>;
+				marvell,mmp-clk-bits-mux = <1 6>;
+			};
+			disp0_gate: disp0_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x4c>;
+				marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+			};
+		};
+		ccic0_mux: ccic0_mux {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-mux";
+			clocks = <&pll1_2 &pll1_12>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-bits-mux = <1 6>;
+		};
+		ccic0_clock: ccic0_clock {
+			compatible = "marvell,mmp-clk-gate";
+			clocks = <&ccic0_mux>;
+			marvell,reg-offset = <0 0x50>;
+			marvell,mmp-clk-mask = <0x1b 0x1b 0x0>;
+		};
+		ccic0_phy_clock: ccic0_phy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ccic0_phy_mux: ccic0_phy_mux {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-mux";
+				clocks = <&pll1_2 &pll1_12>;
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-bits-mux = <1 7>;
+			};
+			ccic0_phy_gate: ccic0_phy_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-mask = <0x24 0x24 0x0>;
+			};
+		};
+		ccic0_sphy_clock: ccic0_sphy_clock {
+			#clock-cells = <0>;
+			compatible = "marvell,mmp-clk-general-composite";
+			ccic0_sphy_div: ccic0_sphy_div {
+				#clock-cells = <0>;
+				compatible = "marvell,mmp-clk-div";
+				clocks = <&ccic0_mux>;
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-bits-div = <5 10>;
+			};
+			ccic0_sphy_gate: ccic0_sphy_gate {
+				compatible = "marvell,mmp-clk-gate";
+				marvell,reg-offset = <0 0x50>;
+				marvell,mmp-clk-mask = <0x300 0x300 0x0>;
+			};
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
index 0247c62..cc06c5d 100644
--- a/arch/arm/boot/dts/pxa910.dtsi
+++ b/arch/arm/boot/dts/pxa910.dtsi
@@ -71,6 +71,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4017000 0x1000>;
 				interrupts = <27>;
+				clocks = <&uart0_clock>;
 				status = "disabled";
 			};
 
@@ -78,6 +79,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4018000 0x1000>;
 				interrupts = <28>;
+				clocks = <&uart1_clock>;
 				status = "disabled";
 			};
 
@@ -85,6 +87,7 @@
 				compatible = "mrvl,mmp-uart";
 				reg = <0xd4036000 0x1000>;
 				interrupts = <59>;
+				clocks = <&uart2_clock>;
 				status = "disabled";
 			};
 
@@ -93,6 +96,7 @@
 				#address-cells = <1>;
 				#size-cells = <1>;
 				reg = <0xd4019000 0x1000>;
+				clocks = <&gpio_clock>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupts = <49>;
@@ -124,6 +128,7 @@
 				#size-cells = <0>;
 				reg = <0xd4011000 0x1000>;
 				interrupts = <7>;
+				clocks = <&twsi0_clock>;
 				mrvl,i2c-fast-mode;
 				status = "disabled";
 			};
@@ -134,6 +139,7 @@
 				#size-cells = <0>;
 				reg = <0xd4037000 0x1000>;
 				interrupts = <54>;
+				clocks = <&twsi1_clock>;
 				status = "disabled";
 			};
 
@@ -142,8 +148,12 @@
 				reg = <0xd4010000 0x1000>;
 				interrupts = <5 6>;
 				interrupt-names = "rtc 1Hz", "rtc alarm";
+				clocks = <&rtc_clock>;
 				status = "disabled";
 			};
 		};
+		soc_clocks: clocks{
+		};
 	};
 };
+/include/ "pxa910-clock.dtsi"
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index ebdba87..ce15826 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -86,8 +86,8 @@ config MACH_GPLUGD
 
 config MACH_MMP_DT
 	bool "Support MMP (ARMv5) platforms from device tree"
-	select CPU_PXA168
-	select CPU_PXA910
+	select COMMON_CLK
+	select CPU_MOHAWK
 	select USE_OF
 	select PINCTRL
 	select PINCTRL_SINGLE
@@ -99,7 +99,8 @@ config MACH_MMP_DT
 config MACH_MMP2_DT
 	bool "Support MMP2 (ARMv7) platforms from device tree"
 	depends on !CPU_MOHAWK
-	select CPU_MMP2
+	select COMMON_CLK
+	select CPU_PJ4
 	select USE_OF
 	select PINCTRL
 	select PINCTRL_SINGLE
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 98f0f63..ab54ff3 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -31,6 +31,6 @@ obj-$(CONFIG_MACH_BROWNSTONE)	+= brownstone.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_MMP_DT)	+= mmp-dt.o
-obj-$(CONFIG_MACH_MMP2_DT)	+= mmp2-dt.o
+obj-$(CONFIG_MACH_MMP2_DT)	+= mmp-dt.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
 obj-$(CONFIG_MACH_GPLUGD)	+= gplugd.o
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index cf445ba..9dcf19c 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -8,3 +8,4 @@ extern void mmp_restart(enum reboot_mode, const char *);
 extern void __init pxa168_clk_init(void);
 extern void __init pxa910_clk_init(void);
 extern void __init mmp2_clk_init(void);
+extern void mmp_clk_of_init(void);
diff --git a/arch/arm/mach-mmp/mmp-dt.c b/arch/arm/mach-mmp/mmp-dt.c
index cca529c..714735e 100644
--- a/arch/arm/mach-mmp/mmp-dt.c
+++ b/arch/arm/mach-mmp/mmp-dt.c
@@ -13,61 +13,42 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
+#include <asm/hardware/cache-tauros2.h>
 
 #include "common.h"
 
 extern void __init mmp_dt_init_timer(void);
 
-static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4026000, "pxa2xx-uart.2", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4025000, "pxa2xx-i2c.1", NULL),
-	OF_DEV_AUXDATA("marvell,mmp-gpio", 0xd4019000, "mmp-gpio", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
-	{}
-};
-
-static const struct of_dev_auxdata pxa910_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4036000, "pxa2xx-uart.2", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4037000, "pxa2xx-i2c.1", NULL),
-	OF_DEV_AUXDATA("marvell,mmp-gpio", 0xd4019000, "mmp-gpio", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
-	{}
-};
-
-static void __init pxa168_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     pxa168_auxdata_lookup, NULL);
-}
-
-static void __init pxa910_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     pxa910_auxdata_lookup, NULL);
-}
-
 static const char *mmp_dt_board_compat[] __initdata = {
 	"mrvl,pxa168-aspenite",
 	"mrvl,pxa910-dkb",
+	"mrvl,mmp2-brownstone",
 	NULL,
 };
 
+void __init mmp_init_timer(void)
+{
+#ifdef CONFIG_CACHE_TAUROS2
+	tauros2_init(0);
+#endif
+	mmp_clk_of_init();
+	mmp_dt_init_timer();
+}
+
 DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
 	.map_io		= mmp_map_io,
-	.init_time	= mmp_dt_init_timer,
-	.init_machine	= pxa168_dt_init,
+	.init_time	= mmp_init_timer,
 	.dt_compat	= mmp_dt_board_compat,
 MACHINE_END
 
 DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)")
 	.map_io		= mmp_map_io,
-	.init_time	= mmp_dt_init_timer,
-	.init_machine	= pxa910_dt_init,
+	.init_time	= mmp_init_timer,
+	.dt_compat	= mmp_dt_board_compat,
+MACHINE_END
+
+DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
+	.map_io		= mmp_map_io,
+	.init_time	= mmp_init_timer,
 	.dt_compat	= mmp_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/mmp2-dt.c b/arch/arm/mach-mmp/mmp2-dt.c
deleted file mode 100644
index 023cb45..0000000
--- a/arch/arm/mach-mmp/mmp2-dt.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  linux/arch/arm/mach-mmp/mmp2-dt.c
- *
- *  Copyright (C) 2012 Marvell Technology Group Ltd.
- *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  publishhed by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/irqchip.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-
-extern void __init mmp_dt_init_timer(void);
-
-static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.2", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4016000, "pxa2xx-uart.3", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4025000, "pxa2xx-i2c.1", NULL),
-	OF_DEV_AUXDATA("marvell,mmp-gpio", 0xd4019000, "mmp2-gpio", NULL),
-	OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
-	{}
-};
-
-static void __init mmp2_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     mmp2_auxdata_lookup, NULL);
-}
-
-static const char *mmp2_dt_board_compat[] __initdata = {
-	"mrvl,mmp2-brownstone",
-	NULL,
-};
-
-DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
-	.map_io		= mmp_map_io,
-	.init_time	= mmp_dt_init_timer,
-	.init_machine	= mmp2_dt_init,
-	.dt_compat	= mmp2_dt_board_compat,
-MACHINE_END
-- 
1.8.3.2

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

* [PATCH 00/12] clk: mmp: clock device tree support
@ 2014-08-26  4:38 Chao Xie
       [not found] ` <1409027904-21859-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Chao Xie @ 2014-08-26  4:38 UTC (permalink / raw)
  To: haojian.zhuang-Re5JQEeQqe8AvxtiuMwx3w,
	haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	chao.xie-eYqpPyKDWXRBDgjK7y7TUQ, xiechao_mail-9Onoh4P/yGk,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

From: Chao Xie <chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>

The patch set focuses at support device tree for clock.

The first part of the patches
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h It enhances the clk-frac.

The second part of the patches
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock

The third part of the patches
  clk: mmp: add basic support functions for DT support
  clk: mmp: add pxa168 DT support for clock driver
  clk: mmp: add pxa910 DT support for clock driver
  clk: mmp: add mmp2 DT support for clock driver
It add the device tree support for pxa168, pxa910 and mmp2.

The final part of the patches
  arm: mmp: Make all the dts file to be compiled by Makefile
  arm: mmp: Make use of the DT supported clock
It changes the mmp platform to use device tree to parse the clocks.

Chao Xie (12):
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add basic support functions for DT support
  clk: mmp: add pxa168 DT support for clock driver
  clk: mmp: add pxa910 DT support for clock driver
  clk: mmp: add mmp2 DT support for clock driver
  arm: mmp: Make all the dts file to be compiled by Makefile
  arm: mmp: Make use of the DT supported clock

 .../bindings/clock/marvell-mmp2-clock.txt          |  20 +
 .../bindings/clock/marvell-pxa168-clock.txt        |  20 +
 .../bindings/clock/marvell-pxa910-clock.txt        |  20 +
 arch/arm/boot/dts/Makefile                         |   3 +
 arch/arm/boot/dts/mmp2-brownstone.dts              |   2 +-
 arch/arm/boot/dts/mmp2.dtsi                        |  20 +-
 arch/arm/boot/dts/pxa168-aspenite.dts              |   2 +-
 arch/arm/boot/dts/pxa168.dtsi                      |  19 +-
 arch/arm/boot/dts/pxa910-dkb.dts                   |   2 +-
 arch/arm/boot/dts/pxa910.dtsi                      |  20 +-
 arch/arm/mach-mmp/Kconfig                          |  10 +-
 arch/arm/mach-mmp/mmp-dt.c                         |  57 +--
 arch/arm/mach-mmp/mmp2-dt.c                        |  26 +-
 drivers/clk/mmp/Makefile                           |   5 +-
 drivers/clk/mmp/clk-frac.c                         |  74 ++-
 drivers/clk/mmp/clk-gate.c                         | 133 ++++++
 drivers/clk/mmp/clk-mix.c                          | 513 +++++++++++++++++++++
 drivers/clk/mmp/clk-mmp2.c                         |   6 +-
 drivers/clk/mmp/clk-of-mmp2.c                      | 307 ++++++++++++
 drivers/clk/mmp/clk-of-pxa168.c                    | 251 ++++++++++
 drivers/clk/mmp/clk-of-pxa910.c                    | 260 +++++++++++
 drivers/clk/mmp/clk-pxa168.c                       |   6 +-
 drivers/clk/mmp/clk-pxa910.c                       |   6 +-
 drivers/clk/mmp/clk.c                              | 192 ++++++++
 drivers/clk/mmp/clk.h                              | 226 ++++++++-
 include/dt-bindings/clock/marvell-mmp2.h           |  74 +++
 include/dt-bindings/clock/marvell-pxa168.h         |  57 +++
 include/dt-bindings/clock/marvell-pxa910.h         |  54 +++
 28 files changed, 2280 insertions(+), 105 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt
 create mode 100644 drivers/clk/mmp/clk-gate.c
 create mode 100644 drivers/clk/mmp/clk-mix.c
 create mode 100644 drivers/clk/mmp/clk-of-mmp2.c
 create mode 100644 drivers/clk/mmp/clk-of-pxa168.c
 create mode 100644 drivers/clk/mmp/clk-of-pxa910.c
 create mode 100644 drivers/clk/mmp/clk.c
 create mode 100644 include/dt-bindings/clock/marvell-mmp2.h
 create mode 100644 include/dt-bindings/clock/marvell-pxa168.h
 create mode 100644 include/dt-bindings/clock/marvell-pxa910.h

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 00/12] clk: mmp: clock device tree support
       [not found] ` <1409027904-21859-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
@ 2014-08-26  4:55   ` Haojian Zhuang
  0 siblings, 0 replies; 15+ messages in thread
From: Haojian Zhuang @ 2014-08-26  4:55 UTC (permalink / raw)
  To: Chao Xie
  Cc: Haojian Zhuang, Mike Turquette, Chao Xie,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

On 26 August 2014 12:38, Chao Xie <chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org> wrote:
> From: Chao Xie <chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
>
> The patch set focuses at support device tree for clock.
>
> The first part of the patches
>   clk: mmp: add prefix "mmp" for structures defined for clk-frac
>   clk: mmp: add spin lock for clk-frac
>   clk: mmp: add init callback for clk-frac
>   clk: mmp: move definiton of mmp_clk_frac to clk.h It enhances the clk-frac.
>
> The second part of the patches
>   clk: mmp: add clock type mix
>   clk: mmp: add mmp private gate clock
>
> The third part of the patches
>   clk: mmp: add basic support functions for DT support
>   clk: mmp: add pxa168 DT support for clock driver
>   clk: mmp: add pxa910 DT support for clock driver
>   clk: mmp: add mmp2 DT support for clock driver
> It add the device tree support for pxa168, pxa910 and mmp2.
>
> The final part of the patches
>   arm: mmp: Make all the dts file to be compiled by Makefile
>   arm: mmp: Make use of the DT supported clock
> It changes the mmp platform to use device tree to parse the clocks.
>
> Chao Xie (12):
>   clk: mmp: add prefix "mmp" for structures defined for clk-frac
>   clk: mmp: add spin lock for clk-frac
>   clk: mmp: add init callback for clk-frac
>   clk: mmp: move definiton of mmp_clk_frac to clk.h
>   clk: mmp: add clock type mix
>   clk: mmp: add mmp private gate clock
>   clk: mmp: add basic support functions for DT support
>   clk: mmp: add pxa168 DT support for clock driver
>   clk: mmp: add pxa910 DT support for clock driver
>   clk: mmp: add mmp2 DT support for clock driver
>   arm: mmp: Make all the dts file to be compiled by Makefile
>   arm: mmp: Make use of the DT supported clock
>
>  .../bindings/clock/marvell-mmp2-clock.txt          |  20 +
>  .../bindings/clock/marvell-pxa168-clock.txt        |  20 +
>  .../bindings/clock/marvell-pxa910-clock.txt        |  20 +
>  arch/arm/boot/dts/Makefile                         |   3 +
>  arch/arm/boot/dts/mmp2-brownstone.dts              |   2 +-
>  arch/arm/boot/dts/mmp2.dtsi                        |  20 +-
>  arch/arm/boot/dts/pxa168-aspenite.dts              |   2 +-
>  arch/arm/boot/dts/pxa168.dtsi                      |  19 +-
>  arch/arm/boot/dts/pxa910-dkb.dts                   |   2 +-
>  arch/arm/boot/dts/pxa910.dtsi                      |  20 +-
>  arch/arm/mach-mmp/Kconfig                          |  10 +-
>  arch/arm/mach-mmp/mmp-dt.c                         |  57 +--
>  arch/arm/mach-mmp/mmp2-dt.c                        |  26 +-
>  drivers/clk/mmp/Makefile                           |   5 +-
>  drivers/clk/mmp/clk-frac.c                         |  74 ++-
>  drivers/clk/mmp/clk-gate.c                         | 133 ++++++
>  drivers/clk/mmp/clk-mix.c                          | 513 +++++++++++++++++++++
>  drivers/clk/mmp/clk-mmp2.c                         |   6 +-
>  drivers/clk/mmp/clk-of-mmp2.c                      | 307 ++++++++++++
>  drivers/clk/mmp/clk-of-pxa168.c                    | 251 ++++++++++
>  drivers/clk/mmp/clk-of-pxa910.c                    | 260 +++++++++++
>  drivers/clk/mmp/clk-pxa168.c                       |   6 +-
>  drivers/clk/mmp/clk-pxa910.c                       |   6 +-
>  drivers/clk/mmp/clk.c                              | 192 ++++++++
>  drivers/clk/mmp/clk.h                              | 226 ++++++++-
>  include/dt-bindings/clock/marvell-mmp2.h           |  74 +++
>  include/dt-bindings/clock/marvell-pxa168.h         |  57 +++
>  include/dt-bindings/clock/marvell-pxa910.h         |  54 +++
>  28 files changed, 2280 insertions(+), 105 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt
>  create mode 100644 drivers/clk/mmp/clk-gate.c
>  create mode 100644 drivers/clk/mmp/clk-mix.c
>  create mode 100644 drivers/clk/mmp/clk-of-mmp2.c
>  create mode 100644 drivers/clk/mmp/clk-of-pxa168.c
>  create mode 100644 drivers/clk/mmp/clk-of-pxa910.c
>  create mode 100644 drivers/clk/mmp/clk.c
>  create mode 100644 include/dt-bindings/clock/marvell-mmp2.h
>  create mode 100644 include/dt-bindings/clock/marvell-pxa168.h
>  create mode 100644 include/dt-bindings/clock/marvell-pxa910.h
>
> --
> 1.8.3.2
>

Hi Mike,

I think that these clock patches are ready to merge. I want to go
through arm-soc tree since chao will also move timer into clock source
directory. Those patches will be depend on these clock patches.

Could you help to give your Ack on these patches?

Best Regards
Haojian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2014-08-26  4:55 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
2014-06-10  1:27 ` [PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac Chao Xie
2014-06-10  1:27 ` [PATCH 02/12] clk: mmp: add spin lock " Chao Xie
     [not found] ` <1402363668-25806-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2014-06-10  1:27   ` [PATCH 03/12] clk: mmp: add init callback " Chao Xie
2014-06-10  1:27 ` [PATCH 04/12] clk: mmp: move definiton of mmp_clk_frac to clk.h Chao Xie
2014-06-10  1:27 ` [PATCH 05/12] clk: mmp: add clock type mix Chao Xie
2014-06-10  1:27 ` [PATCH 06/12] clk: mmp: add mmp private gate clock Chao Xie
2014-06-10  1:27 ` [PATCH 07/12] clk: mmp: add clock type composite for mix Chao Xie
2014-06-10  1:27 ` [PATCH 08/12] clk: mmp: add clock type master Chao Xie
2014-06-10  1:27 ` [PATCH 09/12] clk: mmp: add spin lock automatic detection from device tree Chao Xie
2014-06-10  1:27 ` [PATCH 10/12] clk: mmp: add device tree support for composite type clock Chao Xie
2014-06-10  1:27 ` [PATCH 11/12] clk: mmp: add device tree support for clocks Chao Xie
2014-06-10  1:27 ` [PATCH 12/12] arm: mmp: support clock device tree for mmp platforms Chao Xie
  -- strict thread matches above, loose matches on Subject: below --
2014-08-26  4:38 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
     [not found] ` <1409027904-21859-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2014-08-26  4:55   ` Haojian Zhuang

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