All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] ZTE platform basic support
@ 2015-03-14 11:49 Jun Nie
  2015-03-14 11:49 ` [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702 Jun Nie
                   ` (9 more replies)
  0 siblings, 10 replies; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

This patch serial add basic support to ZTE ZX296702
platform.

Jun Nie (10):
  ARM: zx: add basic support of ZTE ZX296702
  ARM: zx: add low level debug support
  MAINTAINERS: add entry for ZTE ARM architecture
  ARM: zx: add initial L2CC initialization
  ARM: zx: bring up the secondary core
  ARM: zx: add cpu hotplug support
  dt/binding: Document ZTE zx296702 devicetree
  ARM: dts: zx: add an initial dts for zx296702
  ARM: zx: Add basic defconfig support to ZX296702
  clk: zx: add zx296702 clock support

 Documentation/devicetree/bindings/arm/zte.txt      |   9 +
 .../devicetree/bindings/clock/zx296702-clk.txt     |  35 ++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 MAINTAINERS                                        |  10 +
 arch/arm/Kconfig                                   |   2 +
 arch/arm/Kconfig.debug                             |  12 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/zx296702-ad1.dts                 |  43 ++
 arch/arm/boot/dts/zx296702.dtsi                    | 127 +++++
 arch/arm/configs/zx_defconfig                      | 129 +++++
 arch/arm/include/debug/zx.S                        |  35 ++
 arch/arm/mach-zx/Kconfig                           |  21 +
 arch/arm/mach-zx/Makefile                          |   3 +
 arch/arm/mach-zx/core.h                            |  18 +
 arch/arm/mach-zx/headsmp.S                         |  38 ++
 arch/arm/mach-zx/hotplug.c                         | 108 ++++
 arch/arm/mach-zx/platsmp.c                         | 150 +++++
 arch/arm/mach-zx/zx296702.c                        |  65 +++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/zte/Makefile                           |   2 +
 drivers/clk/zte/clk-pll.c                          | 211 +++++++
 drivers/clk/zte/clk-zx296702.c                     | 611 +++++++++++++++++++++
 drivers/clk/zte/clk.h                              |  30 +
 include/dt-bindings/clock/zx296702-clock.h         | 158 ++++++
 25 files changed, 1821 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/zte.txt
 create mode 100644 Documentation/devicetree/bindings/clock/zx296702-clk.txt
 create mode 100644 arch/arm/boot/dts/zx296702-ad1.dts
 create mode 100644 arch/arm/boot/dts/zx296702.dtsi
 create mode 100644 arch/arm/configs/zx_defconfig
 create mode 100644 arch/arm/include/debug/zx.S
 create mode 100644 arch/arm/mach-zx/Kconfig
 create mode 100644 arch/arm/mach-zx/Makefile
 create mode 100644 arch/arm/mach-zx/core.h
 create mode 100644 arch/arm/mach-zx/headsmp.S
 create mode 100644 arch/arm/mach-zx/hotplug.c
 create mode 100644 arch/arm/mach-zx/platsmp.c
 create mode 100644 arch/arm/mach-zx/zx296702.c
 create mode 100644 drivers/clk/zte/Makefile
 create mode 100644 drivers/clk/zte/clk-pll.c
 create mode 100644 drivers/clk/zte/clk-zx296702.c
 create mode 100644 drivers/clk/zte/clk.h
 create mode 100644 include/dt-bindings/clock/zx296702-clock.h

-- 
1.9.1

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

* [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 21:21   ` Arnd Bergmann
  2015-03-14 11:49 ` [PATCH 02/10] ARM: zx: add low level debug support Jun Nie
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Add basic code for ZTE ZX296702 platform.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/Kconfig            |  2 ++
 arch/arm/Makefile           |  1 +
 arch/arm/mach-zx/Kconfig    | 21 +++++++++++++++++++++
 arch/arm/mach-zx/Makefile   |  1 +
 arch/arm/mach-zx/zx296702.c | 20 ++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 arch/arm/mach-zx/Kconfig
 create mode 100644 arch/arm/mach-zx/Makefile
 create mode 100644 arch/arm/mach-zx/zx296702.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9f1f09a..7516833 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -967,6 +967,8 @@ source "arch/arm/mach-vt8500/Kconfig"
 
 source "arch/arm/mach-w90x900/Kconfig"
 
+source "arch/arm/mach-zx/Kconfig"
+
 source "arch/arm/mach-zynq/Kconfig"
 
 # Definitions to make life easier
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 7f99cd6..33b1588 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -204,6 +204,7 @@ machine-$(CONFIG_ARCH_VERSATILE)	+= versatile
 machine-$(CONFIG_ARCH_VEXPRESS)		+= vexpress
 machine-$(CONFIG_ARCH_VT8500)		+= vt8500
 machine-$(CONFIG_ARCH_W90X900)		+= w90x900
+machine-$(CONFIG_ARCH_ZX)		+= zx
 machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
 machine-$(CONFIG_PLAT_SPEAR)		+= spear
 
diff --git a/arch/arm/mach-zx/Kconfig b/arch/arm/mach-zx/Kconfig
new file mode 100644
index 0000000..6c1628d
--- /dev/null
+++ b/arch/arm/mach-zx/Kconfig
@@ -0,0 +1,21 @@
+config ARCH_ZX
+	bool "ZTE ZX family" if ARCH_MULTI_V7
+	help
+	  Support for ZTE ZX-based family of processors. TV
+	  set-top-box processor is supported. More will be
+	  added soon.
+
+menu "ZTE ZX options"
+	depends on ARCH_ZX
+
+config SOC_ZX296702
+	bool "Enable support for ZX296702 SoC"
+	select ARM_GIC
+	select ARM_GLOBAL_TIMER
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if SMP
+	select MIGHT_HAVE_CACHE_L2X0
+	help
+	  Support for ZTE ZX296702 SoC which is a dual core CortexA9MP
+
+endmenu
diff --git a/arch/arm/mach-zx/Makefile b/arch/arm/mach-zx/Makefile
new file mode 100644
index 0000000..7a541c7
--- /dev/null
+++ b/arch/arm/mach-zx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SOC_ZX296702) += zx296702.o
diff --git a/arch/arm/mach-zx/zx296702.c b/arch/arm/mach-zx/zx296702.c
new file mode 100644
index 0000000..fdd7961
--- /dev/null
+++ b/arch/arm/mach-zx/zx296702.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+static const char *zx296702_dt_compat[] __initconst = {
+	"zte,zx296702",
+	NULL,
+};
+
+DT_MACHINE_START(ZX, "ZTE ZX296702 (Device Tree)")
+	.dt_compat	= zx296702_dt_compat,
+MACHINE_END
-- 
1.9.1

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

* [PATCH 02/10] ARM: zx: add low level debug support
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
  2015-03-14 11:49 ` [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702 Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-15 22:44   ` Matthias Brugger
  2015-03-15 22:48   ` Russell King - ARM Linux
  2015-03-14 11:49 ` [PATCH 03/10] MAINTAINERS: add entry for ZTE ARM architecture Jun Nie
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Use the UART0 peripheral for low level debug. Only the UART port 0 is
currently supported.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/Kconfig.debug      | 12 ++++++++++++
 arch/arm/include/debug/zx.S | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)
 create mode 100644 arch/arm/include/debug/zx.S

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 970de75..b2a0e9a 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1169,6 +1169,17 @@ choice
 		  For more details about semihosting, please see
 		  chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd.
 
+	config DEBUG_ZTE_ZX
+		bool "Use ZTE ZX UART"
+		depends on ARCH_ZX
+		help
+		  Say Y here if you are enabling ZTE ZX296702 SOC and need
+		  debug uart support.
+
+		  This option is preferred over the platform specific
+		  options; the platform specific options are deprecated
+		  and will be soon removed.
+
 	config DEBUG_LL_UART_8250
 		bool "Kernel low-level debugging via 8250 UART"
 		help
@@ -1315,6 +1326,7 @@ config DEBUG_LL_INCLUDE
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
 	default "debug/vf.S" if DEBUG_VF_UART
 	default "debug/vt8500.S" if DEBUG_VT8500_UART0
+	default "debug/zx.S" if DEBUG_ZTE_ZX
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "debug/bcm63xx.S" if DEBUG_UART_BCM63XX
 	default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0
diff --git a/arch/arm/include/debug/zx.S b/arch/arm/include/debug/zx.S
new file mode 100644
index 0000000..aa745ac
--- /dev/null
+++ b/arch/arm/include/debug/zx.S
@@ -0,0 +1,35 @@
+/*
+ * Debugging macro include header
+ *
+ * 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.
+ *
+ */
+
+#define UART01x_DR              0x04    /* Data read or write */
+#define UART01x_FR              0x14    /* Flag register (Read only) */
+
+#define UART01x_FR_TXFF         0x020
+
+
+#define UART0_PADDR		0x09405000
+#define UART0_VADDR		0xfc705000
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, =UART0_PADDR	@ physical
+		ldr	\rv, =UART0_VADDR	@ virtual
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx, #UART01x_DR]
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro  busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #UART01x_FR]
+		tst	\rd, #UART01x_FR_TXFF
+		bne	1001b
+		.endm
-- 
1.9.1

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

* [PATCH 03/10] MAINTAINERS: add entry for ZTE ARM architecture
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
  2015-03-14 11:49 ` [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702 Jun Nie
  2015-03-14 11:49 ` [PATCH 02/10] ARM: zx: add low level debug support Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 11:49 ` [PATCH 04/10] ARM: zx: add initial L2CC initialization Jun Nie
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Add entry for ZTE ARM architecture

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 69cc89f..6f173fe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1590,6 +1590,16 @@ S:	Maintained
 F:	arch/arm/mach-pxa/z2.c
 F:	arch/arm/mach-pxa/include/mach/z2.h
 
+ARM/ZTE ARCHITECTURE
+M:	Jun Nie <jun.nie@linaro.org>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-zx/
+F:	arch/arm/include/debug/zx.S
+F:	drivers/clk/zte/
+F:	Documentation/devicetree/bindings/arm/zte.txt
+F:	Documentation/devicetree/bindings/clock/zx296702-clk.txt
+
 ARM/ZYNQ ARCHITECTURE
 M:	Michal Simek <michal.simek@xilinx.com>
 R:	S?ren Brinkmann <soren.brinkmann@xilinx.com>
-- 
1.9.1

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

* [PATCH 04/10] ARM: zx: add initial L2CC initialization
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (2 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 03/10] MAINTAINERS: add entry for ZTE ARM architecture Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 21:22   ` Arnd Bergmann
  2015-03-16 10:41   ` Russell King - ARM Linux
  2015-03-14 11:49 ` [PATCH 05/10] ARM: zx: bring up the secondary core Jun Nie
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Add an initial L2 Cache controller initialization.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/mach-zx/zx296702.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm/mach-zx/zx296702.c b/arch/arm/mach-zx/zx296702.c
index fdd7961..9c055ea 100644
--- a/arch/arm/mach-zx/zx296702.c
+++ b/arch/arm/mach-zx/zx296702.c
@@ -7,9 +7,52 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include "core.h"
+
+static void __init zx_l2x0_init(void)
+{
+	void __iomem *base;
+	struct device_node *np;
+	unsigned int val;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
+	if (!np)
+		goto out;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		of_node_put(np);
+		goto out;
+	}
+
+	val = readl_relaxed(base + L310_PREFETCH_CTRL);
+	val |= 0x70800000;
+	writel_relaxed(val, base + L310_PREFETCH_CTRL);
+
+	writel_relaxed(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN,
+		       base + L310_POWER_CTRL);
+
+	iounmap(base);
+	of_node_put(np);
+
+out:
+	l2x0_of_init(0x7c433C01, 0x8000c3fe);
+}
+
+static void __init zx296702_init_machine(void)
+{
+	zx_l2x0_init();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
 static const char *zx296702_dt_compat[] __initconst = {
 	"zte,zx296702",
 	NULL,
@@ -17,4 +60,5 @@ static const char *zx296702_dt_compat[] __initconst = {
 
 DT_MACHINE_START(ZX, "ZTE ZX296702 (Device Tree)")
 	.dt_compat	= zx296702_dt_compat,
+	.init_machine	= zx296702_init_machine,
 MACHINE_END
-- 
1.9.1

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

* [PATCH 05/10] ARM: zx: bring up the secondary core
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (3 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 04/10] ARM: zx: add initial L2CC initialization Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 21:25   ` Arnd Bergmann
  2015-03-14 11:49 ` [PATCH 06/10] ARM: zx: add cpu hotplug support Jun Nie
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Use release_pen mechanism to bring up the secondary core.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/mach-zx/Makefile   |   1 +
 arch/arm/mach-zx/core.h     |  17 +++++
 arch/arm/mach-zx/headsmp.S  |  38 ++++++++++++
 arch/arm/mach-zx/platsmp.c  | 147 ++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-zx/zx296702.c |   1 +
 5 files changed, 204 insertions(+)
 create mode 100644 arch/arm/mach-zx/core.h
 create mode 100644 arch/arm/mach-zx/headsmp.S
 create mode 100644 arch/arm/mach-zx/platsmp.c

diff --git a/arch/arm/mach-zx/Makefile b/arch/arm/mach-zx/Makefile
index 7a541c7..7c2edf6 100644
--- a/arch/arm/mach-zx/Makefile
+++ b/arch/arm/mach-zx/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_SOC_ZX296702) += zx296702.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-zx/core.h b/arch/arm/mach-zx/core.h
new file mode 100644
index 0000000..400c7b4
--- /dev/null
+++ b/arch/arm/mach-zx/core.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_ZX_CORE_H
+#define __MACH_ZX_CORE_H
+
+extern struct smp_operations zx_smp_ops;
+
+void zx_secondary_startup(void);
+
+#endif /* __MACH_ZX_CORE_H */
diff --git a/arch/arm/mach-zx/headsmp.S b/arch/arm/mach-zx/headsmp.S
new file mode 100644
index 0000000..8f70ff7
--- /dev/null
+++ b/arch/arm/mach-zx/headsmp.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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/linkage.h>
+
+/*
+ * zx2967 specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(zx_secondary_startup)
+	bl	v7_invalidate_l1
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+ENDPROC(zx_secondary_startup)
+
+	.align	2
+1:	.long	.
+	.long	pen_release
diff --git a/arch/arm/mach-zx/platsmp.c b/arch/arm/mach-zx/platsmp.c
new file mode 100644
index 0000000..e508a9c
--- /dev/null
+++ b/arch/arm/mach-zx/platsmp.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+
+#include "core.h"
+
+#define AON_SYS_CTRL_RESERVED1		0xa8
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __init zx_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *np;
+	unsigned long base = 0;
+	void __iomem *scu_base;
+	void __iomem *aonsysctrl_base;
+
+	base = scu_a9_get_base();
+	scu_base = ioremap(base, SZ_256);
+	if (!scu_base) {
+		pr_err("%s: failed to map scu\n", __func__);
+		return;
+	}
+
+	scu_enable(scu_base);
+	iounmap(scu_base);
+
+	np = of_find_compatible_node(NULL, NULL, "zte,aon-sysctrl");
+	if (!np) {
+		pr_err("%s: failed to find sysctrl node\n", __func__);
+		return;
+	}
+
+	aonsysctrl_base = of_iomap(np, 0);
+	if (!aonsysctrl_base) {
+		pr_err("%s: failed to map aonsysctrl\n", __func__);
+		of_node_put(np);
+		return;
+	}
+
+	/*
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The BootMonitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
+	 */
+	__raw_writel(virt_to_phys(zx_secondary_startup),
+		     aonsysctrl_base + AON_SYS_CTRL_RESERVED1);
+
+	iounmap(aonsysctrl_base);
+	of_node_put(np);
+}
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+	pen_release = val;
+	/* make sure pen_release is visible */
+	smp_wmb();
+	sync_cache_w(&pen_release);
+}
+
+static void zx_secondary_init(unsigned int cpu)
+{
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+static int zx_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * This is really belt and braces; we hold unintended secondary
+	 * CPUs in the holding pen until we're ready for them.  However,
+	 * since we haven't sent them a soft interrupt, they shouldn't
+	 * be there.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		/* sync pen_release value */
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+struct smp_operations zx_smp_ops __initdata = {
+	.smp_prepare_cpus	= zx_smp_prepare_cpus,
+	.smp_secondary_init	= zx_secondary_init,
+	.smp_boot_secondary	= zx_boot_secondary,
+};
diff --git a/arch/arm/mach-zx/zx296702.c b/arch/arm/mach-zx/zx296702.c
index 9c055ea..d5d8be6 100644
--- a/arch/arm/mach-zx/zx296702.c
+++ b/arch/arm/mach-zx/zx296702.c
@@ -59,6 +59,7 @@ static const char *zx296702_dt_compat[] __initconst = {
 };
 
 DT_MACHINE_START(ZX, "ZTE ZX296702 (Device Tree)")
+	.smp		= smp_ops(zx_smp_ops),
 	.dt_compat	= zx296702_dt_compat,
 	.init_machine	= zx296702_init_machine,
 MACHINE_END
-- 
1.9.1

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

* [PATCH 06/10] ARM: zx: add cpu hotplug support
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (4 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 05/10] ARM: zx: bring up the secondary core Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 21:26   ` Arnd Bergmann
  2015-03-14 11:49 ` [PATCH 07/10] dt/binding: Document ZTE zx296702 devicetree Jun Nie
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

It's a clone of vexpress cpu hotplug implementation.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/mach-zx/Makefile  |   1 +
 arch/arm/mach-zx/core.h    |   1 +
 arch/arm/mach-zx/hotplug.c | 108 +++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-zx/platsmp.c |   3 ++
 4 files changed, 113 insertions(+)
 create mode 100644 arch/arm/mach-zx/hotplug.c

diff --git a/arch/arm/mach-zx/Makefile b/arch/arm/mach-zx/Makefile
index 7c2edf6..a3b386e7 100644
--- a/arch/arm/mach-zx/Makefile
+++ b/arch/arm/mach-zx/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_SOC_ZX296702) += zx296702.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-zx/core.h b/arch/arm/mach-zx/core.h
index 400c7b4..9f6b719 100644
--- a/arch/arm/mach-zx/core.h
+++ b/arch/arm/mach-zx/core.h
@@ -13,5 +13,6 @@
 extern struct smp_operations zx_smp_ops;
 
 void zx_secondary_startup(void);
+void zx_cpu_die(unsigned int cpu);
 
 #endif /* __MACH_ZX_CORE_H */
diff --git a/arch/arm/mach-zx/hotplug.c b/arch/arm/mach-zx/hotplug.c
new file mode 100644
index 0000000..1b660e1
--- /dev/null
+++ b/arch/arm/mach-zx/hotplug.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_plat.h>
+#include <asm/cp15.h>
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+		"mcr	p15, 0, %1, c7, c5, 0\n"
+	"	mcr	p15, 0, %1, c7, c10, 4\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, %3\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+		"mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, %1\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  : "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+	/*
+	 * there is no power-control hardware on this platform, so all
+	 * we can do is put the core into WFI; this is safe as the calling
+	 * code will have already disabled interrupts
+	 */
+	for (;;) {
+		wfi();
+
+		if (pen_release == cpu_logical_map(cpu)) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+
+		/*
+		 * Getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
+		 */
+		(*spurious)++;
+	}
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void __ref zx_cpu_die(unsigned int cpu)
+{
+	int spurious = 0;
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_do_lowpower(cpu, &spurious);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+
+	if (spurious)
+		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
diff --git a/arch/arm/mach-zx/platsmp.c b/arch/arm/mach-zx/platsmp.c
index e508a9c..ca157c3 100644
--- a/arch/arm/mach-zx/platsmp.c
+++ b/arch/arm/mach-zx/platsmp.c
@@ -144,4 +144,7 @@ struct smp_operations zx_smp_ops __initdata = {
 	.smp_prepare_cpus	= zx_smp_prepare_cpus,
 	.smp_secondary_init	= zx_secondary_init,
 	.smp_boot_secondary	= zx_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= zx_cpu_die,
+#endif
 };
-- 
1.9.1

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

* [PATCH 07/10] dt/binding: Document ZTE zx296702 devicetree
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (5 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 06/10] ARM: zx: add cpu hotplug support Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 11:49 ` [PATCH 08/10] ARM: dts: zx: add an initial dts for zx296702 Jun Nie
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Document the new compatible for zx296702 platform and
clock control.

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 Documentation/devicetree/bindings/arm/zte.txt      |  9 ++++++
 .../devicetree/bindings/clock/zx296702-clk.txt     | 35 ++++++++++++++++++++++
 .../devicetree/bindings/vendor-prefixes.txt        |  1 +
 3 files changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/zte.txt
 create mode 100644 Documentation/devicetree/bindings/clock/zx296702-clk.txt

diff --git a/Documentation/devicetree/bindings/arm/zte.txt b/Documentation/devicetree/bindings/arm/zte.txt
new file mode 100644
index 0000000..edd6791
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/zte.txt
@@ -0,0 +1,9 @@
+ZTE platforms device tree bindings
+---------------------------------------
+
+-  ZX296702 board:
+    Required root node properties:
+      - compatible = "zte,zx296702-ad1", "zte,zx296702"
+
+Low power management required properties:
+      - compatible = "zte,aon-sysctrl"
diff --git a/Documentation/devicetree/bindings/clock/zx296702-clk.txt b/Documentation/devicetree/bindings/clock/zx296702-clk.txt
new file mode 100644
index 0000000..9b527b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zx296702-clk.txt
@@ -0,0 +1,35 @@
+Device Tree Clock bindings for ZTE zx296702
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+	"zte,zx296702-topcrm":
+		zx296702 top clock selection, divider and gating
+
+	"zte,zx296702-lsp0crpm" or
+	"zte,zx296702-lsp1crpm":
+		zx296702 device level clock selection and gating
+
+- reg: Address and length of the register set
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx5-clock.h
+for the full list of i.MX5 clock IDs.
+
+
+clks: topcrm at 0x09800000 {
+        compatible = "zte,zx296702-topcrm";
+        reg = <0x09800000 0x1000>;
+        #clock-cells = <1>;
+};
+
+uart0: serial at 0x09405000 {
+        compatible = "zte,zx296702-uart";
+        reg = <0x09405000 0x1000>;
+        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clks ZX296702_UART0_PCLK>;
+        status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 389ca13..e4f96ad 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -197,3 +197,4 @@ xillybus	Xillybus Ltd.
 xlnx	Xilinx
 zyxel	ZyXEL Communications Corp.
 zarlink	Zarlink Semiconductor
+zte	ZTE Corp.
-- 
1.9.1

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

* [PATCH 08/10] ARM: dts: zx: add an initial dts for zx296702
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (6 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 07/10] dt/binding: Document ZTE zx296702 devicetree Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 21:30   ` Arnd Bergmann
  2015-03-14 11:49 ` [PATCH 09/10] ARM: zx: Add basic defconfig support to ZX296702 Jun Nie
  2015-03-14 11:49 ` [PATCH 10/10] clk: zx: add zx296702 clock support Jun Nie
  9 siblings, 1 reply; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Add initial dts file for ZX296702 and board ZX296702-AD1.  More
peripherals will be added later.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/boot/dts/Makefile         |   1 +
 arch/arm/boot/dts/zx296702-ad1.dts |  43 +++++++++++++
 arch/arm/boot/dts/zx296702.dtsi    | 127 +++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 arch/arm/boot/dts/zx296702-ad1.dts
 create mode 100644 arch/arm/boot/dts/zx296702.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a1c776b..55dcfbc 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -645,6 +645,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
 	mt6592-evb.dtb \
 	mt8127-moose.dtb \
 	mt8135-evbp1.dtb
+dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
 endif
 
 always		:= $(dtb-y)
diff --git a/arch/arm/boot/dts/zx296702-ad1.dts b/arch/arm/boot/dts/zx296702-ad1.dts
new file mode 100644
index 0000000..cac207a
--- /dev/null
+++ b/arch/arm/boot/dts/zx296702-ad1.dts
@@ -0,0 +1,43 @@
+
+/dts-v1/;
+
+#include "zx296702.dtsi"
+
+/ {
+	model = "ZTE ZX296702 AD1 Board";
+	compatible = "zte,zx296702-ad1", "zte,zx296702";
+
+	memory {
+		reg = <0x50000000 0x20000000>;
+	};
+};
+
+&dwmmc0 {
+	num-slots = <1>;
+	supports-highspeed;
+	non-removable;
+	disable-wp;
+	status = "okay";
+
+	slot at 0 {
+		reg = <0>;
+		bus-width = <4>;
+	};
+};
+
+&dwmmc1 {
+	num-slots = <1>;
+	supports-highspeed;
+	non-removable;
+	disable-wp;
+	status = "okay";
+
+	slot at 0 {
+		reg = <0>;
+		bus-width = <8>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/zx296702.dtsi b/arch/arm/boot/dts/zx296702.dtsi
new file mode 100644
index 0000000..2e66345
--- /dev/null
+++ b/arch/arm/boot/dts/zx296702.dtsi
@@ -0,0 +1,127 @@
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/zx296702-clock.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu at 1 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <1>;
+		};
+	};
+
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		intc: interrupt-controller at 00801000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			interrupt-controller;
+			reg = <0x00801000 0x1000>,
+			      <0x00800100 0x100>;
+		};
+
+		global_timer: timer at 008000200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x00800200 0x20>;
+			interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-parent = <&intc>;
+			clocks = <&clks ZX296702_A9_PERIPHCLK>;
+		};
+
+		l2cc: cache-controller at 0x00c00000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x00c00000 0x1000>;
+			arm,data-latency = <1 1 1>;
+			arm,tag-latency = <1 1 1>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		lsp1crpm: lsp1crpm at 0x09400000 {
+			compatible = "zte,zx296702-lsp1crpm";
+			reg = <0x09400000 0x1000>;
+		};
+
+		uart0: serial at 0x09405000 {
+			compatible = "zte,zx296702-uart";
+			reg = <0x09405000 0x1000>;
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clks ZX296702_UART0_PCLK>;
+			status = "disabled";
+		};
+
+		uart1: serial at 0x09406000 {
+			compatible = "zte,zx296702-uart";
+			reg = <0x09406000 0x1000>;
+			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clks ZX296702_UART1_WCLK>;
+			status = "disabled";
+		};
+
+		dwmmc0: dwmmc at 0x09408000 {
+			compatible = "snps,dw-mshc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x09408000 0x1000>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			fifo-depth = <32>;
+			clocks = <&clks ZX296702_SDMMC0_PCLK>,
+				 <&clks ZX296702_SDMMC0_WCLK>;
+			clock-names = "biu", "ciu";
+			status = "disabled";
+		};
+
+		clks: topcrm at 0x09800000 {
+			compatible = "zte,zx296702-topcrm";
+			reg = <0x09800000 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		lsp0crpm: lsp0crpm at 0x0b000000 {
+			compatible = "zte,zx296702-lsp0crpm";
+			reg = <0x0b000000 0x1000>;
+		};
+
+		dwmmc1: dwmmc at 0x0b003000 {
+			compatible = "snps,dw-mshc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0b003000 0x1000>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			fifo-depth = <32>;
+			clocks = <&clks ZX296702_SDMMC1_PCLK>,
+				 <&clks ZX296702_SDMMC1_WCLK>;
+			clock-names = "biu", "ciu";
+			status = "disabled";
+		};
+
+		aon_sysctrl: aon-sysctrl at 0xa0007000 {
+			compatible = "zte,aon-sysctrl";
+			reg = <0xa0007000 0x1000>;
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH 09/10] ARM: zx: Add basic defconfig support to ZX296702
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (7 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 08/10] ARM: dts: zx: add an initial dts for zx296702 Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-15 13:15   ` Shawn Guo
  2015-03-14 11:49 ` [PATCH 10/10] clk: zx: add zx296702 clock support Jun Nie
  9 siblings, 1 reply; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Add basic defconfig support to zx SOC, including uart, mmc
 and other common config

Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 arch/arm/configs/zx_defconfig | 129 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)
 create mode 100644 arch/arm/configs/zx_defconfig

diff --git a/arch/arm/configs/zx_defconfig b/arch/arm/configs/zx_defconfig
new file mode 100644
index 0000000..a9a62fc
--- /dev/null
+++ b/arch/arm/configs/zx_defconfig
@@ -0,0 +1,129 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_ZX=y
+CONFIG_SOC_ZX296702=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_KSM=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HIBERNATION=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_DEBUG=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.2.100:/nfsroot/ ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M earlyprintk"
+#CONFIG_NET is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=192
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_UID_STAT=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_NETDEVICES=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SPI=y
+CONFIG_LOGO=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_CONSOLE_POLL=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_DEBUG=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+#CONFIG_NFS_FS is not set
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=4096
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_TIMEOUT=5
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_FTRACE is not set
+CONFIG_KGDB=y
+CONFIG_KGDB_KDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_STACKTRACE=y
+CONFIG_DEBUG_ZTE_ZX=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_GPIOLIB=y
-- 
1.9.1

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

* [PATCH 10/10] clk: zx: add zx296702 clock support
  2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
                   ` (8 preceding siblings ...)
  2015-03-14 11:49 ` [PATCH 09/10] ARM: zx: Add basic defconfig support to ZX296702 Jun Nie
@ 2015-03-14 11:49 ` Jun Nie
  2015-03-14 21:33   ` Arnd Bergmann
  2015-03-16 11:33   ` Russell King - ARM Linux
  9 siblings, 2 replies; 27+ messages in thread
From: Jun Nie @ 2015-03-14 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

It adds a clock driver for zx296702 SoC to register the clock tree to
Common Clock Framework.  All the clocks of bus topology and some the
peripheral clocks are ready with this commit.  Some missing leaf clocks
for peripherals will be added later when needed.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
 drivers/clk/Makefile                       |   1 +
 drivers/clk/zte/Makefile                   |   2 +
 drivers/clk/zte/clk-pll.c                  | 211 ++++++++++
 drivers/clk/zte/clk-zx296702.c             | 611 +++++++++++++++++++++++++++++
 drivers/clk/zte/clk.h                      |  30 ++
 include/dt-bindings/clock/zx296702-clock.h | 158 ++++++++
 6 files changed, 1013 insertions(+)
 create mode 100644 drivers/clk/zte/Makefile
 create mode 100644 drivers/clk/zte/clk-pll.c
 create mode 100644 drivers/clk/zte/clk-zx296702.c
 create mode 100644 drivers/clk/zte/clk.h
 create mode 100644 include/dt-bindings/clock/zx296702-clock.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d478ceb..3b428bf 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -69,4 +69,5 @@ obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
 obj-$(CONFIG_X86)			+= x86/
+obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
diff --git a/drivers/clk/zte/Makefile b/drivers/clk/zte/Makefile
new file mode 100644
index 0000000..95b707c
--- /dev/null
+++ b/drivers/clk/zte/Makefile
@@ -0,0 +1,2 @@
+obj-y := clk-pll.o
+obj-$(CONFIG_SOC_ZX296702) += clk-zx296702.o
diff --git a/drivers/clk/zte/clk-pll.c b/drivers/clk/zte/clk-pll.c
new file mode 100644
index 0000000..b8c6935
--- /dev/null
+++ b/drivers/clk/zte/clk-pll.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "clk.h"
+
+#define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
+
+static int rate_to_idx(struct clk_zx_pll *zx_pll, unsigned long rate)
+{
+	const struct zx_pll_config *config = zx_pll->lookup_table;
+	int i;
+
+	for (i = 0; i < zx_pll->count; i++) {
+		if (config[i].rate > rate)
+			return i > 0 ? i - 1 : 0;
+
+		if (config[i].rate == rate)
+			return i;
+	}
+
+	return i - 1;
+}
+
+static int hw_to_idx(struct clk_zx_pll *zx_pll)
+{
+	const struct zx_pll_config *config = zx_pll->lookup_table;
+	u32 hw_cfg0, hw_cfg1;
+	unsigned long flags = 0;
+	int i;
+
+	if (zx_pll->lock)
+		spin_lock_irqsave(zx_pll->lock, flags);
+
+	hw_cfg0 = readl(zx_pll->reg_base);
+	hw_cfg1 = readl(zx_pll->reg_base + 4);
+
+	if (zx_pll->lock)
+		spin_unlock_irqrestore(zx_pll->lock, flags);
+
+	/* For matching the value in lookup table */
+	hw_cfg0 &= ~BIT(30); /* clear lock bit */
+	hw_cfg0 |= BIT(31); /* set PD bit */
+
+	for (i = 0; i < zx_pll->count; i++) {
+		if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1)
+			return i;
+	}
+
+	return -1;
+}
+
+static unsigned long zx_pll_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
+	int idx;
+
+	idx = hw_to_idx(zx_pll);
+	if (unlikely(idx == -1))
+		return 0;
+
+	return zx_pll->lookup_table[idx].rate;
+}
+
+static long zx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *prate)
+{
+	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
+	int idx;
+
+	idx = rate_to_idx(zx_pll, rate);
+
+	return zx_pll->lookup_table[idx].rate;
+}
+
+static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	/* Assume current cpu is not running on current PLL */
+	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
+	const struct zx_pll_config *config;
+	unsigned long flags = 0;
+	int idx;
+	u32 reg;
+
+	idx = rate_to_idx(zx_pll, rate);
+	config = &zx_pll->lookup_table[idx];
+
+	if (zx_pll->lock)
+		spin_lock_irqsave(zx_pll->lock, flags);
+
+	writel(config->cfg0, zx_pll->reg_base);
+	writel(config->cfg1, zx_pll->reg_base + 4);
+	reg = readl(zx_pll->reg_base);
+	reg &= ~BIT(31);
+	writel(reg, zx_pll->reg_base);
+	while (!(readl(zx_pll->reg_base) & BIT(30)))
+		cpu_relax();
+
+	if (zx_pll->lock)
+		spin_unlock_irqrestore(zx_pll->lock, flags);
+
+	return 0;
+}
+
+static int zx_pll_enable(struct clk_hw *hw)
+{
+	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
+	unsigned long flags = 0;
+	u32 reg;
+
+	if (zx_pll->lock)
+		spin_lock_irqsave(zx_pll->lock, flags);
+
+	reg = readl(zx_pll->reg_base);
+	writel(reg & ~BIT(31), zx_pll->reg_base);
+	while (!(readl(zx_pll->reg_base) & BIT(30)))
+		cpu_relax();
+
+	if (zx_pll->lock)
+		spin_unlock_irqrestore(zx_pll->lock, flags);
+
+	return 0;
+}
+
+static void zx_pll_disable(struct clk_hw *hw)
+{
+	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
+	unsigned long flags = 0;
+	u32 reg;
+
+	if (zx_pll->lock)
+		spin_lock_irqsave(zx_pll->lock, flags);
+
+	reg = readl(zx_pll->reg_base);
+	writel(reg | BIT(31), zx_pll->reg_base);
+
+	if (zx_pll->lock)
+		spin_unlock_irqrestore(zx_pll->lock, flags);
+}
+
+static int zx_pll_is_enabled(struct clk_hw *hw)
+{
+	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
+	unsigned long flags = 0;
+	u32 reg;
+
+	if (zx_pll->lock)
+		spin_lock_irqsave(zx_pll->lock, flags);
+
+	reg = readl(zx_pll->reg_base);
+
+	if (zx_pll->lock)
+		spin_unlock_irqrestore(zx_pll->lock, flags);
+
+	return !(reg & BIT(31));
+}
+
+static const struct clk_ops zx_pll_ops = {
+	.recalc_rate = zx_pll_recalc_rate,
+	.round_rate = zx_pll_round_rate,
+	.set_rate = zx_pll_set_rate,
+	.enable = zx_pll_enable,
+	.disable = zx_pll_disable,
+	.is_enabled = zx_pll_is_enabled,
+};
+
+struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
+	unsigned long flags, void __iomem *reg_base,
+	const struct zx_pll_config *lookup_table, int count, spinlock_t *lock)
+{
+	struct clk_zx_pll *zx_pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL);
+	if (!zx_pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &zx_pll_ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	zx_pll->reg_base = reg_base;
+	zx_pll->lookup_table = lookup_table;
+	zx_pll->count = count;
+	zx_pll->lock = lock;
+	zx_pll->hw.init = &init;
+
+	clk = clk_register(NULL, &zx_pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(zx_pll);
+
+	return clk;
+}
diff --git a/drivers/clk/zte/clk-zx296702.c b/drivers/clk/zte/clk-zx296702.c
new file mode 100644
index 0000000..b76a6e8
--- /dev/null
+++ b/drivers/clk/zte/clk-zx296702.c
@@ -0,0 +1,611 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/zx296702-clock.h>
+#include "clk.h"
+
+static DEFINE_SPINLOCK(reg_lock);
+
+static void __iomem *topcrm_base;
+static void __iomem *lsp0crpm_base;
+static void __iomem *lsp1crpm_base;
+
+static struct clk *clk[ZX296702_CLK_END];
+static struct clk_onecell_data clk_data;
+
+#define CLK_MUX			(topcrm_base + 0x04)
+#define CLK_DIV			(topcrm_base + 0x08)
+#define CLK_EN0			(topcrm_base + 0x0c)
+#define CLK_EN1			(topcrm_base + 0x10)
+#define VOU_LOCAL_CLKEN		(topcrm_base + 0x68)
+#define VOU_LOCAL_CLKSEL	(topcrm_base + 0x70)
+#define VOU_LOCAL_DIV2_SET	(topcrm_base + 0x74)
+#define CLK_MUX1		(topcrm_base + 0x8c)
+
+#define CLK_UART0		(lsp1crpm_base + 0x20)
+#define CLK_UART1		(lsp1crpm_base + 0x24)
+#define CLK_SDMMC0		(lsp1crpm_base + 0x2c)
+#define CLK_SDMMC1		(lsp0crpm_base + 0x0c)
+
+static const struct zx_pll_config pll_a9_config[] = {
+	{ .rate = 700000000, .cfg0 = 0x800405d1, .cfg1 = 0x04555555 },
+	{ .rate = 800000000, .cfg0 = 0x80040691, .cfg1 = 0x04aaaaaa },
+	{ .rate = 900000000, .cfg0 = 0x80040791, .cfg1 = 0x04000000 },
+	{ .rate = 1000000000, .cfg0 = 0x80040851, .cfg1 = 0x04555555 },
+	{ .rate = 1100000000, .cfg0 = 0x80040911, .cfg1 = 0x04aaaaaa },
+	{ .rate = 1200000000, .cfg0 = 0x80040a11, .cfg1 = 0x04000000 },
+};
+
+static const struct clk_div_table main_hlk_div[] = {
+	{ .val = 1, .div = 2, },
+	{ .val = 3, .div = 4, },
+	{ /* sentinel */ }
+};
+
+static const struct clk_div_table a9_as1_aclk_divider[] = {
+	{ .val = 0, .div = 1, },
+	{ .val = 1, .div = 2, },
+	{ .val = 3, .div = 4, },
+	{ /* sentinel */ }
+};
+
+static const struct clk_div_table sec_wclk_divider[] = {
+	{ .val = 0, .div = 1, },
+	{ .val = 1, .div = 2, },
+	{ .val = 3, .div = 4, },
+	{ .val = 5, .div = 6, },
+	{ .val = 7, .div = 8, },
+	{ /* sentinel */ }
+};
+
+static const char const *matrix_aclk_sel[] = {
+	"pll_mm0_198M",
+	"osc",
+	"clk_148M5",
+	"pll_lsp_104M",
+};
+
+static const char const *a9_wclk_sel[] = {
+	"pll_a9",
+	"osc",
+	"clk_500",
+	"clk_250",
+};
+
+static const char const *a9_as1_aclk_sel[] = {
+	"clk_250",
+	"osc",
+	"pll_mm0_396M",
+	"pll_mac_333M",
+};
+
+static const char const *a9_trace_clkin_sel[] = {
+	"clk_74M25",
+	"pll_mm1_108M",
+	"clk_125",
+	"clk_148M5",
+};
+
+static const char const *decppu_aclk_sel[] = {
+	"clk_250",
+	"pll_mm0_198M",
+	"pll_lsp_104M",
+	"pll_audio_294M912",
+};
+
+static const char const *vou_main_wclk_sel[] = {
+	"clk_148M5",
+	"clk_74M25",
+	"clk_27",
+	"pll_mm1_54M",
+};
+
+static const char const *vou_scaler_wclk_sel[] = {
+	"clk_250",
+	"pll_mac_333M",
+	"pll_audio_294M912",
+	"pll_mm0_198M",
+};
+
+static const char const *r2d_wclk_sel[] = {
+	"pll_audio_294M912",
+	"pll_mac_333M",
+	"pll_a9_350M",
+	"pll_mm0_396M",
+};
+
+static const char const *ddr_wclk_sel[] = {
+	"pll_mac_333M",
+	"pll_ddr_266M",
+	"pll_audio_294M912",
+	"pll_mm0_198M",
+};
+
+static const char const *nand_wclk_sel[] = {
+	"pll_lsp_104M",
+	"osc",
+};
+
+static const char const *lsp_26_wclk_sel[] = {
+	"pll_lsp_26M",
+	"osc",
+};
+
+static const char const *vl0_sel[] = {
+	"vou_main_channel_div",
+	"vou_aux_channel_div",
+};
+
+static const char const *hdmi_sel[] = {
+	"vou_main_channel_wclk",
+	"vou_aux_channel_wclk",
+};
+
+static const char const *sdmmc0_wclk_sel[] = {
+	"lsp1_104M_wclk",
+	"lsp1_26M_wclk",
+};
+
+static const char const *sdmmc1_wclk_sel[] = {
+	"lsp0_104M_wclk",
+	"lsp0_26M_wclk",
+};
+
+static const char const *uart_wclk_sel[] = {
+	"lsp1_104M_wclk",
+	"lsp1_26M_wclk",
+};
+
+static inline struct clk *zx_divtbl(const char *name, const char *parent,
+				    void __iomem *reg, u8 shift, u8 width,
+				    const struct clk_div_table *table)
+{
+	return clk_register_divider_table(NULL, name, parent, 0, reg, shift,
+					  width, 0, table, &reg_lock);
+}
+
+static inline struct clk *zx_div(const char *name, const char *parent,
+				 void __iomem *reg, u8 shift, u8 width)
+{
+	return clk_register_divider(NULL, name, parent, 0,
+				    reg, shift, width, 0, &reg_lock);
+}
+
+static inline struct clk *zx_mux(const char *name, const char **parents,
+		int num_parents, void __iomem *reg, u8 shift, u8 width)
+{
+	return clk_register_mux(NULL, name, parents, num_parents,
+				0, reg, shift, width, 0, &reg_lock);
+}
+
+static inline struct clk *zx_gate(const char *name, const char *parent,
+				  void __iomem *reg, u8 shift)
+{
+	return clk_register_gate(NULL, name, parent, CLK_IGNORE_UNUSED,
+				 reg, shift, 0, &reg_lock);
+}
+
+static void __init zx296702_clocks_init(struct device_node *np)
+{
+	struct device_node *node;
+	int i;
+
+	topcrm_base = of_iomap(np, 0);
+	WARN_ON(!topcrm_base);
+
+	node = of_find_compatible_node(NULL, NULL, "zte,zx296702-lsp0crpm");
+	lsp0crpm_base = of_iomap(node, 0);
+	WARN_ON(!lsp0crpm_base);
+
+	node = of_find_compatible_node(NULL, NULL, "zte,zx296702-lsp1crpm");
+	lsp1crpm_base = of_iomap(node, 0);
+	WARN_ON(!lsp1crpm_base);
+
+	clk[ZX296702_OSC] =
+		clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT,
+				30000000);
+	clk[ZX296702_PLL_A9] =
+		clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base
+				+ 0x01c, pll_a9_config,
+				ARRAY_SIZE(pll_a9_config), &reg_lock);
+
+	/* TODO: pll_a9_350M look like changeble follow a9 pll */
+	clk[ZX296702_PLL_A9_350M] =
+		clk_register_fixed_rate(NULL, "pll_a9_350M", "osc", 0,
+				350000000);
+	clk[ZX296702_PLL_MAC_1000M] =
+		clk_register_fixed_rate(NULL, "pll_mac_1000M", "osc", 0,
+				1000000000);
+	clk[ZX296702_PLL_MAC_333M] =
+		clk_register_fixed_rate(NULL, "pll_mac_333M",	 "osc", 0,
+				333000000);
+	clk[ZX296702_PLL_MM0_1188M] =
+		clk_register_fixed_rate(NULL, "pll_mm0_1188M", "osc", 0,
+				1188000000);
+	clk[ZX296702_PLL_MM0_396M] =
+		clk_register_fixed_rate(NULL, "pll_mm0_396M",  "osc", 0,
+				396000000);
+	clk[ZX296702_PLL_MM0_198M] =
+		clk_register_fixed_rate(NULL, "pll_mm0_198M",  "osc", 0,
+				198000000);
+	clk[ZX296702_PLL_MM1_108M] =
+		clk_register_fixed_rate(NULL, "pll_mm1_108M",  "osc", 0,
+				108000000);
+	clk[ZX296702_PLL_MM1_72M] =
+		clk_register_fixed_rate(NULL, "pll_mm1_72M",	 "osc", 0,
+				72000000);
+	clk[ZX296702_PLL_MM1_54M] =
+		clk_register_fixed_rate(NULL, "pll_mm1_54M",	 "osc", 0,
+				54000000);
+	clk[ZX296702_PLL_LSP_104M] =
+		clk_register_fixed_rate(NULL, "pll_lsp_104M",  "osc", 0,
+				104000000);
+	clk[ZX296702_PLL_LSP_26M] =
+		clk_register_fixed_rate(NULL, "pll_lsp_26M",	 "osc", 0,
+				26000000);
+	clk[ZX296702_PLL_DDR_266M] =
+		clk_register_fixed_rate(NULL, "pll_ddr_266M",	 "osc", 0,
+				266000000);
+	clk[ZX296702_PLL_AUDIO_294M912] =
+		clk_register_fixed_rate(NULL, "pll_audio_294M912", "osc", 0,
+				294912000);
+
+	/* bus clock */
+	clk[ZX296702_MATRIX_ACLK] =
+		zx_mux("matrix_aclk", matrix_aclk_sel,
+				ARRAY_SIZE(matrix_aclk_sel), CLK_MUX, 2, 2);
+	clk[ZX296702_MAIN_HCLK] =
+		zx_divtbl("main_hclk", "matrix_aclk", CLK_DIV, 0, 2,
+				main_hlk_div);
+	clk[ZX296702_MAIN_PCLK] =
+		zx_divtbl("main_pclk", "matrix_aclk", CLK_DIV, 2, 2,
+				main_hlk_div);
+
+	/* cpu clock */
+	clk[ZX296702_CLK_500] =
+		clk_register_fixed_factor(NULL, "clk_500", "pll_mac_1000M", 0,
+				1, 2);
+	clk[ZX296702_CLK_250] =
+		clk_register_fixed_factor(NULL, "clk_250", "pll_mac_1000M", 0,
+				1, 4);
+	clk[ZX296702_CLK_125] =
+		clk_register_fixed_factor(NULL, "clk_125", "clk_250", 0, 1, 2);
+	clk[ZX296702_CLK_148M5] =
+		clk_register_fixed_factor(NULL, "clk_148M5", "pll_mm0_1188M", 0,
+				1, 8);
+	clk[ZX296702_CLK_74M25] =
+		clk_register_fixed_factor(NULL, "clk_74M25", "pll_mm0_1188M", 0,
+				1, 16);
+	clk[ZX296702_A9_WCLK] =
+		zx_mux("a9_wclk", a9_wclk_sel, ARRAY_SIZE(a9_wclk_sel), CLK_MUX,
+				0, 2);
+	clk[ZX296702_A9_AS1_ACLK_MUX] =
+		zx_mux("a9_as1_aclk_mux", a9_as1_aclk_sel,
+				ARRAY_SIZE(a9_as1_aclk_sel), CLK_MUX, 4, 2);
+	clk[ZX296702_A9_TRACE_CLKIN_MUX] =
+		zx_mux("a9_trace_clkin_mux", a9_trace_clkin_sel,
+				ARRAY_SIZE(a9_trace_clkin_sel), CLK_MUX1, 0, 2);
+	clk[ZX296702_A9_AS1_ACLK_DIV] =
+		zx_divtbl("a9_as1_aclk_div", "a9_as1_aclk_mux", CLK_DIV, 4, 2,
+				a9_as1_aclk_divider);
+
+	/* multi-media clock */
+	clk[ZX296702_CLK_2] =
+		clk_register_fixed_factor(NULL, "clk_2", "pll_mm1_72M", 0,
+				1, 36);
+	clk[ZX296702_CLK_27] =
+		clk_register_fixed_factor(NULL, "clk_27", "pll_mm1_54M", 0,
+				1, 2);
+	clk[ZX296702_DECPPU_ACLK_MUX] =
+		zx_mux("decppu_aclk_mux", decppu_aclk_sel,
+				ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 6, 2);
+	clk[ZX296702_PPU_ACLK_MUX] =
+		zx_mux("ppu_aclk_mux", decppu_aclk_sel,
+				ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 8, 2);
+	clk[ZX296702_MALI400_ACLK_MUX] =
+		zx_mux("mali400_aclk_mux", decppu_aclk_sel,
+				ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 12, 2);
+	clk[ZX296702_VOU_ACLK_MUX] =
+		zx_mux("vou_aclk_mux", decppu_aclk_sel,
+				ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 10, 2);
+	clk[ZX296702_VOU_MAIN_WCLK_MUX] =
+		zx_mux("vou_main_wclk_mux", vou_main_wclk_sel,
+				ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 14, 2);
+	clk[ZX296702_VOU_AUX_WCLK_MUX] =
+		zx_mux("vou_aux_wclk_mux", vou_main_wclk_sel,
+				ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 16, 2);
+	clk[ZX296702_VOU_SCALER_WCLK_MUX] =
+		zx_mux("vou_scaler_wclk_mux", vou_scaler_wclk_sel,
+				ARRAY_SIZE(vou_scaler_wclk_sel), CLK_MUX,
+				18, 2);
+	clk[ZX296702_R2D_ACLK_MUX] =
+		zx_mux("r2d_aclk_mux", decppu_aclk_sel,
+				ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 20, 2);
+	clk[ZX296702_R2D_WCLK_MUX] =
+		zx_mux("r2d_wclk_mux", r2d_wclk_sel,
+				ARRAY_SIZE(r2d_wclk_sel), CLK_MUX, 22, 2);
+
+	/* other clock */
+	clk[ZX296702_CLK_50] =
+		clk_register_fixed_factor(NULL, "clk_50", "pll_mac_1000M",
+				0, 1, 20);
+	clk[ZX296702_CLK_25] =
+		clk_register_fixed_factor(NULL, "clk_25", "pll_mac_1000M",
+				0, 1, 40);
+	clk[ZX296702_CLK_12] =
+		clk_register_fixed_factor(NULL, "clk_12", "pll_mm1_72M",
+				0, 1, 6);
+	clk[ZX296702_CLK_16M384] =
+		clk_register_fixed_factor(NULL, "clk_16M384",
+				"pll_audio_294M912", 0, 1, 18);
+	clk[ZX296702_CLK_32K768] =
+		clk_register_fixed_factor(NULL, "clk_32K768", "clk_16M384",
+				0, 1, 500);
+	clk[ZX296702_SEC_WCLK_DIV] =
+		zx_divtbl("sec_wclk_div", "pll_lsp_104M", CLK_DIV, 6, 3,
+				sec_wclk_divider);
+	clk[ZX296702_DDR_WCLK_MUX] =
+		zx_mux("ddr_wclk_mux", ddr_wclk_sel,
+				ARRAY_SIZE(ddr_wclk_sel), CLK_MUX, 24, 2);
+	clk[ZX296702_NAND_WCLK_MUX] =
+		zx_mux("nand_wclk_mux", nand_wclk_sel,
+				ARRAY_SIZE(nand_wclk_sel), CLK_MUX, 24, 2);
+	clk[ZX296702_LSP_26_WCLK_MUX] =
+		zx_mux("lsp_26_wclk_mux", lsp_26_wclk_sel,
+				ARRAY_SIZE(lsp_26_wclk_sel), CLK_MUX, 27, 1);
+
+	/* gates */
+	clk[ZX296702_A9_AS0_ACLK] =
+		zx_gate("a9_as0_aclk",	"matrix_aclk",		CLK_EN0, 0);
+	clk[ZX296702_A9_AS1_ACLK] =
+		zx_gate("a9_as1_aclk",	"a9_as1_aclk_div",	CLK_EN0, 1);
+	clk[ZX296702_A9_TRACE_CLKIN] =
+		zx_gate("a9_trace_clkin", "a9_trace_clkin_mux",	CLK_EN0, 2);
+	clk[ZX296702_DECPPU_AXI_M_ACLK] =
+		zx_gate("decppu_axi_m_aclk", "decppu_aclk_mux", CLK_EN0, 3);
+	clk[ZX296702_DECPPU_AHB_S_HCLK] =
+		zx_gate("decppu_ahb_s_hclk",	"main_hclk",	CLK_EN0, 4);
+	clk[ZX296702_PPU_AXI_M_ACLK] =
+		zx_gate("ppu_axi_m_aclk",	"ppu_aclk_mux",	CLK_EN0, 5);
+	clk[ZX296702_PPU_AHB_S_HCLK] =
+		zx_gate("ppu_ahb_s_hclk",	"main_hclk",	CLK_EN0, 6);
+	clk[ZX296702_VOU_AXI_M_ACLK] =
+		zx_gate("vou_axi_m_aclk",	"vou_aclk_mux",	CLK_EN0, 7);
+	clk[ZX296702_VOU_APB_PCLK] =
+		zx_gate("vou_apb_pclk",	"main_pclk",		CLK_EN0, 8);
+	clk[ZX296702_VOU_MAIN_CHANNEL_WCLK] =
+		zx_gate("vou_main_channel_wclk", "vou_main_wclk_mux",
+				CLK_EN0, 9);
+	clk[ZX296702_VOU_AUX_CHANNEL_WCLK] =
+		zx_gate("vou_aux_channel_wclk", "vou_aux_wclk_mux",
+				CLK_EN0, 10);
+	clk[ZX296702_VOU_HDMI_OSCLK_CEC] =
+		zx_gate("vou_hdmi_osclk_cec", "clk_2",		CLK_EN0, 11);
+	clk[ZX296702_VOU_SCALER_WCLK] =
+		zx_gate("vou_scaler_wclk", "vou_scaler_wclk_mux", CLK_EN0, 12);
+	clk[ZX296702_MALI400_AXI_M_ACLK] =
+		zx_gate("mali400_axi_m_aclk", "mali400_aclk_mux", CLK_EN0, 13);
+	clk[ZX296702_MALI400_APB_PCLK] =
+		zx_gate("mali400_apb_pclk",	"main_pclk",	CLK_EN0, 14);
+	clk[ZX296702_R2D_WCLK] =
+		zx_gate("r2d_wclk",		"r2d_wclk_mux",	CLK_EN0, 15);
+	clk[ZX296702_R2D_AXI_M_ACLK] =
+		zx_gate("r2d_axi_m_aclk",	"r2d_aclk_mux",	CLK_EN0, 16);
+	clk[ZX296702_R2D_AHB_HCLK] =
+		zx_gate("r2d_ahb_hclk",		"main_hclk",	CLK_EN0, 17);
+	clk[ZX296702_DDR3_AXI_S0_ACLK] =
+		zx_gate("ddr3_axi_s0_aclk",	"matrix_aclk",	CLK_EN0, 18);
+	clk[ZX296702_DDR3_APB_PCLK] =
+		zx_gate("ddr3_apb_pclk",	"main_pclk",	CLK_EN0, 19);
+	clk[ZX296702_DDR3_WCLK] =
+		zx_gate("ddr3_wclk",		"ddr_wclk_mux",	CLK_EN0, 20);
+	clk[ZX296702_USB20_0_AHB_HCLK] =
+		zx_gate("usb20_0_ahb_hclk",	"main_hclk",	CLK_EN0, 21);
+	clk[ZX296702_USB20_0_EXTREFCLK] =
+		zx_gate("usb20_0_extrefclk",	"clk_12",	CLK_EN0, 22);
+	clk[ZX296702_USB20_1_AHB_HCLK] =
+		zx_gate("usb20_1_ahb_hclk",	"main_hclk",	CLK_EN0, 23);
+	clk[ZX296702_USB20_1_EXTREFCLK] =
+		zx_gate("usb20_1_extrefclk",	"clk_12",	CLK_EN0, 24);
+	clk[ZX296702_USB20_2_AHB_HCLK] =
+		zx_gate("usb20_2_ahb_hclk",	"main_hclk",	CLK_EN0, 25);
+	clk[ZX296702_USB20_2_EXTREFCLK] =
+		zx_gate("usb20_2_extrefclk",	"clk_12",	CLK_EN0, 26);
+	clk[ZX296702_GMAC_AXI_M_ACLK] =
+		zx_gate("gmac_axi_m_aclk",	"matrix_aclk",	CLK_EN0, 27);
+	clk[ZX296702_GMAC_APB_PCLK] =
+		zx_gate("gmac_apb_pclk",	"main_pclk",	CLK_EN0, 28);
+	clk[ZX296702_GMAC_125_CLKIN] =
+		zx_gate("gmac_125_clkin",	"clk_125",	CLK_EN0, 29);
+	clk[ZX296702_GMAC_RMII_CLKIN] =
+		zx_gate("gmac_rmii_clkin",	"clk_50",	CLK_EN0, 30);
+	clk[ZX296702_GMAC_25M_CLK] =
+		zx_gate("gmac_25M_clk",		"clk_25",	CLK_EN0, 31);
+	clk[ZX296702_NANDFLASH_AHB_HCLK] =
+		zx_gate("nandflash_ahb_hclk", "main_hclk",	CLK_EN1, 0);
+	clk[ZX296702_NANDFLASH_WCLK] =
+		zx_gate("nandflash_wclk",     "nand_wclk_mux",	CLK_EN1, 1);
+	clk[ZX296702_LSP0_APB_PCLK] =
+		zx_gate("lsp0_apb_pclk",	"main_pclk",	CLK_EN1, 2);
+	clk[ZX296702_LSP0_AHB_HCLK] =
+		zx_gate("lsp0_ahb_hclk",	"main_hclk",	CLK_EN1, 3);
+	clk[ZX296702_LSP0_26M_WCLK] =
+		zx_gate("lsp0_26M_wclk",   "lsp_26_wclk_mux",	CLK_EN1, 4);
+	clk[ZX296702_LSP0_104M_WCLK] =
+		zx_gate("lsp0_104M_wclk",	"pll_lsp_104M",	CLK_EN1, 5);
+	clk[ZX296702_LSP0_16M384_WCLK] =
+		zx_gate("lsp0_16M384_wclk",	"clk_16M384",	CLK_EN1, 6);
+	/* FIXME: apb_pclk enable bit is bit7. We hack it as reserved 31 for
+	 * UART does not work after parent clk is disabled/enabled */
+	clk[ZX296702_LSP1_APB_PCLK] =
+		zx_gate("lsp1_apb_pclk",	"main_pclk",	CLK_EN1, 31);
+	clk[ZX296702_LSP1_26M_WCLK] =
+		zx_gate("lsp1_26M_wclk",     "lsp_26_wclk_mux",	CLK_EN1, 8);
+	clk[ZX296702_LSP1_104M_WCLK] =
+		zx_gate("lsp1_104M_wclk",    "pll_lsp_104M",	CLK_EN1, 9);
+	clk[ZX296702_LSP1_32K_CLK] =
+		zx_gate("lsp1_32K_clk",	"clk_32K768",		CLK_EN1, 10);
+	clk[ZX296702_AON_HCLK] =
+		zx_gate("aon_hclk",		"main_hclk",	CLK_EN1, 11);
+	clk[ZX296702_SYS_CTRL_PCLK] =
+		zx_gate("sys_ctrl_pclk",	"main_pclk",	CLK_EN1, 12);
+	clk[ZX296702_DMA_PCLK] =
+		zx_gate("dma_pclk",		"main_pclk",	CLK_EN1, 13);
+	clk[ZX296702_DMA_ACLK] =
+		zx_gate("dma_aclk",		"matrix_aclk",	CLK_EN1, 14);
+	clk[ZX296702_SEC_HCLK] =
+		zx_gate("sec_hclk",		"main_hclk",	CLK_EN1, 15);
+	clk[ZX296702_AES_WCLK] =
+		zx_gate("aes_wclk",		"sec_wclk_div",	CLK_EN1, 16);
+	clk[ZX296702_DES_WCLK] =
+		zx_gate("des_wclk",		"sec_wclk_div",	CLK_EN1, 17);
+	clk[ZX296702_IRAM_ACLK] =
+		zx_gate("iram_aclk",		"matrix_aclk",	CLK_EN1, 18);
+	clk[ZX296702_IROM_ACLK] =
+		zx_gate("irom_aclk",		"matrix_aclk",	CLK_EN1, 19);
+	clk[ZX296702_BOOT_CTRL_HCLK] =
+		zx_gate("boot_ctrl_hclk",	"main_hclk",	CLK_EN1, 20);
+	clk[ZX296702_EFUSE_CLK_30] =
+		zx_gate("efuse_clk_30",	"osc",			CLK_EN1, 21);
+
+	/* TODO: add VOU Local clocks */
+	clk[ZX296702_VOU_MAIN_CHANNEL_DIV] =
+		zx_div("vou_main_channel_div", "vou_main_channel_wclk",
+				VOU_LOCAL_DIV2_SET, 1, 1);
+	clk[ZX296702_VOU_AUX_CHANNEL_DIV] =
+		zx_div("vou_aux_channel_div", "vou_aux_channel_wclk",
+				VOU_LOCAL_DIV2_SET, 0, 1);
+	clk[ZX296702_VOU_TV_ENC_HD_DIV] =
+		zx_div("vou_tv_enc_hd_div", "vou_tv_enc_hd_mux",
+				VOU_LOCAL_DIV2_SET, 3, 1);
+	clk[ZX296702_VOU_TV_ENC_SD_DIV] =
+		zx_div("vou_tv_enc_sd_div", "vou_tv_enc_sd_mux",
+				VOU_LOCAL_DIV2_SET, 2, 1);
+	clk[ZX296702_VL0_MUX] =
+		zx_mux("vl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 8, 1);
+	clk[ZX296702_VL1_MUX] =
+		zx_mux("vl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 9, 1);
+	clk[ZX296702_VL2_MUX] =
+		zx_mux("vl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 10, 1);
+	clk[ZX296702_GL0_MUX] =
+		zx_mux("gl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 5, 1);
+	clk[ZX296702_GL1_MUX] =
+		zx_mux("gl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 6, 1);
+	clk[ZX296702_GL2_MUX] =
+		zx_mux("gl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 7, 1);
+	clk[ZX296702_WB_MUX] =
+		zx_mux("wb_mux",  vl0_sel, ARRAY_SIZE(vl0_sel),
+				VOU_LOCAL_CLKSEL, 11, 1);
+	clk[ZX296702_HDMI_MUX] =
+		zx_mux("hdmi_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel),
+				VOU_LOCAL_CLKSEL, 4, 1);
+	clk[ZX296702_VOU_TV_ENC_HD_MUX] =
+		zx_mux("vou_tv_enc_hd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel),
+				VOU_LOCAL_CLKSEL, 3, 1);
+	clk[ZX296702_VOU_TV_ENC_SD_MUX] =
+		zx_mux("vou_tv_enc_sd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel),
+				VOU_LOCAL_CLKSEL, 2, 1);
+	clk[ZX296702_VL0_CLK] =
+		zx_gate("vl0_clk", "vl0_mux", VOU_LOCAL_CLKEN, 8);
+	clk[ZX296702_VL1_CLK] =
+		zx_gate("vl1_clk", "vl1_mux", VOU_LOCAL_CLKEN, 9);
+	clk[ZX296702_VL2_CLK] =
+		zx_gate("vl2_clk", "vl2_mux", VOU_LOCAL_CLKEN, 10);
+	clk[ZX296702_GL0_CLK] =
+		zx_gate("gl0_clk", "gl0_mux", VOU_LOCAL_CLKEN, 5);
+	clk[ZX296702_GL1_CLK] =
+		zx_gate("gl1_clk", "gl1_mux", VOU_LOCAL_CLKEN, 6);
+	clk[ZX296702_GL2_CLK] =
+		zx_gate("gl2_clk", "gl2_mux", VOU_LOCAL_CLKEN, 7);
+	clk[ZX296702_WB_CLK] =
+		zx_gate("wb_clk", "wb_mux", VOU_LOCAL_CLKEN, 11);
+	clk[ZX296702_CL_CLK] =
+		zx_gate("cl_clk", "vou_main_channel_div", VOU_LOCAL_CLKEN, 12);
+	clk[ZX296702_MAIN_MIX_CLK] =
+		zx_gate("main_mix_clk", "vou_main_channel_div",
+				VOU_LOCAL_CLKEN, 4);
+	clk[ZX296702_AUX_MIX_CLK] =
+		zx_gate("aux_mix_clk", "vou_aux_channel_div",
+				VOU_LOCAL_CLKEN, 3);
+	clk[ZX296702_HDMI_CLK] =
+		zx_gate("hdmi_clk", "hdmi_mux", VOU_LOCAL_CLKEN, 2);
+	clk[ZX296702_VOU_TV_ENC_HD_DAC_CLK] =
+		zx_gate("vou_tv_enc_hd_dac_clk", "vou_tv_enc_hd_div",
+				VOU_LOCAL_CLKEN, 1);
+	clk[ZX296702_VOU_TV_ENC_SD_DAC_CLK] =
+		zx_gate("vou_tv_enc_sd_dac_clk", "vou_tv_enc_sd_div",
+				VOU_LOCAL_CLKEN, 0);
+
+	/* UART0 */
+	clk[ZX296702_UART0_WCLK_MUX] =
+		zx_mux("uart0_wclk_mux", uart_wclk_sel,
+				ARRAY_SIZE(uart_wclk_sel), CLK_UART0, 4, 1);
+	clk[ZX296702_UART0_WCLK] =
+		zx_gate("uart0_wclk", "uart0_wclk_mux", CLK_UART0, 1);
+	clk[ZX296702_UART0_PCLK] =
+		zx_gate("uart0_pclk", "lsp1_apb_pclk", CLK_UART0, 0);
+
+	/* UART1 */
+	clk[ZX296702_UART1_WCLK_MUX] =
+		zx_mux("uart1_wclk_mux", uart_wclk_sel,
+				ARRAY_SIZE(uart_wclk_sel), CLK_UART1, 4, 1);
+	clk[ZX296702_UART1_WCLK] =
+		zx_gate("uart1_wclk", "uart1_wclk_mux", CLK_UART1, 1);
+	clk[ZX296702_UART1_PCLK] =
+		zx_gate("uart1_pclk", "lsp1_apb_pclk", CLK_UART1, 0);
+
+	/* SDMMC0 */
+	clk[ZX296702_SDMMC0_WCLK_MUX] =
+		zx_mux("sdmmc0_wclk_mux", sdmmc0_wclk_sel,
+				ARRAY_SIZE(sdmmc0_wclk_sel), CLK_SDMMC0, 4, 1);
+	clk[ZX296702_SDMMC0_WCLK_DIV] =
+		zx_div("sdmmc0_wclk_div", "sdmmc0_wclk_mux", CLK_SDMMC0, 12, 4);
+	clk[ZX296702_SDMMC0_WCLK] =
+		zx_gate("sdmmc0_wclk", "sdmmc0_wclk_div", CLK_SDMMC0, 1);
+	clk[ZX296702_SDMMC0_PCLK] =
+		zx_gate("sdmmc0_pclk", "lsp1_apb_pclk", CLK_SDMMC0, 0);
+
+	/* SDMMC1 */
+	clk[ZX296702_SDMMC1_WCLK_MUX] =
+		zx_mux("sdmmc1_wclk_mux", sdmmc1_wclk_sel,
+				ARRAY_SIZE(sdmmc1_wclk_sel), CLK_SDMMC1, 4, 1);
+	clk[ZX296702_SDMMC1_WCLK_DIV] =
+		zx_div("sdmmc1_wclk_div", "sdmmc1_wclk_mux", CLK_SDMMC1, 12, 4);
+	clk[ZX296702_SDMMC1_WCLK] =
+		zx_gate("sdmmc1_wclk", "sdmmc1_wclk_div", CLK_SDMMC1, 1);
+	clk[ZX296702_SDMMC1_PCLK] =
+		zx_gate("sdmmc1_pclk", "lsp1_apb_pclk", CLK_SDMMC1, 0);
+
+	/* CA9 PERIPHCLK = a9_wclk / 2 */
+	clk[ZX296702_A9_PERIPHCLK] =
+		clk_register_fixed_factor(NULL, "a9_periphclk", "a9_wclk",
+				0, 1, 2);
+
+	for (i = 0; i < ARRAY_SIZE(clk); i++) {
+		if (IS_ERR(clk[i])) {
+			pr_err("zx296702 clk %d: register failed with %ld\n",
+				i, PTR_ERR(clk[i]));
+			return;
+		}
+	}
+
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+CLK_OF_DECLARE(zx296702_clock, "zte,zx296702-topcrm", zx296702_clocks_init);
diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h
new file mode 100644
index 0000000..419d93b
--- /dev/null
+++ b/drivers/clk/zte/clk.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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.
+ */
+
+#ifndef __ZTE_CLK_H
+#define __ZTE_CLK_H
+
+struct zx_pll_config {
+	unsigned long rate;
+	u32 cfg0;
+	u32 cfg1;
+};
+
+struct clk_zx_pll {
+	struct clk_hw hw;
+	void __iomem *reg_base;
+	const struct zx_pll_config *lookup_table; /* order by rate asc */
+	int count;
+	spinlock_t *lock;
+};
+
+struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
+	unsigned long flags, void __iomem *reg_base,
+	const struct zx_pll_config *lookup_table, int count, spinlock_t *lock);
+#endif
diff --git a/include/dt-bindings/clock/zx296702-clock.h b/include/dt-bindings/clock/zx296702-clock.h
new file mode 100644
index 0000000..c9a304b
--- /dev/null
+++ b/include/dt-bindings/clock/zx296702-clock.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ * Copyright (C) 2014 ZTE Corporation.
+ *
+ * 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.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_ZX296702_H
+#define __DT_BINDINGS_CLOCK_ZX296702_H
+
+#define ZX296702_OSC				0
+#define ZX296702_PLL_A9				1
+#define ZX296702_PLL_A9_350M			2
+#define ZX296702_PLL_MAC_1000M			3
+#define ZX296702_PLL_MAC_333M			4
+#define ZX296702_PLL_MM0_1188M			5
+#define ZX296702_PLL_MM0_396M			6
+#define ZX296702_PLL_MM0_198M			7
+#define ZX296702_PLL_MM1_108M			8
+#define ZX296702_PLL_MM1_72M			9
+#define ZX296702_PLL_MM1_54M			10
+#define ZX296702_PLL_LSP_104M			11
+#define ZX296702_PLL_LSP_26M			12
+#define ZX296702_PLL_AUDIO_294M912		13
+#define ZX296702_PLL_DDR_266M			14
+#define ZX296702_CLK_148M5			15
+#define ZX296702_MATRIX_ACLK			16
+#define ZX296702_MAIN_HCLK			17
+#define ZX296702_MAIN_PCLK			18
+#define ZX296702_CLK_500			19
+#define ZX296702_CLK_250			20
+#define ZX296702_CLK_125			21
+#define ZX296702_CLK_74M25			22
+#define ZX296702_A9_WCLK			23
+#define ZX296702_A9_AS1_ACLK_MUX		24
+#define ZX296702_A9_TRACE_CLKIN_MUX		25
+#define ZX296702_A9_AS1_ACLK_DIV		26
+#define ZX296702_CLK_2				27
+#define ZX296702_CLK_27				28
+#define ZX296702_DECPPU_ACLK_MUX		29
+#define ZX296702_PPU_ACLK_MUX			30
+#define ZX296702_MALI400_ACLK_MUX		31
+#define ZX296702_VOU_ACLK_MUX			32
+#define ZX296702_VOU_MAIN_WCLK_MUX		33
+#define ZX296702_VOU_AUX_WCLK_MUX		34
+#define ZX296702_VOU_SCALER_WCLK_MUX		35
+#define ZX296702_R2D_ACLK_MUX			36
+#define ZX296702_R2D_WCLK_MUX			37
+#define ZX296702_CLK_50				38
+#define ZX296702_CLK_25				39
+#define ZX296702_CLK_12				40
+#define ZX296702_CLK_16M384			41
+#define ZX296702_CLK_32K768			42
+#define ZX296702_SEC_WCLK_DIV			43
+#define ZX296702_DDR_WCLK_MUX			44
+#define ZX296702_NAND_WCLK_MUX			45
+#define ZX296702_LSP_26_WCLK_MUX		46
+#define ZX296702_A9_AS0_ACLK			47
+#define ZX296702_A9_AS1_ACLK			48
+#define ZX296702_A9_TRACE_CLKIN			49
+#define ZX296702_DECPPU_AXI_M_ACLK		50
+#define ZX296702_DECPPU_AHB_S_HCLK		51
+#define ZX296702_PPU_AXI_M_ACLK			52
+#define ZX296702_PPU_AHB_S_HCLK			53
+#define ZX296702_VOU_AXI_M_ACLK			54
+#define ZX296702_VOU_APB_PCLK			55
+#define ZX296702_VOU_MAIN_CHANNEL_WCLK		56
+#define ZX296702_VOU_AUX_CHANNEL_WCLK		57
+#define ZX296702_VOU_HDMI_OSCLK_CEC		58
+#define ZX296702_VOU_SCALER_WCLK		59
+#define ZX296702_MALI400_AXI_M_ACLK		60
+#define ZX296702_MALI400_APB_PCLK		61
+#define ZX296702_R2D_WCLK			62
+#define ZX296702_R2D_AXI_M_ACLK			63
+#define ZX296702_R2D_AHB_HCLK			64
+#define ZX296702_DDR3_AXI_S0_ACLK		65
+#define ZX296702_DDR3_APB_PCLK			66
+#define ZX296702_DDR3_WCLK			67
+#define ZX296702_USB20_0_AHB_HCLK		68
+#define ZX296702_USB20_0_EXTREFCLK		69
+#define ZX296702_USB20_1_AHB_HCLK		70
+#define ZX296702_USB20_1_EXTREFCLK		71
+#define ZX296702_USB20_2_AHB_HCLK		72
+#define ZX296702_USB20_2_EXTREFCLK		73
+#define ZX296702_GMAC_AXI_M_ACLK		74
+#define ZX296702_GMAC_APB_PCLK			75
+#define ZX296702_GMAC_125_CLKIN			76
+#define ZX296702_GMAC_RMII_CLKIN		77
+#define ZX296702_GMAC_25M_CLK			78
+#define ZX296702_NANDFLASH_AHB_HCLK		79
+#define ZX296702_NANDFLASH_WCLK			80
+#define ZX296702_LSP0_APB_PCLK			81
+#define ZX296702_LSP0_AHB_HCLK			82
+#define ZX296702_LSP0_26M_WCLK			83
+#define ZX296702_LSP0_104M_WCLK			84
+#define ZX296702_LSP0_16M384_WCLK		85
+#define ZX296702_LSP1_APB_PCLK			86
+#define ZX296702_LSP1_26M_WCLK			87
+#define ZX296702_LSP1_104M_WCLK			88
+#define ZX296702_LSP1_32K_CLK			89
+#define ZX296702_AON_HCLK			90
+#define ZX296702_SYS_CTRL_PCLK			91
+#define ZX296702_DMA_PCLK			92
+#define ZX296702_DMA_ACLK			93
+#define ZX296702_SEC_HCLK			94
+#define ZX296702_AES_WCLK			95
+#define ZX296702_DES_WCLK			96
+#define ZX296702_IRAM_ACLK			97
+#define ZX296702_IROM_ACLK			98
+#define ZX296702_BOOT_CTRL_HCLK			99
+#define ZX296702_EFUSE_CLK_30			100
+#define ZX296702_VOU_MAIN_CHANNEL_DIV		101
+#define ZX296702_VOU_AUX_CHANNEL_DIV		102
+#define ZX296702_VOU_TV_ENC_HD_DIV		103
+#define ZX296702_VOU_TV_ENC_SD_DIV		104
+#define ZX296702_VL0_MUX			105
+#define ZX296702_VL1_MUX			106
+#define ZX296702_VL2_MUX			107
+#define ZX296702_GL0_MUX			108
+#define ZX296702_GL1_MUX			109
+#define ZX296702_GL2_MUX			110
+#define ZX296702_WB_MUX				111
+#define ZX296702_HDMI_MUX			112
+#define ZX296702_VOU_TV_ENC_HD_MUX		113
+#define ZX296702_VOU_TV_ENC_SD_MUX		114
+#define ZX296702_VL0_CLK			115
+#define ZX296702_VL1_CLK			116
+#define ZX296702_VL2_CLK			117
+#define ZX296702_GL0_CLK			118
+#define ZX296702_GL1_CLK			119
+#define ZX296702_GL2_CLK			120
+#define ZX296702_WB_CLK				121
+#define ZX296702_CL_CLK				122
+#define ZX296702_MAIN_MIX_CLK			123
+#define ZX296702_AUX_MIX_CLK			124
+#define ZX296702_HDMI_CLK			125
+#define ZX296702_VOU_TV_ENC_HD_DAC_CLK		126
+#define ZX296702_VOU_TV_ENC_SD_DAC_CLK		127
+#define ZX296702_UART0_WCLK_MUX			128
+#define ZX296702_UART0_WCLK			129
+#define ZX296702_UART0_PCLK			130
+#define ZX296702_UART1_WCLK_MUX			131
+#define ZX296702_UART1_WCLK			132
+#define ZX296702_UART1_PCLK			133
+#define ZX296702_SDMMC0_WCLK_MUX		134
+#define ZX296702_SDMMC0_WCLK_DIV		135
+#define ZX296702_SDMMC0_WCLK			136
+#define ZX296702_SDMMC0_PCLK			137
+#define ZX296702_SDMMC1_WCLK_MUX		138
+#define ZX296702_SDMMC1_WCLK_DIV		139
+#define ZX296702_SDMMC1_WCLK			140
+#define ZX296702_SDMMC1_PCLK			141
+#define ZX296702_A9_PERIPHCLK			142
+#define ZX296702_CLK_END			143
+
+#endif /* __DT_BINDINGS_CLOCK_ZX296702_H */
-- 
1.9.1

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

* [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702
  2015-03-14 11:49 ` [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702 Jun Nie
@ 2015-03-14 21:21   ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-14 21:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 March 2015 19:49:36 Jun Nie wrote:
> @@ -0,0 +1,21 @@
> +config ARCH_ZX
> +       bool "ZTE ZX family" if ARCH_MULTI_V7
> +       help
> +         Support for ZTE ZX-based family of processors. TV
> +         set-top-box processor is supported. More will be
> +         added soon.
> +
> +menu "ZTE ZX options"
> +       depends on ARCH_ZX

Better use a "menuconfig" statement here.

> +config SOC_ZX296702
> +       bool "Enable support for ZX296702 SoC"
> +       select ARM_GIC
> +       select ARM_GLOBAL_TIMER
> +       select HAVE_ARM_SCU if SMP
> +       select HAVE_ARM_TWD if SMP
> +       select MIGHT_HAVE_CACHE_L2X0
> +       help
> +         Support for ZTE ZX296702 SoC which is a dual core CortexA9MP
> +
> +endmenu

MIGHT_HAVE_CACHE_L2X0 is implied by ARCH_MULTI_V7, so you can drop
that here.

	Arnd

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

* [PATCH 04/10] ARM: zx: add initial L2CC initialization
  2015-03-14 11:49 ` [PATCH 04/10] ARM: zx: add initial L2CC initialization Jun Nie
@ 2015-03-14 21:22   ` Arnd Bergmann
  2015-03-16  2:48     ` Shawn Guo
  2015-03-16 10:41   ` Russell King - ARM Linux
  1 sibling, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-14 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 March 2015 19:49:39 Jun Nie wrote:
> Add an initial L2 Cache controller initialization.
> 
> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> 

This should not be needed at all, we expect all platforms
to describe the l2 cache controller in DT to the degree
that is required to have it probed automatically.

Is there any special requirement about this platform that
makes this impossible?

	Arnd

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

* [PATCH 05/10] ARM: zx: bring up the secondary core
  2015-03-14 11:49 ` [PATCH 05/10] ARM: zx: bring up the secondary core Jun Nie
@ 2015-03-14 21:25   ` Arnd Bergmann
  2015-03-16  7:23     ` Shawn Guo
  0 siblings, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-14 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 March 2015 19:49:40 Jun Nie wrote:
> +
> +       /*
> +        * This is really belt and braces; we hold unintended secondary
> +        * CPUs in the holding pen until we're ready for them.  However,
> +        * since we haven't sent them a soft interrupt, they shouldn't
> +        * be there.
> +        */
> +       write_pen_release(cpu);
> +
> 

Why do you need the holding pen on this platform? Is there a firmware
bug or just missing hardware support for proper SMP power management?

	Arnd

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

* [PATCH 06/10] ARM: zx: add cpu hotplug support
  2015-03-14 11:49 ` [PATCH 06/10] ARM: zx: add cpu hotplug support Jun Nie
@ 2015-03-14 21:26   ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-14 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 March 2015 19:49:41 Jun Nie wrote:
> It's a clone of vexpress cpu hotplug implementation.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> 

Please explain exactly why you cannot use a proper CPU poweroff
function here. Nobody should copy that code from vexpress for a
real system.

	Arnd

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

* [PATCH 08/10] ARM: dts: zx: add an initial dts for zx296702
  2015-03-14 11:49 ` [PATCH 08/10] ARM: dts: zx: add an initial dts for zx296702 Jun Nie
@ 2015-03-14 21:30   ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-14 21:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 March 2015 19:49:43 Jun Nie wrote:
> 
> +#include "skeleton.dtsi"
> +#include <dt-bindings/clock/zx296702-clock.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +/ {
> +       aliases {
> +               serial0 = &uart0;
> +               serial1 = &uart1;
> +       };

Move the aliases to the board specific file: other boards might not
have the same set of uarts visible to users.

> +       cpus {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               cpu at 0 {
> +                       compatible = "arm,cortex-a9";
> +                       device_type = "cpu";
> +                       reg = <0>;
> +               };
> +
> +               cpu at 1 {
> +                       compatible = "arm,cortex-a9";
> +                       device_type = "cpu";
> +                       reg = <1>;
> +               };
> +       };
> +

No enable-method?

> +               lsp1crpm: lsp1crpm at 0x09400000 {
> +                       compatible = "zte,zx296702-lsp1crpm";
> +                       reg = <0x09400000 0x1000>;
> +               };

What is an lsp1crpm?

> +               dwmmc0: dwmmc at 0x09408000 {

The node name should be "mmc", not "dwmmc".
> +
> +               clks: topcrm at 0x09800000 {
> +                       compatible = "zte,zx296702-topcrm";
> +                       reg = <0x09800000 0x1000>;
> +                       #clock-cells = <1>;
> +               };
> +
> +               lsp0crpm: lsp0crpm at 0x0b000000 {
> +                       compatible = "zte,zx296702-lsp0crpm";
> +                       reg = <0x0b000000 0x1000>;
> +               };

What is a topcrm and an lsp0crpm?

> +               dwmmc1: dwmmc at 0x0b003000 {
> +                       compatible = "snps,dw-mshc";
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +                       reg = <0x0b003000 0x1000>;
> +                       interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
> +                       fifo-depth = <32>;
> +                       clocks = <&clks ZX296702_SDMMC1_PCLK>,
> +                                <&clks ZX296702_SDMMC1_WCLK>;
> +                       clock-names = "biu", "ciu";
> +                       status = "disabled";
> +               };
> +
> +               aon_sysctrl: aon-sysctrl at 0xa0007000 {
> +                       compatible = "zte,aon-sysctrl";
> +                       reg = <0xa0007000 0x1000>;
> +               };
> +       };

This looks like  it's a system controller, so the node name
should probably be "system-controller", not aon-sysctrl,
and you may want to claim compatibility with "syscon" as well.

All the nodes need to have a documented binding.

	Arnd

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

* [PATCH 10/10] clk: zx: add zx296702 clock support
  2015-03-14 11:49 ` [PATCH 10/10] clk: zx: add zx296702 clock support Jun Nie
@ 2015-03-14 21:33   ` Arnd Bergmann
  2015-03-16 11:33   ` Russell King - ARM Linux
  1 sibling, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-14 21:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 14 March 2015 19:49:45 Jun Nie wrote:
> +
> +static void __init zx296702_clocks_init(struct device_node *np)
> +{
> +       struct device_node *node;
> +       int i;
> +
> +       topcrm_base = of_iomap(np, 0);
> +       WARN_ON(!topcrm_base);
> +
> +       node = of_find_compatible_node(NULL, NULL, "zte,zx296702-lsp0crpm");
> +       lsp0crpm_base = of_iomap(node, 0);
> +       WARN_ON(!lsp0crpm_base);
> +
> +       node = of_find_compatible_node(NULL, NULL, "zte,zx296702-lsp1crpm");
> +       lsp1crpm_base = of_iomap(node, 0);
> +       WARN_ON(!lsp1crpm_base);
> +

Could you make this three separate clock controllers instead?

	Arnd

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

* [PATCH 09/10] ARM: zx: Add basic defconfig support to ZX296702
  2015-03-14 11:49 ` [PATCH 09/10] ARM: zx: Add basic defconfig support to ZX296702 Jun Nie
@ 2015-03-15 13:15   ` Shawn Guo
  0 siblings, 0 replies; 27+ messages in thread
From: Shawn Guo @ 2015-03-15 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 14, 2015 at 07:49:44PM +0800, Jun Nie wrote:
> Add basic defconfig support to zx SOC, including uart, mmc
>  and other common config
> 
> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> ---
>  arch/arm/configs/zx_defconfig | 129 ++++++++++++++++++++++++++++++++++++++++++

I see a warning with make zx_defconfig.

arch/arm/configs/zx_defconfig:121:warning: override: reassigning to symbol DEBUG_PREEMPT

Shawn

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

* [PATCH 02/10] ARM: zx: add low level debug support
  2015-03-14 11:49 ` [PATCH 02/10] ARM: zx: add low level debug support Jun Nie
@ 2015-03-15 22:44   ` Matthias Brugger
  2015-03-15 22:48   ` Russell King - ARM Linux
  1 sibling, 0 replies; 27+ messages in thread
From: Matthias Brugger @ 2015-03-15 22:44 UTC (permalink / raw)
  To: linux-arm-kernel



On 14/03/15 12:49, Jun Nie wrote:
> Use the UART0 peripheral for low level debug. Only the UART port 0 is
> currently supported.
> 
> Signed-off-by: Jun Nie <jun.nie@linaro.org>
> ---
>  arch/arm/Kconfig.debug      | 12 ++++++++++++
>  arch/arm/include/debug/zx.S | 35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+)
>  create mode 100644 arch/arm/include/debug/zx.S
> 
> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index 970de75..b2a0e9a 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -1169,6 +1169,17 @@ choice
>  		  For more details about semihosting, please see
>  		  chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd.
>  
> +	config DEBUG_ZTE_ZX
> +		bool "Use ZTE ZX UART"
> +		depends on ARCH_ZX
> +		help
> +		  Say Y here if you are enabling ZTE ZX296702 SOC and need
> +		  debug uart support.
> +
> +		  This option is preferred over the platform specific
> +		  options; the platform specific options are deprecated
> +		  and will be soon removed.
> +
>  	config DEBUG_LL_UART_8250
>  		bool "Kernel low-level debugging via 8250 UART"
>  		help
> @@ -1315,6 +1326,7 @@ config DEBUG_LL_INCLUDE
>  	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
>  	default "debug/vf.S" if DEBUG_VF_UART
>  	default "debug/vt8500.S" if DEBUG_VT8500_UART0
> +	default "debug/zx.S" if DEBUG_ZTE_ZX
>  	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
>  	default "debug/bcm63xx.S" if DEBUG_UART_BCM63XX
>  	default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0
> diff --git a/arch/arm/include/debug/zx.S b/arch/arm/include/debug/zx.S
> new file mode 100644
> index 0000000..aa745ac
> --- /dev/null
> +++ b/arch/arm/include/debug/zx.S
> @@ -0,0 +1,35 @@
> +/*
> + * Debugging macro include header
> + *
> + * 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.
> + *
> + */
> +
> +#define UART01x_DR              0x04    /* Data read or write */
> +#define UART01x_FR              0x14    /* Flag register (Read only) */
> +
> +#define UART01x_FR_TXFF         0x020
> +
> +
> +#define UART0_PADDR		0x09405000
> +#define UART0_VADDR		0xfc705000

Why don't you use CONFIG_DEBUG_UART_VIRT and CONFIG_DEBUG_UART_PHYS?

> +
> +		.macro	addruart, rp, rv, tmp
> +		ldr	\rp, =UART0_PADDR	@ physical
> +		ldr	\rv, =UART0_VADDR	@ virtual
> +		.endm
> +
> +		.macro	senduart,rd,rx
> +		strb	\rd, [\rx, #UART01x_DR]
> +		.endm
> +
> +		.macro	waituart,rd,rx
> +		.endm
> +
> +		.macro  busyuart,rd,rx
> +1001:		ldr	\rd, [\rx, #UART01x_FR]
> +		tst	\rd, #UART01x_FR_TXFF
> +		bne	1001b
> +		.endm
> 

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

* [PATCH 02/10] ARM: zx: add low level debug support
  2015-03-14 11:49 ` [PATCH 02/10] ARM: zx: add low level debug support Jun Nie
  2015-03-15 22:44   ` Matthias Brugger
@ 2015-03-15 22:48   ` Russell King - ARM Linux
  2015-03-16  2:37     ` Shawn Guo
  1 sibling, 1 reply; 27+ messages in thread
From: Russell King - ARM Linux @ 2015-03-15 22:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 14, 2015 at 07:49:37PM +0800, Jun Nie wrote:
> Use the UART0 peripheral for low level debug. Only the UART port 0 is
> currently supported.

None of this code is necessary - in fact, you don't have to add one line
of assembly code what so ever.

We have generic PL011 debug support.  Please use that, you only need to
ensure that the phys and virtual addresses are properly configured in
arch/arm/Kconfig.debug and that the appropriate symbol is selected.

Thanks.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH 02/10] ARM: zx: add low level debug support
  2015-03-15 22:48   ` Russell King - ARM Linux
@ 2015-03-16  2:37     ` Shawn Guo
  2015-03-16 10:08       ` Arnd Bergmann
  0 siblings, 1 reply; 27+ messages in thread
From: Shawn Guo @ 2015-03-16  2:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Mar 15, 2015 at 10:48:18PM +0000, Russell King - ARM Linux wrote:
> On Sat, Mar 14, 2015 at 07:49:37PM +0800, Jun Nie wrote:
> > Use the UART0 peripheral for low level debug. Only the UART port 0 is
> > currently supported.
> 
> None of this code is necessary - in fact, you don't have to add one line
> of assembly code what so ever.
> 
> We have generic PL011 debug support.  Please use that, you only need to
> ensure that the phys and virtual addresses are properly configured in
> arch/arm/Kconfig.debug and that the appropriate symbol is selected.

For some reason we never understood, ZTE designers chose to use a
different offset on Data and Flag register, which make it difficult to
reuse pl01x.S.

/* Data read or written from the interface. */
#define UART01x_DR	0x00
#define ZX_UART01x_DR	0x04

/* Flag register (Read only). */
#define ZX_UART01x_FR	0x14
#define UART01x_FR	0x18

We chose to duplicate the file to avoid churning generic pl01x.S.  Would
something like below be acceptable?  Or any better idea?

diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
index 92ef808a2337..da83512c4788 100644
--- a/arch/arm/include/debug/pl01x.S
+++ b/arch/arm/include/debug/pl01x.S
@@ -12,6 +12,13 @@
 */
 #include <linux/amba/serial.h>
 
+#ifdef CONFIG_ARCH_ZX
+#undef UART01x_DR
+#undef UART01x_FR
+#define UART01x_DR     0x04
+#define UART01x_FR     0x14
+#endif
+
 #ifdef CONFIG_DEBUG_UART_PHYS
                .macro  addruart, rp, rv, tmp
                ldr     \rp, =CONFIG_DEBUG_UART_PHYS


Shawn

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

* [PATCH 04/10] ARM: zx: add initial L2CC initialization
  2015-03-14 21:22   ` Arnd Bergmann
@ 2015-03-16  2:48     ` Shawn Guo
  2015-03-16  3:04       ` Jisheng Zhang
  0 siblings, 1 reply; 27+ messages in thread
From: Shawn Guo @ 2015-03-16  2:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 14, 2015 at 10:22:39PM +0100, Arnd Bergmann wrote:
> On Saturday 14 March 2015 19:49:39 Jun Nie wrote:
> > Add an initial L2 Cache controller initialization.
> > 
> > Signed-off-by: Jun Nie <jun.nie@linaro.org>
> > 
> 
> This should not be needed at all, we expect all platforms
> to describe the l2 cache controller in DT to the degree
> that is required to have it probed automatically.
> 
> Is there any special requirement about this platform that
> makes this impossible?

The L2 device tree bindings do not cover PREFETCH_CTRL and POWER_CTRL
registers.  I do not remember, but there might be some reason that these
registers are not defined by DT bindings, e.g. POWER_CTRL is not
available on all pl310 revisions?

Shawn

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

* [PATCH 04/10] ARM: zx: add initial L2CC initialization
  2015-03-16  2:48     ` Shawn Guo
@ 2015-03-16  3:04       ` Jisheng Zhang
  0 siblings, 0 replies; 27+ messages in thread
From: Jisheng Zhang @ 2015-03-16  3:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shawn,

On Sun, 15 Mar 2015 19:48:33 -0700
Shawn Guo <shawn.guo@linaro.org> wrote:

> On Sat, Mar 14, 2015 at 10:22:39PM +0100, Arnd Bergmann wrote:
> > On Saturday 14 March 2015 19:49:39 Jun Nie wrote:
> > > Add an initial L2 Cache controller initialization.
> > > 
> > > Signed-off-by: Jun Nie <jun.nie@linaro.org>
> > > 
> > 
> > This should not be needed at all, we expect all platforms
> > to describe the l2 cache controller in DT to the degree
> > that is required to have it probed automatically.
> > 
> > Is there any special requirement about this platform that
> > makes this impossible?
> 
> The L2 device tree bindings do not cover PREFETCH_CTRL and POWER_CTRL
> registers.  I do not remember, but there might be some reason that these
> registers are not defined by DT bindings, e.g. POWER_CTRL is not
> available on all pl310 revisions?

The key may be PREFETCH_CTRL can only be accessed in Secure World. So the
community require firmware/bootloader to do the setting rather than rely
on linux kernel.

Thanks,
Jisheng

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

* [PATCH 05/10] ARM: zx: bring up the secondary core
  2015-03-14 21:25   ` Arnd Bergmann
@ 2015-03-16  7:23     ` Shawn Guo
  0 siblings, 0 replies; 27+ messages in thread
From: Shawn Guo @ 2015-03-16  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 14, 2015 at 10:25:03PM +0100, Arnd Bergmann wrote:
> On Saturday 14 March 2015 19:49:40 Jun Nie wrote:
> > +
> > +       /*
> > +        * This is really belt and braces; we hold unintended secondary
> > +        * CPUs in the holding pen until we're ready for them.  However,
> > +        * since we haven't sent them a soft interrupt, they shouldn't
> > +        * be there.
> > +        */
> > +       write_pen_release(cpu);
> > +
> > 
> 
> Why do you need the holding pen on this platform? Is there a firmware
> bug or just missing hardware support for proper SMP power management?

Arnd,

As this is how things are handled in vendor's kernel, we thought the
hardware might be lack of SMP power management.  But we will check with
vendor to see if there is any level of hardware support for secondary
core management, so that we can save the use of holding pen.

Thanks for the comment.

Shawn

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

* [PATCH 02/10] ARM: zx: add low level debug support
  2015-03-16  2:37     ` Shawn Guo
@ 2015-03-16 10:08       ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2015-03-16 10:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 16 March 2015 10:37:42 Shawn Guo wrote:
> 
> We chose to duplicate the file to avoid churning generic pl01x.S.  Would
> something like below be acceptable?  Or any better idea?
> 
> diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
> index 92ef808a2337..da83512c4788 100644
> --- a/arch/arm/include/debug/pl01x.S
> +++ b/arch/arm/include/debug/pl01x.S
> @@ -12,6 +12,13 @@
>  */
>  #include <linux/amba/serial.h>
>  
> +#ifdef CONFIG_ARCH_ZX
> +#undef UART01x_DR
> +#undef UART01x_FR
> +#define UART01x_DR     0x04
> +#define UART01x_FR     0x14
> +#endif
> +
>  #ifdef CONFIG_DEBUG_UART_PHYS
> 

This is almost right, but breaks a corner case where you want to debug
the boot on a platform other than ZX, but in a kernel that also has
ARCH_ZX enabled. I think the best way to solve this is to have
CONFIG_DEBUG_ZTE_ZX select CONFIG_DEBUG_UART_PL01X, and then
use #ifdef CONFIG_DEBUG_ZTE_ZX above rather than CONFIG_ARCH_ZX.

	Arnd

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

* [PATCH 04/10] ARM: zx: add initial L2CC initialization
  2015-03-14 11:49 ` [PATCH 04/10] ARM: zx: add initial L2CC initialization Jun Nie
  2015-03-14 21:22   ` Arnd Bergmann
@ 2015-03-16 10:41   ` Russell King - ARM Linux
  1 sibling, 0 replies; 27+ messages in thread
From: Russell King - ARM Linux @ 2015-03-16 10:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 14, 2015 at 07:49:39PM +0800, Jun Nie wrote:
> +static void __init zx_l2x0_init(void)
> +{
> +	void __iomem *base;
> +	struct device_node *np;
> +	unsigned int val;
> +
> +	np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
> +	if (!np)
> +		goto out;
> +
> +	base = of_iomap(np, 0);
> +	if (!base) {
> +		of_node_put(np);
> +		goto out;
> +	}

NAK, really, NAK.  We're trying to get away from platforms doing crap
like this.

> +
> +	val = readl_relaxed(base + L310_PREFETCH_CTRL);
> +	val |= 0x70800000;
> +	writel_relaxed(val, base + L310_PREFETCH_CTRL);

So that's:

	L310_PREFETCH_CTRL_DBL_LINEFILL |
	L310_PREFETCH_CTRL_INSTR_PREFETCH |
	L310_PREFETCH_CTRL_DATA_PREFETCH |
	L310_PREFETCH_CTRL_DBL_LINEFILL_INCR

which you can enable by adding:

	arm,double-linefill
	arm,double-linefill-incr

The prefetch enables are also accessible via the auxillary control
register when the cache is not enabled (see below.)

> +
> +	writel_relaxed(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN,
> +		       base + L310_POWER_CTRL);

These should be done by your boot loader - they're highly SoC specific.

> +out:
> +	l2x0_of_init(0x7c433C01, 0x8000c3fe);

Why these random values?

Firstly, the L2 code takes care of bits 0, 26, 27, 30 for you already.
I fail to see why you would want to hard-code the cache size here
either; the cache size is supposed to be configured by the hardware
designers at implementation stage and the aux control register is
supposed to take up that configuration at reset.

You see to be setting bits 10-13 inclusive, which include:

	L310_AUX_CTRL_HIGHPRIO_SO_DEV
	L310_AUX_CTRL_STORE_LIMITATION
	L310_AUX_CTRL_EXCLUSIVE_CACHE

Are you sure you're supposed to be setting these bits?

Bits 28 and 29 are the same as bits 28 and 29 in the prefetch register
(as in, you read or write those bits in either register and you're
accessing the exact same bits.)

The only possible bits you should be playing around with here which
we don't have a way to cater for are bits 22, 28, 29.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH 10/10] clk: zx: add zx296702 clock support
  2015-03-14 11:49 ` [PATCH 10/10] clk: zx: add zx296702 clock support Jun Nie
  2015-03-14 21:33   ` Arnd Bergmann
@ 2015-03-16 11:33   ` Russell King - ARM Linux
  1 sibling, 0 replies; 27+ messages in thread
From: Russell King - ARM Linux @ 2015-03-16 11:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 14, 2015 at 07:49:45PM +0800, Jun Nie wrote:
> +static int hw_to_idx(struct clk_zx_pll *zx_pll)
> +{
> +	const struct zx_pll_config *config = zx_pll->lookup_table;
> +	u32 hw_cfg0, hw_cfg1;
> +	unsigned long flags = 0;
> +	int i;
> +
> +	if (zx_pll->lock)
> +		spin_lock_irqsave(zx_pll->lock, flags);
> +
> +	hw_cfg0 = readl(zx_pll->reg_base);
> +	hw_cfg1 = readl(zx_pll->reg_base + 4);
> +
> +	if (zx_pll->lock)
> +		spin_unlock_irqrestore(zx_pll->lock, flags);
> +
> +	/* For matching the value in lookup table */
> +	hw_cfg0 &= ~BIT(30); /* clear lock bit */
> +	hw_cfg0 |= BIT(31); /* set PD bit */

Use definitions for these bits rather than BIT(n) and a comment.

> +static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +			   unsigned long parent_rate)
> +{
> +	/* Assume current cpu is not running on current PLL */
> +	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
> +	const struct zx_pll_config *config;
> +	unsigned long flags = 0;
> +	int idx;
> +	u32 reg;
> +
> +	idx = rate_to_idx(zx_pll, rate);
> +	config = &zx_pll->lookup_table[idx];
> +
> +	if (zx_pll->lock)
> +		spin_lock_irqsave(zx_pll->lock, flags);

Is this code ever safe without having a lock to take?

> +
> +	writel(config->cfg0, zx_pll->reg_base);
> +	writel(config->cfg1, zx_pll->reg_base + 4);

Use a definition for this +4 (and also for the first register too.)

> +	reg = readl(zx_pll->reg_base);
> +	reg &= ~BIT(31);
> +	writel(reg, zx_pll->reg_base);

You've only just written zx_pll->reg_base - why do you need to read it
back?  Wouldn't this be better (and in any case, using relaxed
accessors is probably a good idea):

	writel_relaxed(config->cfg0, zx_pll->reg_base);
	writel_relaxed(config->cfg1, zx_pll->reg_base + 4);
	writel_relaxed(config->cfg0 & ~ZX_PLL_PD, zx_pll->reg_base);

Looks nicer, doesn't it?

In any case, why should setting the rate enable the PLL?  I notice you
use the PD bit below in the enable/disable functions, so this seems
rather silly - it looks like it should be preserved, and then the wait
for the PLL to lock (below) should be conditional on the PLL being
enabled.

> +	while (!(readl(zx_pll->reg_base) & BIT(30)))
> +		cpu_relax();

What if the bit never sets?  You can probably use readl_relaxed() here.

> +
> +	if (zx_pll->lock)
> +		spin_unlock_irqrestore(zx_pll->lock, flags);
> +
> +	return 0;
> +}
> +
> +static int zx_pll_enable(struct clk_hw *hw)
> +{
> +	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
> +	unsigned long flags = 0;
> +	u32 reg;
> +
> +	if (zx_pll->lock)
> +		spin_lock_irqsave(zx_pll->lock, flags);
> +
> +	reg = readl(zx_pll->reg_base);
> +	writel(reg & ~BIT(31), zx_pll->reg_base);
> +	while (!(readl(zx_pll->reg_base) & BIT(30)))
> +		cpu_relax();

What if the bit never sets?

> +
> +	if (zx_pll->lock)
> +		spin_unlock_irqrestore(zx_pll->lock, flags);
> +
> +	return 0;
> +}
> +
> +static void zx_pll_disable(struct clk_hw *hw)
> +{
> +	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
> +	unsigned long flags = 0;
> +	u32 reg;
> +
> +	if (zx_pll->lock)
> +		spin_lock_irqsave(zx_pll->lock, flags);
> +
> +	reg = readl(zx_pll->reg_base);
> +	writel(reg | BIT(31), zx_pll->reg_base);
> +
> +	if (zx_pll->lock)
> +		spin_unlock_irqrestore(zx_pll->lock, flags);
> +}
> +
> +static int zx_pll_is_enabled(struct clk_hw *hw)
> +{
> +	struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
> +	unsigned long flags = 0;
> +	u32 reg;
> +
> +	if (zx_pll->lock)
> +		spin_lock_irqsave(zx_pll->lock, flags);
> +
> +	reg = readl(zx_pll->reg_base);
> +
> +	if (zx_pll->lock)
> +		spin_unlock_irqrestore(zx_pll->lock, flags);

You don't need locking to read from a single register.

> +
> +	return !(reg & BIT(31));
> +}
> +
> +static const struct clk_ops zx_pll_ops = {
> +	.recalc_rate = zx_pll_recalc_rate,
> +	.round_rate = zx_pll_round_rate,
> +	.set_rate = zx_pll_set_rate,
> +	.enable = zx_pll_enable,
> +	.disable = zx_pll_disable,
> +	.is_enabled = zx_pll_is_enabled,
> +};
> +
> +struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
> +	unsigned long flags, void __iomem *reg_base,
> +	const struct zx_pll_config *lookup_table, int count, spinlock_t *lock)
> +{
> +	struct clk_zx_pll *zx_pll;
> +	struct clk *clk;
> +	struct clk_init_data init;
> +
> +	zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL);
> +	if (!zx_pll)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = &zx_pll_ops;
> +	init.flags = flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +
> +	zx_pll->reg_base = reg_base;
> +	zx_pll->lookup_table = lookup_table;
> +	zx_pll->count = count;
> +	zx_pll->lock = lock;

As mentioned above, I think this is unsafe if lock is NULL.  You probably
want to subsitute a lock specific to the PLL if none was provided.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

end of thread, other threads:[~2015-03-16 11:33 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-14 11:49 [PATCH 00/10] ZTE platform basic support Jun Nie
2015-03-14 11:49 ` [PATCH 01/10] ARM: zx: add basic support of ZTE ZX296702 Jun Nie
2015-03-14 21:21   ` Arnd Bergmann
2015-03-14 11:49 ` [PATCH 02/10] ARM: zx: add low level debug support Jun Nie
2015-03-15 22:44   ` Matthias Brugger
2015-03-15 22:48   ` Russell King - ARM Linux
2015-03-16  2:37     ` Shawn Guo
2015-03-16 10:08       ` Arnd Bergmann
2015-03-14 11:49 ` [PATCH 03/10] MAINTAINERS: add entry for ZTE ARM architecture Jun Nie
2015-03-14 11:49 ` [PATCH 04/10] ARM: zx: add initial L2CC initialization Jun Nie
2015-03-14 21:22   ` Arnd Bergmann
2015-03-16  2:48     ` Shawn Guo
2015-03-16  3:04       ` Jisheng Zhang
2015-03-16 10:41   ` Russell King - ARM Linux
2015-03-14 11:49 ` [PATCH 05/10] ARM: zx: bring up the secondary core Jun Nie
2015-03-14 21:25   ` Arnd Bergmann
2015-03-16  7:23     ` Shawn Guo
2015-03-14 11:49 ` [PATCH 06/10] ARM: zx: add cpu hotplug support Jun Nie
2015-03-14 21:26   ` Arnd Bergmann
2015-03-14 11:49 ` [PATCH 07/10] dt/binding: Document ZTE zx296702 devicetree Jun Nie
2015-03-14 11:49 ` [PATCH 08/10] ARM: dts: zx: add an initial dts for zx296702 Jun Nie
2015-03-14 21:30   ` Arnd Bergmann
2015-03-14 11:49 ` [PATCH 09/10] ARM: zx: Add basic defconfig support to ZX296702 Jun Nie
2015-03-15 13:15   ` Shawn Guo
2015-03-14 11:49 ` [PATCH 10/10] clk: zx: add zx296702 clock support Jun Nie
2015-03-14 21:33   ` Arnd Bergmann
2015-03-16 11:33   ` Russell King - ARM Linux

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