linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/14] add hisilicon soc support
@ 2013-03-12 17:08 Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 01/14] clocksource: move sp timer driver Haojian Zhuang
                   ` (13 more replies)
  0 siblings, 14 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Changelog:
v2:
   1. Rename mach-hs to mach-hi3xxx.
   2. Remove CONFIG_MACH_HS_DT.
   3. Move sp804 dual timer driver into drivers/clocksource.
   4. Make sp804 driver to support DT. Append CLOCKSOURCE_OF_DECLARE() in sp804 driver.
   5. Update hisilicon,hi3620-clkgate & hisilicon,hi3620-clkrst property in clk-hi3xxx driver.

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

* [PATCH v2 01/14] clocksource: move sp timer driver
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 18:11   ` Arnd Bergmann
  2013-03-12 19:08   ` Russell King - ARM Linux
  2013-03-12 17:08 ` [PATCH v2 02/14] clocksource: sp804: add device tree support Haojian Zhuang
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Move ARM SP804 timer driver from arch/arm directory into
drivers/clocksource directory.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig                          |    5 -
 arch/arm/common/Makefile                  |    1 -
 arch/arm/common/timer-sp.c                |  191 -----------------------------
 arch/arm/include/asm/hardware/arm_timer.h |   35 ------
 arch/arm/include/asm/hardware/timer-sp.h  |   15 ---
 arch/arm/mach-highbank/highbank.c         |    4 +-
 arch/arm/mach-integrator/integrator_ap.c  |    2 +-
 arch/arm/mach-integrator/integrator_cp.c  |    4 +-
 arch/arm/mach-realview/core.c             |    4 +-
 arch/arm/mach-versatile/core.c            |    4 +-
 arch/arm/mach-vexpress/ct-ca9x4.c         |    5 +-
 arch/arm/mach-vexpress/v2m.c              |    4 +-
 drivers/clocksource/Kconfig               |    5 +
 drivers/clocksource/Makefile              |    1 +
 drivers/clocksource/timer-sp.c            |  191 +++++++++++++++++++++++++++++
 include/clocksource/arm_timer.h           |   35 ++++++
 include/clocksource/timer-sp.h            |   19 +++
 17 files changed, 264 insertions(+), 261 deletions(-)
 delete mode 100644 arch/arm/common/timer-sp.c
 delete mode 100644 arch/arm/include/asm/hardware/arm_timer.h
 delete mode 100644 arch/arm/include/asm/hardware/timer-sp.h
 create mode 100644 drivers/clocksource/timer-sp.c
 create mode 100644 include/clocksource/arm_timer.h
 create mode 100644 include/clocksource/timer-sp.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2363926..10d7e2c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1177,11 +1177,6 @@ config PLAT_PXA
 config PLAT_VERSATILE
 	bool
 
-config ARM_TIMER_SP804
-	bool
-	select CLKSRC_MMIO
-	select HAVE_SCHED_CLOCK
-
 source arch/arm/mm/Kconfig
 
 config ARM_NR_BANKS
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 45f7eae..a4e49e7 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -12,4 +12,3 @@ obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
 obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
-obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
deleted file mode 100644
index 9d2d3ba..0000000
--- a/arch/arm/common/timer-sp.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- *  linux/arch/arm/common/timer-sp.c
- *
- *  Copyright (C) 1999 - 2003 ARM Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/clk.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/sched_clock.h>
-#include <asm/hardware/arm_timer.h>
-
-static long __init sp804_get_clock_rate(const char *name)
-{
-	struct clk *clk;
-	long rate;
-	int err;
-
-	clk = clk_get_sys("sp804", name);
-	if (IS_ERR(clk)) {
-		pr_err("sp804: %s clock not found: %d\n", name,
-			(int)PTR_ERR(clk));
-		return PTR_ERR(clk);
-	}
-
-	err = clk_prepare(clk);
-	if (err) {
-		pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
-		clk_put(clk);
-		return err;
-	}
-
-	err = clk_enable(clk);
-	if (err) {
-		pr_err("sp804: %s clock failed to enable: %d\n", name, err);
-		clk_unprepare(clk);
-		clk_put(clk);
-		return err;
-	}
-
-	rate = clk_get_rate(clk);
-	if (rate < 0) {
-		pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
-		clk_disable(clk);
-		clk_unprepare(clk);
-		clk_put(clk);
-	}
-
-	return rate;
-}
-
-static void __iomem *sched_clock_base;
-
-static u32 sp804_read(void)
-{
-	return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
-}
-
-void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
-						     const char *name,
-						     int use_sched_clock)
-{
-	long rate = sp804_get_clock_rate(name);
-
-	if (rate < 0)
-		return;
-
-	/* setup timer 0 as free-running clocksource */
-	writel(0, base + TIMER_CTRL);
-	writel(0xffffffff, base + TIMER_LOAD);
-	writel(0xffffffff, base + TIMER_VALUE);
-	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
-		base + TIMER_CTRL);
-
-	clocksource_mmio_init(base + TIMER_VALUE, name,
-		rate, 200, 32, clocksource_mmio_readl_down);
-
-	if (use_sched_clock) {
-		sched_clock_base = base;
-		setup_sched_clock(sp804_read, 32, rate);
-	}
-}
-
-
-static void __iomem *clkevt_base;
-static unsigned long clkevt_reload;
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	/* clear the interrupt */
-	writel(1, clkevt_base + TIMER_INTCLR);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static void sp804_set_mode(enum clock_event_mode mode,
-	struct clock_event_device *evt)
-{
-	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
-
-	writel(ctrl, clkevt_base + TIMER_CTRL);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		writel(clkevt_reload, clkevt_base + TIMER_LOAD);
-		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* period set, and timer enabled in 'next_event' hook */
-		ctrl |= TIMER_CTRL_ONESHOT;
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	default:
-		break;
-	}
-
-	writel(ctrl, clkevt_base + TIMER_CTRL);
-}
-
-static int sp804_set_next_event(unsigned long next,
-	struct clock_event_device *evt)
-{
-	unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
-
-	writel(next, clkevt_base + TIMER_LOAD);
-	writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
-
-	return 0;
-}
-
-static struct clock_event_device sp804_clockevent = {
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= sp804_set_mode,
-	.set_next_event	= sp804_set_next_event,
-	.rating		= 300,
-};
-
-static struct irqaction sp804_timer_irq = {
-	.name		= "timer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= sp804_timer_interrupt,
-	.dev_id		= &sp804_clockevent,
-};
-
-void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
-	const char *name)
-{
-	struct clock_event_device *evt = &sp804_clockevent;
-	long rate = sp804_get_clock_rate(name);
-
-	if (rate < 0)
-		return;
-
-	clkevt_base = base;
-	clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
-	evt->name = name;
-	evt->irq = irq;
-	evt->cpumask = cpu_possible_mask;
-
-	setup_irq(irq, &sp804_timer_irq);
-	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
-}
diff --git a/arch/arm/include/asm/hardware/arm_timer.h b/arch/arm/include/asm/hardware/arm_timer.h
deleted file mode 100644
index d6030ff..0000000
--- a/arch/arm/include/asm/hardware/arm_timer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __ASM_ARM_HARDWARE_ARM_TIMER_H
-#define __ASM_ARM_HARDWARE_ARM_TIMER_H
-
-/*
- * ARM timer implementation, found in Integrator, Versatile and Realview
- * platforms.  Not all platforms support all registers and bits in these
- * registers, so we mark them with A for Integrator AP, C for Integrator
- * CP, V for Versatile and R for Realview.
- *
- * Integrator AP has 16-bit timers, Integrator CP, Versatile and Realview
- * can have 16-bit or 32-bit selectable via a bit in the control register.
- *
- * Every SP804 contains two identical timers.
- */
-#define TIMER_1_BASE	0x00
-#define TIMER_2_BASE	0x20
-
-#define TIMER_LOAD	0x00			/* ACVR rw */
-#define TIMER_VALUE	0x04			/* ACVR ro */
-#define TIMER_CTRL	0x08			/* ACVR rw */
-#define TIMER_CTRL_ONESHOT	(1 << 0)	/*  CVR */
-#define TIMER_CTRL_32BIT	(1 << 1)	/*  CVR */
-#define TIMER_CTRL_DIV1		(0 << 2)	/* ACVR */
-#define TIMER_CTRL_DIV16	(1 << 2)	/* ACVR */
-#define TIMER_CTRL_DIV256	(2 << 2)	/* ACVR */
-#define TIMER_CTRL_IE		(1 << 5)	/*   VR */
-#define TIMER_CTRL_PERIODIC	(1 << 6)	/* ACVR */
-#define TIMER_CTRL_ENABLE	(1 << 7)	/* ACVR */
-
-#define TIMER_INTCLR	0x0c			/* ACVR wo */
-#define TIMER_RIS	0x10			/*  CVR ro */
-#define TIMER_MIS	0x14			/*  CVR ro */
-#define TIMER_BGLOAD	0x18			/*  CVR rw */
-
-#endif
diff --git a/arch/arm/include/asm/hardware/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h
deleted file mode 100644
index 2dd9d3f..0000000
--- a/arch/arm/include/asm/hardware/timer-sp.h
+++ /dev/null
@@ -1,15 +0,0 @@
-void __sp804_clocksource_and_sched_clock_init(void __iomem *,
-					      const char *, int);
-
-static inline void sp804_clocksource_init(void __iomem *base, const char *name)
-{
-	__sp804_clocksource_and_sched_clock_init(base, name, 0);
-}
-
-static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
-							  const char *name)
-{
-	__sp804_clocksource_and_sched_clock_init(base, name, 1);
-}
-
-void sp804_clockevents_init(void __iomem *, unsigned int, const char *);
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index a4f9f50..cfd843b 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -27,14 +27,14 @@
 #include <linux/smp.h>
 #include <linux/amba/bus.h>
 #include <linux/clk-provider.h>
+#include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
 #include <asm/arch_timer.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
-#include <asm/hardware/arm_timer.h>
-#include <asm/hardware/timer-sp.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index ea96144..c2112ff 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -41,11 +41,11 @@
 #include <linux/stat.h>
 #include <linux/sys_soc.h>
 #include <linux/termios.h>
+#include <clocksource/arm_timer.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/hardware/arm_timer.h>
 #include <asm/setup.h>
 #include <asm/param.h>		/* HZ */
 #include <asm/mach-types.h>
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 2b0db82..40373ec 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -28,12 +28,13 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/sys_soc.h>
+#include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
-#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
 
 #include <mach/cm.h>
@@ -45,7 +46,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <asm/hardware/timer-sp.h>
 
 #include <plat/clcd.h>
 #include <plat/sched_clock.h>
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 1d5ee5c..26a3da38 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -31,11 +31,12 @@
 #include <linux/amba/mmci.h>
 #include <linux/gfp.h>
 #include <linux/mtd/physmap.h>
+#include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
-#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
 
 #include <asm/mach/arch.h>
@@ -45,7 +46,6 @@
 
 #include <mach/platform.h>
 #include <mach/irqs.h>
-#include <asm/hardware/timer-sp.h>
 
 #include <plat/clcd.h>
 #include <plat/sched_clock.h>
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 25160ae..e894a1f 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -38,9 +38,10 @@
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
 #include <linux/bitops.h>
+#include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
 #include <asm/irq.h>
-#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
 #include <asm/mach-types.h>
 
@@ -50,7 +51,6 @@
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/hardware/timer-sp.h>
 
 #include <plat/clcd.h>
 #include <plat/sched_clock.h>
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 6f34497..48f6676 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -11,16 +11,15 @@
 #include <linux/clkdev.h>
 #include <linux/vexpress.h>
 #include <linux/irqchip/arm-gic.h>
+#include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
-#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
 #include <mach/ct-ca9x4.h>
 
-#include <asm/hardware/timer-sp.h>
-
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 915683c..51e8701 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -21,6 +21,8 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/vexpress.h>
+#include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
 #include <asm/arch_timer.h>
 #include <asm/mach-types.h>
@@ -29,9 +31,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/timer-sp.h>
 
 #include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e8c4532..4c04d19 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -63,6 +63,11 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 config ARM_ARCH_TIMER
 	bool
 
+config ARM_TIMER_SP804
+	bool
+	select CLKSRC_MMIO
+	select HAVE_SCHED_CLOCK
+
 config CLKSRC_METAG_GENERIC
 	def_bool y if METAG
 	help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1c1b15d..9d3ad88 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -22,4 +22,5 @@ obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
 obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
+obj-$(CONFIG_ARM_TIMER_SP804)		+= timer-sp.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
diff --git a/drivers/clocksource/timer-sp.c b/drivers/clocksource/timer-sp.c
new file mode 100644
index 0000000..a7f2510
--- /dev/null
+++ b/drivers/clocksource/timer-sp.c
@@ -0,0 +1,191 @@
+/*
+ *  linux/arch/arm/common/timer-sp.c
+ *
+ *  Copyright (C) 1999 - 2003 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <clocksource/arm_timer.h>
+
+#include <asm/sched_clock.h>
+
+static long __init sp804_get_clock_rate(const char *name)
+{
+	struct clk *clk;
+	long rate;
+	int err;
+
+	clk = clk_get_sys("sp804", name);
+	if (IS_ERR(clk)) {
+		pr_err("sp804: %s clock not found: %d\n", name,
+			(int)PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+
+	err = clk_prepare(clk);
+	if (err) {
+		pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
+		clk_put(clk);
+		return err;
+	}
+
+	err = clk_enable(clk);
+	if (err) {
+		pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+		clk_unprepare(clk);
+		clk_put(clk);
+		return err;
+	}
+
+	rate = clk_get_rate(clk);
+	if (rate < 0) {
+		pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
+		clk_disable(clk);
+		clk_unprepare(clk);
+		clk_put(clk);
+	}
+
+	return rate;
+}
+
+static void __iomem *sched_clock_base;
+
+static u32 sp804_read(void)
+{
+	return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
+}
+
+void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
+						     const char *name,
+						     int use_sched_clock)
+{
+	long rate = sp804_get_clock_rate(name);
+
+	if (rate < 0)
+		return;
+
+	/* setup timer 0 as free-running clocksource */
+	writel(0, base + TIMER_CTRL);
+	writel(0xffffffff, base + TIMER_LOAD);
+	writel(0xffffffff, base + TIMER_VALUE);
+	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
+		base + TIMER_CTRL);
+
+	clocksource_mmio_init(base + TIMER_VALUE, name,
+		rate, 200, 32, clocksource_mmio_readl_down);
+
+	if (use_sched_clock) {
+		sched_clock_base = base;
+		setup_sched_clock(sp804_read, 32, rate);
+	}
+}
+
+
+static void __iomem *clkevt_base;
+static unsigned long clkevt_reload;
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	/* clear the interrupt */
+	writel(1, clkevt_base + TIMER_INTCLR);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void sp804_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
+
+	writel(ctrl, clkevt_base + TIMER_CTRL);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		writel(clkevt_reload, clkevt_base + TIMER_LOAD);
+		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* period set, and timer enabled in 'next_event' hook */
+		ctrl |= TIMER_CTRL_ONESHOT;
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		break;
+	}
+
+	writel(ctrl, clkevt_base + TIMER_CTRL);
+}
+
+static int sp804_set_next_event(unsigned long next,
+	struct clock_event_device *evt)
+{
+	unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
+
+	writel(next, clkevt_base + TIMER_LOAD);
+	writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
+
+	return 0;
+}
+
+static struct clock_event_device sp804_clockevent = {
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= sp804_set_mode,
+	.set_next_event	= sp804_set_next_event,
+	.rating		= 300,
+};
+
+static struct irqaction sp804_timer_irq = {
+	.name		= "timer",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= sp804_timer_interrupt,
+	.dev_id		= &sp804_clockevent,
+};
+
+void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
+	const char *name)
+{
+	struct clock_event_device *evt = &sp804_clockevent;
+	long rate = sp804_get_clock_rate(name);
+
+	if (rate < 0)
+		return;
+
+	clkevt_base = base;
+	clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
+	evt->name = name;
+	evt->irq = irq;
+	evt->cpumask = cpu_possible_mask;
+
+	setup_irq(irq, &sp804_timer_irq);
+	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
+}
diff --git a/include/clocksource/arm_timer.h b/include/clocksource/arm_timer.h
new file mode 100644
index 0000000..f4a443a
--- /dev/null
+++ b/include/clocksource/arm_timer.h
@@ -0,0 +1,35 @@
+#ifndef __CLOCKSOURCE_ARM_TIMER_H
+#define __CLOCKSOURCE_ARM_TIMER_H
+
+/*
+ * ARM timer implementation, found in Integrator, Versatile and Realview
+ * platforms.  Not all platforms support all registers and bits in these
+ * registers, so we mark them with A for Integrator AP, C for Integrator
+ * CP, V for Versatile and R for Realview.
+ *
+ * Integrator AP has 16-bit timers, Integrator CP, Versatile and Realview
+ * can have 16-bit or 32-bit selectable via a bit in the control register.
+ *
+ * Every SP804 contains two identical timers.
+ */
+#define TIMER_1_BASE	0x00
+#define TIMER_2_BASE	0x20
+
+#define TIMER_LOAD	0x00			/* ACVR rw */
+#define TIMER_VALUE	0x04			/* ACVR ro */
+#define TIMER_CTRL	0x08			/* ACVR rw */
+#define TIMER_CTRL_ONESHOT	(1 << 0)	/*  CVR */
+#define TIMER_CTRL_32BIT	(1 << 1)	/*  CVR */
+#define TIMER_CTRL_DIV1		(0 << 2)	/* ACVR */
+#define TIMER_CTRL_DIV16	(1 << 2)	/* ACVR */
+#define TIMER_CTRL_DIV256	(2 << 2)	/* ACVR */
+#define TIMER_CTRL_IE		(1 << 5)	/*   VR */
+#define TIMER_CTRL_PERIODIC	(1 << 6)	/* ACVR */
+#define TIMER_CTRL_ENABLE	(1 << 7)	/* ACVR */
+
+#define TIMER_INTCLR	0x0c			/* ACVR wo */
+#define TIMER_RIS	0x10			/*  CVR ro */
+#define TIMER_MIS	0x14			/*  CVR ro */
+#define TIMER_BGLOAD	0x18			/*  CVR rw */
+
+#endif
diff --git a/include/clocksource/timer-sp.h b/include/clocksource/timer-sp.h
new file mode 100644
index 0000000..0ad4186
--- /dev/null
+++ b/include/clocksource/timer-sp.h
@@ -0,0 +1,19 @@
+#ifndef __TIMER_SP_H
+#define __TIMER_SP_H
+
+void __sp804_clocksource_and_sched_clock_init(void __iomem *,
+					      const char *, int);
+
+static inline void sp804_clocksource_init(void __iomem *base, const char *name)
+{
+	__sp804_clocksource_and_sched_clock_init(base, name, 0);
+}
+
+static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
+							  const char *name)
+{
+	__sp804_clocksource_and_sched_clock_init(base, name, 1);
+}
+
+void sp804_clockevents_init(void __iomem *, unsigned int, const char *);
+#endif	/* __TIMER_SP_H */
-- 
1.7.10.4

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

* [PATCH v2 02/14] clocksource: sp804: add device tree support
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 01/14] clocksource: move sp timer driver Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 18:14   ` Arnd Bergmann
  2013-03-12 18:51   ` Arnd Bergmann
  2013-03-12 17:08 ` [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF Haojian Zhuang
                   ` (11 subsequent siblings)
  13 siblings, 2 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Parse clock & irq from device tree for sp804.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/clocksource/timer-sp.c |  105 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/drivers/clocksource/timer-sp.c b/drivers/clocksource/timer-sp.c
index a7f2510..f8c2c54 100644
--- a/drivers/clocksource/timer-sp.c
+++ b/drivers/clocksource/timer-sp.c
@@ -19,16 +19,23 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <clocksource/arm_timer.h>
+#include <clocksource/timer-sp.h>
 
 #include <asm/sched_clock.h>
 
+#define SP804_CLKSRC	"sp804 source"
+#define SP804_CLKEVT	"sp804 event"
+
 static long __init sp804_get_clock_rate(const char *name)
 {
 	struct clk *clk;
@@ -189,3 +196,101 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
 	setup_irq(irq, &sp804_timer_irq);
 	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
 }
+
+static struct device_node *from = NULL;
+
+static struct of_device_id sp804_timer_match[] __initdata = {
+	{ .compatible = "arm,sp804", },
+	{}
+};
+
+static struct clk __init *sp804_dt_init_clk(struct device_node *np, int i,
+					    const char *name)
+{
+	struct clk_lookup *lookup = NULL;
+	struct clk *clk;
+
+	clk = of_clk_get(np, i);
+	if (IS_ERR(clk))
+		return clk;
+	lookup = clkdev_alloc(clk, name, "sp804");
+	if (!lookup) {
+		clk_put(clk);
+		return ERR_PTR(-EINVAL);
+	}
+	clkdev_add(lookup);
+	return clk;
+}
+
+static void __init sp804_dt_init(void)
+{
+	struct device_node *np = NULL;
+	struct clk *clksrc = NULL, *clkevt = NULL;
+	void __iomem *base;
+	int retsrc, retevt, i = 0, irq = 0;
+	u32 srcoffs = 0, evtoffs = 0;
+
+	np = of_find_matching_node(from, sp804_timer_match);
+	WARN_ON(!np);
+	if (!np) {
+		pr_err("Failed to find sp804 timer\n");
+		return;
+	}
+	from = np;
+	/* check whether timer node is available */
+	if (!of_device_is_available(np))
+		return;
+
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	if (!base)
+		return;
+
+	retsrc = of_property_read_u32(np, "arm,sp804-clocksource", &srcoffs);
+	retevt = of_property_read_u32(np, "arm,sp804-clockevent", &evtoffs);
+	if (retsrc < 0 && retevt < 0)
+		goto err;
+
+	if (!retsrc) {
+		if (srcoffs) {
+			/* TIMER2 is clock source */
+			i = 1;
+			srcoffs = TIMER_2_BASE;
+		} else {
+			/* TIMER1 is clock source */
+			i = 0;
+			srcoffs = TIMER_1_BASE;
+		}
+		clksrc = sp804_dt_init_clk(np, i, SP804_CLKSRC);
+		if (IS_ERR(clksrc))
+			goto err;
+		sp804_clocksource_and_sched_clock_init(base + srcoffs,
+						       SP804_CLKSRC);
+	}
+	if (!retevt) {
+		if (evtoffs) {
+			/* TIMER2 is clock event */
+			i = 1;
+			evtoffs = TIMER_2_BASE;
+		} else {
+			/* TIMER1 is clock event */
+			i = 0;
+			evtoffs = TIMER_1_BASE;
+		}
+		irq = irq_of_parse_and_map(np, i);
+		if (irq < 0)
+			goto err_evt;
+		clkevt = sp804_dt_init_clk(np, i, SP804_CLKEVT);
+		if (IS_ERR(clkevt))
+			goto err_evt;
+		sp804_clockevents_init(base + evtoffs, irq, SP804_CLKEVT);
+	}
+
+	return;
+err_evt:
+	if (clksrc)
+		clk_put(clksrc);
+err:
+	iounmap(base);
+}
+CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init);
-- 
1.7.10.4

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

* [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 01/14] clocksource: move sp timer driver Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 02/14] clocksource: sp804: add device tree support Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 19:17   ` Arnd Bergmann
  2013-03-12 17:08 ` [PATCH v2 04/14] ARM: highbank: use clocksource_of_init for sp804 Haojian Zhuang
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

of_find_matching_node() & of_device_is_available() are depend on CONFIG_OF
macro. If CONFIG_OF isn't defined for non-DT mode, the build error
occurs.

So add CONFIG_OF for those DT functions.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/clocksource/timer-sp.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clocksource/timer-sp.c b/drivers/clocksource/timer-sp.c
index f8c2c54..5f2d700 100644
--- a/drivers/clocksource/timer-sp.c
+++ b/drivers/clocksource/timer-sp.c
@@ -197,6 +197,7 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
 	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
 }
 
+#ifdef CONFIG_OF
 static struct device_node *from = NULL;
 
 static struct of_device_id sp804_timer_match[] __initdata = {
@@ -294,3 +295,4 @@ err:
 	iounmap(base);
 }
 CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init);
+#endif
-- 
1.7.10.4

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

* [PATCH v2 04/14] ARM: highbank: use clocksource_of_init for sp804
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (2 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 05/14] ARM: integrator: " Haojian Zhuang
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Since sp804 hardware information could be stored in DTS file, remove
those ioremap operations. Use clocksource_of_init() instead.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/ecx-common.dtsi |    4 +++-
 arch/arm/mach-highbank/highbank.c |   19 +------------------
 2 files changed, 4 insertions(+), 19 deletions(-)

diff --git a/arch/arm/boot/dts/ecx-common.dtsi b/arch/arm/boot/dts/ecx-common.dtsi
index d61b535..7ae5b2d 100644
--- a/arch/arm/boot/dts/ecx-common.dtsi
+++ b/arch/arm/boot/dts/ecx-common.dtsi
@@ -105,8 +105,10 @@
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0xfff34000 0x1000>;
 			interrupts = <0 18 4>;
-			clocks = <&pclk>;
+			clocks = <&pclk &pclk>;
 			clock-names = "apb_pclk";
+			arm,sp804-clocksource = <0x20>;
+			arm,sp804-clockevent = <0>;
 		};
 
 		rtc at fff35000 {
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index cfd843b..7829c2d 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -91,33 +91,16 @@ static void __init highbank_init_irq(void)
 #endif
 }
 
-static struct clk_lookup lookup = {
-	.dev_id = "sp804",
-	.con_id = NULL,
-};
-
 static void __init highbank_timer_init(void)
 {
-	int irq;
 	struct device_node *np;
-	void __iomem *timer_base;
 
 	/* Map system registers */
 	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
 	sregs_base = of_iomap(np, 0);
 	WARN_ON(!sregs_base);
 
-	np = of_find_compatible_node(NULL, NULL, "arm,sp804");
-	timer_base = of_iomap(np, 0);
-	WARN_ON(!timer_base);
-	irq = irq_of_parse_and_map(np, 0);
-
-	of_clk_init(NULL);
-	lookup.clk = of_clk_get(np, 0);
-	clkdev_add(&lookup);
-
-	sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1");
-	sp804_clockevents_init(timer_base, irq, "timer0");
+	clocksource_of_init();
 
 	twd_local_timer_of_register();
 
-- 
1.7.10.4

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (3 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 04/14] ARM: highbank: use clocksource_of_init for sp804 Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 18:54   ` Arnd Bergmann
                     ` (2 more replies)
  2013-03-12 17:08 ` [PATCH v2 06/14] ARM: vexpress: " Haojian Zhuang
                   ` (8 subsequent siblings)
  13 siblings, 3 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Remove all code to parse sp804 in integrator platform driver. Use
clocksource_of_init() instead since these code are implemented in sp804
driver already.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/integrator.dtsi        |    3 +++
 arch/arm/boot/dts/integratorap.dts       |   15 +++++------
 arch/arm/boot/dts/integratorcp.dts       |    9 +++----
 arch/arm/mach-integrator/Kconfig         |    3 +++
 arch/arm/mach-integrator/integrator_ap.c |   41 +-----------------------------
 arch/arm/mach-integrator/integrator_cp.c |   35 ++-----------------------
 6 files changed, 20 insertions(+), 86 deletions(-)

diff --git a/arch/arm/boot/dts/integrator.dtsi b/arch/arm/boot/dts/integrator.dtsi
index 813b91d..749ac21 100644
--- a/arch/arm/boot/dts/integrator.dtsi
+++ b/arch/arm/boot/dts/integrator.dtsi
@@ -9,18 +9,21 @@
 		reg = <0x13000000 0x100>;
 		interrupt-parent = <&pic>;
 		interrupts = <5>;
+		status = "disabled";
 	};
 
 	timer at 13000100 {
 		reg = <0x13000100 0x100>;
 		interrupt-parent = <&pic>;
 		interrupts = <6>;
+		status = "disabled";
 	};
 
 	timer at 13000200 {
 		reg = <0x13000200 0x100>;
 		interrupt-parent = <&pic>;
 		interrupts = <7>;
+		status = "disabled";
 	};
 
 	pic at 14000000 {
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index c9c3fa3..70e321c 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -9,11 +9,6 @@
 	model = "ARM Integrator/AP";
 	compatible = "arm,integrator-ap";
 
-	aliases {
-		arm,timer-primary = &timer2;
-		arm,timer-secondary = &timer1;
-	};
-
 	chosen {
 		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
 	};
@@ -24,15 +19,19 @@
 	};
 
 	timer0: timer at 13000000 {
-		compatible = "arm,integrator-timer";
+		compatible = "arm,sp804", "arm,primecell";
 	};
 
 	timer1: timer at 13000100 {
-		compatible = "arm,integrator-timer";
+		compatible = "arm,sp804", "arm,primecell";
+		arm,sp804-clockevent = <0>;
+		status = "ok";
 	};
 
 	timer2: timer at 13000200 {
-		compatible = "arm,integrator-timer";
+		compatible = "arm,sp804", "arm,primecell";
+		arm,sp804-clocksource = <0>;
+		status = "ok";
 	};
 
 	pic: pic at 14000000 {
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index 8b11939..19b2e3e 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -9,11 +9,6 @@
 	model = "ARM Integrator/CP";
 	compatible = "arm,integrator-cp";
 
-	aliases {
-		arm,timer-primary = &timer2;
-		arm,timer-secondary = &timer1;
-	};
-
 	chosen {
 		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
 	};
@@ -29,10 +24,14 @@
 
 	timer1: timer at 13000100 {
 		compatible = "arm,sp804", "arm,primecell";
+		arm,sp804-clockevent = <0>;
+		status = "ok";
 	};
 
 	timer2: timer at 13000200 {
 		compatible = "arm,sp804", "arm,primecell";
+		arm,sp804-clocksource = <0>;
+		status = "ok";
 	};
 
 	pic: pic at 14000000 {
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index abeff25..031f43a 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -5,6 +5,7 @@ menu "Integrator Options"
 config ARCH_INTEGRATOR_AP
 	bool "Support Integrator/AP and Integrator/PP2 platforms"
 	select CLKSRC_MMIO
+	select CLKSRC_OF
 	select MIGHT_HAVE_PCI
 	select SERIAL_AMBA_PL010
 	select SERIAL_AMBA_PL010_CONSOLE
@@ -15,6 +16,8 @@ config ARCH_INTEGRATOR_AP
 
 config ARCH_INTEGRATOR_CP
 	bool "Support Integrator/CP platform"
+	select CLKSRC_MMIO
+	select CLKSRC_OF
 	select ARCH_CINTEGRATOR
 	select ARM_TIMER_SP804
 	select PLAT_VERSATILE_CLCD
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index c2112ff..2266944 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -425,45 +425,6 @@ void __init ap_init_early(void)
 
 #ifdef CONFIG_OF
 
-static void __init ap_of_timer_init(void)
-{
-	struct device_node *node;
-	const char *path;
-	void __iomem *base;
-	int err;
-	int irq;
-	struct clk *clk;
-	unsigned long rate;
-
-	clk = clk_get_sys("ap_timer", NULL);
-	BUG_ON(IS_ERR(clk));
-	clk_prepare_enable(clk);
-	rate = clk_get_rate(clk);
-
-	err = of_property_read_string(of_aliases,
-				"arm,timer-primary", &path);
-	if (WARN_ON(err))
-		return;
-	node = of_find_node_by_path(path);
-	base = of_iomap(node, 0);
-	if (WARN_ON(!base))
-		return;
-	writel(0, base + TIMER_CTRL);
-	integrator_clocksource_init(rate, base);
-
-	err = of_property_read_string(of_aliases,
-				"arm,timer-secondary", &path);
-	if (WARN_ON(err))
-		return;
-	node = of_find_node_by_path(path);
-	base = of_iomap(node, 0);
-	if (WARN_ON(!base))
-		return;
-	irq = irq_of_parse_and_map(node, 0);
-	writel(0, base + TIMER_CTRL);
-	integrator_clockevent_init(rate, base, irq);
-}
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
 	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
 	{ /* Sentinel */ }
@@ -582,7 +543,7 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq_of,
 	.handle_irq	= fpga_handle_irq,
-	.init_time	= ap_of_timer_init,
+	.init_time	= clocksource_of_init,
 	.init_machine	= ap_init_of,
 	.restart	= integrator_restart,
 	.dt_compat      = ap_dt_board_compat,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 40373ec..6e1c340 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -28,6 +28,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/sys_soc.h>
+#include <linux/clocksource.h>
 #include <clocksource/arm_timer.h>
 #include <clocksource/timer-sp.h>
 
@@ -251,38 +252,6 @@ static void __init intcp_init_early(void)
 
 #ifdef CONFIG_OF
 
-static void __init cp_of_timer_init(void)
-{
-	struct device_node *node;
-	const char *path;
-	void __iomem *base;
-	int err;
-	int irq;
-
-	err = of_property_read_string(of_aliases,
-				"arm,timer-primary", &path);
-	if (WARN_ON(err))
-		return;
-	node = of_find_node_by_path(path);
-	base = of_iomap(node, 0);
-	if (WARN_ON(!base))
-		return;
-	writel(0, base + TIMER_CTRL);
-	sp804_clocksource_init(base, node->name);
-
-	err = of_property_read_string(of_aliases,
-				"arm,timer-secondary", &path);
-	if (WARN_ON(err))
-		return;
-	node = of_find_node_by_path(path);
-	base = of_iomap(node, 0);
-	if (WARN_ON(!base))
-		return;
-	irq = irq_of_parse_and_map(node, 0);
-	writel(0, base + TIMER_CTRL);
-	sp804_clockevents_init(base, irq, node->name);
-}
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
 	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
 	{ /* Sentinel */ }
@@ -386,7 +355,7 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq_of,
 	.handle_irq	= fpga_handle_irq,
-	.init_time	= cp_of_timer_init,
+	.init_time	= clocksource_of_init,
 	.init_machine	= intcp_init_of,
 	.restart	= integrator_restart,
 	.dt_compat      = intcp_dt_board_compat,
-- 
1.7.10.4

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

* [PATCH v2 06/14] ARM: vexpress: use clocksource_of_init for sp804
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (4 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 05/14] ARM: integrator: " Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 07/14] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Remove all code to parse sp804. Use clocksource_of_init() instead since
all these code are implemented in sp804 driver already.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/vexpress-v2m-rs1.dtsi |    2 ++
 arch/arm/boot/dts/vexpress-v2m.dtsi     |    2 ++
 arch/arm/boot/dts/vexpress-v2p-ca9.dts  |    2 ++
 arch/arm/mach-vexpress/Kconfig          |    1 +
 arch/arm/mach-vexpress/v2m.c            |   13 ++-----------
 5 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index ac870fb..3fa798f 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -183,6 +183,8 @@
 				interrupts = <2>;
 				clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
 				clock-names = "timclken1", "timclken2", "apb_pclk";
+				arm,sp804-clocksource = <0x20>;
+				arm,sp804-clockevent = <0>;
 			};
 
 			v2m_timer23: timer at 120000 {
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index f142036..86e4046 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -182,6 +182,8 @@
 				interrupts = <2>;
 				clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
 				clock-names = "timclken1", "timclken2", "apb_pclk";
+				arm,sp804-clocksource = <0x20>;
+				arm,sp804-clockevent = <0>;
 			};
 
 			v2m_timer23: timer at 12000 {
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
index 1420bb1..a2eba95 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
@@ -98,6 +98,8 @@
 			     <0 49 4>;
 		clocks = <&oscclk2>, <&oscclk2>;
 		clock-names = "timclk", "apb_pclk";
+		arm,sp804-clocksource = <0x20>;
+		arm,sp804-clockevent = <0>;
 	};
 
 	watchdog at 100e5000 {
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 52d315b..ff78c15 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -5,6 +5,7 @@ config ARCH_VEXPRESS
 	select ARM_GIC
 	select ARM_TIMER_SP804
 	select CLKDEV_LOOKUP
+	select CLKSRC_OF
 	select COMMON_CLK
 	select COMMON_CLK_VERSATILE
 	select CPU_V7
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 51e8701..bb599d3 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -21,6 +21,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/vexpress.h>
+#include <linux/clocksource.h>
 #include <clocksource/arm_timer.h>
 #include <clocksource/timer-sp.h>
 
@@ -431,19 +432,9 @@ void __init v2m_dt_init_early(void)
 
 static void __init v2m_dt_timer_init(void)
 {
-	struct device_node *node = NULL;
-
 	vexpress_clk_of_init();
 
-	do {
-		node = of_find_compatible_node(node, NULL, "arm,sp804");
-	} while (node && vexpress_get_site_by_node(node) != VEXPRESS_SITE_MB);
-	if (node) {
-		pr_info("Using SP804 '%s' as a clock & events source\n",
-				node->full_name);
-		v2m_sp804_init(of_iomap(node, 0),
-				irq_of_parse_and_map(node, 0));
-	}
+	clocksource_of_init();
 
 	if (arch_timer_of_register() != 0)
 		twd_local_timer_of_register();
-- 
1.7.10.4

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

* [PATCH v2 07/14] ARM: debug: support debug ll on hisilicon soc
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (5 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 06/14] ARM: vexpress: " Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 08/14] clk: hs: add clock support Haojian Zhuang
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Support UART0 debug ll on hisilicon Hi3620 SoC.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig.debug             |   15 +++++++++++++++
 arch/arm/include/debug/hisilicon.S |   30 ++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 arch/arm/include/debug/hisilicon.S

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index ecfcdba..fd2a39d 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -240,6 +240,20 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX6Q.
 
+	config DEBUG_HI3620_UART
+		bool "Hisilicon HI3620 Debug UART"
+		depends on ARCH_HI3xxx
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on HI3620 UART.
+
+	config DEBUG_HI3716_UART
+		bool "Hisilicon Hi3716 Debug UART"
+		depends on ARCH_HI3xxx
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on HI3716 UART.
+
 	config DEBUG_MMP_UART2
 		bool "Kernel low-level debugging message via MMP UART2"
 		depends on ARCH_MMP
@@ -589,6 +603,7 @@ config DEBUG_LL_INCLUDE
 				 DEBUG_IMX53_UART ||\
 				 DEBUG_IMX6Q_UART
 	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
+	default "debug/hisilicon.S" if DEBUG_HI3620_UART || DEBUG_HI3716_UART
 	default "debug/mvebu.S" if DEBUG_MVEBU_UART
 	default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
 	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
diff --git a/arch/arm/include/debug/hisilicon.S b/arch/arm/include/debug/hisilicon.S
new file mode 100644
index 0000000..47ad019
--- /dev/null
+++ b/arch/arm/include/debug/hisilicon.S
@@ -0,0 +1,30 @@
+/*
+ * Early serial output macro for Hisilicon SoC
+ *
+ * Copyright (C) 2012-2013 Hisilicon Technologies Co., Ltd.
+ * Copyright (C) 2012-2013 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_DEBUG_HI3620_UART)
+#define HS_UART_PHYS_BASE	0xfcb00000
+#define HS_UART_VIRT_BASE	0xfeb00000
+#elif defined(CONFIG_DEBUG_HI3716_UART)
+#define HS_UART_PHYS_BASE	0xf8b00000
+#define HS_UART_VIRT_BASE	0xfeb00000
+#endif
+
+#if defined(CONFIG_DEBUG_HI3620_UART) || defined(CONFIG_DEBUG_HI3716_UART)
+		.macro	addruart,rp,rv,tmp
+		ldr	\rp, =HS_UART_PHYS_BASE
+		ldr	\rv, =HS_UART_VIRT_BASE
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#endif
-- 
1.7.10.4

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

* [PATCH v2 08/14] clk: hs: add clock support
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (6 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 07/14] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 19:00   ` Arnd Bergmann
  2013-03-12 17:08 ` [PATCH v2 09/14] ARM: hs: add board support with device tree Haojian Zhuang
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add clock support with device tree on Hisilicon SoC.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/clk/Makefile     |    1 +
 drivers/clk/clk-hi3xxx.c |  650 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 651 insertions(+)
 create mode 100644 drivers/clk/clk-hi3xxx.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 0147022..b065e76 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_COMMON_CLK)	+= clk-mux.o
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
+obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3xxx.o
 obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs/
 obj-$(CONFIG_ARCH_SOCFPGA)	+= socfpga/
diff --git a/drivers/clk/clk-hi3xxx.c b/drivers/clk/clk-hi3xxx.c
new file mode 100644
index 0000000..3ff0118
--- /dev/null
+++ b/drivers/clk/clk-hi3xxx.c
@@ -0,0 +1,650 @@
+/*
+ * Hisilicon clock driver
+ *
+ * Copyright (c) 2012-2013 Hisilicon Limited.
+ * Copyright (c) 2012-2013 Linaro Limited.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *	   Xin Li <li.xin@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#define HI3620_DISABLE_OFF		0x4
+#define HI3620_STATUS_OFF		0x8
+
+#define WIDTH_TO_MASK(width)	((1 << (width)) - 1)
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+struct hi3620_periclk {
+	struct clk_hw	hw;
+	void __iomem	*enable;	/* enable register */
+	void __iomem	*reset;		/* reset register */
+	u32		ebits;		/* bits in enable/disable register */
+	u32		rbits;		/* bits in reset/unreset register */
+	spinlock_t	*lock;
+};
+
+struct hi3620_muxclk {
+	struct clk_hw	hw;
+	void __iomem	*reg;		/* mux register */
+	u8		shift;
+	u8		width;
+	u32		mbits;		/* mask bits in mux register */
+	spinlock_t	*lock;
+};
+
+struct hi3620_divclk {
+	struct clk_hw	hw;
+	void __iomem	*reg;		/* divider register */
+	u8		shift;
+	u8		width;
+	u32		mbits;		/* mask bits in divider register */
+	const struct clk_div_table	*table;
+	spinlock_t	*lock;
+};
+
+struct hs_clk {
+	void __iomem	*pmctrl;
+	void __iomem	*sctrl;
+	spinlock_t	lock;
+};
+
+static struct hs_clk hs_clk;
+
+static int hi3620_clkgate_prepare(struct clk_hw *hw)
+{
+	struct hi3620_periclk *pclk;
+	unsigned long flags = 0;
+
+	pclk = container_of(hw, struct hi3620_periclk, hw);
+
+	if (pclk->lock)
+		spin_lock_irqsave(pclk->lock, flags);
+	writel_relaxed(pclk->ebits, pclk->enable + HI3620_DISABLE_OFF);
+	writel_relaxed(pclk->rbits, pclk->reset + HI3620_DISABLE_OFF);
+	readl_relaxed(pclk->reset + HI3620_STATUS_OFF);
+	if (pclk->lock)
+		spin_unlock_irqrestore(pclk->lock, flags);
+	return 0;
+}
+
+static int hi3620_clkgate_enable(struct clk_hw *hw)
+{
+	struct hi3620_periclk *pclk;
+	unsigned long flags = 0;
+
+	pclk = container_of(hw, struct hi3620_periclk, hw);
+	if (pclk->lock)
+		spin_lock_irqsave(pclk->lock, flags);
+	writel_relaxed(pclk->ebits, pclk->enable);
+	readl_relaxed(pclk->enable + HI3620_STATUS_OFF);
+	if (pclk->lock)
+		spin_unlock_irqrestore(pclk->lock, flags);
+	return 0;
+}
+
+static void hi3620_clkgate_disable(struct clk_hw *hw)
+{
+	struct hi3620_periclk *pclk;
+	unsigned long flags = 0;
+
+	pclk = container_of(hw, struct hi3620_periclk, hw);
+	if (pclk->lock)
+		spin_lock_irqsave(pclk->lock, flags);
+	writel_relaxed(pclk->ebits, pclk->enable + HI3620_DISABLE_OFF);
+	readl_relaxed(pclk->enable + HI3620_STATUS_OFF);
+	if (pclk->lock)
+		spin_unlock_irqrestore(pclk->lock, flags);
+}
+
+static struct clk_ops hi3620_clkgate_ops = {
+	.prepare	= hi3620_clkgate_prepare,
+	.enable		= hi3620_clkgate_enable,
+	.disable	= hi3620_clkgate_disable,
+};
+
+static void __init hi3620_clkgate_setup(struct device_node *np)
+{
+	struct hi3620_periclk *pclk;
+	struct clk_init_data *init;
+	struct clk *clk;
+	const char *clk_name, *name, **parent_names;
+	u32 rdata[2], gdata[2];
+
+	if (!hs_clk.sctrl)
+		return;
+
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		return;
+	if (of_property_read_u32_array(np, "hisilicon,hi3620-clkreset",
+				       &rdata[0], 2))
+		return;
+	if (of_property_read_u32_array(np, "hisilicon,hi3620-clkgate",
+				       &gdata[0], 2))
+		return;
+
+	/* gate only has the fixed parent */
+	parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+	parent_names[0] = of_clk_get_parent_name(np, 0);
+
+	pclk = kzalloc(sizeof(*pclk), GFP_KERNEL);
+	if (!pclk)
+		goto err_pclk;
+
+	init = kzalloc(sizeof(*init), GFP_KERNEL);
+	if (!init)
+		goto err_init;
+	init->name = kstrdup(clk_name, GFP_KERNEL);
+	init->ops = &hi3620_clkgate_ops;
+	init->flags = CLK_SET_RATE_PARENT;
+	init->parent_names = parent_names;
+	init->num_parents = 1;
+
+	pclk->reset = hs_clk.sctrl + rdata[0];
+	pclk->rbits = rdata[1];
+	pclk->enable = hs_clk.sctrl + gdata[0];
+	pclk->ebits = gdata[1];
+	pclk->lock = &hs_clk.lock;
+	pclk->hw.init = init;
+
+	clk = clk_register(NULL, &pclk->hw);
+	if (IS_ERR(clk))
+		goto err_clk;
+	if (!of_property_read_string(np, "clock-names", &name))
+		clk_register_clkdev(clk, name, NULL);
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return;
+err_clk:
+	kfree(init);
+err_init:
+	kfree(pclk);
+err_pclk:
+	kfree(parent_names);
+}
+
+static u8 hi3620_clk_get_parent(struct clk_hw *hw)
+{
+	struct hi3620_muxclk *mclk;
+	u32 data;
+	unsigned long flags = 0;
+
+	mclk = container_of(hw, struct hi3620_muxclk, hw);
+
+	if (mclk->lock)
+		spin_lock_irqsave(mclk->lock, flags);
+
+	data = readl_relaxed(mclk->reg) >> mclk->shift;
+	data &= WIDTH_TO_MASK(mclk->width);
+
+	if (mclk->lock)
+		spin_unlock_irqrestore(mclk->lock, flags);
+
+	if (data >= __clk_get_num_parents(hw->clk))
+		return -EINVAL;
+
+	return (u8)data;
+}
+
+static int hi3620_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct hi3620_muxclk *mclk;
+	u32 data;
+	unsigned long flags = 0;
+
+	mclk = container_of(hw, struct hi3620_muxclk, hw);
+
+	if (mclk->lock)
+		spin_lock_irqsave(mclk->lock, flags);
+
+	data = readl_relaxed(mclk->reg);
+	data &= ~(WIDTH_TO_MASK(mclk->width) << mclk->shift);
+	data |= index << mclk->shift;
+	writel_relaxed(data, mclk->reg);
+	/* set mask enable bits */
+	data |= mclk->mbits;
+	writel_relaxed(data, mclk->reg);
+
+	if (mclk->lock)
+		spin_unlock_irqrestore(mclk->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops hi3620_clkmux_ops = {
+	.get_parent	= hi3620_clk_get_parent,
+	.set_parent	= hi3620_clk_set_parent,
+};
+
+static void __init hi3620_clkmux_setup(struct device_node *np)
+{
+	struct hi3620_muxclk *mclk;
+	struct clk_init_data *init;
+	struct clk *clk;
+	const char *clk_name, **parent_names;
+	u32 rdata[2];
+	u8 num_parents;
+	int i;
+
+	if (!hs_clk.sctrl)
+		return;
+
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		return;
+	if (of_property_read_u32_array(np, "hisilicon,hi3620-clkmux",
+				       &rdata[0], 2))
+		return;
+	/* get the count of items in mux */
+	for (i = 0; ; i++) {
+		/* parent's #clock-cells property is always 0 */
+		if (!of_parse_phandle(np, "clocks", i))
+			break;
+	}
+	parent_names = kzalloc(sizeof(char *) * i, GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	for (num_parents = i, i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(np, i);
+
+	mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+	if (!mclk)
+		goto err_mclk;
+	init = kzalloc(sizeof(*init), GFP_KERNEL);
+	if (!init)
+		goto err_init;
+	init->name = kstrdup(clk_name, GFP_KERNEL);
+	init->ops = &hi3620_clkmux_ops;
+	init->flags = CLK_SET_RATE_PARENT;
+	init->parent_names = parent_names;
+	init->num_parents = num_parents;
+
+	mclk->reg = hs_clk.sctrl + rdata[0];
+	/* enable_mask bits are in higher 16bits */
+	mclk->mbits = rdata[1] << 16;
+	mclk->shift = ffs(rdata[1]) - 1;
+	mclk->width = fls(rdata[1]) - ffs(rdata[1]) + 1;
+	mclk->lock = &hs_clk.lock;
+	mclk->hw.init = init;
+
+	clk = clk_register(NULL, &mclk->hw);
+	if (IS_ERR(clk))
+		goto err_clk;
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+	return;
+err_clk:
+	kfree(init);
+err_init:
+	kfree(mclk);
+err_mclk:
+	kfree(parent_names);
+}
+
+static void __init hs_clkgate_setup(struct device_node *np)
+{
+	struct clk *clk;
+	const char *clk_name, **parent_names, *name;
+	unsigned long flags = 0;
+	u32 data[2];
+
+	if (!hs_clk.sctrl)
+		return;
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		return;
+	if (of_property_read_u32_array(np, "hisilicon,clkgate",
+				       &data[0], 2))
+		return;
+	if (of_property_read_bool(np, "hisilicon,clkgate-inverted"))
+		flags = CLK_GATE_SET_TO_DISABLE;
+	/* gate only has the fixed parent */
+	parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+	parent_names[0] = of_clk_get_parent_name(np, 0);
+
+	clk = clk_register_gate(NULL, clk_name, parent_names[0], 0,
+				hs_clk.sctrl + data[0], (u8)data[1], flags,
+				&hs_clk.lock);
+	if (IS_ERR(clk))
+		goto err;
+	if (!of_property_read_string(np, "clock-names", &name))
+		clk_register_clkdev(clk, name, NULL);
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return;
+err:
+	kfree(parent_names);
+}
+
+void __init hs_fixed_factor_clk_setup(struct device_node *np)
+{
+	struct clk *clk;
+	const char *clk_name, **parent_names;
+	u32 data[2];
+
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		return;
+	if (of_property_read_u32_array(np, "hisilicon,fixed-factor",
+				       data, 2))
+		return ;
+	/* gate only has the fixed parent */
+	parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+	parent_names[0] = of_clk_get_parent_name(np, 0);
+
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_names[0], 0,
+					data[0], data[1]);
+	if (IS_ERR(clk))
+		goto err;
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return;
+err:
+	kfree(parent_names);
+}
+
+static unsigned int hi3620_get_table_maxdiv(const struct clk_div_table *table)
+{
+	unsigned int maxdiv = 0;
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div > maxdiv)
+			maxdiv = clkt->div;
+	return maxdiv;
+}
+
+static unsigned int hi3620_get_table_div(const struct clk_div_table *table,
+							unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+	return 0;
+}
+
+static unsigned int hi3620_get_table_val(const struct clk_div_table *table,
+					 unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned long hi3620_clkdiv_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct hi3620_divclk *dclk = container_of(hw, struct hi3620_divclk, hw);
+	unsigned int div, val;
+
+	val = readl_relaxed(dclk->reg) >> dclk->shift;
+	val &= WIDTH_TO_MASK(dclk->width);
+
+	div = hi3620_get_table_div(dclk->table, val);
+	if (!div) {
+		pr_warning("%s: Invalid divisor for clock %s\n", __func__,
+			   __clk_get_name(hw->clk));
+		return parent_rate;
+	}
+
+	return parent_rate / div;
+}
+
+static bool hi3620_is_valid_table_div(const struct clk_div_table *table,
+				      unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static int hi3620_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *best_parent_rate)
+{
+	struct hi3620_divclk *dclk = container_of(hw, struct hi3620_divclk, hw);
+	struct clk *clk_parent = __clk_get_parent(hw->clk);
+	int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	maxdiv = hi3620_get_table_maxdiv(dclk->table);
+
+	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+		parent_rate = *best_parent_rate;
+		bestdiv = DIV_ROUND_UP(parent_rate, rate);
+		bestdiv = bestdiv == 0 ? 1 : bestdiv;
+		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+		return bestdiv;
+	}
+
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		if (!hi3620_is_valid_table_div(dclk->table, i))
+			continue;
+		parent_rate = __clk_round_rate(clk_parent,
+					       MULT_ROUND_UP(rate, i));
+		now = parent_rate / i;
+		if (now <= rate && now > best) {
+			bestdiv = i;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = hi3620_get_table_maxdiv(dclk->table);
+		*best_parent_rate = __clk_round_rate(clk_parent, 1);
+	}
+
+	return bestdiv;
+}
+
+static long hi3620_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	int div;
+
+	if (!rate)
+		rate = 1;
+	div = hi3620_clkdiv_bestdiv(hw, rate, prate);
+
+	return *prate / div;
+}
+
+static int hi3620_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct hi3620_divclk *dclk = container_of(hw, struct hi3620_divclk, hw);
+	unsigned int div, value;
+	unsigned long flags = 0;
+	u32 data;
+
+	div = parent_rate / rate;
+	value = hi3620_get_table_val(dclk->table, div);
+
+	if (value > WIDTH_TO_MASK(dclk->width))
+		value = WIDTH_TO_MASK(dclk->width);
+
+	if (dclk->lock)
+		spin_lock_irqsave(dclk->lock, flags);
+
+	data = readl_relaxed(dclk->reg);
+	data &= ~(WIDTH_TO_MASK(dclk->width) << dclk->shift);
+	data |= value << dclk->shift;
+	data |= dclk->mbits;
+	writel_relaxed(data, dclk->reg);
+
+	if (dclk->lock)
+		spin_unlock_irqrestore(dclk->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops hi3620_clkdiv_ops = {
+	.recalc_rate = hi3620_clkdiv_recalc_rate,
+	.round_rate = hi3620_clkdiv_round_rate,
+	.set_rate = hi3620_clkdiv_set_rate,
+};
+
+void __init hi3620_clkdiv_setup(struct device_node *np)
+{
+	struct clk *clk;
+	const char *clk_name, **parent_names;
+	struct clk_init_data *init;
+	struct clk_div_table *table;
+	struct hi3620_divclk *dclk;
+	unsigned int table_num;
+	int i;
+	u32 data[2];
+	const char *propname = "hisilicon,clkdiv-table";
+	const char *cellname = "#hisilicon,clkdiv-table-cells";
+	struct of_phandle_args div_table;
+
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		return;
+	if (of_property_read_u32_array(np, "hisilicon,clkdiv",
+				       &data[0], 2))
+		return;
+
+	/*process the div_table*/
+	for (i = 0; ; i++) {
+		if (of_parse_phandle_with_args(np, propname, cellname,
+					       i, &div_table))
+			break;
+	}
+
+	/*table ends with <0, 0>, so plus one to table_num*/
+	table_num = i + 1;
+
+	table = kzalloc(sizeof(struct clk_div_table) * table_num, GFP_KERNEL);
+	if (!table)
+		return ;
+
+	for (i = 0; ; i++) {
+		if (of_parse_phandle_with_args(np, propname, cellname,
+					       i, &div_table))
+			break;
+
+		table[i].val = div_table.args[0];
+		table[i].div = div_table.args[1];
+	}
+
+	/* gate only has the fixed parent */
+	parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		goto err_par;
+	parent_names[0] = of_clk_get_parent_name(np, 0);
+
+	dclk = kzalloc(sizeof(*dclk), GFP_KERNEL);
+	if (!dclk)
+		goto err_dclk;
+	init = kzalloc(sizeof(*init), GFP_KERNEL);
+	if (!init)
+		goto err_init;
+	init->name = kstrdup(clk_name, GFP_KERNEL);
+	init->ops = &hi3620_clkdiv_ops;
+	init->parent_names = parent_names;
+	init->num_parents = 1;
+
+	dclk->reg = hs_clk.sctrl + data[0];
+	dclk->shift = ffs(data[1]) - 1;
+	dclk->width = fls(data[1]) - ffs(data[1]) + 1;
+	dclk->mbits = data[1] << 16;
+	dclk->lock = &hs_clk.lock;
+	dclk->hw.init = init;
+	dclk->table = table;
+	clk = clk_register(NULL, &dclk->hw);
+	if (IS_ERR(clk))
+		goto err_clk;
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return;
+err_clk:
+	kfree(init);
+err_init:
+	kfree(dclk);
+err_dclk:
+	kfree(parent_names);
+err_par:
+	kfree(table);
+}
+
+static const __initconst struct of_device_id hs_clk_match[] = {
+	{
+		.compatible = "fixed-clock",
+		.data = of_fixed_clk_setup,
+	}, {
+		.compatible = "hisilicon,hi3620-clk-mux",
+		.data = hi3620_clkmux_setup,
+	}, {
+		.compatible = "hisilicon,hi3620-clk-gate",
+		.data = hi3620_clkgate_setup,
+	}, {
+		.compatible = "hisilicon,hi3620-clk-div",
+		.data = hi3620_clkdiv_setup,
+	}, {
+		.compatible = "hisilicon,clk-gate",
+		.data = hs_clkgate_setup,
+	}, {
+		.compatible = "hisilicon,clk-fixed-factor",
+		.data = hs_fixed_factor_clk_setup,
+	},
+};
+
+void __init hs_init_clocks(void)
+{
+	struct device_node *node;
+
+	/* map pmctrl registers */
+	node = of_find_compatible_node(NULL, NULL, "hisilicon,pmctrl");
+	hs_clk.pmctrl = of_iomap(node, 0);
+	WARN_ON(!hs_clk.pmctrl);
+
+	node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
+	hs_clk.sctrl = of_iomap(node, 0);
+
+	of_clk_init(hs_clk_match);
+}
-- 
1.7.10.4

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

* [PATCH v2 09/14] ARM: hs: add board support with device tree
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (7 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 08/14] clk: hs: add clock support Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 10/14] ARM: hs: enable hi4511 " Haojian Zhuang
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add board support with device tree for Hisilicon Hi36xx/Hi37xx platform.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig              |    2 ++
 arch/arm/Makefile             |    1 +
 arch/arm/mach-hi3xxx/Kconfig  |   13 ++++++++++++
 arch/arm/mach-hi3xxx/Makefile |    5 +++++
 arch/arm/mach-hi3xxx/hi3xxx.c |   45 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 66 insertions(+)
 create mode 100644 arch/arm/mach-hi3xxx/Kconfig
 create mode 100644 arch/arm/mach-hi3xxx/Makefile
 create mode 100644 arch/arm/mach-hi3xxx/hi3xxx.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 10d7e2c..11ef3ea 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1060,6 +1060,8 @@ source "arch/arm/mach-gemini/Kconfig"
 
 source "arch/arm/mach-h720x/Kconfig"
 
+source "arch/arm/mach-hi3xxx/Kconfig"
+
 source "arch/arm/mach-highbank/Kconfig"
 
 source "arch/arm/mach-integrator/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ee4605f..4b0de9e 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -148,6 +148,7 @@ machine-$(CONFIG_ARCH_EBSA110)		+= ebsa110
 machine-$(CONFIG_ARCH_EP93XX)		+= ep93xx
 machine-$(CONFIG_ARCH_GEMINI)		+= gemini
 machine-$(CONFIG_ARCH_H720X)		+= h720x
+machine-$(CONFIG_ARCH_HI3xxx)		+= hi3xxx
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
 machine-$(CONFIG_ARCH_INTEGRATOR)	+= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		+= iop13xx
diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig
new file mode 100644
index 0000000..a991dee
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/Kconfig
@@ -0,0 +1,13 @@
+config ARCH_HI3xxx
+	bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
+	select ARM_AMBA
+	select ARM_GIC
+	select CACHE_L2X0
+	select CACHE_PL310
+	select CLKSRC_OF
+	select PINCTRL
+	select PINCTRL_SINGLE
+	select SERIAL_AMBA_PL011
+	select SERIAL_AMBA_PL011_CONSOLE
+	help
+	  Support for Hisilicon Hi36xx/Hi37xx processor family
diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
new file mode 100644
index 0000000..d68ebb3
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Hisilicon Hi36xx/Hi37xx processors line
+#
+
+obj-y	+= hi3xxx.o
diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
new file mode 100644
index 0000000..f93f8b9
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/hi3xxx.c
@@ -0,0 +1,45 @@
+/*
+ * (Hisilicon's Hi36xx/Hi37xx SoC based) flattened device tree enabled machine
+ *
+ * Copyright (c) 2012-2013 Hisilicon Ltd.
+ * Copyright (c) 2012-2013 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/clocksource.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+extern void __init hs_init_clocks(void);
+static void __init hi3xxx_timer_init(void)
+{
+	hs_init_clocks();
+	clocksource_of_init();
+}
+
+static void __init hs_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *hs_compat[] __initdata = {
+	"hisilicon,hi3620-hi4511",
+	NULL,
+};
+
+DT_MACHINE_START(HI3xxx, "Hisilicon Hi36xx/Hi37xx (Flattened Device Tree)")
+	/* Maintainer: Haojian Zhuang <haojian.zhuang@linaro.org> */
+	.map_io		= debug_ll_io_init,
+	.init_irq	= irqchip_init,
+	.init_time	= hi3xxx_timer_init,
+	.init_machine	= hs_init,
+	.dt_compat	= hs_compat,
+MACHINE_END
-- 
1.7.10.4

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

* [PATCH v2 10/14] ARM: hs: enable hi4511 with device tree
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (8 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 09/14] ARM: hs: add board support with device tree Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 11/14] ARM: config: append arch hs into multi defconfig Haojian Zhuang
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Enable Hisilicon Hi4511 development platform with device tree support.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/Makefile    |    1 +
 arch/arm/boot/dts/hi3620.dtsi | 1155 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/hi4511.dts  |  743 ++++++++++++++++++++++++++
 3 files changed, 1899 insertions(+)
 create mode 100644 arch/arm/boot/dts/hi3620.dtsi
 create mode 100644 arch/arm/boot/dts/hi4511.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 1d14ebb..3c0410e 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -49,6 +49,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos5250-smdk5250.dtb \
 	exynos5250-snow.dtb \
 	exynos5440-ssdk5440.dtb
+dtb-$(CONFIG_ARCH_HI3xxx) += hi4511.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
 	ecx-2000.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
new file mode 100644
index 0000000..e33fe7f
--- /dev/null
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -0,0 +1,1155 @@
+/*
+ * Hisilicon Ltd. Hi3620 SoC
+ *
+ * Copyright (C) 2012-2013 Hisilicon Ltd.
+ * Copyright (C) 2012-2013 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	osc32k: osc at 0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "osc32khz";
+	};
+	osc26m: osc at 1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "osc26mhz";
+	};
+	pclk: clk at 0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "apb_pclk";
+	};
+	pll_arm0: clk at 1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1600000000>;
+		clock-output-names = "armpll0";
+	};
+	pll_arm1: clk at 2 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1600000000>;
+		clock-output-names = "armpll1";
+	};
+	pll_peri: clk at 3 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1440000000>;
+		clock-output-names = "armpll2";
+	};
+	pll_usb: clk at 4 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1440000000>;
+		clock-output-names = "armpll3";
+	};
+	pll_hdmi: clk at 5 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1188000000>;
+		clock-output-names = "armpll4";
+	};
+	pll_gpu: clk at 6 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1300000000>;
+		clock-output-names = "armpll5";
+	};
+
+	amba {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "arm,amba-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		pmctrl: pmctrl at fca08000 {
+			compatible = "hisilicon,pmctrl";
+			reg = <0xfca08000 0x1000>;
+ 		};
+
+		sctrl: sctrl at fc802000 {
+			compatible = "hisilicon,sctrl";
+			reg = <0xfc802000 0x1000>;
+
+			refclk_uart0: refclk at 0 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "rclk_uart0";
+				/* each item value */
+				/* reg_offset, enable_bits */
+				hisilicon,hi3620-clkmux = <0x100 0x80>;
+			};
+			refclk_uart1: refclk at 1 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "rclk_uart1";
+				hisilicon,hi3620-clkmux = <0x100 0x100>;
+			};
+			refclk_uart2: refclk at 2 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "rclk_uart2";
+				hisilicon,hi3620-clkmux = <0x100 0x200>;
+			};
+			refclk_uart3: refclk at 3 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "rclk_uart3";
+				hisilicon,hi3620-clkmux = <0x100 0x400>;
+			};
+			refclk_uart4: refclk at 4 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "rclk_uart4";
+				hisilicon,hi3620-clkmux = <0x100 0x800>;
+			};
+			refclk_cfgaxi: refclk at 5 {
+				compatible = "hisilicon,clk-fixed-factor";
+				#clock-cells = <0>;
+				clocks = <&pll_peri>;
+				clock-output-names = "rclk_cfgaxi";
+				/*mult, div*/
+				hisilicon,fixed-factor = <1 30>;
+			};
+			refclk_spi0: refclk at 6 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &refclk_cfgaxi>;
+				clock-output-names = "rclk_spi0";
+				hisilicon,hi3620-clkmux = <0x100 0x1000>;
+			};
+			refclk_spi1: refclk at 7 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &refclk_cfgaxi>;
+				clock-output-names = "rclk_spi1";
+				hisilicon,hi3620-clkmux = <0x100 0x2000>;
+			};
+			refclk_spi2: refclk at 8 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &refclk_cfgaxi>;
+				clock-output-names = "rclk_spi2";
+				hisilicon,hi3620-clkmux = <0x100 0x4000>;
+			};
+			refclk_pwm0: refclk at 9 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &osc26m>;
+				clock-output-names = "rclk_pwm0";
+				hisilicon,hi3620-clkmux = <0x104 0x400>;
+			};
+			refclk_pwm1: refclk at 10 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &osc26m>;
+				clock-output-names = "rclk_pwm1";
+				hisilicon,hi3620-clkmux = <0x104 0x800>;
+			};
+			refclk_tcxo: refclk at 11 {
+				compatible = "hisilicon,clk-fixed-factor";
+				#clock-cells = <0>;
+				clocks = <&osc26m>;
+				clock-output-names = "rclk_tcxo";
+				hisilicon,fixed-factor = <1 4>;
+			};
+			refclk_timer0: refclk at 12 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk01>;
+				clock-output-names = "rclk_tim0";
+				hisilicon,hi3620-clkmux = <0 0x8000>;
+			};
+			refclk_timer1: refclk at 13 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk01>;
+				clock-output-names = "rclk_tim1";
+				hisilicon,hi3620-clkmux = <0 0x20000>;
+			};
+			refclk_timer2: refclk at 14 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk23>;
+				clock-output-names = "rclk_tim2";
+				hisilicon,hi3620-clkmux = <0 0x80000>;
+			};
+			refclk_timer3: refclk at 15 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk23>;
+				clock-output-names = "rclk_tim3";
+				hisilicon,hi3620-clkmux = <0 0x200000>;
+			};
+			refclk_timer4: refclk at 16 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk45>;
+				clock-output-names = "rclk_tim4";
+				hisilicon,hi3620-clkmux = <0x18 0x1>;
+			};
+			refclk_timer5: refclk at 17 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk45>;
+				clock-output-names = "rclk_tim5";
+				hisilicon,hi3620-clkmux = <0x18 0x4>;
+			};
+			refclk_timer6: refclk at 18 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk67>;
+				clock-output-names = "rclk_tim6";
+				hisilicon,hi3620-clkmux = <0x18 0x10>;
+			};
+			refclk_timer7: refclk at 19 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk67>;
+				clock-output-names = "rclk_tim7";
+				hisilicon,hi3620-clkmux = <0x18 0x40>;
+			};
+			refclk_timer8: refclk at 20 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk89>;
+				clock-output-names = "rclk_tim8";
+				hisilicon,hi3620-clkmux = <0x18 0x100>;
+			};
+			refclk_timer9: refclk at 21 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk89>;
+				clock-output-names = "rclk_tim9";
+				hisilicon,hi3620-clkmux = <0x18 0x400>;
+			};
+			refclk_shareAXI: refclk at 22 {
+				compatible = "hisilicon,hi3620-clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "rclk_shareAXI";
+				hisilicon,hi3620-clkmux = <0x24 0x8000>;
+			};
+			uartclk0: clkgate at 0 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_uart0>;
+				clock-output-names = "uartclk0";
+				hisilicon,hi3620-clkreset = <0x98 0x10000>;
+				hisilicon,hi3620-clkgate = <0x40 0x10000>;
+			};
+			uartclk1: clkgate at 1 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_uart1>;
+				clock-output-names = "uartclk1";
+				hisilicon,hi3620-clkreset = <0x98 0x20000>;
+				hisilicon,hi3620-clkgate = <0x40 0x20000>;
+			};
+			uartclk2: clkgate at 2 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_uart2>;
+				clock-output-names = "uartclk2";
+				hisilicon,hi3620-clkreset = <0x98 0x40000>;
+				hisilicon,hi3620-clkgate = <0x40 0x40000>;
+			};
+			uartclk3: clkgate at 3 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_uart3>;
+				clock-output-names = "uartclk3";
+				hisilicon,hi3620-clkreset = <0x98 0x80000>;
+				hisilicon,hi3620-clkgate = <0x40 0x80000>;
+			};
+			uartclk4: clkgate at 4 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_uart4>;
+				clock-output-names = "uartclk4";
+				hisilicon,hi3620-clkreset = <0x98 0x100000>;
+				hisilicon,hi3620-clkgate = <0x40 0x100000>;
+			};
+			gpioclk0: clkgate at 5 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk0";
+				hisilicon,hi3620-clkreset = <0x80 0x100>;
+				hisilicon,hi3620-clkgate = <0x20 0x100>;
+			};
+			gpioclk1: clkgate at 6 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk1";
+				hisilicon,hi3620-clkreset = <0x80 0x200>;
+				hisilicon,hi3620-clkgate = <0x20 0x200>;
+			};
+			gpioclk2: clkgate at 7 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk2";
+				hisilicon,hi3620-clkreset = <0x80 0x400>;
+				hisilicon,hi3620-clkgate = <0x20 0x400>;
+			};
+			gpioclk3: clkgate at 8 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk3";
+				hisilicon,hi3620-clkreset = <0x80 0x800>;
+				hisilicon,hi3620-clkgate = <0x20 0x800>;
+			};
+			gpioclk4: clkgate at 9 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk4";
+				hisilicon,hi3620-clkreset = <0x80 0x1000>;
+				hisilicon,hi3620-clkgate = <0x20 0x1000>;
+			};
+			gpioclk5: clkgate at 10 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk5";
+				hisilicon,hi3620-clkreset = <0x80 0x2000>;
+				hisilicon,hi3620-clkgate = <0x20 0x2000>;
+			};
+			gpioclk6: clkgate at 11 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk6";
+				hisilicon,hi3620-clkreset = <0x80 0x4000>;
+				hisilicon,hi3620-clkgate = <0x20 0x4000>;
+			};
+			gpioclk7: clkgate at 12 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk7";
+				hisilicon,hi3620-clkreset = <0x80 0x8000>;
+				hisilicon,hi3620-clkgate = <0x20 0x8000>;
+			};
+			gpioclk8: clkgate at 13 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk8";
+				hisilicon,hi3620-clkreset = <0x80 0x10000>;
+				hisilicon,hi3620-clkgate = <0x20 0x10000>;
+			};
+			gpioclk9: clkgate at 14 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk9";
+				hisilicon,hi3620-clkreset = <0x80 0x20000>;
+				hisilicon,hi3620-clkgate = <0x20 0x20000>;
+			};
+			gpioclk10: clkgate at 15 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk10";
+				hisilicon,hi3620-clkreset = <0x80 0x40000>;
+				hisilicon,hi3620-clkgate = <0x20 0x40000>;
+			};
+			gpioclk11: clkgate at 16 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk11";
+				hisilicon,hi3620-clkreset = <0x80 0x80000>;
+				hisilicon,hi3620-clkgate = <0x20 0x80000>;
+			};
+			gpioclk12: clkgate at 17 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk12";
+				hisilicon,hi3620-clkreset = <0x80 0x100000>;
+				hisilicon,hi3620-clkgate = <0x20 0x100000>;
+			};
+			gpioclk13: clkgate at 18 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk13";
+				hisilicon,hi3620-clkreset = <0x80 0x200000>;
+				hisilicon,hi3620-clkgate = <0x20 0x200000>;
+			};
+			gpioclk14: clkgate at 19 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk14";
+				hisilicon,hi3620-clkreset = <0x80 0x400000>;
+				hisilicon,hi3620-clkgate = <0x20 0x400000>;
+			};
+			gpioclk15: clkgate at 20 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk15";
+				hisilicon,hi3620-clkreset = <0x80 0x800000>;
+				hisilicon,hi3620-clkgate = <0x20 0x800000>;
+			};
+			gpioclk16: clkgate at 21 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk16";
+				hisilicon,hi3620-clkreset = <0x80 0x1000000>;
+				hisilicon,hi3620-clkgate = <0x20 0x1000000>;
+			};
+			gpioclk17: clkgate at 22 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk17";
+				hisilicon,hi3620-clkreset = <0x80 0x2000000>;
+				hisilicon,hi3620-clkgate = <0x20 0x2000000>;
+			};
+			gpioclk18: clkgate at 23 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk18";
+				hisilicon,hi3620-clkreset = <0x80 0x4000000>;
+				hisilicon,hi3620-clkgate = <0x20 0x4000000>;
+			};
+			gpioclk19: clkgate at 24 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk19";
+				hisilicon,hi3620-clkreset = <0x80 0x8000000>;
+				hisilicon,hi3620-clkgate = <0x20 0x8000000>;
+			};
+			gpioclk20: clkgate at 25 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk20";
+				hisilicon,hi3620-clkreset = <0x80 0x10000000>;
+				hisilicon,hi3620-clkgate = <0x20 0x10000000>;
+			};
+			gpioclk21: clkgate at 26 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk21";
+				hisilicon,hi3620-clkreset = <0x80 0x20000000>;
+				hisilicon,hi3620-clkgate = <0x20 0x20000000>;
+			};
+			spiclk0: clkgate at 27 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_spi0>;
+				clock-output-names = "spiclk0";
+				hisilicon,hi3620-clkreset = <0x98 0x200000>;
+				hisilicon,hi3620-clkgate = <0x40 0x200000>;
+			};
+			spiclk1: clkgate at 28 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_spi1>;
+				clock-output-names = "spiclk1";
+				hisilicon,hi3620-clkreset = <0x98 0x400000>;
+				hisilicon,hi3620-clkgate = <0x40 0x400000>;
+			};
+			spiclk2: clkgate at 29 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_spi2>;
+				clock-output-names = "spiclk2";
+				hisilicon,hi3620-clkreset = <0x98 0x800000>;
+				hisilicon,hi3620-clkgate = <0x40 0x800000>;
+			};
+			pwmclk0: clkgate at 30 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_pwm0>;
+				clock-output-names = "pwmclk0";
+				hisilicon,hi3620-clkreset = <0x98 0x80>;
+				hisilicon,hi3620-clkgate = <0x40 0x80>;
+			};
+			pwmclk1: clkgate at 31 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_pwm1>;
+				clock-output-names = "pwmclk1";
+				hisilicon,hi3620-clkreset = <0x98 0x100>;
+				hisilicon,hi3620-clkgate = <0x40 0x100>;
+			};
+			timerclk01: clkgate at 32 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_tcxo>;
+				clock-output-names = "timerclk01";
+				hisilicon,hi3620-clkreset = <0x80 0x1>;
+				hisilicon,hi3620-clkgate = <0x20 0x3>;
+			};
+			timerclk23: clkgate at 33 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_tcxo>;
+				clock-output-names = "timerclk23";
+				hisilicon,hi3620-clkreset = <0x80 0x2>;
+				hisilicon,hi3620-clkgate = <0x20 0xc>;
+			};
+			timerclk45: clkgate at 34 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_tcxo>;
+				clock-output-names = "timerclk45";
+				hisilicon,hi3620-clkreset = <0x98 0x8>;
+				hisilicon,hi3620-clkgate = <0x40 0x8>;
+			};
+			timerclk67: clkgate at 35 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_tcxo>;
+				clock-output-names = "timerclk67";
+				hisilicon,hi3620-clkreset = <0x98 0x10>;
+				hisilicon,hi3620-clkgate = <0x40 0x10>;
+			};
+			timerclk89: clkgate at 36 {
+				compatible = "hisilicon,hi3620-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_tcxo>;
+				clock-output-names = "timerclk89";
+				hisilicon,hi3620-clkreset = <0x98 0x20>;
+				hisilicon,hi3620-clkgate = <0x40 0x20>;
+			};
+			timclk0: clkgate at 37 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer0>;
+				clock-output-names = "timclk0";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0 16>;
+			};
+			timclk1: clkgate at 38 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer1>;
+				clock-output-names = "timclk1";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0 18>;
+			};
+			timclk2: clkgate at 39 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer2>;
+				clock-output-names = "timclk2";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0 20>;
+			};
+			timclk3: clkgate at 40 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer3>;
+				clock-output-names = "timclk3";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0 22>;
+			};
+			timclk4: clkgate at 41 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer4>;
+				clock-output-names = "timclk4";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0x18 0>;
+			};
+			timclk5: clkgate at 42 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer5>;
+				clock-output-names = "timclk5";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0x18 2>;
+			};
+			timclk6: clkgate at 43 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer6>;
+				clock-output-names = "timclk6";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0x18 4>;
+			};
+			timclk7: clkgate at 44 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer7>;
+				clock-output-names = "timclk7";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0x18 6>;
+			};
+			timclk8: clkgate at 45 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer8>;
+				clock-output-names = "timclk8";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0x18 8>;
+			};
+			timclk9: clkgate at 46 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&refclk_timer9>;
+				clock-output-names = "timclk9";
+				hisilicon,clkgate-inverted;
+				hisilicon,clkgate = <0x18 10>;
+			};
+			dtable: clkdiv at 0 {
+				#hisilicon,clkdiv-table-cells = <2>;
+			};
+			div_shareaxi: clkdiv at 1 {
+				compatible = "hisilicon,hi3620-clk-div";
+				#clock-cells = <0>;
+				clocks = <&refclk_shareAXI>;
+				clock-output-names = "shareAXI_div";
+				hisilicon,clkdiv-table = <
+					&dtable 0 1 &dtable 1 2 &dtable 2 3 &dtable 3 4
+					&dtable 4 5 &dtable 5 6 &dtable 6 7 &dtable 7 8
+					&dtable 8 9 &dtable 9 10 &dtable 10 11 &dtable 11 12
+					&dtable 12 13 &dtable 13 14 &dtable 14 15 &dtable 15 16
+					&dtable 16 17 &dtable 17 18 &dtable 18 19 &dtable 19 20
+					&dtable 20 21 &dtable 21 22 &dtable 22 23 &dtable 23 24
+					&dtable 24 25 &dtable 25 26 &dtable 26 27 &dtable 27 28
+					&dtable 28 29 &dtable 29 30 &dtable 30 31 &dtable 31 32>;
+				/* divider register offset, mask */
+				hisilicon,clkdiv = <0x100 0x1f>;
+			};
+			div_cfgaxi: clkdiv at 2 {
+				compatible = "hisilicon,hi3620-clk-div";
+				#clock-cells = <0>;
+				clocks = <&div_shareaxi>;
+				clock-output-names = "cfgAXI_div";
+				hisilicon,clkdiv-table = <&dtable 0x01 2>;
+				hisilicon,clkdiv = <0x100 0x60>;
+			};
+ 		};
+
+		l2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xfc10000 0x100000>;
+			interrupts = <0 15 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		intc: interrupt-controller at fc001000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			/* gic dist base, gic cpu base */
+			reg = <0xfc001000 0x1000>, <0xfc000100 0x100>;
+		};
+
+		timer0: timer at fc800000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfc800000 0x1000>;
+			/* timer00 & timer01 */
+			interrupts = <0 0 4>, <0 1 4>;
+			clocks = <&timclk0 &timclk1>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer1: timer at fc801000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfc801000 0x1000>;
+			/* timer10 & timer11 */
+			interrupts = <0 2 4>, <0 3 4>;
+			clocks = <&timclk2 &timclk3>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer2: timer at fca01000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfca01000 0x1000>;
+			/* timer20 & timer21 */
+			interrupts = <0 4 4>, <0 5 4>;
+			clocks = <&timclk4 &timclk5>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer3: timer at fca02000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfca02000 0x1000>;
+			/* timer30 & timer31 */
+			interrupts = <0 6 4>, <0 7 4>;
+			clocks = <&timclk6 &timclk7>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer4: timer at fca03000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfca03000 0x1000>;
+			/* timer40 & timer41 */
+			interrupts = <0 96 4>, <0 97 4>;
+			clocks = <&timclk8 &timclk9>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart0: uart at fcb00000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb00000 0x1000>;
+			interrupts = <0 20 4>;
+			clocks = <&uartclk0>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart1: uart at fcb01000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb01000 0x1000>;
+			interrupts = <0 21 4>;
+			clocks = <&uartclk1>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart2: uart at fcb02000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb02000 0x1000>;
+			interrupts = <0 22 4>;
+			clocks = <&uartclk2>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart3: uart at fcb03000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb03000 0x1000>;
+			interrupts = <0 23 4>;
+			clocks = <&uartclk3>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart4: uart at fcb04000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb04000 0x1000>;
+			interrupts = <0 24 4>;
+			clocks = <&uartclk4>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		gpio0: gpio at fc806000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc806000 0x1000>;
+			interrupts = <0 64 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 2 0 1 &pmx0 3 0 1 &pmx0 4 0 1
+					&pmx0 5 0 1 &pmx0 6 1 1 &pmx0 7 2 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk0>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio1: gpio at fc807000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc807000 0x1000>;
+			interrupts = <0 65 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 3 1 &pmx0 1 3 1 &pmx0 2 3 1
+					&pmx0 3 3 1 &pmx0 4 3 1 &pmx0 5 4 1
+					&pmx0 6 5 1 &pmx0 7 6 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk1>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio2: gpio at fc808000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc808000 0x1000>;
+			interrupts = <0 66 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 7 1 &pmx0 1 8 1 &pmx0 2 9 1
+					&pmx0 3 10 1 &pmx0 4 3 1 &pmx0 5 3 1
+					&pmx0 6 3 1 &pmx0 7 3 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk2>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio3: gpio at fc809000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc809000 0x1000>;
+			interrupts = <0 67 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 3 1 &pmx0 1 3 1 &pmx0 2 3 1
+					&pmx0 3 3 1 &pmx0 4 11 1 &pmx0 5 11 1
+					&pmx0 6 11 1 &pmx0 7 11 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk3>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio4: gpio at fc80a000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80a000 0x1000>;
+			interrupts = <0 68 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 11 1 &pmx0 1 11 1 &pmx0 2 11 1
+					&pmx0 3 11 1 &pmx0 4 12 1 &pmx0 5 12 1
+					&pmx0 6 13 1 &pmx0 7 13 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk4>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio5: gpio at fc80b000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80b000 0x1000>;
+			interrupts = <0 69 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 14 1 &pmx0 1 15 1 &pmx0 2 16 1
+					&pmx0 3 16 1 &pmx0 4 16 1 &pmx0 5 16 1
+					&pmx0 6 16 1 &pmx0 7 16 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk5>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio6: gpio at fc80c000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80c000 0x1000>;
+			interrupts = <0 70 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 16 1 &pmx0 1 16 1 &pmx0 2 17 1
+					&pmx0 3 17 1 &pmx0 4 18 1 &pmx0 5 18 1
+					&pmx0 6 18 1 &pmx0 7 19 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk6>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio7: gpio at fc80d000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80d000 0x1000>;
+			interrupts = <0 71 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 19 1 &pmx0 1 20 1 &pmx0 2 21 1
+					&pmx0 3 22 1 &pmx0 4 23 1 &pmx0 5 24 1
+					&pmx0 6 25 1 &pmx0 7 26 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk7>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio8: gpio at fc80e000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80e000 0x1000>;
+			interrupts = <0 72 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 27 1 &pmx0 1 28 1 &pmx0 2 29 1
+					&pmx0 3 30 1 &pmx0 4 31 1 &pmx0 5 32 1
+					&pmx0 6 33 1 &pmx0 7 34 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk8>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio9: gpio at fc80f000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80f000 0x1000>;
+			interrupts = <0 73 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 35 1 &pmx0 1 36 1 &pmx0 2 37 1
+					&pmx0 3 38 1 &pmx0 4 39 1 &pmx0 5 40 1
+					&pmx0 6 41 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk9>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio10: gpio at fc810000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc810000 0x1000>;
+			interrupts = <0 74 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 2 43 1 &pmx0 3 44 1 &pmx0 4 45 1
+					&pmx0 5 45 1 &pmx0 6 46 1 &pmx0 7 46 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk10>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio11: gpio at fc811000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc811000 0x1000>;
+			interrupts = <0 75 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 47 1 &pmx0 1 47 1 &pmx0 2 47 1
+					&pmx0 3 47 1 &pmx0 4 47 1 &pmx0 5 48 1
+					&pmx0 6 49 1 &pmx0 7 49 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk11>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio12: gpio at fc812000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc812000 0x1000>;
+			interrupts = <0 76 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 49 1 &pmx0 1 50 1 &pmx0 2 49 1
+					&pmx0 3 49 1 &pmx0 4 51 1 &pmx0 5 51 1
+					&pmx0 6 51 1 &pmx0 7 52 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk12>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio13: gpio at fc813000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc813000 0x1000>;
+			interrupts = <0 77 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 51 1 &pmx0 1 51 1 &pmx0 2 53 1
+					&pmx0 3 53 1 &pmx0 4 53 1 &pmx0 5 54 1
+					&pmx0 6 55 1 &pmx0 7 56 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk13>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio14: gpio at fc814000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc814000 0x1000>;
+			interrupts = <0 78 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 57 1 &pmx0 1 97 1 &pmx0 2 97 1
+					&pmx0 3 58 1 &pmx0 4 59 1 &pmx0 5 60 1
+					&pmx0 6 60 1 &pmx0 7 61 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk14>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio15: gpio at fc815000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc815000 0x1000>;
+			interrupts = <0 79 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 61 1 &pmx0 1 62 1 &pmx0 2 62 1
+					&pmx0 3 63 1 &pmx0 4 63 1 &pmx0 5 64 1
+					&pmx0 6 64 1 &pmx0 7 65 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk15>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio16: gpio at fc816000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc816000 0x1000>;
+			interrupts = <0 80 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 66 1 &pmx0 1 67 1 &pmx0 2 68 1
+					&pmx0 3 69 1 &pmx0 4 70 1 &pmx0 5 71 1
+					&pmx0 6 72 1 &pmx0 7 73 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk16>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio17: gpio at fc817000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc817000 0x1000>;
+			interrupts = <0 81 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 74 1 &pmx0 1 75 1 &pmx0 2 76 1
+					&pmx0 3 77 1 &pmx0 4 78 1 &pmx0 5 79 1
+					&pmx0 6 80 1 &pmx0 7 81 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk17>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio18: gpio at fc818000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc818000 0x1000>;
+			interrupts = <0 82 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 82 1 &pmx0 1 83 1 &pmx0 2 83 1
+					&pmx0 3 84 1 &pmx0 4 84 1 &pmx0 5 85 1
+					&pmx0 6 86 1 &pmx0 7 87 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk18>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio19: gpio at fc819000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc819000 0x1000>;
+			interrupts = <0 83 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 87 1 &pmx0 1 87 1 &pmx0 2 88 1
+					&pmx0 3 88 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk19>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio20: gpio at fc81a000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc81a000 0x1000>;
+			interrupts = <0 84 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 89 1 &pmx0 1 89 1 &pmx0 2 90 1
+					&pmx0 3 90 1 &pmx0 4 91 1 &pmx0 5 92 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk20>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		gpio21: gpio at fc81b000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc81b000 0x1000>;
+			interrupts = <0 85 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 3 94 1 &pmx0 7 96 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk21>;
+			clock-names = "apb_pclk";
+			status = "disable";
+		};
+
+		pmx0: pinmux at fc803000 {
+			compatible = "pinctrl-single";
+			reg = <0xfc803000 0x188>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			#gpio-range-cells = <3>;
+			ranges;
+
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <7>;
+			/* pin base, nr pins & gpio function */
+			pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
+						&range 12 1 0 &range 13 29 1
+						&range 43 1 0 &range 44 49 1
+						&range 94 1 1 &range 96 2 1>;
+
+			range: gpio-range {
+				#pinctrl-single,gpio-range-cells = <3>;
+			};
+		};
+
+		pmx1: pinmux at fc803800 {
+			compatible = "pinconf-single";
+			reg = <0xfc803800 0x2dc>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			pinctrl-single,register-width = <32>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
new file mode 100644
index 0000000..0a50faf
--- /dev/null
+++ b/arch/arm/boot/dts/hi4511.dts
@@ -0,0 +1,743 @@
+/*
+ *  Copyright (C) 2012-2013 Linaro Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ *  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.
+ */
+
+/dts-v1/;
+/include/ "hi3620.dtsi"
+
+/ {
+	model = "Hisilicon Hi4511 Development Board";
+	compatible = "hisilicon,hi3620-hi4511";
+
+	chosen {
+		bootargs = "console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on mem=512m earlyprintk";
+	};
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	amba {
+		timer0: timer at fc800000 {
+			arm,sp804-clockevent = <0>;
+			status = "ok";
+		};
+		timer1: timer at fc801000 {
+			arm,sp804-clocksource = <0x20>;
+			status = "ok";
+		};
+
+		uart0: uart at fcb00000 {	/* console */
+/*
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart0_pmx_func &uart0_cfg_func>;
+			pinctrl-1 = <&uart0_pmx_idle &uart0_cfg_idle>;
+*/
+			status = "ok";
+		};
+
+		uart1: uart at fcb01000 { /* modem */
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart1_pmx_func &uart1_cfg_func>;
+			pinctrl-1 = <&uart1_pmx_idle &uart1_cfg_idle>;
+			status = "ok";
+		};
+
+		uart2: uart at fcb02000 { /* audience */
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart2_pmx_func &uart2_cfg_func>;
+			pinctrl-1 = <&uart2_pmx_idle &uart2_cfg_idle>;
+			status = "ok";
+		};
+
+		uart3: uart at fcb03000 {
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart3_pmx_func &uart3_cfg_func>;
+			pinctrl-1 = <&uart3_pmx_idle &uart3_cfg_idle>;
+			status = "ok";
+		};
+
+		uart4: uart at fcb04000 {
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart4_pmx_func &uart4_cfg_func>;
+			pinctrl-1 = <&uart4_pmx_idle &uart4_cfg_func>;
+			status = "ok";
+		};
+
+		gpio0: gpio at fc806000 {
+			status = "ok";
+		};
+
+		gpio1: gpio at fc807000 {
+			status = "ok";
+		};
+
+		gpio2: gpio at fc808000 {
+			status = "ok";
+		};
+
+		gpio3: gpio at fc809000 {
+			status = "ok";
+		};
+
+		gpio4: gpio at fc80a000 {
+			status = "ok";
+		};
+
+		gpio5: gpio at fc80b000 {
+			status = "ok";
+		};
+
+		gpio6: gpio at fc80c000 {
+			status = "ok";
+		};
+
+		gpio7: gpio at fc80d000 {
+			status = "ok";
+		};
+
+		gpio8: gpio at fc80e000 {
+			status = "ok";
+		};
+
+		gpio9: gpio at fc80f000 {
+			status = "ok";
+		};
+
+		gpio10: gpio at fc810000 {
+			status = "ok";
+		};
+
+		gpio11: gpio at fc811000 {
+			status = "ok";
+		};
+
+		gpio12: gpio at fc812000 {
+			status = "ok";
+		};
+
+		gpio13: gpio at fc813000 {
+			status = "ok";
+		};
+
+		gpio14: gpio at fc814000 {
+			status = "ok";
+		};
+
+		gpio15: gpio at fc815000 {
+			status = "ok";
+		};
+
+		gpio16: gpio at fc816000 {
+			status = "ok";
+		};
+
+		gpio17: gpio at fc817000 {
+			status = "ok";
+		};
+
+		gpio18: gpio at fc818000 {
+			status = "ok";
+		};
+
+		gpio19: gpio at fc819000 {
+			status = "ok";
+		};
+
+		gpio20: gpio at fc81a000 {
+			status = "ok";
+		};
+
+		gpio21: gpio at fc81b000 {
+			status = "ok";
+		};
+
+		gpio-keys {
+			compatible = "gpio-keys";
+
+			call {
+				label = "call";
+				gpios = <&gpio17 2 0>;
+				linux,code = <169>;	/* KEY_PHONE */
+			};
+		};
+
+		pmx0: pinmux at fc803000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pmx_func>;
+
+			board_pmx_pins: pinmux_board_pmx_pins {
+				pinctrl-single,pins = <
+					0x008 0x0	/* GPIO -- eFUSE_DOUT */
+					0x100 0x0	/* USIM_CLK & USIM_DATA (IOMG63) */
+					0x104 0x0	/* USIM_RST (IOMG96) */
+				>;
+			};
+			uart0_pmx_func: pinmux_uart0_pins at 0  {
+				pinctrl-single,pins = <
+					0x0f0 0x0
+					0x0f4 0x0	/* UART0_RX & UART0_TX */
+				>;
+			};
+			uart0_pmx_idle: pinmux_uart0_pins at 1 {
+				pinctrl-single,pins = <
+					/*0x0f0 0x1*/	/* UART0_CTS & UART0_RTS */
+					0x0f4 0x1	/* UART0_RX & UART0_TX */
+				>;
+			};
+			uart1_pmx_func: pinmux_uart1_pins at 0  {
+				pinctrl-single,pins = <
+					0x0f8 0x0	/* UART1_CTS & UART1_RTS (IOMG61) */
+					0x0fc 0x0	/* UART1_RX & UART1_TX (IOMG62) */
+				>;
+			};
+			uart1_pmx_idle: pinmux_uart1_pins at 1  {
+				pinctrl-single,pins = <
+					0x0f8 0x1	/* GPIO (IOMG61) */
+					0x0fc 0x1	/* GPIO (IOMG62) */
+				>;
+			};
+			uart2_pmx_func: pinmux_uart2_pins at 0 {
+				pinctrl-single,pins = <
+					0x104 0x2	/* UART2_RXD (IOMG96) */
+					0x108 0x2	/* UART2_TXD (IOMG64) */
+				>;
+			};
+			uart2_pmx_idle: pinmux_uart2_pins at 1 {
+				pinctrl-single,pins = <
+					0x104 0x1	/* GPIO (IOMG96) */
+					0x108 0x1	/* GPIO (IOMG64) */
+				>;
+			};
+			uart3_pmx_func: pinmux_uart3_pins at 0 {
+				pinctrl-single,pins = <
+					0x160 0x2	/* UART3_CTS & UART3_RTS (IOMG85) */
+					0x164 0x2	/* UART3_RXD & UART3_TXD (IOMG86) */
+				>;
+			};
+			uart3_pmx_idle: pinmux_uart3_pins at 1 {
+				pinctrl-single,pins = <
+					0x160 0x1	/* GPIO (IOMG85) */
+					0x164 0x1	/* GPIO (IOMG86) */
+				>;
+			};
+			uart4_pmx_func: pinmux_uart4_pins at 0 {
+				pinctrl-single,pins = <
+					0x168 0x0	/* UART4_CTS & UART4_RTS (IOMG87) */
+					0x16c 0x0	/* UART4_RXD (IOMG88) */
+					0x170 0x0	/* UART4_TXD (IOMG93) */
+				>;
+			};
+			uart4_pmx_idle: pinmux_uart4_pins at 1 {
+				pinctrl-single,pins = <
+					0x168 0x1	/* GPIO (IOMG87) */
+					0x16c 0x1	/* GPIO (IOMG88) */
+					0x170 0x1	/* GPIO (IOMG93) */
+				>;
+			};
+			i2c0_pmx_func: pinmux_i2c0_pins at 0 {
+				pinctrl-single,pins = <
+					0x0b4 0x0	/* I2C0_SCL & I2C0_SDA (IOMG45) */
+				>;
+			};
+			i2c0_pmx_idle: pinmux_i2c0_pins at 1 {
+				pinctrl-single,pins = <
+					0x0b4 0x1	/* GPIO (IOMG45) */
+				>;
+			};
+			i2c1_pmx_func: pinmux_i2c1_pins at 0 {
+				pinctrl-single,pins = <
+					0x0b8 0x0	/* I2C1_SCL & I2C1_SDA (IOMG46) */
+				>;
+			};
+			i2c1_pmx_idle: pinmux_i2c1_pins at 1 {
+				pinctrl-single,pins = <
+					0x0b8 0x1	/* GPIO (IOMG46) */
+				>;
+			};
+			i2c2_pmx_func: pinmux_i2c2_pins at 0 {
+				pinctrl-single,pins = <
+					0x068 0x0	/* I2C2_SCL (IOMG26) */
+					0x06c 0x0	/* I2C2_SDA (IOMG27) */
+				>;
+			};
+			i2c2_pmx_idle: pinmux_i2c2_pins at 0 {
+				pinctrl-single,pins = <
+					0x068 0x1	/* GPIO (IOMG26) */
+					0x06c 0x1	/* GPIO (IOMG27) */
+				>;
+			};
+			i2c3_pmx_func: pinmux_i2c3_pins at 0 {
+				pinctrl-single,pins = <
+					0x050 0x2	/* I2C3_SCL (IOMG20) */
+					0x054 0x2	/* I2C3_SDA (IOMG21) */
+				>;
+			};
+			i2c3_pmx_idle: pinmux_i2c3_pins at 0 {
+				pinctrl-single,pins = <
+					0x050 0x1	/* GPIO (IOMG20) */
+					0x054 0x1	/* GPIO (IOMG21) */
+				>;
+			};
+			spi0_pmx_func: pinmux_spi0_pins at 0 {
+				pinctrl-single,pins = <
+					0x0d4 0x0	/* SPI0_CLK/SPI0_DI/SPI0_DO (IOMG53) */
+					0x0d8 0x0	/* SPI0_CS0 (IOMG54) */
+					0x0dc 0x0	/* SPI0_CS1 (IOMG55) */
+					0x0e0 0x0	/* SPI0_CS2 (IOMG56) */
+					0x0e4 0x0	/* SPI0_CS3 (IOMG57) */
+				>;
+			};
+			spi0_pmx_idle: pinmux_spi0_pins at 1 {
+				pinctrl-single,pins = <
+					0x0d4 0x1	/* GPIO (IOMG53) */
+					0x0d8 0x1	/* GPIO (IOMG54) */
+					0x0dc 0x1	/* GPIO (IOMG55) */
+					0x0e0 0x1	/* GPIO (IOMG56) */
+					0x0e4 0x1	/* GPIO (IOMG57) */
+				>;
+			};
+			spi1_pmx_func: pinmux_spi1_pins at 0 {
+				pinctrl-single,pins = <
+					0x184 0x0	/* SPI1_CLK/SPI1_DI (IOMG98) */
+					0x0e8 0x0	/* SPI1_DO (IOMG58) */
+					0x0ec 0x0	/* SPI1_CS (IOMG95) */
+				>;
+			};
+			spi1_pmx_idle: pinmux_spi1_pins at 1 {
+				pinctrl-single,pins = <
+					0x184 0x1	/* GPIO (IOMG98) */
+					0x0e8 0x1	/* GPIO (IOMG58) */
+					0x0ec 0x1	/* GPIO (IOMG95) */
+				>;
+			};
+			kpc_pmx_func: pinmux_kpc_pins at 0 {
+				pinctrl-single,pins = <
+					0x12c 0x0	/* KEY_IN0 (IOMG73) */
+					0x130 0x0	/* KEY_IN1 (IOMG74) */
+					0x134 0x0	/* KEY_IN2 (IOMG75) */
+					0x10c 0x0	/* KEY_OUT0 (IOMG65) */
+					0x110 0x0	/* KEY_OUT1 (IOMG66) */
+					0x114 0x0	/* KEY_OUT2 (IOMG67) */
+				>;
+			};
+			kpc_pmx_idle: pinmux_kpc_pins at 1 {
+				pinctrl-single,pins = <
+					0x12c 0x1	/* GPIO (IOMG73) */
+					0x130 0x1	/* GPIO (IOMG74) */
+					0x134 0x1	/* GPIO (IOMG75) */
+					0x10c 0x1	/* GPIO (IOMG65) */
+					0x110 0x1	/* GPIO (IOMG66) */
+					0x114 0x1	/* GPIO (IOMG67) */
+				>;
+			};
+			gpio_key_func: pinmux_gpiokey_pins {
+				pinctrl-single,pins = <
+					0x10c 0x1	/* KEY_OUT0/GPIO (IOMG65) */
+					0x130 0x1	/* KEY_IN1/GPIO (IOMG74) */
+				>;
+			};
+			emmc_pmx_func: pinmux_emmc_pins at 0 {
+				pinctrl-single,pins = <
+					0x030 0x2	/* eMMC_CMD/eMMC_CLK (IOMG12) */
+					0x018 0x0	/* NAND_CS3_N (IOMG6) */
+					0x024 0x0	/* NAND_BUSY2_N (IOMG8) */
+					0x028 0x0	/* NAND_BUSY3_N (IOMG9) */
+					0x02c 0x2	/* eMMC_DATA[0:7] (IOMG10) */
+				>;
+			};
+			emmc_pmx_idle: pinmux_emmc_pins at 1 {
+				pinctrl-single,pins = <
+					0x030 0x0	/* GPIO (IOMG12) */
+					0x018 0x1	/* GPIO (IOMG6) */
+					0x024 0x1	/* GPIO (IOMG8) */
+					0x028 0x1	/* GPIO (IOMG9) */
+					0x02c 0x1	/* GPIO (IOMG10) */
+				>;
+			};
+			sd_pmx_func: pinmux_sd_pins at 0 {
+				pinctrl-single,pins = <
+					0x0bc 0x0	/* SD_CLK/SD_CMD/SD_DATA0/SD_DATA1/SD_DATA2 (IOMG47) */
+					0x0c0 0x0	/* SD_DATA3 (IOMG48) */
+				>;
+			};
+			sd_pmx_idle: pinmux_sd_pins at 1 {
+				pinctrl-single,pins = <
+					0x0bc 0x1	/* GPIO (IOMG47) */
+					0x0c0 0x1	/* GPIO (IOMG48) */
+				>;
+			};
+			nand_pmx_func: pinmux_nand_pins at 0 {
+				pinctrl-single,pins = <
+					0x00c 0x0	/* NAND_ALE/NAND_CLE/.../NAND_DATA[0:7] (IOMG3) */
+					0x010 0x0	/* NAND_CS1_N (IOMG4) */
+					0x014 0x0	/* NAND_CS2_N (IOMG5) */
+					0x018 0x0	/* NAND_CS3_N (IOMG6) */
+					0x01c 0x0	/* NAND_BUSY0_N (IOMG94) */
+					0x020 0x0	/* NAND_BUSY1_N (IOMG7) */
+					0x024 0x0	/* NAND_BUSY2_N (IOMG8) */
+					0x028 0x0	/* NAND_BUSY3_N (IOMG9) */
+					0x02c 0x0	/* NAND_DATA[8:15] (IOMG10) */
+				>;
+			};
+			nand_pmx_idle: pinmux_nand_pins at 1 {
+				pinctrl-single,pins = <
+					0x00c 0x1	/* GPIO (IOMG3) */
+					0x010 0x1	/* GPIO (IOMG4) */
+					0x014 0x1	/* GPIO (IOMG5) */
+					0x018 0x1	/* GPIO (IOMG6) */
+					0x01c 0x1	/* GPIO (IOMG94) */
+					0x020 0x1	/* GPIO (IOMG7) */
+					0x024 0x1	/* GPIO (IOMG8) */
+					0x028 0x1	/* GPIO (IOMG9) */
+					0x02c 0x1	/* GPIO (IOMG10) */
+				>;
+			};
+			sdio_pmx_func: pinmux_sdio_pins at 0 {
+				pinctrl-single,pins = <
+					0x0c4 0x0	/* SDIO_CLK/SDIO_CMD/SDIO_DATA[0:3] (IOMG49) */
+				>;
+			};
+			sdio_pmx_idle: pinmux_sdio_pins at 1 {
+				pinctrl-single,pins = <
+					0x0c4 0x1	/* GPIO (IOMG49) */
+				>;
+			};
+			audio_out_pmx_func: pinmux_audio_pins at 0 {
+				pinctrl-single,pins = <
+					0x0f0 0x1	/* GPIO (IOMG59), audio spk & earphone */
+				>;
+			};
+		};
+
+		pmx1: pinmux at fc803800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <	&board_pu_pins &board_pd_pins &board_pd_ps_pins
+					&board_np_pins &board_ps_pins &kpc_cfg_func
+					&audio_out_cfg_func>;
+			board_pu_pins: pinmux_board_pu_pins {
+				pinctrl-single,pins = <
+					0x014 0		/* GPIO_158 (IOCFG2) */
+					0x018 0		/* GPIO_159 (IOCFG3) */
+					0x01c 0		/* BOOT_MODE0 (IOCFG4) */
+					0x020 0		/* BOOT_MODE1 (IOCFG5) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+			};
+			board_pd_pins: pinmux_board_pd_pins {
+				pinctrl-single,pins = <
+					0x038 0		/* eFUSE_DOUT (IOCFG11) */
+					0x150 0		/* ISP_GPIO8 (IOCFG93) */
+					0x154 0		/* ISP_GPIO9 (IOCFG94) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			board_pd_ps_pins: pinmux_board_pd_ps_pins {
+				pinctrl-single,pins = <
+					0x2d8 0		/* CLK_OUT0 (IOCFG190) */
+					0x004 0		/* PMU_SPI_DATA (IOCFG192) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			board_np_pins: pinmux_board_np_pins {
+				pinctrl-single,pins = <
+					0x24c 0		/* KEYPAD_OUT7 (IOCFG155) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			board_ps_pins: pinmux_board_ps_pins {
+				pinctrl-single,pins = <
+					0x000 0		/* PMU_SPI_CLK (IOCFG191) */
+					0x008 0		/* PMU_SPI_CS_N (IOCFG193) */
+				>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			uart0_cfg_func: pinmux_uart0_pins at 2 {
+				pinctrl-single,pins = <
+					0x208 0		/* UART0_RXD (IOCFG138) */
+					0x20c 0		/* UART0_TXD (IOCFG139) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart0_cfg_idle: pinmux_uart0_pins at 3 {
+				pinctrl-single,pins = <
+					0x208 0		/* UART0_RXD (IOCFG138) */
+					0x20c 0		/* UART0_TXD (IOCFG139) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart1_cfg_func: pinmux_uart1_pins at 2 {
+				pinctrl-single,pins = <
+					0x210 0		/* UART1_CTS (IOCFG140) */
+					0x214 0		/* UART1_RTS (IOCFG141) */
+					0x218 0		/* UART1_RXD (IOCFG142) */
+					0x21c 0		/* UART1_TXD (IOCFG143) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart1_cfg_idle: pinmux_uart1_pins at 3 {
+				pinctrl-single,pins = <
+					0x210 0		/* UART1_CTS (IOCFG140) */
+					0x214 0		/* UART1_RTS (IOCFG141) */
+					0x218 0		/* UART1_RXD (IOCFG142) */
+					0x21c 0		/* UART1_TXD (IOCFG143) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart2_cfg_func: pinmux_uart2_pins at 2 {
+				pinctrl-single,pins = <
+					0x220 0		/* UART2_CTS (IOCFG144) */
+					0x224 0		/* UART2_RTS (IOCFG145) */
+					0x228 0		/* UART2_RXD (IOCFG146) */
+					0x22c 0		/* UART2_TXD (IOCFG147) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart2_cfg_idle: pinmux_uart2_pins at 3 {
+				pinctrl-single,pins = <
+					0x220 0		/* GPIO (IOCFG144) */
+					0x224 0		/* GPIO (IOCFG145) */
+					0x228 0		/* GPIO (IOCFG146) */
+					0x22c 0		/* GPIO (IOCFG147) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart3_cfg_func: pinmux_uart3_pins at 2 {
+				pinctrl-single,pins = <
+					0x294 0		/* UART3_CTS (IOCFG173) */
+					0x298 0		/* UART3_RTS (IOCFG174) */
+					0x29c 0		/* UART3_RXD (IOCFG175) */
+					0x2a0 0		/* UART3_TXD (IOCFG176) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart3_cfg_idle: pinmux_uart3_pins at 3 {
+				pinctrl-single,pins = <
+					0x294 0		/* UART3_CTS (IOCFG173) */
+					0x298 0		/* UART3_RTS (IOCFG174) */
+					0x29c 0		/* UART3_RXD (IOCFG175) */
+					0x2a0 0		/* UART3_TXD (IOCFG176) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart4_cfg_func: pinmux_uart4_pins at 2 {
+				pinctrl-single,pins = <
+					0x2a4 0		/* UART4_CTS (IOCFG177) */
+					0x2a8 0		/* UART4_RTS (IOCFG178) */
+					0x2ac 0		/* UART4_RXD (IOCFG179) */
+					0x2b0 0		/* UART4_TXD (IOCFG180) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			i2c0_cfg_func: pinmux_i2c0_pins at 2 {
+				pinctrl-single,pins = <
+					0x17c 0		/* I2C0_SCL (IOCFG103) */
+					0x180 0		/* I2C0_SDA (IOCFG104) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			i2c1_cfg_func: pinmux_i2c1_pins at 2 {
+				pinctrl-single,pins = <
+					0x184 0		/* I2C1_SCL (IOCFG105) */
+					0x188 0		/* I2C1_SDA (IOCFG106) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			i2c2_cfg_func: pinmux_i2c2_pins at 2 {
+				pinctrl-single,pins = <
+					0x118 0		/* I2C2_SCL (IOCFG79) */
+					0x11c 0		/* I2C2_SDA (IOCFG80) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			i2c3_cfg_func: pinmux_i2c3_pins at 2 {
+				pinctrl-single,pins = <
+					0x100 0		/* I2C3_SCL (IOCFG73) */
+					0x104 0		/* I2C3_SDA (IOCFG74) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi0_cfg_func1: pinmux_spi0_pins at 2 {
+				pinctrl-single,pins = <
+					0x1d4 0		/* SPI0_CLK (IOCFG125) */
+					0x1d8 0		/* SPI0_DI (IOCFG126) */
+					0x1dc 0		/* SPI0_DO (IOCFG127) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi0_cfg_func2: pinmux_spi0_pins at 3 {
+				pinctrl-single,pins = <
+					0x1e0 0		/* SPI0_CS0 (IOCFG128) */
+					0x1e4 0		/* SPI0_CS1 (IOCFG129) */
+					0x1e8 0		/* SPI0_CS2 (IOCFG130 */
+					0x1ec 0		/* SPI0_CS3 (IOCFG131) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi1_cfg_func1: pinmux_spi1_pins at 2 {
+				pinctrl-single,pins = <
+					0x1f0 0		/* SPI1_CLK (IOCFG132) */
+					0x1f4 0		/* SPI1_DI (IOCFG133) */
+					0x1f8 0		/* SPI1_DO (IOCFG134) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi1_cfg_func2: pinmux_spi1_pins at 3 {
+				pinctrl-single,pins = <
+					0x1fc 0		/* SPI1_CS (IOCFG135) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			kpc_cfg_func: pinmux_kpc_pins at 2 {
+				pinctrl-single,pins = <
+					0x250 0		/* KEY_IN0 (IOCFG156) */
+					0x254 0		/* KEY_IN1 (IOCFG157) */
+					0x258 0		/* KEY_IN2 (IOCFG158) */
+					0x230 0		/* KEY_OUT0 (IOCFG148) */
+					0x234 0		/* KEY_OUT1 (IOCFG149) */
+					0x238 0		/* KEY_OUT2 (IOCFG150) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			emmc_cfg_func: pinmux_emmc_pins at 2 {
+				pinctrl-single,pins = <
+					0x0ac 0		/* eMMC_CMD (IOCFG40) */
+					0x0b0 0		/* eMMC_CLK (IOCFG41) */
+					0x058 0		/* NAND_CS3_N (IOCFG19) */
+					0x064 0		/* NAND_BUSY2_N (IOCFG22) */
+					0x068 0		/* NAND_BUSY3_N (IOCFG23) */
+					0x08c 0		/* NAND_DATA8 (IOCFG32) */
+					0x090 0		/* NAND_DATA9 (IOCFG33) */
+					0x094 0		/* NAND_DATA10 (IOCFG34) */
+					0x098 0		/* NAND_DATA11 (IOCFG35) */
+					0x09c 0		/* NAND_DATA12 (IOCFG36) */
+					0x0a0 0		/* NAND_DATA13 (IOCFG37) */
+					0x0a4 0		/* NAND_DATA14 (IOCFG38) */
+					0x0a8 0		/* NAND_DATA15 (IOCFG39) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			sd_cfg_func1: pinmux_sd_pins at 2 {
+				pinctrl-single,pins = <
+					0x18c 0		/* SD_CLK (IOCFG107) */
+					0x190 0		/* SD_CMD (IOCFG108) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			sd_cfg_func2: pinmux_sd_pins at 3 {
+				pinctrl-single,pins = <
+					0x194 0		/* SD_DATA0 (IOCFG109) */
+					0x198 0		/* SD_DATA1 (IOCFG110) */
+					0x19c 0		/* SD_DATA2 (IOCFG111) */
+					0x1a0 0		/* SD_DATA3 (IOCFG112) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x70 0xf0>;
+			};
+			nand_cfg_func1: pinmux_nand_pins at 2 {
+				pinctrl-single,pins = <
+					0x03c 0		/* NAND_ALE (IOCFG12) */
+					0x040 0		/* NAND_CLE (IOCFG13) */
+					0x06c 0		/* NAND_DATA0 (IOCFG24) */
+					0x070 0		/* NAND_DATA1 (IOCFG25) */
+					0x074 0		/* NAND_DATA2 (IOCFG26) */
+					0x078 0		/* NAND_DATA3 (IOCFG27) */
+					0x07c 0		/* NAND_DATA4 (IOCFG28) */
+					0x080 0		/* NAND_DATA5 (IOCFG29) */
+					0x084 0		/* NAND_DATA6 (IOCFG30) */
+					0x088 0		/* NAND_DATA7 (IOCFG31) */
+					0x08c 0		/* NAND_DATA8 (IOCFG32) */
+					0x090 0		/* NAND_DATA9 (IOCFG33) */
+					0x094 0		/* NAND_DATA10 (IOCFG34) */
+					0x098 0		/* NAND_DATA11 (IOCFG35) */
+					0x09c 0		/* NAND_DATA12 (IOCFG36) */
+					0x0a0 0		/* NAND_DATA13 (IOCFG37) */
+					0x0a4 0		/* NAND_DATA14 (IOCFG38) */
+					0x0a8 0		/* NAND_DATA15 (IOCFG39) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			nand_cfg_func2: pinmux_nand_pins at 3 {
+				pinctrl-single,pins = <
+					0x044 0		/* NAND_RE_N (IOCFG14) */
+					0x048 0		/* NAND_WE_N (IOCFG15) */
+					0x04c 0		/* NAND_CS0_N (IOCFG16) */
+					0x050 0		/* NAND_CS1_N (IOCFG17) */
+					0x054 0		/* NAND_CS2_N (IOCFG18) */
+					0x058 0		/* NAND_CS3_N (IOCFG19) */
+					0x05c 0		/* NAND_BUSY0_N (IOCFG20) */
+					0x060 0		/* NAND_BUSY1_N (IOCFG21) */
+					0x064 0		/* NAND_BUSY2_N (IOCFG22) */
+					0x068 0		/* NAND_BUSY3_N (IOCFG23) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			sdio_cfg_func: pinmux_sdio_pins at 2 {
+				pinctrl-single,pins = <
+					0x1a4 0		/* SDIO0_CLK (IOCG113) */
+					0x1a8 0		/* SDIO0_CMD (IOCG114) */
+					0x1ac 0		/* SDIO0_DATA0 (IOCG115) */
+					0x1b0 0		/* SDIO0_DATA1 (IOCG116) */
+					0x1b4 0		/* SDIO0_DATA2 (IOCG117) */
+					0x1b8 0		/* SDIO0_DATA3 (IOCG118) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			audio_out_cfg_func: pinmux_audio_pins at 1 {
+				pinctrl-single,pins = <
+					0x200 0		/* GPIO (IOCFG136) */
+					0x204 0		/* GPIO (IOCFG137) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+		};
+	};
+};
-- 
1.7.10.4

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

* [PATCH v2 11/14] ARM: config: append arch hs into multi defconfig
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (9 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 10/14] ARM: hs: enable hi4511 " Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 12/14] Document: append hisilicon clock binding Haojian Zhuang
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Append ARCH_HI3xxx (Hisilicon SoC) into multi_v7_defconfig.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/configs/multi_v7_defconfig |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index e31d442..1891611 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -5,6 +5,7 @@ CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_HI3xxx=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_ARCH_SUNXI=y
 # CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
-- 
1.7.10.4

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

* [PATCH v2 12/14] Document: append hisilicon clock binding
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (10 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 11/14] ARM: config: append arch hs into multi defconfig Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 13/14] Document: dts: create hisilicon document Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 14/14] Document: add device tree binding file for sp804 Haojian Zhuang
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add hisilicon clock binding document for device tree.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 .../devicetree/bindings/clock/hisilicon.txt        |   73 ++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/hisilicon.txt

diff --git a/Documentation/devicetree/bindings/clock/hisilicon.txt b/Documentation/devicetree/bindings/clock/hisilicon.txt
new file mode 100644
index 0000000..be8db9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hisilicon.txt
@@ -0,0 +1,73 @@
+Device Tree Clock bindings for arch-vt8500
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties for mux clocks:
+ - compatible : Shall be "hisilicon,hi3620-clk-mux".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - hisilicon,hi3620-mux : array of mux register offset & mask bits
+
+Required properties for Hi3620 gate clocks:
+ - compatible : Shall be "hisilicon,hi3620-clk-gate".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - hisilicon,hi3620-clkgate : array of enable register offset & enable bits
+ - hisilicon,hi3620-clkreset : array of reset register offset & enable bits
+
+Required properties for clock divider:
+ - compatible : Shall be "hisilicon,hi3620-clk-div".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - #hisilicon,clkdiv-table-cells : the number of parameters after phandle in
+   hisilicon,clkdiv-table property.
+ - hisilicon,clkdiv-table : list of value that are used to configure clock
+   divider. They're value of phandle, index & divider value.
+ - hisilicon,clkdiv : array of divider register offset & mask bits.
+
+Required properties for gate clocks:
+ - compatible : Shall be "hisilicon,clk-gate".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - hisilicon,clkgate-inverted : bool value. True means that set-to-disable.
+
+Required properties for clock fixed factor divider:
+ - compatible : Shall be "hisilicon,fixed-factor".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - hisilicon,fixed-factor : array of multiplier & divider.
+
+For example:
+	timclk1: clkgate at 38 {
+		compatible = "hisilicon,clk-gate";
+		#clock-cells = <0>;
+		clocks = <&refclk_timer1>;
+		clock-output-names = "timclk1";
+		hisilicon,clkgate-inverted;
+		hisilicon,clkgate = <0 18>;
+	};
+
+	dtable: clkdiv at 0 {
+		#hisilicon,clkdiv-table-cells = <2>;
+	};
+
+	div_cfgaxi: clkdiv at 2 {
+		compatible = "hisilicon,hi3620-clk-div";
+		#clock-cells = <0>;
+		clocks = <&div_shareaxi>;
+		clock-output-names = "cfgAXI_div";
+		hisilicon,clkdiv-table = <&dtable 0x01 2>;
+		hisilicon,clkdiv = <0x100 0x60>;
+	};
-- 
1.7.10.4

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

* [PATCH v2 13/14] Document: dts: create hisilicon document
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (11 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 12/14] Document: append hisilicon clock binding Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 17:08 ` [PATCH v2 14/14] Document: add device tree binding file for sp804 Haojian Zhuang
  13 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Append the illustration on two boards from hisilicon.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 .../devicetree/bindings/arm/hisilicon/hisilicon.txt          |   10 ++++++++++
 1 file changed, 10 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
new file mode 100644
index 0000000..3be60c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -0,0 +1,10 @@
+Hisilicon Platforms Device Tree Bindings
+----------------------------------------------------
+
+Hi3716 Development Board
+Required root node properties:
+	- compatible = "hisilicon,hi3716-dkb";
+
+Hi4511 Board
+Required root node properties:
+	- compatible = "hisilicon,hi3620-hi4511";
-- 
1.7.10.4

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

* [PATCH v2 14/14] Document: add device tree binding file for sp804
  2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
                   ` (12 preceding siblings ...)
  2013-03-12 17:08 ` [PATCH v2 13/14] Document: dts: create hisilicon document Haojian Zhuang
@ 2013-03-12 17:08 ` Haojian Zhuang
  2013-03-12 19:02   ` Arnd Bergmann
  13 siblings, 1 reply; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-12 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add binding document for sp804 dual timer.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 .../devicetree/bindings/timer/arm,sp804.txt        |   27 ++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/arm,sp804.txt

diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
new file mode 100644
index 0000000..ec1ae45
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
@@ -0,0 +1,27 @@
+ARM sp804 Dual Timers
+---------------------------------------
+
+Required properties:
+- compatible: Should be "arm,sp804" & "arm,primecell"
+- interrupts: Should contain the list of Dual Timer interrupts
+	interrupts = <0 0 4>, <0 1 4>;
+- reg: Should contain location and length for dual timer register.
+- clocks: clock driving the dual timer hardware
+	clocks = <&timclk0 &timclk1>;
+
+Optional properties:
+- arm,sp804-clocksource: Should contain the register offset of TIMER1 or
+  TIMER2 in Dual Timer Controller.
+	arm,sp804-clocksource = <0x20>;
+
+Example:
+
+	timer0: timer at fc800000 {
+		compatible = "arm,sp804", "arm,primecell";
+		reg = <0xfc800000 0x1000>;
+		/* timer00 & timer01 */
+		interrupts = <0 0 4>, <0 1 4>;
+		clocks = <&timclk0 &timclk1>;
+		clock-names = "apb_pclk";
+		status = "disabled";
+	};
-- 
1.7.10.4

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

* [PATCH v2 01/14] clocksource: move sp timer driver
  2013-03-12 17:08 ` [PATCH v2 01/14] clocksource: move sp timer driver Haojian Zhuang
@ 2013-03-12 18:11   ` Arnd Bergmann
  2013-03-13  2:20     ` Haojian Zhuang
  2013-03-12 19:08   ` Russell King - ARM Linux
  1 sibling, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 18:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Haojian,

The patch looks good in principle, but I have two comments:

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> Move ARM SP804 timer driver from arch/arm directory into
> drivers/clocksource directory.

The patch description should always explain why we do it, not
what is being done in here. Something like "all clocksource
drivers should get moved there, and this is needed for integrating
into the clocksource_of infrastructure.
'
>  arch/arm/Kconfig                          |    5 -
>  arch/arm/common/Makefile                  |    1 -
>  arch/arm/common/timer-sp.c                |  191 -----------------------------
>  arch/arm/include/asm/hardware/arm_timer.h |   35 ------
>  arch/arm/include/asm/hardware/timer-sp.h  |   15 ---
>  arch/arm/mach-highbank/highbank.c         |    4 +-
>  arch/arm/mach-integrator/integrator_ap.c  |    2 +-
>  arch/arm/mach-integrator/integrator_cp.c  |    4 +-
>  arch/arm/mach-realview/core.c             |    4 +-
>  arch/arm/mach-versatile/core.c            |    4 +-
>  arch/arm/mach-vexpress/ct-ca9x4.c         |    5 +-
>  arch/arm/mach-vexpress/v2m.c              |    4 +-
>  drivers/clocksource/Kconfig               |    5 +
>  drivers/clocksource/Makefile              |    1 +
>  drivers/clocksource/timer-sp.c            |  191 +++++++++++++++++++++++++++++
>  include/clocksource/arm_timer.h           |   35 ++++++
>  include/clocksource/timer-sp.h            |   19 +++

Please use 'git format-patch -M' to generate the patches. I just
realized I forgot it myself in the spear series.

I have now set 'git config diff.renames true' and would recommend to
everybody to do the same.

	Arnd

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

* [PATCH v2 02/14] clocksource: sp804: add device tree support
  2013-03-12 17:08 ` [PATCH v2 02/14] clocksource: sp804: add device tree support Haojian Zhuang
@ 2013-03-12 18:14   ` Arnd Bergmann
  2013-03-12 18:51   ` Arnd Bergmann
  1 sibling, 0 replies; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> Parse clock & irq from device tree for sp804.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  drivers/clocksource/timer-sp.c |  105 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 105 insertions(+)
> 


The patch looks ok to me, but it need  a binding document in 
Documentation/devicetree/bindings/

	Arnd

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

* [PATCH v2 02/14] clocksource: sp804: add device tree support
  2013-03-12 17:08 ` [PATCH v2 02/14] clocksource: sp804: add device tree support Haojian Zhuang
  2013-03-12 18:14   ` Arnd Bergmann
@ 2013-03-12 18:51   ` Arnd Bergmann
  2013-03-12 18:53     ` Rob Herring
  1 sibling, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 18:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> +static void __init sp804_dt_init(void)
> +{
...
> +
> +       np = of_find_matching_node(from, sp804_timer_match);
...
> +}
> +CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init);

On second thought, I guess it would be nice if we could change the
calling conventions for CLOCKSOURCE_OF_DECLARE init functions to
always pass the device along.  It is a bit silly if we already have
the node in clocksource_of_init and then require the init function
to call of_find_matching_node(). That change would also make patch
3 in this series unnecessary.

	Arnd

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

* [PATCH v2 02/14] clocksource: sp804: add device tree support
  2013-03-12 18:51   ` Arnd Bergmann
@ 2013-03-12 18:53     ` Rob Herring
  0 siblings, 0 replies; 45+ messages in thread
From: Rob Herring @ 2013-03-12 18:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/12/2013 01:51 PM, Arnd Bergmann wrote:
> On Tuesday 12 March 2013, Haojian Zhuang wrote:
>> +static void __init sp804_dt_init(void)
>> +{
> ...
>> +
>> +       np = of_find_matching_node(from, sp804_timer_match);
> ...
>> +}
>> +CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init);
> 
> On second thought, I guess it would be nice if we could change the
> calling conventions for CLOCKSOURCE_OF_DECLARE init functions to
> always pass the device along.  It is a bit silly if we already have
> the node in clocksource_of_init and then require the init function
> to call of_find_matching_node(). That change would also make patch
> 3 in this series unnecessary.
> 

My pull request to you yesterday does this. And I also have similar
sp804 patches I'm working on...

Rob

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 17:08 ` [PATCH v2 05/14] ARM: integrator: " Haojian Zhuang
@ 2013-03-12 18:54   ` Arnd Bergmann
  2013-03-13  2:00     ` Haojian Zhuang
  2013-03-13  5:25     ` Linus Walleij
  2013-03-12 19:15   ` Rob Herring
  2013-03-13  6:35   ` Linus Walleij
  2 siblings, 2 replies; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 18:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> 
> -       aliases {
> -               arm,timer-primary = &timer2;
> -               arm,timer-secondary = &timer1;
> -       };
> -
>         chosen {
>                 bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
>         };
> @@ -29,10 +24,14 @@
>  
>         timer1: timer at 13000100 {
>                 compatible = "arm,sp804", "arm,primecell";
> +               arm,sp804-clockevent = <0>;
> +               status = "ok";
>         };

I would prefer to keep the old way of doing this. The "aliases" node is
meant for configuration, while the timer device itself should not care
whether it is used as a clockevent or clocksource or some other device.

We could probably change the identifiers in the aliases to
"linux,clocksource" and "linux,clockevents" instead of
"arm,timer-primary" and "arm,timer-secondary".

	Arnd

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

* [PATCH v2 08/14] clk: hs: add clock support
  2013-03-12 17:08 ` [PATCH v2 08/14] clk: hs: add clock support Haojian Zhuang
@ 2013-03-12 19:00   ` Arnd Bergmann
  2013-03-13  4:08     ` Haojian Zhuang
  0 siblings, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 19:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> +void __init hs_init_clocks(void)
> +{
> +       struct device_node *node;
> +
> +       /* map pmctrl registers */
> +       node = of_find_compatible_node(NULL, NULL, "hisilicon,pmctrl");
> +       hs_clk.pmctrl = of_iomap(node, 0);
> +       WARN_ON(!hs_clk.pmctrl);
> +
> +       node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
> +       hs_clk.sctrl = of_iomap(node, 0);
> +
> +       of_clk_init(hs_clk_match);
> +}

You should be able to just use CLK_OF_DECLARE() with each member of
hs_clk_match[] now and call of_clk_init(NULL) from platform code.

This requires moving the of_iomap() calls somewhere else, but it
could be a function that gets called by whichever setup function
gets run first.

	Arnd

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

* [PATCH v2 14/14] Document: add device tree binding file for sp804
  2013-03-12 17:08 ` [PATCH v2 14/14] Document: add device tree binding file for sp804 Haojian Zhuang
@ 2013-03-12 19:02   ` Arnd Bergmann
  2013-03-13  1:45     ` Haojian Zhuang
  0 siblings, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 19:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> Add binding document for sp804 dual timer.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

Ah, I was missing this one earlier when looking at patch 2. I would actually
suggest combining both into a single patch.

	Arnd

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

* [PATCH v2 01/14] clocksource: move sp timer driver
  2013-03-12 17:08 ` [PATCH v2 01/14] clocksource: move sp timer driver Haojian Zhuang
  2013-03-12 18:11   ` Arnd Bergmann
@ 2013-03-12 19:08   ` Russell King - ARM Linux
  1 sibling, 0 replies; 45+ messages in thread
From: Russell King - ARM Linux @ 2013-03-12 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

You really should use git diff -M for patches like this..

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 17:08 ` [PATCH v2 05/14] ARM: integrator: " Haojian Zhuang
  2013-03-12 18:54   ` Arnd Bergmann
@ 2013-03-12 19:15   ` Rob Herring
  2013-03-12 19:33     ` Arnd Bergmann
  2013-03-15 11:54     ` Russell King - ARM Linux
  2013-03-13  6:35   ` Linus Walleij
  2 siblings, 2 replies; 45+ messages in thread
From: Rob Herring @ 2013-03-12 19:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
> Remove all code to parse sp804 in integrator platform driver. Use
> clocksource_of_init() instead since these code are implemented in sp804
> driver already.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  arch/arm/boot/dts/integrator.dtsi        |    3 +++
>  arch/arm/boot/dts/integratorap.dts       |   15 +++++------
>  arch/arm/boot/dts/integratorcp.dts       |    9 +++----
>  arch/arm/mach-integrator/Kconfig         |    3 +++
>  arch/arm/mach-integrator/integrator_ap.c |   41 +-----------------------------
>  arch/arm/mach-integrator/integrator_cp.c |   35 ++-----------------------
>  6 files changed, 20 insertions(+), 86 deletions(-)


> diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
> index c9c3fa3..70e321c 100644
> --- a/arch/arm/boot/dts/integratorap.dts
> +++ b/arch/arm/boot/dts/integratorap.dts
> @@ -9,11 +9,6 @@
>  	model = "ARM Integrator/AP";
>  	compatible = "arm,integrator-ap";
>  
> -	aliases {
> -		arm,timer-primary = &timer2;
> -		arm,timer-secondary = &timer1;
> -	};
> -
>  	chosen {
>  		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
>  	};
> @@ -24,15 +19,19 @@
>  	};
>  
>  	timer0: timer at 13000000 {
> -		compatible = "arm,integrator-timer";
> +		compatible = "arm,sp804", "arm,primecell";

You are breaking existing dtb's changing this, but this is wrong for
other reasons. The integrator does not have an SP804. It is the same
programming model, but is a single timer and not the dual timer. So
having a different compatible string is the correct way. I doubt it has
the primecell ID registers which is what "arm,primecell" indicates.

>  	};
>  
>  	timer1: timer at 13000100 {
> -		compatible = "arm,integrator-timer";
> +		compatible = "arm,sp804", "arm,primecell";
> +		arm,sp804-clockevent = <0>;

I don't like this nor the old way with aliases. We should describe the
h/w features of the timer to determine what to use it for. AFAICT, all 3
timers are identical on integrator and it does not matter which one
Linux picks for clocksource vs. clockevent.

Rob

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

* [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF
  2013-03-12 17:08 ` [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF Haojian Zhuang
@ 2013-03-12 19:17   ` Arnd Bergmann
  2013-03-13  3:25     ` Haojian Zhuang
  0 siblings, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 19:17 UTC (permalink / raw)
  To: linux-arm-kernel

(resending this email as I got a few rejects from mailing lists when
I accidentally had an invalid email address for Mike)

On Tuesday 12 March 2013, Haojian Zhuang wrote:
> of_find_matching_node() & of_device_is_available() are depend on CONFIG_OF
> macro. If CONFIG_OF isn't defined for non-DT mode, the build error
> occurs.
> 
> So add CONFIG_OF for those DT functions.

I don't like this patch too much:

We should be able to do this without the #ifdef. The problem is really that the
declarations are also hidden behind an #ifdef. I think we should change the
linux/of.h header file to either provide alternative empty inline functions
or at least leave the declarations visible so we can compile the code as
long as the call gets discarded.

>  
> +#ifdef CONFIG_OF
>  static struct device_node *from = NULL;
>  
>  static struct of_device_id sp804_timer_match[] __initdata = {
> @@ -294,3 +295,4 @@ err:
>  	iounmap(base);
>  }
>  CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init);
> +#endif

There is actually an empty definition for CLOCKSOURCE_OF_DECLARE(),
but I think it would be better to still define it the same way as
with CONFIG_OF enabled but attribute((__unused__)), like:

#ifdef CONFIG_CLKSRC_OF
extern void clocksource_of_init(void);
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)                        \
        static const struct of_device_id __clksrc_of_table_##name       \
                __used __section(__clksrc_of_table)                     \
                 = { .compatible = compat, .data = fn };
#else
static inline void clocksource_of_init(void) {}
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)                        \
        static const struct of_device_id __clksrc_of_table_##name       \
                __unused = { .compatible = compat, .data = fn };
#endif

This way, all the code still gets built, but since there is nothing
pointing to __clksrc_of_table_##name and it is marked __unused, it
gets dropped along with all other symbols that are only referenced
from it.

	Arnd

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 19:15   ` Rob Herring
@ 2013-03-12 19:33     ` Arnd Bergmann
  2013-03-12 20:52       ` Rob Herring
  2013-03-13  9:03       ` Linus Walleij
  2013-03-15 11:54     ` Russell King - ARM Linux
  1 sibling, 2 replies; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-12 19:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 12 March 2013, Rob Herring wrote:
> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:

> You are breaking existing dtb's changing this, but this is wrong for
> other reasons. The integrator does not have an SP804. It is the same
> programming model, but is a single timer and not the dual timer. So
> having a different compatible string is the correct way. I doubt it has
> the primecell ID registers which is what "arm,primecell" indicates.

At least the qemu model has the primecell ID only for actual sp804 but
not for the integrator, see http://git.qemu.org/?p=qemu.git;a=blob;f=hw/arm_timer.c

> >  	};
> >  
> >  	timer1: timer at 13000100 {
> > -		compatible = "arm,integrator-timer";
> > +		compatible = "arm,sp804", "arm,primecell";
> > +		arm,sp804-clockevent = <0>;
> 
> I don't like this nor the old way with aliases. We should describe the
> h/w features of the timer to determine what to use it for. AFAICT, all 3
> timers are identical on integrator and it does not matter which one
> Linux picks for clocksource vs. clockevent.

Interesting point. I remember we had a discussion about this when the
initial binding integrator code was merged, but I don't remember what
the intent was for doing it like this. Probably just minimizing the
changes to the existing code.

	Arnd

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 19:33     ` Arnd Bergmann
@ 2013-03-12 20:52       ` Rob Herring
  2013-03-13  2:04         ` Haojian Zhuang
  2013-03-13  9:03       ` Linus Walleij
  1 sibling, 1 reply; 45+ messages in thread
From: Rob Herring @ 2013-03-12 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/12/2013 02:33 PM, Arnd Bergmann wrote:
> On Tuesday 12 March 2013, Rob Herring wrote:
>> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
> 
>> You are breaking existing dtb's changing this, but this is wrong for
>> other reasons. The integrator does not have an SP804. It is the same
>> programming model, but is a single timer and not the dual timer. So
>> having a different compatible string is the correct way. I doubt it has
>> the primecell ID registers which is what "arm,primecell" indicates.
> 
> At least the qemu model has the primecell ID only for actual sp804 but
> not for the integrator, see http://git.qemu.org/?p=qemu.git;a=blob;f=hw/arm_timer.c

Right. I think I added that to qemu...

Since the primecell ID registers are defined to be at 0xFF? offset, it
is quite impossible for the integrator timers to have the ID registers
within their 0x100 address space.

> 
>>>  	};
>>>  
>>>  	timer1: timer at 13000100 {
>>> -		compatible = "arm,integrator-timer";
>>> +		compatible = "arm,sp804", "arm,primecell";
>>> +		arm,sp804-clockevent = <0>;
>>
>> I don't like this nor the old way with aliases. We should describe the
>> h/w features of the timer to determine what to use it for. AFAICT, all 3
>> timers are identical on integrator and it does not matter which one
>> Linux picks for clocksource vs. clockevent.
> 
> Interesting point. I remember we had a discussion about this when the
> initial binding integrator code was merged, but I don't remember what
> the intent was for doing it like this. Probably just minimizing the
> changes to the existing code.

Re-reading the thread on this for Integrator, I don't think any
conclusion was really made, but it got merged. I don't think we should
a) change the existing alias names or b) expand their usage. OMAP is a
good example of lots of timers and using h/w properties to select
particular instances based on properties. I think on the ARM boards the
selection has been pretty arbitrary. I traced the commit history back
for the timer code and could not find any evidence to the contrary
except on VExpress which has broken sp804 on the core tile.

Another part is sched_clock selection. I use the sp804 on highbank, but
the ARM boards have their 24MHz counter. Also, if I'm on midway, then I
want to use the arch timers even though the sp804 is still there. My
sched_clock patches yesterday attempt to address that. Any comments on
what characteristics should be used to select timer would be helpful.
Higher frequency and/or bits is better, but to what limit in frequency?

Rob

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

* [PATCH v2 14/14] Document: add device tree binding file for sp804
  2013-03-12 19:02   ` Arnd Bergmann
@ 2013-03-13  1:45     ` Haojian Zhuang
  0 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  1:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 03:02, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 12 March 2013, Haojian Zhuang wrote:
>> Add binding document for sp804 dual timer.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>
> Ah, I was missing this one earlier when looking at patch 2. I would actually
> suggest combining both into a single patch.
>
>         Arnd

OK. I'll merge it into the patch #2.

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 18:54   ` Arnd Bergmann
@ 2013-03-13  2:00     ` Haojian Zhuang
  2013-03-13  5:25     ` Linus Walleij
  1 sibling, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  2:00 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 02:54, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 12 March 2013, Haojian Zhuang wrote:
>>
>> -       aliases {
>> -               arm,timer-primary = &timer2;
>> -               arm,timer-secondary = &timer1;
>> -       };
>> -
>>         chosen {
>>                 bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
>>         };
>> @@ -29,10 +24,14 @@
>>
>>         timer1: timer at 13000100 {
>>                 compatible = "arm,sp804", "arm,primecell";
>> +               arm,sp804-clockevent = <0>;
>> +               status = "ok";
>>         };
>
> I would prefer to keep the old way of doing this. The "aliases" node is
> meant for configuration, while the timer device itself should not care
> whether it is used as a clockevent or clocksource or some other device.
>
> We could probably change the identifiers in the aliases to
> "linux,clocksource" and "linux,clockevents" instead of
> "arm,timer-primary" and "arm,timer-secondary".
>
>         Arnd

SP804 is a dual timer. Either TIMER1 or TIMER2 in the same SP804
could be configured as clock source. And either TIMER1 or TIMER2 in
the same SP804 could be configured as clock event.


Integratorap/cp is always using TIMER1 of SP804-A as clocksource,
and TIMER1 of SP804-B as clockevent. This usage case always
drop TIMER2 usage.

I tried to add arm,sp804-clocksource to specify whether TIMER1 or
TIMER2 is configured as clocksource. For example, realview is using
TIMER2 of SP804-B as clockevent and TIMER1 of SP804-A as
clocksource.

If we decide to support the property like "arm,sp804-clocksource",
we could get the TIMER offset & clock source information at the same
time. Then alias configuration is duplicated.

If we decide to support alais configuration like "linux,clocksource",
we could get clock source/event information. But we don't know which
TIMER is used in the same SP804. We still need one property to
identify it. And people are also using both TIMERs in the same SP804,
like vexpress v2m.

Which method do we choose?

Regards
Haojian

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 20:52       ` Rob Herring
@ 2013-03-13  2:04         ` Haojian Zhuang
  2013-03-13  6:41           ` Linus Walleij
  0 siblings, 1 reply; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  2:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 04:52, Rob Herring <robherring2@gmail.com> wrote:
> On 03/12/2013 02:33 PM, Arnd Bergmann wrote:
>> On Tuesday 12 March 2013, Rob Herring wrote:
>>> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
>
> Since the primecell ID registers are defined to be at 0xFF? offset, it
> is quite impossible for the integrator timers to have the ID registers
> within their 0x100 address space.
>
I'm sorry that I don't know this. I can add "arm,integrator-timer" into
compatible table of sp804 driver. I think that we could resolve this
issue. What's your opinion?

>>
>>>>     };
>>>>
>>>>     timer1: timer at 13000100 {
>>>> -           compatible = "arm,integrator-timer";
>>>> +           compatible = "arm,sp804", "arm,primecell";
>>>> +           arm,sp804-clockevent = <0>;
>>>
>>> I don't like this nor the old way with aliases. We should describe the
>>> h/w features of the timer to determine what to use it for. AFAICT, all 3
>>> timers are identical on integrator and it does not matter which one
>>> Linux picks for clocksource vs. clockevent.
>>
>> Interesting point. I remember we had a discussion about this when the
>> initial binding integrator code was merged, but I don't remember what
>> the intent was for doing it like this. Probably just minimizing the
>> changes to the existing code.
>
> Re-reading the thread on this for Integrator, I don't think any
> conclusion was really made, but it got merged. I don't think we should
> a) change the existing alias names or b) expand their usage. OMAP is a
> good example of lots of timers and using h/w properties to select
> particular instances based on properties. I think on the ARM boards the
> selection has been pretty arbitrary. I traced the commit history back
> for the timer code and could not find any evidence to the contrary
> except on VExpress which has broken sp804 on the core tile.
>
> Another part is sched_clock selection. I use the sp804 on highbank, but
> the ARM boards have their 24MHz counter. Also, if I'm on midway, then I
> want to use the arch timers even though the sp804 is still there. My
> sched_clock patches yesterday attempt to address that. Any comments on
> what characteristics should be used to select timer would be helpful.
> Higher frequency and/or bits is better, but to what limit in frequency?
>
> Rob
>

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

* [PATCH v2 01/14] clocksource: move sp timer driver
  2013-03-12 18:11   ` Arnd Bergmann
@ 2013-03-13  2:20     ` Haojian Zhuang
  0 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  2:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 02:11, Arnd Bergmann <arnd@arndb.de> wrote:
> Hi Haojian,
>
> The patch looks good in principle, but I have two comments:
>
> On Tuesday 12 March 2013, Haojian Zhuang wrote:
>> Move ARM SP804 timer driver from arch/arm directory into
>> drivers/clocksource directory.
>
> The patch description should always explain why we do it, not
> what is being done in here. Something like "all clocksource
> drivers should get moved there, and this is needed for integrating
> into the clocksource_of infrastructure.
> '
>>  arch/arm/Kconfig                          |    5 -
>>  arch/arm/common/Makefile                  |    1 -
>>  arch/arm/common/timer-sp.c                |  191 -----------------------------
>>  arch/arm/include/asm/hardware/arm_timer.h |   35 ------
>>  arch/arm/include/asm/hardware/timer-sp.h  |   15 ---
>>  arch/arm/mach-highbank/highbank.c         |    4 +-
>>  arch/arm/mach-integrator/integrator_ap.c  |    2 +-
>>  arch/arm/mach-integrator/integrator_cp.c  |    4 +-
>>  arch/arm/mach-realview/core.c             |    4 +-
>>  arch/arm/mach-versatile/core.c            |    4 +-
>>  arch/arm/mach-vexpress/ct-ca9x4.c         |    5 +-
>>  arch/arm/mach-vexpress/v2m.c              |    4 +-
>>  drivers/clocksource/Kconfig               |    5 +
>>  drivers/clocksource/Makefile              |    1 +
>>  drivers/clocksource/timer-sp.c            |  191 +++++++++++++++++++++++++++++
>>  include/clocksource/arm_timer.h           |   35 ++++++
>>  include/clocksource/timer-sp.h            |   19 +++
>
> Please use 'git format-patch -M' to generate the patches. I just
> realized I forgot it myself in the spear series.
>
> I have now set 'git config diff.renames true' and would recommend to
> everybody to do the same.
>
>         Arnd

This configuration is so good. Thanks a lot.

Regards
Haojian

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

* [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF
  2013-03-12 19:17   ` Arnd Bergmann
@ 2013-03-13  3:25     ` Haojian Zhuang
  2013-03-14 13:48       ` Arnd Bergmann
  0 siblings, 1 reply; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  3:25 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 03:17, Arnd Bergmann <arnd@arndb.de> wrote:
> (resending this email as I got a few rejects from mailing lists when
> I accidentally had an invalid email address for Mike)
>
> On Tuesday 12 March 2013, Haojian Zhuang wrote:
>> of_find_matching_node() & of_device_is_available() are depend on CONFIG_OF
>> macro. If CONFIG_OF isn't defined for non-DT mode, the build error
>> occurs.
>>
>> So add CONFIG_OF for those DT functions.
>
> I don't like this patch too much:
>
> We should be able to do this without the #ifdef. The problem is really that the
> declarations are also hidden behind an #ifdef. I think we should change the
> linux/of.h header file to either provide alternative empty inline functions
> or at least leave the declarations visible so we can compile the code as
> long as the call gets discarded.
>
>>
>> +#ifdef CONFIG_OF
>>  static struct device_node *from = NULL;
>>
>>  static struct of_device_id sp804_timer_match[] __initdata = {
>> @@ -294,3 +295,4 @@ err:
>>       iounmap(base);
>>  }
>>  CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init);
>> +#endif
>
> There is actually an empty definition for CLOCKSOURCE_OF_DECLARE(),
> but I think it would be better to still define it the same way as
> with CONFIG_OF enabled but attribute((__unused__)), like:
>
> #ifdef CONFIG_CLKSRC_OF
> extern void clocksource_of_init(void);
> #define CLOCKSOURCE_OF_DECLARE(name, compat, fn)                        \
>         static const struct of_device_id __clksrc_of_table_##name       \
>                 __used __section(__clksrc_of_table)                     \
>                  = { .compatible = compat, .data = fn };
> #else
> static inline void clocksource_of_init(void) {}
> #define CLOCKSOURCE_OF_DECLARE(name, compat, fn)                        \
>         static const struct of_device_id __clksrc_of_table_##name       \
>                 __unused = { .compatible = compat, .data = fn };
> #endif
>
> This way, all the code still gets built, but since there is nothing
> pointing to __clksrc_of_table_##name and it is marked __unused, it
> gets dropped along with all other symbols that are only referenced
> from it.
>
>         Arnd
>

If CONFIG_CLKSRC_OF is depend on CONFIG_USEOF, I think that
we can resolve all these issue. We don't need to define
CLOCKSOURCE_OF_DECLARE() for non-DT mode, and we also
don't need to define of_device_is_available(), ... in non-DT mode.

We only need to add "depends on USE_OF" for CLKSRC_OF
configuration. It's simpler. What's your opinion?

Regards
Haojian

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

* [PATCH v2 08/14] clk: hs: add clock support
  2013-03-12 19:00   ` Arnd Bergmann
@ 2013-03-13  4:08     ` Haojian Zhuang
  0 siblings, 0 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  4:08 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 03:00, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 12 March 2013, Haojian Zhuang wrote:
>> +void __init hs_init_clocks(void)
>> +{
>> +       struct device_node *node;
>> +
>> +       /* map pmctrl registers */
>> +       node = of_find_compatible_node(NULL, NULL, "hisilicon,pmctrl");
>> +       hs_clk.pmctrl = of_iomap(node, 0);
>> +       WARN_ON(!hs_clk.pmctrl);
>> +
>> +       node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
>> +       hs_clk.sctrl = of_iomap(node, 0);
>> +
>> +       of_clk_init(hs_clk_match);
>> +}
>
> You should be able to just use CLK_OF_DECLARE() with each member of
> hs_clk_match[] now and call of_clk_init(NULL) from platform code.
>
> This requires moving the of_iomap() calls somewhere else, but it
> could be a function that gets called by whichever setup function
> gets run first.
>
>         Arnd

Yes, it's better. I'll update it.

Regards
Haojian

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 18:54   ` Arnd Bergmann
  2013-03-13  2:00     ` Haojian Zhuang
@ 2013-03-13  5:25     ` Linus Walleij
  1 sibling, 0 replies; 45+ messages in thread
From: Linus Walleij @ 2013-03-13  5:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Mar 12, 2013 at 7:54 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 12 March 2013, Haojian Zhuang wrote:

>>         timer1: timer at 13000100 {
>>                 compatible = "arm,sp804", "arm,primecell";
>> +               arm,sp804-clockevent = <0>;
>> +               status = "ok";
>>         };
>
> I would prefer to keep the old way of doing this. The "aliases" node is
> meant for configuration, while the timer device itself should not care
> whether it is used as a clockevent or clocksource or some other device.
>
> We could probably change the identifiers in the aliases to
> "linux,clocksource" and "linux,clockevents" instead of
> "arm,timer-primary" and "arm,timer-secondary".

I named it like that exactly to be OS-neutral.

The idea is that what timer is to be used for primary and secondary
may have implications on things like power consumption and
one timer may be broken in the HW etc. That is not a Linux-specific
thing.

A bit hard to do things right here :-/

Yours,
Linus Walleij

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 17:08 ` [PATCH v2 05/14] ARM: integrator: " Haojian Zhuang
  2013-03-12 18:54   ` Arnd Bergmann
  2013-03-12 19:15   ` Rob Herring
@ 2013-03-13  6:35   ` Linus Walleij
  2 siblings, 0 replies; 45+ messages in thread
From: Linus Walleij @ 2013-03-13  6:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Mar 12, 2013 at 6:08 PM, Haojian Zhuang
<haojian.zhuang@linaro.org> wrote:

> Remove all code to parse sp804 in integrator platform driver. Use
> clocksource_of_init() instead since these code are implemented in sp804
> driver already.

(...)
> --- a/arch/arm/boot/dts/integratorap.dts
> +++ b/arch/arm/boot/dts/integratorap.dts
>         timer0: timer at 13000000 {
> -               compatible = "arm,integrator-timer";
> +               compatible = "arm,sp804", "arm,primecell";
>         };
>
>         timer1: timer at 13000100 {
> -               compatible = "arm,integrator-timer";
> +               compatible = "arm,sp804", "arm,primecell";
> +               arm,sp804-clockevent = <0>;
> +               status = "ok";
>         };
>
>         timer2: timer at 13000200 {
> -               compatible = "arm,integrator-timer";
> +               compatible = "arm,sp804", "arm,primecell";
> +               arm,sp804-clocksource = <0>;
> +               status = "ok";
>         };

This is wrong. The Integrator/AP timer is not an SP804.
It may look similar but it's a totally different kind of beast.

What is needed is to break out the timer code from
integrator_ap.c and move it to drivers/clocksource,
but wait with that until you fixed the SP804 in the
Integrator/CP, which is probably what you want to
prioritize.

(...)
> --- a/arch/arm/mach-integrator/Kconfig
> +++ b/arch/arm/mach-integrator/Kconfig
(...)
> -static void __init ap_of_timer_init(void)
> -{
> -       struct device_node *node;
> -       const char *path;
> -       void __iomem *base;
> -       int err;
> -       int irq;
> -       struct clk *clk;
> -       unsigned long rate;
> -
> -       clk = clk_get_sys("ap_timer", NULL);

As you see you are not changing this clock lookup either, which
will never work.

Please restrict the patch to altering Integrator/CP.

Yours,
Linus Walleij

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-13  2:04         ` Haojian Zhuang
@ 2013-03-13  6:41           ` Linus Walleij
  2013-03-13  7:09             ` Haojian Zhuang
  2013-03-13 13:56             ` Rob Herring
  0 siblings, 2 replies; 45+ messages in thread
From: Linus Walleij @ 2013-03-13  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 13, 2013 at 3:04 AM, Haojian Zhuang
<haojian.zhuang@linaro.org> wrote:
> On 13 March 2013 04:52, Rob Herring <robherring2@gmail.com> wrote:
>> On 03/12/2013 02:33 PM, Arnd Bergmann wrote:
>>> On Tuesday 12 March 2013, Rob Herring wrote:
>>>> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
>>
>> Since the primecell ID registers are defined to be at 0xFF? offset, it
>> is quite impossible for the integrator timers to have the ID registers
>> within their 0x100 address space.
>>
> I'm sorry that I don't know this. I can add "arm,integrator-timer" into
> compatible table of sp804 driver. I think that we could resolve this
> issue. What's your opinion?

As per the other discussion:

The Integrator/AP has a timer which is different from the SP804.

The Integrator/CP has an SP804.

Please restrict the patch set to Integrator/CP.

Yours,
Linus Walleij

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-13  6:41           ` Linus Walleij
@ 2013-03-13  7:09             ` Haojian Zhuang
  2013-03-13  8:43               ` Arnd Bergmann
  2013-03-13  9:00               ` Linus Walleij
  2013-03-13 13:56             ` Rob Herring
  1 sibling, 2 replies; 45+ messages in thread
From: Haojian Zhuang @ 2013-03-13  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 March 2013 14:41, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Wed, Mar 13, 2013 at 3:04 AM, Haojian Zhuang
> <haojian.zhuang@linaro.org> wrote:
>> On 13 March 2013 04:52, Rob Herring <robherring2@gmail.com> wrote:
>>> On 03/12/2013 02:33 PM, Arnd Bergmann wrote:
>>>> On Tuesday 12 March 2013, Rob Herring wrote:
>>>>> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
>>>
>>> Since the primecell ID registers are defined to be at 0xFF? offset, it
>>> is quite impossible for the integrator timers to have the ID registers
>>> within their 0x100 address space.
>>>
>> I'm sorry that I don't know this. I can add "arm,integrator-timer" into
>> compatible table of sp804 driver. I think that we could resolve this
>> issue. What's your opinion?
>
> As per the other discussion:
>
> The Integrator/AP has a timer which is different from the SP804.
>
> The Integrator/CP has an SP804.
>
> Please restrict the patch set to Integrator/CP.
>
> Yours,
> Linus Walleij

According to Rob's comment, I thought that only prime-cell ID registers
are not contained in integrator-timer controller.

Yes, I missed to include lookup to handle integrator-ap timer. I think that
we can use a string name that are binded to different compatible name.
Code is in below.

#define SP804_TIMER       0
#define INTEGRATOR_TIMER     1
#define ID_BUF_SIZE         16

match table:
{.compatible = "arm,sp804", .data = SP804_TIMER, },
{.compaitlbe = "arm,integrator-timer", .data = INTEGRATOR_TIMER, },

sp804_get_clock_rate():
    char dev_id_buf[ID_BUF_SIZE];
    if (match->data)
        snprintf(dev_id_buf, ID_BUF_SIZE, "ap_timer");
    else
        snprintf(dev_id_buf, ID_BUF_SIZE, "sp804");
    clk = clk_get_sys(dev_id_buf, name);

sp804_dt_init_clk():
    char dev_id_buf[ID_BUF_SIZE];
    if (match->data)
        snprintf(dev_id_buf, ID_BUF_SIZE, "ap_timer");
    else
        snprintf(dev_id_buf, ID_BUF_SIZE, "sp804");
    lookup = clkdev_alloc(clk, name, dev_id_buf);

I think it won't break out code any more. Since most code are same, we
could handle it in the same driver.

Regards
Haojian

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-13  7:09             ` Haojian Zhuang
@ 2013-03-13  8:43               ` Arnd Bergmann
  2013-03-13  9:00               ` Linus Walleij
  1 sibling, 0 replies; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-13  8:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 13 March 2013, Haojian Zhuang wrote:
> match table:
> {.compatible = "arm,sp804", .data = SP804_TIMER, },
> {.compaitlbe = "arm,integrator-timer", .data = INTEGRATOR_TIMER, },
> 
> sp804_get_clock_rate():
>     char dev_id_buf[ID_BUF_SIZE];
>     if (match->data)
>         snprintf(dev_id_buf, ID_BUF_SIZE, "ap_timer");
>     else
>         snprintf(dev_id_buf, ID_BUF_SIZE, "sp804");
>     clk = clk_get_sys(dev_id_buf, name);
> 
> sp804_dt_init_clk():
>     char dev_id_buf[ID_BUF_SIZE];
>     if (match->data)
>         snprintf(dev_id_buf, ID_BUF_SIZE, "ap_timer");
>     else
>         snprintf(dev_id_buf, ID_BUF_SIZE, "sp804");
>     lookup = clkdev_alloc(clk, name, dev_id_buf);
> 
> I think it won't break out code any more. Since most code are same, we
> could handle it in the same driver.
> 

The data member of struct of_device_id is a pointer, you could
point that directly to a const string containing the name, if that
is the only difference, or to another structure that describes
the other parameters.

	Arnd

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-13  7:09             ` Haojian Zhuang
  2013-03-13  8:43               ` Arnd Bergmann
@ 2013-03-13  9:00               ` Linus Walleij
  2013-03-15 12:15                 ` Russell King - ARM Linux
  1 sibling, 1 reply; 45+ messages in thread
From: Linus Walleij @ 2013-03-13  9:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 13, 2013 at 8:09 AM, Haojian Zhuang
<haojian.zhuang@linaro.org> wrote:
> On 13 March 2013 14:41, Linus Walleij <linus.walleij@linaro.org> wrote:

>> Please restrict the patch set to Integrator/CP.
>
> According to Rob's comment, I thought that only prime-cell ID registers
> are not contained in integrator-timer controller.

No, you have missed the most important aspect of all.

The Integrator/AP timer is only 16 bit. Look:

static void integrator_clocksource_init(unsigned long inrate,
					void __iomem *base)
{
(...)
	clocksource_mmio_init(base + TIMER_VALUE, "timer2",
			rate, 200, 16, clocksource_mmio_readl_down);
(...)
}

Compare:

void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
						     const char *name,
						     int use_sched_clock)
{
(...)
	clocksource_mmio_init(base + TIMER_VALUE, name,
		rate, 200, 32, clocksource_mmio_readl_down);
(...)
}

I had the idea of merging the drivers in the past so I'm
positive to the change from a larger perspective.
But then you also have to take the bit-width precision
into account.

If you apply the patch, the Integrator/AP will appear
to work, then if you leave it dormant until the counter
wraps around it will hang or screw up the timeline.

Another part of the problem I see is that the code in the
SP804 driver is lacking features found in the code for the
driver inside integrator_ap.c, I detail these below...

> Yes, I missed to include lookup to handle integrator-ap timer. I think that
> we can use a string name that are binded to different compatible name.
> Code is in below.
(...)
> sp804_get_clock_rate():
>     char dev_id_buf[ID_BUF_SIZE];
>     if (match->data)
>         snprintf(dev_id_buf, ID_BUF_SIZE, "ap_timer");
>     else
>         snprintf(dev_id_buf, ID_BUF_SIZE, "sp804");
>     clk = clk_get_sys(dev_id_buf, name);
>
> sp804_dt_init_clk():
>     char dev_id_buf[ID_BUF_SIZE];
>     if (match->data)
>         snprintf(dev_id_buf, ID_BUF_SIZE, "ap_timer");
>     else
>         snprintf(dev_id_buf, ID_BUF_SIZE, "sp804");
>     lookup = clkdev_alloc(clk, name, dev_id_buf);

If this is what you want to attain, I think it would be better to
just patch the clock lookups in
drivers/clk/clk-integrator.c and rename the "ap_timer"
lookup to "sp804" and skip all the above.

> I think it won't break out code any more. Since most code are same, we
> could handle it in the same driver.

So it will definately break stuff. Being 16bit is not all,
here are other differences:

static u32 notrace integrator_read_sched_clock(void)
{
	return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
}

static void integrator_clocksource_init(unsigned long inrate,
					void __iomem *base)
{
(...)
	setup_sched_clock(integrator_read_sched_clock, 16, rate);
}

Since you do not call even integrator_clocksource_init() anymore
after this, you are breaking sched_clock() for the Integrator/AP.
The SP804 doesn't even have a sched_clock option.
You make it fall back to using jiffies.

So you would have to add this to the SP804 driver, and make
sure sched_clock() is registered for the "arm,integrator"
compatible string.

Then the Integrator/AP timer has this code in the
integrator_clockevent_init() function:

	clkevt_base = base;
	/* Calculate and program a divisor */
	if (rate > 0x100000 * HZ) {
		rate /= 256;
		ctrl |= TIMER_CTRL_DIV256;
	} else if (rate > 0x10000 * HZ) {
		rate /= 16;
		ctrl |= TIMER_CTRL_DIV16;
	}

It appears the SP804 has no code to handle this
divisor/prescaler at all. Which means that you regress
the Integrator/AP again.

It appears (from arm_timer.h) that the SP804 actually
has this prescaler, but then first make a separate patch
to make the SP804 driver use that divisor (like above) so
you don't degrade the quality of the AP timer. The prescaler
make it possible to let the system sleep for longer times
when using NO_HZ so it's *pretty* important (and it will
increas the quality of all SP804-based machines as well).

As you surely understand, since the counter on the
Integrator/AP is only 16 bit this is very important, since
we don't want it to wake up too often.

Then the clocksource init function has this:

	if (rate >= 1500000) {
		rate /= 16;
		ctrl |= TIMER_CTRL_DIV16;
	}

Here I'm more uncertain. As I know from extensive
discussions with John and Thomas, there are many many
factors to decide the clocksource. Basically the above lines
limits the precision of the clocksource in exchange for a
longer time until wrap-around. Again, the 16bit nature of the
Integrator/AP timer is a factor here.

Yours,
Linus Walleij

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 19:33     ` Arnd Bergmann
  2013-03-12 20:52       ` Rob Herring
@ 2013-03-13  9:03       ` Linus Walleij
  1 sibling, 0 replies; 45+ messages in thread
From: Linus Walleij @ 2013-03-13  9:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Mar 12, 2013 at 8:33 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 12 March 2013, Rob Herring wrote:
>> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
>
>> You are breaking existing dtb's changing this, but this is wrong for
>> other reasons. The integrator does not have an SP804. It is the same
>> programming model, but is a single timer and not the dual timer. So
>> having a different compatible string is the correct way. I doubt it has
>> the primecell ID registers which is what "arm,primecell" indicates.
>
> At least the qemu model has the primecell ID only for actual sp804 but
> not for the integrator, see http://git.qemu.org/?p=qemu.git;a=blob;f=hw/arm_timer.c

That is the for the Integrator/CP model right?

Part of the problem with the current patch series is assuming
similarity between the Integrator/AP and Integrator/CP.

The hardware (VHDL code) for the Integrator/CP SP804 block
is certainly based on the Integrator/AP (unnamed "integrator timer")
but many changes were made, the most drastic extending the
counters from 16 to 32 bits.

Yours,
Linus Walleij

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-13  6:41           ` Linus Walleij
  2013-03-13  7:09             ` Haojian Zhuang
@ 2013-03-13 13:56             ` Rob Herring
  1 sibling, 0 replies; 45+ messages in thread
From: Rob Herring @ 2013-03-13 13:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/13/2013 01:41 AM, Linus Walleij wrote:
> On Wed, Mar 13, 2013 at 3:04 AM, Haojian Zhuang
> <haojian.zhuang@linaro.org> wrote:
>> On 13 March 2013 04:52, Rob Herring <robherring2@gmail.com> wrote:
>>> On 03/12/2013 02:33 PM, Arnd Bergmann wrote:
>>>> On Tuesday 12 March 2013, Rob Herring wrote:
>>>>> On 03/12/2013 12:08 PM, Haojian Zhuang wrote:
>>>
>>> Since the primecell ID registers are defined to be at 0xFF? offset, it
>>> is quite impossible for the integrator timers to have the ID registers
>>> within their 0x100 address space.
>>>
>> I'm sorry that I don't know this. I can add "arm,integrator-timer" into
>> compatible table of sp804 driver. I think that we could resolve this
>> issue. What's your opinion?
> 
> As per the other discussion:
> 
> The Integrator/AP has a timer which is different from the SP804.
> 
> The Integrator/CP has an SP804.

Not quite. I was wrong that they are the same, The AP has 16-bit timers
and the CP has 32-bit timers. While the individual timer on the AP is
the same programming model as the sp804, it is still not the sp804 block.

Rob

> 
> Please restrict the patch set to Integrator/CP.
> 
> Yours,
> Linus Walleij
> 

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

* [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF
  2013-03-13  3:25     ` Haojian Zhuang
@ 2013-03-14 13:48       ` Arnd Bergmann
  0 siblings, 0 replies; 45+ messages in thread
From: Arnd Bergmann @ 2013-03-14 13:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 13 March 2013, Haojian Zhuang wrote:
> If CONFIG_CLKSRC_OF is depend on CONFIG_USEOF, I think that
> we can resolve all these issue. We don't need to define
> CLOCKSOURCE_OF_DECLARE() for non-DT mode, and we also
> don't need to define of_device_is_available(), ... in non-DT mode.
> 
> We only need to add "depends on USE_OF" for CLKSRC_OF
> configuration. It's simpler. What's your opinion?
> 

I think that is not the right symbol. USE_OF is an ARM specific symbol
that should not get selected from common code. Also I think 'depends on'
is much better than 'select', because it has fewer side-effects.

Right now, CLKSRC_OF is only selected by platforms that also select USE_OF
on ARM, which seems appropriate for now, but if we want to make
CLKSRC_OF a generally visible option, it should use 'depends on OF'.

What I don't understand is how that relates to my comment on your
code. My goal was to support drivers that can contain all the code
needed for CLKSRC_OF without any #ifdef but that still work if CONFIG_OF
and CONFIG_CLKSRC_OF are both disabled.

	Arnd

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-12 19:15   ` Rob Herring
  2013-03-12 19:33     ` Arnd Bergmann
@ 2013-03-15 11:54     ` Russell King - ARM Linux
  1 sibling, 0 replies; 45+ messages in thread
From: Russell King - ARM Linux @ 2013-03-15 11:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Mar 12, 2013 at 02:15:09PM -0500, Rob Herring wrote:
> You are breaking existing dtb's changing this, but this is wrong for
> other reasons. The integrator does not have an SP804. It is the same
> programming model,

No, it is not the same programming model.  It is a subset of the model.
Integrator/AP is only 16-bit, and needs to have a prescaler configured
according to the clockrate.  Integrator/CP and later platforms have
SP804, which looks the same, but is 32-bit instead.

If you look at arch/arm/include/asm/hardware/arm_timer.h, you will see
that I fully documented what registers and bits are present on each
platform of AP, CP, Versatile/AB,PB and Realview.

Note that even through the CP and Versatile platforms are both called
SP804, there are subtle differences between the implementations.

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-13  9:00               ` Linus Walleij
@ 2013-03-15 12:15                 ` Russell King - ARM Linux
  2013-03-15 13:59                   ` Linus Walleij
  0 siblings, 1 reply; 45+ messages in thread
From: Russell King - ARM Linux @ 2013-03-15 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 13, 2013 at 10:00:14AM +0100, Linus Walleij wrote:
> Then the Integrator/AP timer has this code in the
> integrator_clockevent_init() function:
> 
> 	clkevt_base = base;
> 	/* Calculate and program a divisor */
> 	if (rate > 0x100000 * HZ) {
> 		rate /= 256;
> 		ctrl |= TIMER_CTRL_DIV256;
> 	} else if (rate > 0x10000 * HZ) {
> 		rate /= 16;
> 		ctrl |= TIMER_CTRL_DIV16;
> 	}
> 
> It appears the SP804 has no code to handle this
> divisor/prescaler at all. Which means that you regress
> the Integrator/AP again.
> 
> It appears (from arm_timer.h) that the SP804 actually
> has this prescaler, but then first make a separate patch
> to make the SP804 driver use that divisor (like above) so
> you don't degrade the quality of the AP timer. The prescaler
> make it possible to let the system sleep for longer times
> when using NO_HZ so it's *pretty* important (and it will
> increas the quality of all SP804-based machines as well).
> 
> As you surely understand, since the counter on the
> Integrator/AP is only 16 bit this is very important, since
> we don't want it to wake up too often.
> 
> Then the clocksource init function has this:
> 
> 	if (rate >= 1500000) {
> 		rate /= 16;
> 		ctrl |= TIMER_CTRL_DIV16;
> 	}
> 
> Here I'm more uncertain. As I know from extensive
> discussions with John and Thomas, there are many many
> factors to decide the clocksource. Basically the above lines
> limits the precision of the clocksource in exchange for a
> longer time until wrap-around. Again, the 16bit nature of the
> Integrator/AP timer is a factor here.

Integrator/AP selects the prescaler based on the fact that it is only a
16-bit counter, which has to be clocked at a rate which gives us our
desired periodic tick interval.

SP804 does not do this because, being a 32-bit counter, it is completely
unnecessary to use the prescaler - and using the prescaler will result
in loss of fine-grained timing accuracy.  Making use of the prescaler
there is absurd - the timer will run to 4000 odd seconds before wrapping
with a prescaler of 1.

You end up needing 64-bit arithmetic if you try to apply the Integrator/AP
logic to SP804 - it becomes this:

 	if (rate > 0x1000000000 * HZ) {
 		rate /= 256;
 		ctrl |= TIMER_CTRL_DIV256;
 	} else if (rate > 0x100000000 * HZ) {
 		rate /= 16;
 		ctrl |= TIMER_CTRL_DIV16;
 	}

or more precisely:
	if (rate > HZ * 0x100 * ((unsigned long long)wrap + 1)) {
...
 	} else if (rate > HZ * 0x10 * ((unsigned long long)wrap + 1)) {
...

You need that wrap value anyway for clockevents_config_and_register.

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

* [PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804
  2013-03-15 12:15                 ` Russell King - ARM Linux
@ 2013-03-15 13:59                   ` Linus Walleij
  0 siblings, 0 replies; 45+ messages in thread
From: Linus Walleij @ 2013-03-15 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 15, 2013 at 1:15 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

> Integrator/AP selects the prescaler based on the fact that it is only a
> 16-bit counter, which has to be clocked at a rate which gives us our
> desired periodic tick interval.

Ah! I knew there was some simple explanation behind this.

Thanks Russell!
Linus Walleij

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

end of thread, other threads:[~2013-03-15 13:59 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-12 17:08 [PATCH v2 00/14] add hisilicon soc support Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 01/14] clocksource: move sp timer driver Haojian Zhuang
2013-03-12 18:11   ` Arnd Bergmann
2013-03-13  2:20     ` Haojian Zhuang
2013-03-12 19:08   ` Russell King - ARM Linux
2013-03-12 17:08 ` [PATCH v2 02/14] clocksource: sp804: add device tree support Haojian Zhuang
2013-03-12 18:14   ` Arnd Bergmann
2013-03-12 18:51   ` Arnd Bergmann
2013-03-12 18:53     ` Rob Herring
2013-03-12 17:08 ` [PATCH v2 03/14] clocksource: sp804: append CONFIG_OF Haojian Zhuang
2013-03-12 19:17   ` Arnd Bergmann
2013-03-13  3:25     ` Haojian Zhuang
2013-03-14 13:48       ` Arnd Bergmann
2013-03-12 17:08 ` [PATCH v2 04/14] ARM: highbank: use clocksource_of_init for sp804 Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 05/14] ARM: integrator: " Haojian Zhuang
2013-03-12 18:54   ` Arnd Bergmann
2013-03-13  2:00     ` Haojian Zhuang
2013-03-13  5:25     ` Linus Walleij
2013-03-12 19:15   ` Rob Herring
2013-03-12 19:33     ` Arnd Bergmann
2013-03-12 20:52       ` Rob Herring
2013-03-13  2:04         ` Haojian Zhuang
2013-03-13  6:41           ` Linus Walleij
2013-03-13  7:09             ` Haojian Zhuang
2013-03-13  8:43               ` Arnd Bergmann
2013-03-13  9:00               ` Linus Walleij
2013-03-15 12:15                 ` Russell King - ARM Linux
2013-03-15 13:59                   ` Linus Walleij
2013-03-13 13:56             ` Rob Herring
2013-03-13  9:03       ` Linus Walleij
2013-03-15 11:54     ` Russell King - ARM Linux
2013-03-13  6:35   ` Linus Walleij
2013-03-12 17:08 ` [PATCH v2 06/14] ARM: vexpress: " Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 07/14] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 08/14] clk: hs: add clock support Haojian Zhuang
2013-03-12 19:00   ` Arnd Bergmann
2013-03-13  4:08     ` Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 09/14] ARM: hs: add board support with device tree Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 10/14] ARM: hs: enable hi4511 " Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 11/14] ARM: config: append arch hs into multi defconfig Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 12/14] Document: append hisilicon clock binding Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 13/14] Document: dts: create hisilicon document Haojian Zhuang
2013-03-12 17:08 ` [PATCH v2 14/14] Document: add device tree binding file for sp804 Haojian Zhuang
2013-03-12 19:02   ` Arnd Bergmann
2013-03-13  1:45     ` 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).