All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC
@ 2013-08-20  2:31 Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 01/11] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
                   ` (10 more replies)
  0 siblings, 11 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

Changelog:
v7:
1. Add hi3xxx_defconfig.
2. Use reg property in clock node.
3. Drop origin clock divider table.
4. Reuse clock divider register helper.
5. Reuse clock gate register helper.
6. Append CLK_GATE_SEPERATED_REG flag in order to support Hisilicon
   Hi3620 SoC.
7. Rebase DEBUG_LL for Hi3xxx.
8. Add more clock node in DTS file.

v6:
1. Remove hisilicon string from properties in clock driver.
2. Replace array by pointer in clock driver. Since only sctrl parent
   node exists at this time.

v5:
1. Remove HIWORD clk patches since they're merged into clk git tree.
2. Set hisilicon,clk-reset property of clkgate node is optional.
3. Update on commandline args in DTS file. Remove earlyprintk, mem, nfs.
4. Move gpio-keys out of amba node in DTS file.

v4:
1. Add clk gate with HIWORD mask for Rockchip.
2. Update comments and code of HIWORD flags for mux/divider.
3. Append a mux without HIWORD mask in Hisilicon 3620.
4. Fix the pinmux setting in Hi4511.

v3:
1. Use clk_register_mux_table().

v2:
1. Reuse mux & divider driver. So append CLK_MUX_HIWORD_MASK &
CLK_DIVIDER_HIWORD_MASK for Hi3620 SoC.
2. Fix system timer running too fast because wrong divider is choosen.
3. Remove .init_irq in DT machine descriptor.

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

* [PATCH v7 01/11] ARM: debug: support debug ll on hisilicon soc
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 02/11] clk: hi3xxx: add clock support Haojian Zhuang
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

Support UART0 debug ll on Hisilicon Hi3620 SoC & Hi3716 SoC.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig.debug | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 814d224..bba9662 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -194,6 +194,22 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on HI3716 UART.
 
+	config DEBUG_HI3620_UART
+		bool "Hisilicon HI3620 Debug UART"
+		depends on ARCH_HI3xxx
+		select DEBUG_UART_PL01X
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on HI3620 UART.
+
+	config DEBUG_HI3716_UART
+		bool "Hisilicon Hi3716 Debug UART"
+		depends on ARCH_HI3xxx
+		select DEBUG_UART_PL01X
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on HI3716 UART.
+
 	config DEBUG_HIGHBANK_UART
 		bool "Kernel low-level debugging messages via Highbank UART"
 		depends on ARCH_HIGHBANK
@@ -980,6 +996,8 @@ config DEBUG_UART_PHYS
 	default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
 	default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
 				ARCH_ORION5X
+	default 0xf8b00000 if DEBUG_HI3716_UART
+	default 0xfcb00000 if DEBUG_HI3620_UART
 	default 0xfe800000 if ARCH_IOP32X
 	default 0xffc02000 if DEBUG_SOCFPGA_UART
 	default 0xffd82340 if ARCH_IOP13XX
@@ -1016,6 +1034,7 @@ config DEBUG_UART_VIRT
 	default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
 	default 0xfe230000 if DEBUG_PICOXCELL_UART
 	default 0xfe800000 if ARCH_IOP32X
+	default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HI3716_UART
 	default 0xfeb24000 if DEBUG_RK3X_UART0
 	default 0xfeb26000 if DEBUG_RK3X_UART1
 	default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
-- 
1.8.1.2

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

* [PATCH v7 02/11] clk: hi3xxx: add clock support
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 01/11] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-21 21:29   ` Mike Turquette
  2013-08-20  2:31 ` [PATCH v7 03/11] clk: gate: add CLK_GATE_SEPERATED_REG flag Haojian Zhuang
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

Add clock support with device tree on Hisilicon SoC.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Cc: Mike Turquette <mturquette@linaro.org>
---
 .../devicetree/bindings/clock/hisilicon.txt        | 118 +++++++++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-hi3xxx.c                           | 272 +++++++++++++++++++++
 3 files changed, 391 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/hisilicon.txt
 create mode 100644 drivers/clk/clk-hi3xxx.c

diff --git a/Documentation/devicetree/bindings/clock/hisilicon.txt b/Documentation/devicetree/bindings/clock/hisilicon.txt
new file mode 100644
index 0000000..e8ee618
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hisilicon.txt
@@ -0,0 +1,118 @@
+Device Tree Clock bindings for arch-hi3xxx
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+All the mux, gate & divider are in clock container of DTS file.
+
+Required properties for mux clocks:
+ - compatible : shall be "hisilicon,clk-mux".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - reg : the mux register address. It should be the offset of the container.
+ - clkmux-mask : mask bits of the mux register.
+ - clkmux-table : array of mux select bits.
+
+Optional properties for mux clocks:
+ - clkmux-hiword-mask : indicates that the bit[31:16] are the hiword mask
+	of mux selected bits (bit[15:0]). The bit[15:0] is valid only when
+	bit[31:16] is set.
+
+
+
+Required properties for gate clocks:
+ - compatible : shall be "hisilicon,clk-gate".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - #clock-cells : from common clock binding; shall be set to 0.
+ - reg : the mux register address. It should be the offset of the container.
+ - clkgate : bit index to control the clock gate in the gate register.
+
+Optional properties for gate clocks:
+ - clkgate-inverted : it indicates that setting 0 could enable the clock gate
+	and setting 1 could disable the clock gate.
+ - clkgate-seperated-reg : it indicates that there're three continuous
+	registers (enable, disable & status) for the same clock gate.
+
+
+
+Required properties for divider clocks:
+ - compatible : shall be "hisilicon,clk-div".
+ - clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+ - clock-output-names : shall be reference name.
+ - reg : the divider register address. It should be the offset of the
+	container.
+ - clkdiv-mask : mask bits of the divider register.
+ - clkdiv-min : the minimum divider of the clock divider.
+ - clkdiv-max : the maximum divider of the clock divider.
+
+Optional properties for divider clocks:
+ - clkdiv-hiword-mask : indicates that the bit[31:16] are the hiword mask
+	of divider selected bits (bit[15:0]). The bit[15:0] is valid only when
+	bit[31:16] is set.
+
+
+
+For example:
+	sctrl: sctrl at fc802000 {
+		compatible = "hisilicon,sctrl";
+		reg = <0xfc802000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+
+		timer0_mux: timer0_mux {
+			compatible = "hisilicon,clk-mux";
+			#clock-cells = <0>;
+			clocks = <&osc32k &timerclk01>;
+			clock-output-names = "timer0_mux";
+			reg = <0>;
+			clkmux-mask = <0x8000>;
+			clkmux-table = <0 0x8000>;
+		};
+		uart0_mux: uart0_mux {
+			compatible = "hisilicon,clk-mux";
+			#clock-cells = <0>;
+			clocks = <&osc26m &pclk>;
+			clock-output-names = "uart0_mux";
+			reg = <0x100>;
+			clkmux-mask = <0x80>;
+			/* each item value */
+			clkmux-table = <0 0x80>;
+			clkmux-hiword-mask;
+		};
+		timclk0: timclk0 {
+			compatible = "hisilicon,clk-gate";
+			#clock-cells = <0>;
+			clocks = <&timer0_mux>;
+			clock-output-names = "timclk0";
+			clkgate-inverted;
+			reg = <0>;
+			clkgate = <16>;
+		};
+		timerclk01: timerclk01 {
+			compatible = "hisilicon,clk-gate";
+			#clock-cells = <0>;
+			clocks = <&timer_rclk01>;
+			clock-output-names = "timerclk01";
+			reg = <0x20>;
+			clkgate = <0>;
+			clkgate-seperated-reg;
+		};
+		mmc1_div: mmc1_div {
+			compatible = "hisilicon,clk-div";
+			#clock-cells = <0>;
+			clocks = <&mmc1_mux>;
+			clock-output-names = "mmc1_div";
+			reg = <0x108>;
+			clkdiv-mask = <0x1e0>;
+			clkdiv-min = <1>;
+			clkdiv-max = <16>;
+			clkdiv-hiword-mask;
+		};
+	};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 7b11106..2451ce6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK)	+= clk-composite.o
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
+obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3xxx.o
 obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_NSPIRE)	+= clk-nspire.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs/
diff --git a/drivers/clk/clk-hi3xxx.c b/drivers/clk/clk-hi3xxx.c
new file mode 100644
index 0000000..69dca7b
--- /dev/null
+++ b/drivers/clk/clk-hi3xxx.c
@@ -0,0 +1,272 @@
+/*
+ * Hisilicon Hi3xxx clock driver
+ *
+ * Copyright (c) 2012-2013 Hisilicon Limited.
+ * Copyright (c) 2012-2013 Linaro Limited.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *	   Xin Li <li.xin@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+struct hi3620_periclk {
+	struct clk_hw	hw;
+	void __iomem	*enable;	/* enable register */
+	u32		ebits;		/* bits in enable/disable register */
+	spinlock_t	*lock;
+};
+
+static void __iomem *hi3xxx_clk_base = NULL;
+
+static DEFINE_SPINLOCK(hi3xxx_clk_lock);
+
+static const struct of_device_id hi3xxx_of_match[] = {
+	{ .compatible = "hisilicon,sctrl" },
+};
+
+static void __iomem __init *hi3xxx_init_clocks(struct device_node *np)
+{
+	struct device_node *parent;
+	const struct of_device_id *match;
+	void __iomem *ret = NULL;
+
+	parent = of_get_parent(np);
+	if (!parent) {
+		pr_warn("Can't find parent node of these clocks\n");
+		goto out;
+	}
+	match = of_match_node(hi3xxx_of_match, parent);
+	if (!match) {
+		pr_warn("Can't find the right parent\n");
+		goto out;
+	}
+
+	if (!hi3xxx_clk_base) {
+		ret = of_iomap(parent, 0);
+		WARN_ON(!ret);
+		hi3xxx_clk_base = ret;
+	} else {
+		ret = hi3xxx_clk_base;
+	}
+out:
+	return ret;
+}
+
+static void __init hi3xxx_clkgate_setup(struct device_node *np)
+{
+	struct clk *clk;
+	const char *clk_name, **parent_names, *name;
+	const __be32 *prop;
+	unsigned long flags = 0;
+	u32 bit_idx;
+	void __iomem *base, *reg;
+
+	base = hi3xxx_init_clocks(np);
+	if (!base)
+		goto err;
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		goto err;
+	if (of_property_read_u32(np, "clkgate", &bit_idx))
+		goto err;
+	prop = of_get_address(np, 0, NULL, NULL);
+	if (!prop)
+		goto err;
+	reg = base + be32_to_cpu(*prop);
+	if (of_property_read_bool(np, "clkgate-inverted"))
+		flags |= CLK_GATE_SET_TO_DISABLE;
+	if (of_property_read_bool(np, "clkgate-seperated-reg"))
+		flags |= CLK_GATE_SEPERATED_REG;
+	/* gate only has the fixed parent */
+	parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		goto err;
+	parent_names[0] = of_clk_get_parent_name(np, 0);
+
+	clk = clk_register_gate(NULL, clk_name, parent_names[0], 0, reg,
+				(u8)bit_idx, flags, &hi3xxx_clk_lock);
+	if (IS_ERR(clk))
+		goto err_clk;
+	if (!of_property_read_string(np, "clock-names", &name))
+		clk_register_clkdev(clk, name, NULL);
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return;
+err_clk:
+	kfree(parent_names);
+err:
+	pr_err("Fail on registering hi3xxx clkgate node.\n");
+}
+CLK_OF_DECLARE(hi3xxx_gate, "hisilicon,clk-gate", hi3xxx_clkgate_setup)
+
+static int __init hi3xxx_parse_mux(struct device_node *np,
+				   u8 *num_parents,
+				   u32 *table)
+{
+	int i, cnt, ret;
+
+	/* get the count of items in mux */
+	for (i = 0, cnt = 0; ; i++, cnt++) {
+		/* parent's #clock-cells property is always 0 */
+		if (!of_parse_phandle(np, "clocks", i))
+			break;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (!of_clk_get_parent_name(np, i))
+			return -ENOENT;
+	}
+	*num_parents = cnt;
+	table = kzalloc(sizeof(u32 *) * cnt, GFP_KERNEL);
+	if (!table)
+		return -ENOMEM;
+	ret = of_property_read_u32_array(np, "clkmux-table",
+					 table, cnt);
+	if (ret)
+		goto err;
+	return 0;
+err:
+	kfree(table);
+	return ret;
+}
+
+static void __init hi3xxx_clkmux_setup(struct device_node *np)
+{
+	struct clk *clk;
+	const char *clk_name, **parent_names = NULL;
+	const __be32 *prop;
+	u32 mask, *table = NULL;
+	u8 num_parents, shift, clk_mux_flags = 0;
+	void __iomem *reg, *base;
+	int i, ret;
+
+	base = hi3xxx_init_clocks(np);
+	if (!base)
+		goto err;
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		goto err;
+	prop = of_get_address(np, 0, NULL, NULL);
+	if (!prop)
+		goto err;
+	reg = base + be32_to_cpu(*prop);
+	if (of_property_read_u32(np, "clkmux-mask", &mask))
+		goto err;
+	if (of_property_read_bool(np, "clkmux-hiword-mask"))
+		clk_mux_flags = CLK_MUX_HIWORD_MASK;
+
+	ret = hi3xxx_parse_mux(np, &num_parents, table);
+	if (ret)
+		goto err;
+
+	parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL);
+	if (!parent_names)
+		goto err_table;
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(np, i);
+
+	shift = ffs(mask) - 1;
+	mask = mask >> shift;
+	clk = clk_register_mux_table(NULL, clk_name, parent_names, num_parents,
+				     CLK_SET_RATE_PARENT, reg, shift, mask,
+				     clk_mux_flags, table, &hi3xxx_clk_lock);
+	if (IS_ERR(clk))
+		goto err_clk;
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+	return;
+err_clk:
+	kfree(parent_names);
+err_table:
+	kfree(table);
+err:
+	pr_err("Fail on registering hi3xxx clkmux node.\n");
+}
+CLK_OF_DECLARE(hi3xxx_mux, "hisilicon,clk-mux", hi3xxx_clkmux_setup)
+
+static void __init hi3xxx_clkdiv_setup(struct device_node *np, int mode)
+{
+	struct clk *clk;
+	const char *clk_name, **parent_names;
+	const __be32 *prop;
+	struct clk_div_table *table;
+	unsigned int table_num;
+	u32 min, max, mask;
+	u8 shift, width, clk_div_flags = 0;
+	void __iomem *reg, *base;
+	int i;
+
+	base = hi3xxx_init_clocks(np);
+	if (!base)
+		goto err;
+
+	if (of_property_read_string(np, "clock-output-names", &clk_name))
+		goto err;
+	if (of_property_read_u32(np, "clkdiv-mask", &mask))
+		goto err;
+	if (of_property_read_u32(np, "clkdiv-min", &min))
+		goto err;
+	if (of_property_read_u32(np, "clkdiv-max", &max))
+		goto err;
+	if (of_property_read_bool(np, "clkdiv-hiword-mask"))
+		clk_div_flags = CLK_DIVIDER_HIWORD_MASK;
+
+	prop = of_get_address(np, 0, NULL, NULL);
+	if (!prop)
+		goto err;
+	reg = base + be32_to_cpu(*prop);
+
+	table_num = max - min + 1;
+	table = kzalloc(sizeof(*table) * table_num, GFP_KERNEL);
+	if (!table)
+		goto err;
+
+	for (i = 0; i < table_num; i++) {
+		table[i].div = min + i;
+		table[i].val = table[i].div - 1;
+	}
+
+	/* gate only has the fixed parent */
+	parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		goto err_par;
+	parent_names[0] = of_clk_get_parent_name(np, 0);
+	shift = ffs(mask) - 1;
+	width = fls(mask) - ffs(mask) + 1;
+	clk = clk_register_divider_table(NULL, clk_name, parent_names[0], 0,
+					 reg, shift, width, clk_div_flags,
+					 table, &hi3xxx_clk_lock);
+	if (IS_ERR(clk))
+		goto err_clk;
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return;
+err_clk:
+	kfree(parent_names);
+err_par:
+	kfree(table);
+err:
+	pr_err("Fail on registering hi3xxx clkdiv node\n");
+}
+CLK_OF_DECLARE(hi3xxx_div, "hisilicon,clk-div", hi3xxx_clkdiv_setup)
-- 
1.8.1.2

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

* [PATCH v7 03/11] clk: gate: add CLK_GATE_SEPERATED_REG flag
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 01/11] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 02/11] clk: hi3xxx: add clock support Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-21 21:18   ` Mike Turquette
  2013-08-20  2:31 ` [PATCH v7 04/11] ARM: hi3xxx: add board support with device tree Haojian Zhuang
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

In Hisilicon Hi3620 SoC, there're two kinds of clock gates.

1. The same bit in one register controls enabling, disabling or reading status
of the clock gate. It's the normal clock gate register.

2. The same bit in three continuous registers control enabling,
disabling or reading status of the clock gate. Since these three
registers are enabling, disabling and reading status of clock gate.

Now reuse common clock gate driver to support the second case with the new
CLK_GATE_SEPERATED_REG flag.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/clk/clk-gate.c       | 18 +++++++++++++++---
 include/linux/clk-provider.h |  7 +++++++
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..5dedfb3 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,10 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		if (gate->flags & CLK_GATE_SEPERATED_REG)
+			reg = 0;
+		else
+			reg = readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +69,13 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	if (gate->flags & CLK_GATE_SEPERATED_REG) {
+		if (enable)
+			writel(reg, gate->reg + CLK_GATE_ENABLE_REG);
+		else
+			writel(reg, gate->reg + CLK_GATE_DISABLE_REG);
+	} else
+		writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +98,10 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	if (gate->flags & CLK_GATE_SEPERATED_REG)
+		reg = readl(gate->reg + CLK_GATE_STATUS_REG);
+	else
+		reg = readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 9487b96..0fdc13f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -214,6 +214,8 @@ void of_fixed_clk_setup(struct device_node *np);
  *   of this register, and mask of gate bits are in higher 16-bit of this
  *   register.  While setting the gate bits, higher 16-bit should also be
  *   updated to indicate changing gate bits.
+ * CLK_GATE_SEPERATED_REG - The enable, disable & status register are three
+ *	seperated registers.
  */
 struct clk_gate {
 	struct clk_hw hw;
@@ -225,6 +227,11 @@ struct clk_gate {
 
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
 #define CLK_GATE_HIWORD_MASK		BIT(1)
+#define CLK_GATE_SEPERATED_REG		BIT(2)
+
+#define CLK_GATE_ENABLE_REG		(0x00)
+#define CLK_GATE_DISABLE_REG		(0x04)
+#define CLK_GATE_STATUS_REG		(0x08)
 
 extern const struct clk_ops clk_gate_ops;
 struct clk *clk_register_gate(struct device *dev, const char *name,
-- 
1.8.1.2

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

* [PATCH v7 04/11] ARM: hi3xxx: add board support with device tree
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (2 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 03/11] clk: gate: add CLK_GATE_SEPERATED_REG flag Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 05/11] ARM: dts: enable hi4511 " Haojian Zhuang
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

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

Changelog:
v3:
1. Remove .map_io() in DT machine descriptor. Since debug_ll_io_init()
is called by default.
2. Remove .init_machine() in DT machine descriptor. Since
of_platform_populate() is called by default in DT mode.

v2:
1. Remove .init_irq() in DT machine descriptor. Since irqchip_init()
is called by default in DT mode.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 .../bindings/arm/hisilicon/hisilicon.txt           | 10 ++++++
 arch/arm/Kconfig                                   |  2 ++
 arch/arm/Makefile                                  |  1 +
 arch/arm/mach-hi3xxx/Kconfig                       | 12 ++++++++
 arch/arm/mach-hi3xxx/Makefile                      |  5 +++
 arch/arm/mach-hi3xxx/hi3xxx.c                      | 36 ++++++++++++++++++++++
 6 files changed, 66 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
 create mode 100644 arch/arm/mach-hi3xxx/Kconfig
 create mode 100644 arch/arm/mach-hi3xxx/Makefile
 create mode 100644 arch/arm/mach-hi3xxx/hi3xxx.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
new file mode 100644
index 0000000..3be60c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -0,0 +1,10 @@
+Hisilicon Platforms Device Tree Bindings
+----------------------------------------------------
+
+Hi3716 Development Board
+Required root node properties:
+	- compatible = "hisilicon,hi3716-dkb";
+
+Hi4511 Board
+Required root node properties:
+	- compatible = "hisilicon,hi3620-hi4511";
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 16f088a..f0e7374 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -943,6 +943,8 @@ source "arch/arm/mach-footbridge/Kconfig"
 
 source "arch/arm/mach-gemini/Kconfig"
 
+source "arch/arm/mach-hi3xxx/Kconfig"
+
 source "arch/arm/mach-highbank/Kconfig"
 
 source "arch/arm/mach-integrator/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a37a50f..23fb0b0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -155,6 +155,7 @@ machine-$(CONFIG_ARCH_EBSA110)		+= ebsa110
 machine-$(CONFIG_ARCH_EP93XX)		+= ep93xx
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
 machine-$(CONFIG_ARCH_GEMINI)		+= gemini
+machine-$(CONFIG_ARCH_HI3xxx)		+= hi3xxx
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
 machine-$(CONFIG_ARCH_INTEGRATOR)	+= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		+= iop13xx
diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig
new file mode 100644
index 0000000..68bd26c
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/Kconfig
@@ -0,0 +1,12 @@
+config ARCH_HI3xxx
+	bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
+	select ARM_AMBA
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select CACHE_L2X0
+	select CLKSRC_OF
+	select GENERIC_CLOCKEVENTS
+	select PINCTRL
+	select PINCTRL_SINGLE
+	help
+	  Support for Hisilicon Hi36xx/Hi37xx processor family
diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
new file mode 100644
index 0000000..d68ebb3
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Hisilicon Hi36xx/Hi37xx processors line
+#
+
+obj-y	+= hi3xxx.o
diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
new file mode 100644
index 0000000..e7c54bc
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/hi3xxx.c
@@ -0,0 +1,36 @@
+/*
+ * (Hisilicon's Hi36xx/Hi37xx SoC based) flattened device tree enabled machine
+ *
+ * Copyright (c) 2012-2013 Hisilicon Ltd.
+ * Copyright (c) 2012-2013 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+static void __init hi3xxx_timer_init(void)
+{
+	of_clk_init(NULL);
+	clocksource_of_init();
+}
+
+static const char *hs_compat[] __initdata = {
+	"hisilicon,hi3620-hi4511",
+	NULL,
+};
+
+DT_MACHINE_START(HI3xxx, "Hisilicon Hi36xx/Hi37xx (Flattened Device Tree)")
+	.init_time	= hi3xxx_timer_init,
+	.dt_compat	= hs_compat,
+MACHINE_END
-- 
1.8.1.2

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (3 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 04/11] ARM: hi3xxx: add board support with device tree Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-22 18:07   ` Kevin Hilman
  2013-08-20  2:31 ` [PATCH v7 06/11] ARM: config: enable hi3xxx in multi_v7_defconfig Haojian Zhuang
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

Enable Hisilicon Hi4511 development platform with device tree support.

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

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index ada589c..a93bcfe 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -64,6 +64,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos5420-smdk5420.dtb \
 	exynos5440-sd5v1.dtb \
 	exynos5440-ssdk5440.dtb
+dtb-$(CONFIG_ARCH_HI3xxx) += hi4511.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
 	ecx-2000.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
new file mode 100644
index 0000000..39fa37f
--- /dev/null
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -0,0 +1,1645 @@
+/*
+ * Hisilicon Ltd. Hi3620 SoC
+ *
+ * Copyright (C) 2012-2013 Hisilicon Ltd.
+ * Copyright (C) 2012-2013 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0x0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	osc32k: osc32k {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "osc32khz";
+	};
+	osc26m: osc26m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "osc26mhz";
+	};
+	pclk: pclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "apb_pclk";
+	};
+	pll_arm0: pll_arm0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1600000000>;
+		clock-output-names = "armpll0";
+	};
+	pll_arm1: pll_arm1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1600000000>;
+		clock-output-names = "armpll1";
+	};
+	pll_peri: pll_peri {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1440000000>;
+		clock-output-names = "armpll2";
+	};
+	pll_usb: pll_usb {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1440000000>;
+		clock-output-names = "armpll3";
+	};
+	pll_hdmi: pll_hdmi {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1188000000>;
+		clock-output-names = "armpll4";
+	};
+	pll_gpu: pll_gpu {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1300000000>;
+		clock-output-names = "armpll5";
+	};
+	rclk_tcxo: rclk_tcxo {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clocks = <&osc26m>;
+		clock-output-names = "rclk_tcxo";
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+	rclk_cfgaxi: rclk_cfgaxi {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clocks = <&pll_peri>;
+		clock-output-names = "rclk_cfgaxi";
+		clock-mult = <1>;
+		clock-div = <30>;
+	};
+	rclk_pico: rclk_pico {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clocks = <&hsic_div>;
+		clock-output-names = "rclk_pico";
+		clock-mult = <1>;
+		clock-div = <40>;
+	};
+
+	amba {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "arm,amba-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		pmctrl: pmctrl at fca08000 {
+			compatible = "hisilicon,pmctrl";
+			reg = <0xfca08000 0x1000>;
+		};
+
+		sctrl: sctrl at fc802000 {
+			compatible = "hisilicon,sctrl";
+			reg = <0xfc802000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+
+			timer0_mux: timer0_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk01>;
+				clock-output-names = "timer0_mux";
+				reg = <0>;
+				clkmux-mask = <0x8000>;
+				clkmux-table = <0 0x8000>;
+			};
+			timer1_mux: timer1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk01>;
+				clock-output-names = "timer1_mux";
+				reg = <0>;
+				clkmux-mask = <0x20000>;
+				clkmux-table = <0 0x20000>;
+			};
+			timer2_mux: timer2_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk23>;
+				clock-output-names = "timer2_mux";
+				reg = <0>;
+				clkmux-mask = <0x80000>;
+				clkmux-table = <0 0x80000>;
+			};
+			timer3_mux: timer3_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk23>;
+				clock-output-names = "timer3_mux";
+				reg = <0>;
+				clkmux-mask = <0x200000>;
+				clkmux-table = <0 0x200000>;
+			};
+			timer4_mux: timer4_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk45>;
+				clock-output-names = "timer4_mux";
+				reg = <0x18>;
+				clkmux-mask = <0x1>;
+				clkmux-table = <0 0x1>;
+			};
+			timer5_mux: timer5_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk45>;
+				clock-output-names = "timer5_mux";
+				reg = <0x18>;
+				clkmux-mask = <0x4>;
+				clkmux-table = <0 0x4>;
+			};
+			timer6_mux: timer6_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk67>;
+				clock-output-names = "timer6_mux";
+				reg = <0x18>;
+				clkmux-mask = <0x10>;
+				clkmux-table = <0 0x10>;
+			};
+			timer7_mux: timer7_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk67>;
+				clock-output-names = "timer7_mux";
+				reg = <0x18>;
+				clkmux-mask = <0x40>;
+				clkmux-table = <0 0x40>;
+			};
+			timer8_mux: timer8_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk89>;
+				clock-output-names = "timer8_mux";
+				reg = <0x18>;
+				clkmux-mask = <0x100>;
+				clkmux-table = <0 0x100>;
+			};
+			timer9_mux: timer9_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &timerclk89>;
+				clock-output-names = "timer9_mux";
+				reg = <0x18>;
+				clkmux-mask = <0x400>;
+				clkmux-table = <0 0x400>;
+			};
+			uart0_mux: uart0_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "uart0_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x80>;
+				/* each item value */
+				clkmux-table = <0 0x80>;
+				clkmux-hiword-mask;
+			};
+			uart1_mux: uart1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "uart1_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x100>;
+				clkmux-table = <0x0 0x100>;
+				clkmux-hiword-mask;
+			};
+			uart2_mux: uart2_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "uart2_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x200>;
+				clkmux-table = <0 0x200>;
+				clkmux-hiword-mask;
+			};
+			uart3_mux: uart3_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "uart3_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x400>;
+				clkmux-table = <0 0x400>;
+				clkmux-hiword-mask;
+			};
+			uart4_mux: uart4_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &pclk>;
+				clock-output-names = "uart4_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x800>;
+				clkmux-table = <0 0x800>;
+				clkmux-hiword-mask;
+			};
+			spi0_mux: spi0_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &rclk_cfgaxi>;
+				clock-output-names = "spi0_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x1000>;
+				clkmux-table = <0 0x1000>;
+				clkmux-hiword-mask;
+			};
+			spi1_mux: spi1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &rclk_cfgaxi>;
+				clock-output-names = "spi1_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x2000>;
+				clkmux-table = <0 0x2000>;
+				clkmux-hiword-mask;
+			};
+			spi2_mux: spi2_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &rclk_cfgaxi>;
+				clock-output-names = "spi2_mux";
+				reg = <0x100>;
+				clkmux-mask = <0x4000>;
+				clkmux-table = <0 0x4000>;
+				clkmux-hiword-mask;
+			};
+			rclk_shareAXI: rclk_shareAXI {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "rclk_shareAXI";
+				reg = <0x100>;
+				clkmux-mask = <0x8000>;
+				clkmux-table = <0 0x8000>;
+				clkmux-hiword-mask;
+			};
+			pwm0_mux: pwm0_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &osc26m>;
+				clock-output-names = "pwm0_mux";
+				reg = <0x104>;
+				clkmux-mask = <0x400>;
+				clkmux-table = <0 0x400>;
+				clkmux-hiword-mask;
+			};
+			pwm1_mux: pwm1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc32k &osc26m>;
+				clock-output-names = "pwm1_mux";
+				reg = <0x104>;
+				clkmux-mask = <0x800>;
+				clkmux-table = <0 0x800>;
+				clkmux-hiword-mask;
+			};
+			sd_mux: sd_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "sd_mux";
+				reg = <0x108>;
+				clkmux-mask = <0x10>;
+				clkmux-table = <0 0x10>;
+				clkmux-hiword-mask;
+			};
+			mmc1_mux: mmc1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "mmc1_mux";
+				reg = <0x108>;
+				clkmux-mask = <0x200>;
+				clkmux-table = <0 0x200>;
+				clkmux-hiword-mask;
+			};
+			rclk_mmc1_mux: rclk_mmc1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&osc26m &mmc1_div>;
+				clock-output-names = "rclk_mmc1_mux";
+				reg = <0x108>;
+				clkmux-mask = <0x400>;
+				clkmux-table = <0 0x400>;
+				clkmux-hiword-mask;
+			};
+			g2d_mux: g2d_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_usb>;
+				clock-output-names = "g2d_mux";
+				reg = <0x10c>;
+				clkmux-mask = <0x20>;
+				clkmux-table = <0 0x20>;
+				clkmux-hiword-mask;
+			};
+			venc_mux: venc_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_usb>;
+				clock-output-names = "venc_mux";
+				reg = <0x10c>;
+				clkmux-mask = <0x800>;
+				clkmux-table = <0 0x800>;
+				clkmux-hiword-mask;
+			};
+			vdec_mux: vdec_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_usb>;
+				clock-output-names = "vdec_mux";
+				reg = <0x110>;
+				clkmux-mask = <0x20>;
+				clkmux-table = <0 0x20>;
+				clkmux-hiword-mask;
+			};
+			vpp_mux: vpp_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_usb>;
+				clock-output-names = "vpp_mux";
+				reg = <0x110>;
+				clkmux-mask = <0x800>;
+				clkmux-table = <0 0x800>;
+				clkmux-hiword-mask;
+			};
+			edc0_mux: edc0_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_usb>;
+				clock-output-names = "edc0_mux";
+				reg = <0x114>;
+				clkmux-mask = <0x40>;
+				clkmux-table = <0 0x40>;
+				clkmux-hiword-mask;
+			};
+			ldi0_mux: ldi0_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_hdmi &pll_usb &pll_gpu>;
+				clock-output-names = "ldi0_mux";
+				reg = <0x114>;
+				clkmux-mask = <0x6000>;
+				clkmux-table = <0 0x2000 0x4000 0x6000>;
+				clkmux-hiword-mask;
+			};
+			edc1_mux: edc1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_usb>;
+				clock-output-names = "edc1_mux";
+				reg = <0x118>;
+				clkmux-mask = <0x40>;
+				clkmux-table = <0 0x40>;
+				clkmux-hiword-mask;
+			};
+			ldi1_mux: ldi1_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_peri &pll_hdmi &pll_usb &pll_gpu>;
+				clock-output-names = "ldi1_mux";
+				reg = <0x118>;
+				clkmux-mask = <0xc000>;
+				clkmux-table = <0 0x4000 0x8000 0xc000>;
+				clkmux-hiword-mask;
+			};
+			rclk_hsic: rclk_hsic {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "rclk_hsic";
+				reg = <0x130>;
+				clkmux-mask = <0x4>;
+				clkmux-table = <0 0x4>;
+				clkmux-hiword-mask;
+			};
+			mmc2_mux: mmc2_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "mmc2_mux";
+				reg = <0x140>;
+				clkmux-mask = <0x10>;
+				clkmux-table = <0 0x10>;
+				clkmux-hiword-mask;
+			};
+			mmc3_mux: mmc3_mux {
+				compatible = "hisilicon,clk-mux";
+				#clock-cells = <0>;
+				clocks = <&pll_usb &pll_peri>;
+				clock-output-names = "mmc3_mux";
+				reg = <0x140>;
+				clkmux-mask = <0x200>;
+				clkmux-table = <0 0x200>;
+				clkmux-hiword-mask;
+			};
+
+			shareaxi_div: shareaxi_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&rclk_shareAXI>;
+				clock-output-names = "shareaxi_div";
+				reg = <0x100>;
+				clkdiv-mask = <0x1f>;
+				clkdiv-min = <1>;
+				clkdiv-max = <32>;
+				clkdiv-hiword-mask;
+			};
+			cfgaxi_div: cfgaxi_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&shareaxi_div>;
+				clock-output-names = "cfgaxi_div";
+				reg = <0x100>;
+				clkdiv-mask = <0x60>;
+				clkdiv-min = <2>;
+				clkdiv-max = <2>;
+				clkdiv-hiword-mask;
+			};
+			sd_div: sd_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&sd_mux>;
+				clock-output-names = "sd_div";
+				reg = <0x108>;
+				clkdiv-mask = <0xf>;
+				clkdiv-min = <1>;
+				clkdiv-max = <16>;
+				clkdiv-hiword-mask;
+			};
+			mmc1_div: mmc1_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&mmc1_mux>;
+				clock-output-names = "mmc1_div";
+				reg = <0x108>;
+				clkdiv-mask = <0x1e0>;
+				clkdiv-min = <1>;
+				clkdiv-max = <16>;
+				clkdiv-hiword-mask;
+			};
+			hsic_div: hsic_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&rclk_hsic>;
+				clock-output-names = "hsic_div";
+				reg = <0x130>;
+				clkdiv-mask = <0x3>;
+				clkdiv-min = <1>;
+				clkdiv-max = <4>;
+				clkdiv-hiword-mask;
+			};
+			mmc2_div: mmc2_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&mmc1_mux>;
+				clock-output-names = "mmc2_div";
+				reg = <0x140>;
+				clkdiv-mask = <0xf>;
+				clkdiv-min = <1>;
+				clkdiv-max = <16>;
+				clkdiv-hiword-mask;
+			};
+			mmc3_div: mmc3_div {
+				compatible = "hisilicon,clk-div";
+				#clock-cells = <0>;
+				clocks = <&mmc1_mux>;
+				clock-output-names = "mmc3_div";
+				reg = <0x140>;
+				clkdiv-mask = <0x1e0>;
+				clkdiv-min = <1>;
+				clkdiv-max = <16>;
+				clkdiv-hiword-mask;
+			};
+
+			timclk0: timclk0 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer0_mux>;
+				clock-output-names = "timclk0";
+				clkgate-inverted;
+				reg = <0>;
+				clkgate = <16>;
+			};
+			timclk1: timclk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer1_mux>;
+				clock-output-names = "timclk1";
+				clkgate-inverted;
+				reg = <0>;
+				clkgate = <18>;
+			};
+			timclk2: timclk2 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer2_mux>;
+				clock-output-names = "timclk2";
+				clkgate-inverted;
+				reg = <0>;
+				clkgate = <20>;
+			};
+			timclk3: timclk3 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer3_mux>;
+				clock-output-names = "timclk3";
+				clkgate-inverted;
+				reg = <0>;
+				clkgate = <22>;
+			};
+			timclk4: timclk4 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer4_mux>;
+				clock-output-names = "timclk4";
+				clkgate-inverted;
+				reg = <0x18>;
+				clkgate = <1>;
+			};
+			timclk5: timclk5 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer5_mux>;
+				clock-output-names = "timclk5";
+				clkgate-inverted;
+				reg = <0x18>;
+				clkgate = <3>;
+			};
+			timclk6: timclk6 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer6_mux>;
+				clock-output-names = "timclk6";
+				clkgate-inverted;
+				reg = <0x18>;
+				clkgate = <5>;
+			};
+			timclk7: timclk7 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer7_mux>;
+				clock-output-names = "timclk7";
+				clkgate-inverted;
+				reg = <0x18>;
+				clkgate = <7>;
+			};
+			timclk8: timclk8 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer8_mux>;
+				clock-output-names = "timclk8";
+				clkgate-inverted;
+				reg = <0x18>;
+				clkgate = <9>;
+			};
+			timclk9: timclk9 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer9_mux>;
+				clock-output-names = "timclk9";
+				clkgate-inverted;
+				reg = <0x18>;
+				clkgate = <11>;
+			};
+			timerclk01: timerclk01 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer_rclk01>;
+				clock-output-names = "timerclk01";
+				reg = <0x20>;
+				clkgate = <0>;
+				clkgate-seperated-reg;
+			};
+			timer_rclk01: timer_rclk01 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_tcxo>;
+				clock-output-names = "timer_rclk01";
+				reg = <0x20>;
+				clkgate = <1>;
+				clkgate-seperated-reg;
+			};
+			timerclk23: timerclk23 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&timer_rclk23>;
+				clock-output-names = "timerclk23";
+				reg = <0x20>;
+				clkgate = <2>;
+				clkgate-seperated-reg;
+			};
+			timer_rclk23: timer_rclk23 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_tcxo>;
+				clock-output-names = "timer_rclk23";
+				reg = <0x20>;
+				clkgate = <3>;
+				clkgate-seperated-reg;
+			};
+			rtcclk: rtcclk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "rtcclk";
+				reg = <0x20>;
+				clkgate = <5>;
+				clkgate-seperated-reg;
+			};
+			kpc_clk: kpc_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "kpc_clk";
+				reg = <0x20>;
+				clkgate = <6>;
+				clkgate-seperated-reg;
+			};
+			gpioclk0: gpioclk0 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk0";
+				reg = <0x20>;
+				clkgate = <8>;
+				clkgate-seperated-reg;
+			};
+			gpioclk1: gpioclk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk1";
+				reg = <0x20>;
+				clkgate = <9>;
+				clkgate-seperated-reg;
+			};
+			gpioclk2: gpioclk2 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk2";
+				reg = <0x20>;
+				clkgate = <10>;
+				clkgate-seperated-reg;
+			};
+			gpioclk3: gpioclk3 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk3";
+				reg = <0x20>;
+				clkgate = <11>;
+				clkgate-seperated-reg;
+			};
+			gpioclk4: gpioclk4 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk4";
+				reg = <0x20>;
+				clkgate = <12>;
+				clkgate-seperated-reg;
+			};
+			gpioclk5: gpioclk5 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk5";
+				reg = <0x20>;
+				clkgate = <13>;
+				clkgate-seperated-reg;
+			};
+			gpioclk6: gpioclk6 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk6";
+				reg = <0x20>;
+				clkgate = <14>;
+				clkgate-seperated-reg;
+			};
+			gpioclk7: gpioclk7 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk7";
+				reg = <0x20>;
+				clkgate = <15>;
+				clkgate-seperated-reg;
+			};
+			gpioclk8: gpioclk8 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk8";
+				reg = <0x20>;
+				clkgate = <16>;
+				clkgate-seperated-reg;
+			};
+			gpioclk9: gpioclk9 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk9";
+				reg = <0x20>;
+				clkgate = <17>;
+				clkgate-seperated-reg;
+			};
+			gpioclk10: gpioclk10 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk10";
+				reg = <0x20>;
+				clkgate = <18>;
+				clkgate-seperated-reg;
+			};
+			gpioclk11: gpioclk11 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk11";
+				reg = <0x20>;
+				clkgate = <19>;
+				clkgate-seperated-reg;
+			};
+			gpioclk12: gpioclk12 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk12";
+				reg = <0x20>;
+				clkgate = <20>;
+				clkgate-seperated-reg;
+			};
+			gpioclk13: gpioclk13 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk13";
+				reg = <0x20>;
+				clkgate = <21>;
+				clkgate-seperated-reg;
+			};
+			gpioclk14: gpioclk14 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk14";
+				reg = <0x20>;
+				clkgate = <22>;
+				clkgate-seperated-reg;
+			};
+			gpioclk15: gpioclk15 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk15";
+				reg = <0x20>;
+				clkgate = <23>;
+				clkgate-seperated-reg;
+			};
+			gpioclk16: gpioclk16 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk16";
+				reg = <0x20>;
+				clkgate = <24>;
+				clkgate-seperated-reg;
+			};
+			gpioclk17: gpioclk17 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk17";
+				reg = <0x20>;
+				clkgate = <25>;
+				clkgate-seperated-reg;
+			};
+			gpioclk18: gpioclk18 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk18";
+				reg = <0x20>;
+				clkgate = <26>;
+				clkgate-seperated-reg;
+			};
+			gpioclk19: gpioclk19 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk19";
+				reg = <0x20>;
+				clkgate = <27>;
+				clkgate-seperated-reg;
+			};
+			gpioclk20: gpioclk20 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk20";
+				reg = <0x20>;
+				clkgate = <28>;
+				clkgate-seperated-reg;
+			};
+			gpioclk21: gpioclk21 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "gpioclk21";
+				reg = <0x20>;
+				clkgate = <29>;
+				clkgate-seperated-reg;
+			};
+			dphy0_clk: dphy0_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&osc26m>;
+				clock-output-names = "dphy0_clk";
+				reg = <0x30>;
+				clkgate = <15>;
+				clkgate-seperated-reg;
+			};
+			dphy1_clk: dphy1_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&osc26m>;
+				clock-output-names = "dphy1_clk";
+				reg = <0x30>;
+				clkgate = <16>;
+				clkgate-seperated-reg;
+			};
+			dphy2_clk: dphy2_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&osc26m>;
+				clock-output-names = "dphy2_clk";
+				reg = <0x30>;
+				clkgate = <17>;
+				clkgate-seperated-reg;
+			};
+			usbpicophy_clk: usbpicophy_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_pico>;
+				clock-output-names = "usbpicophy_clk";
+				reg = <0x30>;
+				clkgate = <24>;
+				clkgate-seperated-reg;
+			};
+			acp_clk: acp_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_cfgaxi>;
+				clock-output-names = "acp_clk";
+				reg = <0x30>;
+				clkgate = <28>;
+				clkgate-seperated-reg;
+			};
+			timerclk45: timerclk45 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_tcxo>;
+				clock-output-names = "timerclk45";
+				reg = <0x40>;
+				clkgate = <3>;
+				clkgate-seperated-reg;
+			};
+			timerclk67: timerclk67 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_tcxo>;
+				clock-output-names = "timerclk67";
+				reg = <0x40>;
+				clkgate = <4>;
+				clkgate-seperated-reg;
+			};
+			timerclk89: timerclk89 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_tcxo>;
+				clock-output-names = "timerclk89";
+				reg = <0x40>;
+				clkgate = <5>;
+				clkgate-seperated-reg;
+			};
+			pwmclk0: pwmclk0 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pwm0_mux>;
+				clock-output-names = "pwmclk0";
+				reg = <0x40>;
+				clkgate = <7>;
+				clkgate-seperated-reg;
+			};
+			pwmclk1: pwmclk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pwm1_mux>;
+				clock-output-names = "pwmclk1";
+				reg = <0x40>;
+				clkgate = <8>;
+				clkgate-seperated-reg;
+			};
+			uartclk0: uartclk0 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&uart0_mux>;
+				clock-output-names = "uartclk0";
+				reg = <0x40>;
+				clkgate = <16>;
+				clkgate-seperated-reg;
+			};
+			uartclk1: uartclk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&uart1_mux>;
+				clock-output-names = "uartclk1";
+				reg = <0x40>;
+				clkgate = <17>;
+				clkgate-seperated-reg;
+			};
+			uartclk2: uartclk2 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&uart2_mux>;
+				clock-output-names = "uartclk2";
+				reg = <0x40>;
+				clkgate = <18>;
+				clkgate-seperated-reg;
+			};
+			uartclk3: uartclk3 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&uart3_mux>;
+				clock-output-names = "uartclk3";
+				reg = <0x40>;
+				clkgate = <19>;
+				clkgate-seperated-reg;
+			};
+			uartclk4: uartclk4 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&uart4_mux>;
+				clock-output-names = "uartclk4";
+				reg = <0x40>;
+				clkgate = <20>;
+				clkgate-seperated-reg;
+			};
+			spiclk0: spiclk0 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&spi0_mux>;
+				clock-output-names = "spiclk0";
+				reg = <0x40>;
+				clkgate = <21>;
+				clkgate-seperated-reg;
+			};
+			spiclk1: spiclk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&spi1_mux>;
+				clock-output-names = "spiclk1";
+				reg = <0x40>;
+				clkgate = <22>;
+				clkgate-seperated-reg;
+			};
+			spiclk2: spiclk2 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&spi2_mux>;
+				clock-output-names = "spiclk2";
+				reg = <0x40>;
+				clkgate = <23>;
+				clkgate-seperated-reg;
+			};
+			i2cclk0: i2cclk0 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "i2cclk0";
+				reg = <0x40>;
+				clkgate = <24>;
+				clkgate-seperated-reg;
+			};
+			i2cclk1: i2cclk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "i2cclk1";
+				reg = <0x40>;
+				clkgate = <25>;
+				clkgate-seperated-reg;
+			};
+			sci_clk: sci_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&osc26m>;
+				clock-output-names = "sci_clk";
+				reg = <0x40>;
+				clkgate = <26>;
+				clkgate-seperated-reg;
+			};
+			i2cclk2: i2cclk2 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "i2cclk2";
+				reg = <0x40>;
+				clkgate = <28>;
+				clkgate-seperated-reg;
+			};
+			i2cclk3: i2cclk3 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&pclk>;
+				clock-output-names = "i2cclk3";
+				reg = <0x40>;
+				clkgate = <29>;
+				clkgate-seperated-reg;
+			};
+			ddrc_per_clk: ddrc_per_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_cfgaxi>;
+				clock-output-names = "ddrc_per_clk";
+				reg = <0x50>;
+				clkgate = <9>;
+				clkgate-seperated-reg;
+			};
+			dmac_clk: dmac_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_cfgaxi>;
+				clock-output-names = "dmac_clk";
+				reg = <0x50>;
+				clkgate = <10>;
+				clkgate-seperated-reg;
+			};
+			usb2dvc_clk: usb2dvc_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_cfgaxi>;
+				clock-output-names = "usb2dvc_clk";
+				reg = <0x50>;
+				clkgate = <10>;
+				clkgate-seperated-reg;
+			};
+			sd_clk: sd_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&sd_div>;
+				clock-output-names = "sd_clk";
+				reg = <0x50>;
+				clkgate = <20>;
+				clkgate-seperated-reg;
+			};
+			mmc_clk1: mmc_clk1 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&rclk_mmc1_mux>;
+				clock-output-names = "mmc_clk1";
+				reg = <0x50>;
+				clkgate = <21>;
+				clkgate-seperated-reg;
+			};
+			mmc_clk2: mmc_clk2 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&mmc2_div>;
+				clock-output-names = "mmc_clk2";
+				reg = <0x50>;
+				clkgate = <22>;
+				clkgate-seperated-reg;
+			};
+			mmc_clk3: mmc_clk3 {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&mmc3_div>;
+				clock-output-names = "mmc_clk3";
+				reg = <0x50>;
+				clkgate = <23>;
+				clkgate-seperated-reg;
+			};
+			mcu_clk: mcu_clk {
+				compatible = "hisilicon,clk-gate";
+				#clock-cells = <0>;
+				clocks = <&acp_clk>;
+				clock-output-names = "mcu_clk";
+				reg = <0x50>;
+				clkgate = <24>;
+				clkgate-seperated-reg;
+			};
+		};
+
+		L2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xfc10000 0x100000>;
+			interrupts = <0 15 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		gic: interrupt-controller at fc001000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			/* gic dist base, gic cpu base */
+			reg = <0xfc001000 0x1000>, <0xfc000100 0x100>;
+		};
+
+		timer0: timer at fc800000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfc800000 0x1000>;
+			/* timer00 & timer01 */
+			interrupts = <0 0 4>, <0 1 4>;
+			clocks = <&timclk0 &timclk1>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer1: timer at fc801000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfc801000 0x1000>;
+			/* timer10 & timer11 */
+			interrupts = <0 2 4>, <0 3 4>;
+			clocks = <&timclk2 &timclk3>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer2: timer at fca01000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfca01000 0x1000>;
+			/* timer20 & timer21 */
+			interrupts = <0 4 4>, <0 5 4>;
+			clocks = <&timclk4 &timclk5>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer3: timer at fca02000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfca02000 0x1000>;
+			/* timer30 & timer31 */
+			interrupts = <0 6 4>, <0 7 4>;
+			clocks = <&timclk6 &timclk7>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer4: timer at fca03000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfca03000 0x1000>;
+			/* timer40 & timer41 */
+			interrupts = <0 96 4>, <0 97 4>;
+			clocks = <&timclk8 &timclk9>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart0: uart at fcb00000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb00000 0x1000>;
+			interrupts = <0 20 4>;
+			clocks = <&uartclk0>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart1: uart at fcb01000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb01000 0x1000>;
+			interrupts = <0 21 4>;
+			clocks = <&uartclk1>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart2: uart at fcb02000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb02000 0x1000>;
+			interrupts = <0 22 4>;
+			clocks = <&uartclk2>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart3: uart at fcb03000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb03000 0x1000>;
+			interrupts = <0 23 4>;
+			clocks = <&uartclk3>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		uart4: uart at fcb04000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfcb04000 0x1000>;
+			interrupts = <0 24 4>;
+			clocks = <&uartclk4>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		gpio0: gpio at fc806000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc806000 0x1000>;
+			interrupts = <0 64 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 2 0 1 &pmx0 3 0 1 &pmx0 4 0 1
+					&pmx0 5 0 1 &pmx0 6 1 1 &pmx0 7 2 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk0>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio1: gpio at fc807000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc807000 0x1000>;
+			interrupts = <0 65 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 3 1 &pmx0 1 3 1 &pmx0 2 3 1
+					&pmx0 3 3 1 &pmx0 4 3 1 &pmx0 5 4 1
+					&pmx0 6 5 1 &pmx0 7 6 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk1>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio2: gpio at fc808000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc808000 0x1000>;
+			interrupts = <0 66 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 7 1 &pmx0 1 8 1 &pmx0 2 9 1
+					&pmx0 3 10 1 &pmx0 4 3 1 &pmx0 5 3 1
+					&pmx0 6 3 1 &pmx0 7 3 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio3: gpio at fc809000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc809000 0x1000>;
+			interrupts = <0 67 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 3 1 &pmx0 1 3 1 &pmx0 2 3 1
+					&pmx0 3 3 1 &pmx0 4 11 1 &pmx0 5 11 1
+					&pmx0 6 11 1 &pmx0 7 11 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk3>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio4: gpio at fc80a000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80a000 0x1000>;
+			interrupts = <0 68 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 11 1 &pmx0 1 11 1 &pmx0 2 11 1
+					&pmx0 3 11 1 &pmx0 4 12 1 &pmx0 5 12 1
+					&pmx0 6 13 1 &pmx0 7 13 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk4>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio5: gpio at fc80b000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80b000 0x1000>;
+			interrupts = <0 69 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 14 1 &pmx0 1 15 1 &pmx0 2 16 1
+					&pmx0 3 16 1 &pmx0 4 16 1 &pmx0 5 16 1
+					&pmx0 6 16 1 &pmx0 7 16 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk5>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio6: gpio at fc80c000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80c000 0x1000>;
+			interrupts = <0 70 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 16 1 &pmx0 1 16 1 &pmx0 2 17 1
+					&pmx0 3 17 1 &pmx0 4 18 1 &pmx0 5 18 1
+					&pmx0 6 18 1 &pmx0 7 19 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk6>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio7: gpio at fc80d000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80d000 0x1000>;
+			interrupts = <0 71 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 19 1 &pmx0 1 20 1 &pmx0 2 21 1
+					&pmx0 3 22 1 &pmx0 4 23 1 &pmx0 5 24 1
+					&pmx0 6 25 1 &pmx0 7 26 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk7>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio8: gpio at fc80e000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80e000 0x1000>;
+			interrupts = <0 72 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 27 1 &pmx0 1 28 1 &pmx0 2 29 1
+					&pmx0 3 30 1 &pmx0 4 31 1 &pmx0 5 32 1
+					&pmx0 6 33 1 &pmx0 7 34 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk8>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio9: gpio at fc80f000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc80f000 0x1000>;
+			interrupts = <0 73 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 35 1 &pmx0 1 36 1 &pmx0 2 37 1
+					&pmx0 3 38 1 &pmx0 4 39 1 &pmx0 5 40 1
+					&pmx0 6 41 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk9>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio10: gpio at fc810000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc810000 0x1000>;
+			interrupts = <0 74 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 2 43 1 &pmx0 3 44 1 &pmx0 4 45 1
+					&pmx0 5 45 1 &pmx0 6 46 1 &pmx0 7 46 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk10>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio11: gpio at fc811000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc811000 0x1000>;
+			interrupts = <0 75 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 47 1 &pmx0 1 47 1 &pmx0 2 47 1
+					&pmx0 3 47 1 &pmx0 4 47 1 &pmx0 5 48 1
+					&pmx0 6 49 1 &pmx0 7 49 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk11>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio12: gpio at fc812000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc812000 0x1000>;
+			interrupts = <0 76 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 49 1 &pmx0 1 50 1 &pmx0 2 49 1
+					&pmx0 3 49 1 &pmx0 4 51 1 &pmx0 5 51 1
+					&pmx0 6 51 1 &pmx0 7 52 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk12>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio13: gpio at fc813000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc813000 0x1000>;
+			interrupts = <0 77 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 51 1 &pmx0 1 51 1 &pmx0 2 53 1
+					&pmx0 3 53 1 &pmx0 4 53 1 &pmx0 5 54 1
+					&pmx0 6 55 1 &pmx0 7 56 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk13>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio14: gpio at fc814000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc814000 0x1000>;
+			interrupts = <0 78 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 57 1 &pmx0 1 97 1 &pmx0 2 97 1
+					&pmx0 3 58 1 &pmx0 4 59 1 &pmx0 5 60 1
+					&pmx0 6 60 1 &pmx0 7 61 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk14>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio15: gpio at fc815000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc815000 0x1000>;
+			interrupts = <0 79 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 61 1 &pmx0 1 62 1 &pmx0 2 62 1
+					&pmx0 3 63 1 &pmx0 4 63 1 &pmx0 5 64 1
+					&pmx0 6 64 1 &pmx0 7 65 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk15>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio16: gpio at fc816000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc816000 0x1000>;
+			interrupts = <0 80 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 66 1 &pmx0 1 67 1 &pmx0 2 68 1
+					&pmx0 3 69 1 &pmx0 4 70 1 &pmx0 5 71 1
+					&pmx0 6 72 1 &pmx0 7 73 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk16>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio17: gpio at fc817000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc817000 0x1000>;
+			interrupts = <0 81 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 74 1 &pmx0 1 75 1 &pmx0 2 76 1
+					&pmx0 3 77 1 &pmx0 4 78 1 &pmx0 5 79 1
+					&pmx0 6 80 1 &pmx0 7 81 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk17>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio18: gpio at fc818000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc818000 0x1000>;
+			interrupts = <0 82 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 82 1 &pmx0 1 83 1 &pmx0 2 83 1
+					&pmx0 3 84 1 &pmx0 4 84 1 &pmx0 5 85 1
+					&pmx0 6 86 1 &pmx0 7 87 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk18>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio19: gpio at fc819000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc819000 0x1000>;
+			interrupts = <0 83 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 87 1 &pmx0 1 87 1 &pmx0 2 88 1
+					&pmx0 3 88 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk19>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio20: gpio at fc81a000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc81a000 0x1000>;
+			interrupts = <0 84 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 0 89 1 &pmx0 1 89 1 &pmx0 2 90 1
+					&pmx0 3 90 1 &pmx0 4 91 1 &pmx0 5 92 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk20>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio21: gpio at fc81b000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0xfc81b000 0x1000>;
+			interrupts = <0 85 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <	&pmx0 3 94 1 &pmx0 7 96 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&gpioclk21>;
+			clock-names = "apb_pclk";
+		};
+
+		pmx0: pinmux at fc803000 {
+			compatible = "pinctrl-single";
+			reg = <0xfc803000 0x188>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			#gpio-range-cells = <3>;
+			ranges;
+
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <7>;
+			/* pin base, nr pins & gpio function */
+			pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
+						&range 12 1 0 &range 13 29 1
+						&range 43 1 0 &range 44 49 1
+						&range 94 1 1 &range 96 2 1>;
+
+			range: gpio-range {
+				#pinctrl-single,gpio-range-cells = <3>;
+			};
+		};
+
+		pmx1: pinmux at fc803800 {
+			compatible = "pinconf-single";
+			reg = <0xfc803800 0x2dc>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			pinctrl-single,register-width = <32>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
new file mode 100644
index 0000000..7e67564
--- /dev/null
+++ b/arch/arm/boot/dts/hi4511.dts
@@ -0,0 +1,648 @@
+/*
+ *  Copyright (C) 2012-2013 Linaro Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "hi3620.dtsi"
+
+/ {
+	model = "Hisilicon Hi4511 Development Board";
+	compatible = "hisilicon,hi3620-hi4511";
+
+	chosen {
+		bootargs = "console=ttyAMA0,115200 root=/dev/ram0 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x40000000 0x20000000>;
+	};
+
+	amba {
+		timer0: timer at fc800000 {
+			status = "ok";
+		};
+
+		uart0: uart at fcb00000 {	/* console */
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart0_pmx_func &uart0_cfg_func>;
+			pinctrl-1 = <&uart0_pmx_idle &uart0_cfg_idle>;
+			status = "ok";
+		};
+
+		uart1: uart at fcb01000 { /* modem */
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart1_pmx_func &uart1_cfg_func>;
+			pinctrl-1 = <&uart1_pmx_idle &uart1_cfg_idle>;
+			status = "ok";
+		};
+
+		uart2: uart at fcb02000 { /* audience */
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart2_pmx_func &uart2_cfg_func>;
+			pinctrl-1 = <&uart2_pmx_idle &uart2_cfg_idle>;
+			status = "ok";
+		};
+
+		uart3: uart at fcb03000 {
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart3_pmx_func &uart3_cfg_func>;
+			pinctrl-1 = <&uart3_pmx_idle &uart3_cfg_idle>;
+			status = "ok";
+		};
+
+		uart4: uart at fcb04000 {
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&uart4_pmx_func &uart4_cfg_func>;
+			pinctrl-1 = <&uart4_pmx_idle &uart4_cfg_func>;
+			status = "ok";
+		};
+
+		pmx0: pinmux at fc803000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&board_pmx_pins>;
+
+			board_pmx_pins: board_pmx_pins {
+				pinctrl-single,pins = <
+					0x008 0x0	/* GPIO -- eFUSE_DOUT */
+					0x100 0x0	/* USIM_CLK & USIM_DATA (IOMG63) */
+				>;
+			};
+			uart0_pmx_func: uart0_pmx_func {
+				pinctrl-single,pins = <
+					0x0f0 0x0
+					0x0f4 0x0	/* UART0_RX & UART0_TX */
+				>;
+			};
+			uart0_pmx_idle: uart0_pmx_idle {
+				pinctrl-single,pins = <
+					/*0x0f0 0x1*/	/* UART0_CTS & UART0_RTS */
+					0x0f4 0x1	/* UART0_RX & UART0_TX */
+				>;
+			};
+			uart1_pmx_func: uart1_pmx_func {
+				pinctrl-single,pins = <
+					0x0f8 0x0	/* UART1_CTS & UART1_RTS (IOMG61) */
+					0x0fc 0x0	/* UART1_RX & UART1_TX (IOMG62) */
+				>;
+			};
+			uart1_pmx_idle: uart1_pmx_idle {
+				pinctrl-single,pins = <
+					0x0f8 0x1	/* GPIO (IOMG61) */
+					0x0fc 0x1	/* GPIO (IOMG62) */
+				>;
+			};
+			uart2_pmx_func: uart2_pmx_func {
+				pinctrl-single,pins = <
+					0x104 0x2	/* UART2_RXD (IOMG96) */
+					0x108 0x2	/* UART2_TXD (IOMG64) */
+				>;
+			};
+			uart2_pmx_idle: uart2_pmx_idle {
+				pinctrl-single,pins = <
+					0x104 0x1	/* GPIO (IOMG96) */
+					0x108 0x1	/* GPIO (IOMG64) */
+				>;
+			};
+			uart3_pmx_func: uart3_pmx_func {
+				pinctrl-single,pins = <
+					0x160 0x2	/* UART3_CTS & UART3_RTS (IOMG85) */
+					0x164 0x2	/* UART3_RXD & UART3_TXD (IOMG86) */
+				>;
+			};
+			uart3_pmx_idle: uart3_pmx_idle {
+				pinctrl-single,pins = <
+					0x160 0x1	/* GPIO (IOMG85) */
+					0x164 0x1	/* GPIO (IOMG86) */
+				>;
+			};
+			uart4_pmx_func: uart4_pmx_func {
+				pinctrl-single,pins = <
+					0x168 0x0	/* UART4_CTS & UART4_RTS (IOMG87) */
+					0x16c 0x0	/* UART4_RXD (IOMG88) */
+					0x170 0x0	/* UART4_TXD (IOMG93) */
+				>;
+			};
+			uart4_pmx_idle: uart4_pmx_idle {
+				pinctrl-single,pins = <
+					0x168 0x1	/* GPIO (IOMG87) */
+					0x16c 0x1	/* GPIO (IOMG88) */
+					0x170 0x1	/* GPIO (IOMG93) */
+				>;
+			};
+			i2c0_pmx_func: i2c0_pmx_func {
+				pinctrl-single,pins = <
+					0x0b4 0x0	/* I2C0_SCL & I2C0_SDA (IOMG45) */
+				>;
+			};
+			i2c0_pmx_idle: i2c0_pmx_idle {
+				pinctrl-single,pins = <
+					0x0b4 0x1	/* GPIO (IOMG45) */
+				>;
+			};
+			i2c1_pmx_func: i2c1_pmx_func {
+				pinctrl-single,pins = <
+					0x0b8 0x0	/* I2C1_SCL & I2C1_SDA (IOMG46) */
+				>;
+			};
+			i2c1_pmx_idle: i2c1_pmx_idle {
+				pinctrl-single,pins = <
+					0x0b8 0x1	/* GPIO (IOMG46) */
+				>;
+			};
+			i2c2_pmx_func: i2c2_pmx_func {
+				pinctrl-single,pins = <
+					0x068 0x0	/* I2C2_SCL (IOMG26) */
+					0x06c 0x0	/* I2C2_SDA (IOMG27) */
+				>;
+			};
+			i2c2_pmx_idle: i2c2_pmx_idle {
+				pinctrl-single,pins = <
+					0x068 0x1	/* GPIO (IOMG26) */
+					0x06c 0x1	/* GPIO (IOMG27) */
+				>;
+			};
+			i2c3_pmx_func: i2c3_pmx_func {
+				pinctrl-single,pins = <
+					0x050 0x2	/* I2C3_SCL (IOMG20) */
+					0x054 0x2	/* I2C3_SDA (IOMG21) */
+				>;
+			};
+			i2c3_pmx_idle: i2c3_pmx_idle {
+				pinctrl-single,pins = <
+					0x050 0x1	/* GPIO (IOMG20) */
+					0x054 0x1	/* GPIO (IOMG21) */
+				>;
+			};
+			spi0_pmx_func: spi0_pmx_func {
+				pinctrl-single,pins = <
+					0x0d4 0x0	/* SPI0_CLK/SPI0_DI/SPI0_DO (IOMG53) */
+					0x0d8 0x0	/* SPI0_CS0 (IOMG54) */
+					0x0dc 0x0	/* SPI0_CS1 (IOMG55) */
+					0x0e0 0x0	/* SPI0_CS2 (IOMG56) */
+					0x0e4 0x0	/* SPI0_CS3 (IOMG57) */
+				>;
+			};
+			spi0_pmx_idle: spi0_pmx_idle {
+				pinctrl-single,pins = <
+					0x0d4 0x1	/* GPIO (IOMG53) */
+					0x0d8 0x1	/* GPIO (IOMG54) */
+					0x0dc 0x1	/* GPIO (IOMG55) */
+					0x0e0 0x1	/* GPIO (IOMG56) */
+					0x0e4 0x1	/* GPIO (IOMG57) */
+				>;
+			};
+			spi1_pmx_func: spi1_pmx_func {
+				pinctrl-single,pins = <
+					0x184 0x0	/* SPI1_CLK/SPI1_DI (IOMG98) */
+					0x0e8 0x0	/* SPI1_DO (IOMG58) */
+					0x0ec 0x0	/* SPI1_CS (IOMG95) */
+				>;
+			};
+			spi1_pmx_idle: spi1_pmx_idle {
+				pinctrl-single,pins = <
+					0x184 0x1	/* GPIO (IOMG98) */
+					0x0e8 0x1	/* GPIO (IOMG58) */
+					0x0ec 0x1	/* GPIO (IOMG95) */
+				>;
+			};
+			kpc_pmx_func: kpc_pmx_func {
+				pinctrl-single,pins = <
+					0x12c 0x0	/* KEY_IN0 (IOMG73) */
+					0x130 0x0	/* KEY_IN1 (IOMG74) */
+					0x134 0x0	/* KEY_IN2 (IOMG75) */
+					0x10c 0x0	/* KEY_OUT0 (IOMG65) */
+					0x110 0x0	/* KEY_OUT1 (IOMG66) */
+					0x114 0x0	/* KEY_OUT2 (IOMG67) */
+				>;
+			};
+			kpc_pmx_idle: kpc_pmx_idle {
+				pinctrl-single,pins = <
+					0x12c 0x1	/* GPIO (IOMG73) */
+					0x130 0x1	/* GPIO (IOMG74) */
+					0x134 0x1	/* GPIO (IOMG75) */
+					0x10c 0x1	/* GPIO (IOMG65) */
+					0x110 0x1	/* GPIO (IOMG66) */
+					0x114 0x1	/* GPIO (IOMG67) */
+				>;
+			};
+			gpio_key_func: gpio_key_func {
+				pinctrl-single,pins = <
+					0x10c 0x1	/* KEY_OUT0/GPIO (IOMG65) */
+					0x130 0x1	/* KEY_IN1/GPIO (IOMG74) */
+				>;
+			};
+			emmc_pmx_func: emmc_pmx_func {
+				pinctrl-single,pins = <
+					0x030 0x2	/* eMMC_CMD/eMMC_CLK (IOMG12) */
+					0x018 0x0	/* NAND_CS3_N (IOMG6) */
+					0x024 0x0	/* NAND_BUSY2_N (IOMG8) */
+					0x028 0x0	/* NAND_BUSY3_N (IOMG9) */
+					0x02c 0x2	/* eMMC_DATA[0:7] (IOMG10) */
+				>;
+			};
+			emmc_pmx_idle: emmc_pmx_idle {
+				pinctrl-single,pins = <
+					0x030 0x0	/* GPIO (IOMG12) */
+					0x018 0x1	/* GPIO (IOMG6) */
+					0x024 0x1	/* GPIO (IOMG8) */
+					0x028 0x1	/* GPIO (IOMG9) */
+					0x02c 0x1	/* GPIO (IOMG10) */
+				>;
+			};
+			sd_pmx_func: sd_pmx_func {
+				pinctrl-single,pins = <
+					0x0bc 0x0	/* SD_CLK/SD_CMD/SD_DATA0/SD_DATA1/SD_DATA2 (IOMG47) */
+					0x0c0 0x0	/* SD_DATA3 (IOMG48) */
+				>;
+			};
+			sd_pmx_idle: sd_pmx_idle {
+				pinctrl-single,pins = <
+					0x0bc 0x1	/* GPIO (IOMG47) */
+					0x0c0 0x1	/* GPIO (IOMG48) */
+				>;
+			};
+			nand_pmx_func: nand_pmx_func {
+				pinctrl-single,pins = <
+					0x00c 0x0	/* NAND_ALE/NAND_CLE/.../NAND_DATA[0:7] (IOMG3) */
+					0x010 0x0	/* NAND_CS1_N (IOMG4) */
+					0x014 0x0	/* NAND_CS2_N (IOMG5) */
+					0x018 0x0	/* NAND_CS3_N (IOMG6) */
+					0x01c 0x0	/* NAND_BUSY0_N (IOMG94) */
+					0x020 0x0	/* NAND_BUSY1_N (IOMG7) */
+					0x024 0x0	/* NAND_BUSY2_N (IOMG8) */
+					0x028 0x0	/* NAND_BUSY3_N (IOMG9) */
+					0x02c 0x0	/* NAND_DATA[8:15] (IOMG10) */
+				>;
+			};
+			nand_pmx_idle: nand_pmx_idle {
+				pinctrl-single,pins = <
+					0x00c 0x1	/* GPIO (IOMG3) */
+					0x010 0x1	/* GPIO (IOMG4) */
+					0x014 0x1	/* GPIO (IOMG5) */
+					0x018 0x1	/* GPIO (IOMG6) */
+					0x01c 0x1	/* GPIO (IOMG94) */
+					0x020 0x1	/* GPIO (IOMG7) */
+					0x024 0x1	/* GPIO (IOMG8) */
+					0x028 0x1	/* GPIO (IOMG9) */
+					0x02c 0x1	/* GPIO (IOMG10) */
+				>;
+			};
+			sdio_pmx_func: sdio_pmx_func {
+				pinctrl-single,pins = <
+					0x0c4 0x0	/* SDIO_CLK/SDIO_CMD/SDIO_DATA[0:3] (IOMG49) */
+				>;
+			};
+			sdio_pmx_idle: sdio_pmx_idle {
+				pinctrl-single,pins = <
+					0x0c4 0x1	/* GPIO (IOMG49) */
+				>;
+			};
+			audio_out_pmx_func: audio_out_pmx_func {
+				pinctrl-single,pins = <
+					0x0f0 0x1	/* GPIO (IOMG59), audio spk & earphone */
+				>;
+			};
+		};
+
+		pmx1: pinmux at fc803800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <	&board_pu_pins &board_pd_pins &board_pd_ps_pins
+					&board_np_pins &board_ps_pins &kpc_cfg_func
+					&audio_out_cfg_func>;
+			board_pu_pins: board_pu_pins {
+				pinctrl-single,pins = <
+					0x014 0		/* GPIO_158 (IOCFG2) */
+					0x018 0		/* GPIO_159 (IOCFG3) */
+					0x01c 0		/* BOOT_MODE0 (IOCFG4) */
+					0x020 0		/* BOOT_MODE1 (IOCFG5) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+			};
+			board_pd_pins: board_pd_pins {
+				pinctrl-single,pins = <
+					0x038 0		/* eFUSE_DOUT (IOCFG11) */
+					0x150 0		/* ISP_GPIO8 (IOCFG93) */
+					0x154 0		/* ISP_GPIO9 (IOCFG94) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			board_pd_ps_pins: board_pd_ps_pins {
+				pinctrl-single,pins = <
+					0x2d8 0		/* CLK_OUT0 (IOCFG190) */
+					0x004 0		/* PMU_SPI_DATA (IOCFG192) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			board_np_pins: board_np_pins {
+				pinctrl-single,pins = <
+					0x24c 0		/* KEYPAD_OUT7 (IOCFG155) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			board_ps_pins: board_ps_pins {
+				pinctrl-single,pins = <
+					0x000 0		/* PMU_SPI_CLK (IOCFG191) */
+					0x008 0		/* PMU_SPI_CS_N (IOCFG193) */
+				>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			uart0_cfg_func: uart0_cfg_func {
+				pinctrl-single,pins = <
+					0x208 0		/* UART0_RXD (IOCFG138) */
+					0x20c 0		/* UART0_TXD (IOCFG139) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart0_cfg_idle: uart0_cfg_idle {
+				pinctrl-single,pins = <
+					0x208 0		/* UART0_RXD (IOCFG138) */
+					0x20c 0		/* UART0_TXD (IOCFG139) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart1_cfg_func: uart1_cfg_func {
+				pinctrl-single,pins = <
+					0x210 0		/* UART1_CTS (IOCFG140) */
+					0x214 0		/* UART1_RTS (IOCFG141) */
+					0x218 0		/* UART1_RXD (IOCFG142) */
+					0x21c 0		/* UART1_TXD (IOCFG143) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart1_cfg_idle: uart1_cfg_idle {
+				pinctrl-single,pins = <
+					0x210 0		/* UART1_CTS (IOCFG140) */
+					0x214 0		/* UART1_RTS (IOCFG141) */
+					0x218 0		/* UART1_RXD (IOCFG142) */
+					0x21c 0		/* UART1_TXD (IOCFG143) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart2_cfg_func: uart2_cfg_func {
+				pinctrl-single,pins = <
+					0x220 0		/* UART2_CTS (IOCFG144) */
+					0x224 0		/* UART2_RTS (IOCFG145) */
+					0x228 0		/* UART2_RXD (IOCFG146) */
+					0x22c 0		/* UART2_TXD (IOCFG147) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart2_cfg_idle: uart2_cfg_idle {
+				pinctrl-single,pins = <
+					0x220 0		/* GPIO (IOCFG144) */
+					0x224 0		/* GPIO (IOCFG145) */
+					0x228 0		/* GPIO (IOCFG146) */
+					0x22c 0		/* GPIO (IOCFG147) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart3_cfg_func: uart3_cfg_func {
+				pinctrl-single,pins = <
+					0x294 0		/* UART3_CTS (IOCFG173) */
+					0x298 0		/* UART3_RTS (IOCFG174) */
+					0x29c 0		/* UART3_RXD (IOCFG175) */
+					0x2a0 0		/* UART3_TXD (IOCFG176) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart3_cfg_idle: uart3_cfg_idle {
+				pinctrl-single,pins = <
+					0x294 0		/* UART3_CTS (IOCFG173) */
+					0x298 0		/* UART3_RTS (IOCFG174) */
+					0x29c 0		/* UART3_RXD (IOCFG175) */
+					0x2a0 0		/* UART3_TXD (IOCFG176) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			uart4_cfg_func: uart4_cfg_func {
+				pinctrl-single,pins = <
+					0x2a4 0		/* UART4_CTS (IOCFG177) */
+					0x2a8 0		/* UART4_RTS (IOCFG178) */
+					0x2ac 0		/* UART4_RXD (IOCFG179) */
+					0x2b0 0		/* UART4_TXD (IOCFG180) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			i2c0_cfg_func: i2c0_cfg_func {
+				pinctrl-single,pins = <
+					0x17c 0		/* I2C0_SCL (IOCFG103) */
+					0x180 0		/* I2C0_SDA (IOCFG104) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			i2c1_cfg_func: i2c1_cfg_func {
+				pinctrl-single,pins = <
+					0x184 0		/* I2C1_SCL (IOCFG105) */
+					0x188 0		/* I2C1_SDA (IOCFG106) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			i2c2_cfg_func: i2c2_cfg_func {
+				pinctrl-single,pins = <
+					0x118 0		/* I2C2_SCL (IOCFG79) */
+					0x11c 0		/* I2C2_SDA (IOCFG80) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			i2c3_cfg_func: i2c3_cfg_func {
+				pinctrl-single,pins = <
+					0x100 0		/* I2C3_SCL (IOCFG73) */
+					0x104 0		/* I2C3_SDA (IOCFG74) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi0_cfg_func1: spi0_cfg_func1 {
+				pinctrl-single,pins = <
+					0x1d4 0		/* SPI0_CLK (IOCFG125) */
+					0x1d8 0		/* SPI0_DI (IOCFG126) */
+					0x1dc 0		/* SPI0_DO (IOCFG127) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi0_cfg_func2: spi0_cfg_func2 {
+				pinctrl-single,pins = <
+					0x1e0 0		/* SPI0_CS0 (IOCFG128) */
+					0x1e4 0		/* SPI0_CS1 (IOCFG129) */
+					0x1e8 0		/* SPI0_CS2 (IOCFG130 */
+					0x1ec 0		/* SPI0_CS3 (IOCFG131) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi1_cfg_func1: spi1_cfg_func1 {
+				pinctrl-single,pins = <
+					0x1f0 0		/* SPI1_CLK (IOCFG132) */
+					0x1f4 0		/* SPI1_DI (IOCFG133) */
+					0x1f8 0		/* SPI1_DO (IOCFG134) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			spi1_cfg_func2: spi1_cfg_func2 {
+				pinctrl-single,pins = <
+					0x1fc 0		/* SPI1_CS (IOCFG135) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			kpc_cfg_func: kpc_cfg_func {
+				pinctrl-single,pins = <
+					0x250 0		/* KEY_IN0 (IOCFG156) */
+					0x254 0		/* KEY_IN1 (IOCFG157) */
+					0x258 0		/* KEY_IN2 (IOCFG158) */
+					0x230 0		/* KEY_OUT0 (IOCFG148) */
+					0x234 0		/* KEY_OUT1 (IOCFG149) */
+					0x238 0		/* KEY_OUT2 (IOCFG150) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+			emmc_cfg_func: emmc_cfg_func {
+				pinctrl-single,pins = <
+					0x0ac 0		/* eMMC_CMD (IOCFG40) */
+					0x0b0 0		/* eMMC_CLK (IOCFG41) */
+					0x058 0		/* NAND_CS3_N (IOCFG19) */
+					0x064 0		/* NAND_BUSY2_N (IOCFG22) */
+					0x068 0		/* NAND_BUSY3_N (IOCFG23) */
+					0x08c 0		/* NAND_DATA8 (IOCFG32) */
+					0x090 0		/* NAND_DATA9 (IOCFG33) */
+					0x094 0		/* NAND_DATA10 (IOCFG34) */
+					0x098 0		/* NAND_DATA11 (IOCFG35) */
+					0x09c 0		/* NAND_DATA12 (IOCFG36) */
+					0x0a0 0		/* NAND_DATA13 (IOCFG37) */
+					0x0a4 0		/* NAND_DATA14 (IOCFG38) */
+					0x0a8 0		/* NAND_DATA15 (IOCFG39) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			sd_cfg_func1: sd_cfg_func1 {
+				pinctrl-single,pins = <
+					0x18c 0		/* SD_CLK (IOCFG107) */
+					0x190 0		/* SD_CMD (IOCFG108) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			sd_cfg_func2: sd_cfg_func2 {
+				pinctrl-single,pins = <
+					0x194 0		/* SD_DATA0 (IOCFG109) */
+					0x198 0		/* SD_DATA1 (IOCFG110) */
+					0x19c 0		/* SD_DATA2 (IOCFG111) */
+					0x1a0 0		/* SD_DATA3 (IOCFG112) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x70 0xf0>;
+			};
+			nand_cfg_func1: nand_cfg_func1 {
+				pinctrl-single,pins = <
+					0x03c 0		/* NAND_ALE (IOCFG12) */
+					0x040 0		/* NAND_CLE (IOCFG13) */
+					0x06c 0		/* NAND_DATA0 (IOCFG24) */
+					0x070 0		/* NAND_DATA1 (IOCFG25) */
+					0x074 0		/* NAND_DATA2 (IOCFG26) */
+					0x078 0		/* NAND_DATA3 (IOCFG27) */
+					0x07c 0		/* NAND_DATA4 (IOCFG28) */
+					0x080 0		/* NAND_DATA5 (IOCFG29) */
+					0x084 0		/* NAND_DATA6 (IOCFG30) */
+					0x088 0		/* NAND_DATA7 (IOCFG31) */
+					0x08c 0		/* NAND_DATA8 (IOCFG32) */
+					0x090 0		/* NAND_DATA9 (IOCFG33) */
+					0x094 0		/* NAND_DATA10 (IOCFG34) */
+					0x098 0		/* NAND_DATA11 (IOCFG35) */
+					0x09c 0		/* NAND_DATA12 (IOCFG36) */
+					0x0a0 0		/* NAND_DATA13 (IOCFG37) */
+					0x0a4 0		/* NAND_DATA14 (IOCFG38) */
+					0x0a8 0		/* NAND_DATA15 (IOCFG39) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			nand_cfg_func2: nand_cfg_func2 {
+				pinctrl-single,pins = <
+					0x044 0		/* NAND_RE_N (IOCFG14) */
+					0x048 0		/* NAND_WE_N (IOCFG15) */
+					0x04c 0		/* NAND_CS0_N (IOCFG16) */
+					0x050 0		/* NAND_CS1_N (IOCFG17) */
+					0x054 0		/* NAND_CS2_N (IOCFG18) */
+					0x058 0		/* NAND_CS3_N (IOCFG19) */
+					0x05c 0		/* NAND_BUSY0_N (IOCFG20) */
+					0x060 0		/* NAND_BUSY1_N (IOCFG21) */
+					0x064 0		/* NAND_BUSY2_N (IOCFG22) */
+					0x068 0		/* NAND_BUSY3_N (IOCFG23) */
+				>;
+				pinctrl-single,bias-pulldown = <0 2 0 2>;
+				pinctrl-single,bias-pullup = <1 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			sdio_cfg_func: sdio_cfg_func {
+				pinctrl-single,pins = <
+					0x1a4 0		/* SDIO0_CLK (IOCG113) */
+					0x1a8 0		/* SDIO0_CMD (IOCG114) */
+					0x1ac 0		/* SDIO0_DATA0 (IOCG115) */
+					0x1b0 0		/* SDIO0_DATA1 (IOCG116) */
+					0x1b4 0		/* SDIO0_DATA2 (IOCG117) */
+					0x1b8 0		/* SDIO0_DATA3 (IOCG118) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+				pinctrl-single,drive-strength = <0x30 0xf0>;
+			};
+			audio_out_cfg_func: audio_out_cfg_func {
+				pinctrl-single,pins = <
+					0x200 0		/* GPIO (IOCFG136) */
+					0x204 0		/* GPIO (IOCFG137) */
+				>;
+				pinctrl-single,bias-pulldown = <2 2 0 2>;
+				pinctrl-single,bias-pullup = <0 1 0 1>;
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		call {
+			label = "call";
+			gpios = <&gpio17 2 0>;
+			linux,code = <169>;	/* KEY_PHONE */
+		};
+	};
+};
-- 
1.8.1.2

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

* [PATCH v7 06/11] ARM: config: enable hi3xxx in multi_v7_defconfig
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (4 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 05/11] ARM: dts: enable hi4511 " Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 07/11] ARM: config: add defconfig for Hi3xxx Haojian Zhuang
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

Enable ARCH_HI3xxx in multi_v7_defconfig.

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

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 6e572c6..6855397 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -8,6 +8,7 @@ CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_BCM=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_HI3xxx=y
 CONFIG_ARCH_KEYSTONE=y
 CONFIG_ARCH_MXC=y
 CONFIG_MACH_IMX51_DT=y
-- 
1.8.1.2

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

* [PATCH v7 07/11] ARM: config: add defconfig for Hi3xxx
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (5 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 06/11] ARM: config: enable hi3xxx in multi_v7_defconfig Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 08/11] ARM: hi3xxx: add smp support Haojian Zhuang
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

Add default config for arch-hi3xxx. It's used for Hisilicon Hi3xxx SoC.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/configs/hi3xxx_defconfig | 56 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 arch/arm/configs/hi3xxx_defconfig

diff --git a/arch/arm/configs/hi3xxx_defconfig b/arch/arm/configs/hi3xxx_defconfig
new file mode 100644
index 0000000..f186bdf
--- /dev/null
+++ b/arch/arm/configs/hi3xxx_defconfig
@@ -0,0 +1,56 @@
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_LZMA=y
+CONFIG_ARCH_HI3xxx=y
+CONFIG_SMP=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_DRM=y
+CONFIG_FB_SIMPLE=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_DMADEVICES=y
+CONFIG_DW_DMAC=y
+CONFIG_PL330_DMA=y
+CONFIG_PWM=y
+CONFIG_EXT4_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
-- 
1.8.1.2

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

* [PATCH v7 08/11] ARM: hi3xxx: add smp support
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (6 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 07/11] ARM: config: add defconfig for Hi3xxx Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-28  2:12   ` Olof Johansson
  2013-08-20  2:31 ` [PATCH v7 09/11] ARM: hi3xxx: add hotplug support Haojian Zhuang
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Zhangfei Gao <zhangfei.gao@linaro.org>

Enable SMP support on hi3xxx platform

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: Zhang Mingjun <zhang.mingjun@linaro.org>
Tested-by: Li Xin <li.xin@linaro.org>
---
 .../bindings/arm/hisilicon/hisilicon.txt           | 47 ++++++++++++++++
 arch/arm/boot/dts/hi3620.dtsi                      | 28 +++++++++-
 arch/arm/boot/dts/hi4511.dts                       |  2 +-
 arch/arm/mach-hi3xxx/Kconfig                       |  2 +
 arch/arm/mach-hi3xxx/Makefile                      |  3 +-
 arch/arm/mach-hi3xxx/core.h                        | 14 +++++
 arch/arm/mach-hi3xxx/hi3xxx.c                      |  5 ++
 arch/arm/mach-hi3xxx/platsmp.c                     | 43 ++++++++++++++
 arch/arm/mach-hi3xxx/system.c                      | 65 ++++++++++++++++++++++
 9 files changed, 206 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-hi3xxx/core.h
 create mode 100644 arch/arm/mach-hi3xxx/platsmp.c
 create mode 100644 arch/arm/mach-hi3xxx/system.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 3be60c8..4cc5c57 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -8,3 +8,50 @@ Required root node properties:
 Hi4511 Board
 Required root node properties:
 	- compatible = "hisilicon,hi3620-hi4511";
+
+
+Hisilicon sctrl resiter
+
+Required properties:
+- compatible : "hisilicon,sctrl"
+- reg : Address and size of sysctrl.
+
+Optional properties:
+- smp_reg : offset in sysctrl for notifying slave cpu booting
+		cpu 1, reg;
+		cpu 2, reg + 0x4;
+		cpu 3, reg + 0x8;
+		If reg value is not zero, cpun exit wfi and go
+- resume_reg : offset in sysctrl for notifying cpu0 when resume
+- reset_reg : offset in sysctrl for system reset
+
+Example:
+	hi3716:
+	sctrl at f8000000 {
+		compatible = "hisilicon,sctrl";
+		reg = <0xf8000000 0x1000>;
+		smp_reg = <0xc0>;
+		reboot_reg = <0x4>;
+	};
+
+	hi3620:
+	sctrl at fc802000 {
+		compatible = "hisilicon,sctrl";
+		reg = <0xfc802000 0x1000>;
+		smp_reg = <0x31c>;
+		resume_reg = <0x308>;
+		reboot_reg = <0x4>;
+	};
+
+Hi3716 cpuctrl register
+Required properties:
+- compatible : "hisilicon,cpuctrl"
+- reg : Address and size of cpuctrl.
+
+Hi3716 specific cpuctrl register, control hotplug info etc.
+Example:
+	hi3716:
+	cpuctrl at f8a22000 {
+		compatible = "hisilicon,cpuctrl";
+		reg = <0xf8a22000 0x2000>;
+	};
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
index 39fa37f..ee81192 100644
--- a/arch/arm/boot/dts/hi3620.dtsi
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -32,6 +32,24 @@
 			reg = <0x0>;
 			next-level-cache = <&L2>;
 		};
+		cpu1: cpu at 1 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+		cpu2: cpu at 2 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+		cpu3: cpu at 3 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
 	};
 
 	osc32k: osc32k {
@@ -130,7 +148,9 @@
 			reg = <0xfc802000 0x1000>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-
+			smp_reg = <0x31c>;
+			resume_reg = <0x308>;
+			reboot_reg = <0x4>;
 
 			timer0_mux: timer0_mux {
 				compatible = "hisilicon,clk-mux";
@@ -1242,6 +1262,12 @@
 			status = "disabled";
 		};
 
+		timer5: timer at fc000600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0xfc000600 0x20>;
+			interrupts = <1 13 0xf01>;
+		};
+
 		uart0: uart at fcb00000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0xfcb00000 0x1000>;
diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
index 7e67564..c9fd329 100644
--- a/arch/arm/boot/dts/hi4511.dts
+++ b/arch/arm/boot/dts/hi4511.dts
@@ -15,7 +15,7 @@
 	compatible = "hisilicon,hi3620-hi4511";
 
 	chosen {
-		bootargs = "console=ttyAMA0,115200 root=/dev/ram0 earlyprintk";
+		bootargs = "console=ttyAMA0,115200 root=/dev/ram0 nr_cpus=4 earlyprintk";
 	};
 
 	memory {
diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig
index 68bd26c..d2e7d57 100644
--- a/arch/arm/mach-hi3xxx/Kconfig
+++ b/arch/arm/mach-hi3xxx/Kconfig
@@ -6,6 +6,8 @@ config ARCH_HI3xxx
 	select CACHE_L2X0
 	select CLKSRC_OF
 	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU
+	select HAVE_SMP
 	select PINCTRL
 	select PINCTRL_SINGLE
 	help
diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
index d68ebb3..0917f1c 100644
--- a/arch/arm/mach-hi3xxx/Makefile
+++ b/arch/arm/mach-hi3xxx/Makefile
@@ -2,4 +2,5 @@
 # Makefile for Hisilicon Hi36xx/Hi37xx processors line
 #
 
-obj-y	+= hi3xxx.o
+obj-y	+= hi3xxx.o system.o
+obj-$(CONFIG_SMP)		+= platsmp.o
diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h
new file mode 100644
index 0000000..2cfd643
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/core.h
@@ -0,0 +1,14 @@
+#ifndef __HISILICON_CORE_H
+#define __HISILICON_CORE_H
+
+#include <linux/init.h>
+#include <linux/reboot.h>
+
+extern void hs_set_cpu_jump(int cpu, void *jump_addr);
+extern int hs_get_cpu_jump(int cpu);
+extern void secondary_startup(void);
+extern void hs_map_io(void);
+extern void hs_restart(enum reboot_mode, const char *cmd);
+extern struct smp_operations hs_smp_ops;
+
+#endif
diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
index e7c54bc..567a0d5 100644
--- a/arch/arm/mach-hi3xxx/hi3xxx.c
+++ b/arch/arm/mach-hi3xxx/hi3xxx.c
@@ -19,8 +19,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include "core.h"
+
 static void __init hi3xxx_timer_init(void)
 {
+	hs_map_io();
 	of_clk_init(NULL);
 	clocksource_of_init();
 }
@@ -33,4 +36,6 @@ static const char *hs_compat[] __initdata = {
 DT_MACHINE_START(HI3xxx, "Hisilicon Hi36xx/Hi37xx (Flattened Device Tree)")
 	.init_time	= hi3xxx_timer_init,
 	.dt_compat	= hs_compat,
+	.smp		= smp_ops(hs_smp_ops),
+	.restart	= hs_restart,
 MACHINE_END
diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c
new file mode 100644
index 0000000..a76a3cc
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/platsmp.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+
+#include "core.h"
+
+static void __init hs_smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned long base;
+	void __iomem *scu_base;
+
+	if (scu_a9_has_base()) {
+		base = scu_a9_get_base();
+		scu_base = ioremap(base, SZ_4K);
+		if (!scu_base) {
+			pr_err("ioremap(scu_base) failed\n");
+			return;
+		}
+		scu_enable(scu_base);
+		iounmap(scu_base);
+	}
+}
+
+static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	hs_set_cpu_jump(cpu, secondary_startup);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+	return 0;
+}
+
+struct smp_operations hs_smp_ops __initdata = {
+	.smp_prepare_cpus	= hs_smp_prepare_cpus,
+	.smp_boot_secondary	= hs_boot_secondary,
+};
diff --git a/arch/arm/mach-hi3xxx/system.c b/arch/arm/mach-hi3xxx/system.c
new file mode 100644
index 0000000..51bb247
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/system.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_plat.h>
+
+#include "core.h"
+
+static void __iomem *hs_sctrl_base;
+static int hs_smp_reg;
+static int hs_resume_reg;
+static int hs_reboot_reg;
+
+void hs_map_io(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
+	if (np) {
+		hs_sctrl_base = of_iomap(np, 0);
+		if (!hs_sctrl_base)
+			pr_err("of_iomap(sctrl_base) failed\n");
+		of_property_read_u32(np, "smp_reg", &hs_smp_reg);
+		of_property_read_u32(np, "resume_reg", &hs_resume_reg);
+		of_property_read_u32(np, "reboot_reg", &hs_reboot_reg);
+	}
+}
+
+void hs_set_cpu_jump(int cpu, void *jump_addr)
+{
+	int offset = hs_smp_reg;
+
+	cpu = cpu_logical_map(cpu);
+	if (cpu > 0)
+		offset +=  0x04 * (cpu - 1);
+	writel_relaxed(virt_to_phys(jump_addr), hs_sctrl_base + offset);
+}
+
+int hs_get_cpu_jump(int cpu)
+{
+	int offset = hs_smp_reg;
+
+	cpu = cpu_logical_map(cpu);
+	if (cpu > 0)
+		offset +=  0x04 * (cpu - 1);
+	return readl_relaxed(hs_sctrl_base + offset);
+}
+
+void hs_restart(enum reboot_mode mode, const char *cmd)
+{
+	writel_relaxed(0xdeadbeef, hs_sctrl_base + hs_reboot_reg);
+
+	while (1)
+		cpu_do_idle();
+}
+
-- 
1.8.1.2

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

* [PATCH v7 09/11] ARM: hi3xxx: add hotplug support
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (7 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 08/11] ARM: hi3xxx: add smp support Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-28  2:21   ` Olof Johansson
  2013-08-20  2:31 ` [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716 Haojian Zhuang
  2013-08-20  2:31 ` [PATCH v7 11/11] ARM: hi3xxx: support hi3716-dkb board Haojian Zhuang
  10 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Zhangfei Gao <zhangfei.gao@linaro.org>

Enable hotplug support on hi3xxx platform

How to test:
cat proc/interrupts
echo 0 > /sys/devices/system/cpu/cpuX/online
cat proc/interrupts
echo 1 > /sys/devices/system/cpu/cpuX/online

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: Zhang Mingjun <zhang.mingjun@linaro.org>
---
 arch/arm/mach-hi3xxx/Makefile  |   1 +
 arch/arm/mach-hi3xxx/core.h    |   5 ++
 arch/arm/mach-hi3xxx/hi3xxx.c  |   1 +
 arch/arm/mach-hi3xxx/hotplug.c | 154 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-hi3xxx/platsmp.c |   5 ++
 5 files changed, 166 insertions(+)
 create mode 100644 arch/arm/mach-hi3xxx/hotplug.c

diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
index 0917f1c..c597cbf 100644
--- a/arch/arm/mach-hi3xxx/Makefile
+++ b/arch/arm/mach-hi3xxx/Makefile
@@ -4,3 +4,4 @@
 
 obj-y	+= hi3xxx.o system.o
 obj-$(CONFIG_SMP)		+= platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h
index 2cfd643..c2ce35d 100644
--- a/arch/arm/mach-hi3xxx/core.h
+++ b/arch/arm/mach-hi3xxx/core.h
@@ -11,4 +11,9 @@ extern void hs_map_io(void);
 extern void hs_restart(enum reboot_mode, const char *cmd);
 extern struct smp_operations hs_smp_ops;
 
+extern void __init hs_hotplug_init(void);
+extern void hs_cpu_die(unsigned int cpu);
+extern int hs_cpu_kill(unsigned int cpu);
+extern void hs_set_cpu(int cpu, bool enable);
+
 #endif
diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
index 567a0d5..01ac68b 100644
--- a/arch/arm/mach-hi3xxx/hi3xxx.c
+++ b/arch/arm/mach-hi3xxx/hi3xxx.c
@@ -24,6 +24,7 @@
 static void __init hi3xxx_timer_init(void)
 {
 	hs_map_io();
+	hs_hotplug_init();
 	of_clk_init(NULL);
 	clocksource_of_init();
 }
diff --git a/arch/arm/mach-hi3xxx/hotplug.c b/arch/arm/mach-hi3xxx/hotplug.c
new file mode 100644
index 0000000..c67f8a2
--- /dev/null
+++ b/arch/arm/mach-hi3xxx/hotplug.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/cpu.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include "core.h"
+
+enum {
+	HI3620_CTRL,
+	HI3716_CTRL,
+};
+
+static void __iomem *ctrl_base;
+static int id;
+
+void hs_set_cpu(int cpu, bool enable)
+{
+	u32 val = 0;
+
+	if (!ctrl_base)
+		return;
+
+	if (id == HI3620_CTRL) {
+		if (enable) {
+			/* MTCMOS */
+			writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xD0);
+			writel_relaxed((0x1011 << cpu), ctrl_base + 0x414);
+			writel_relaxed((0x401011 << cpu), ctrl_base + 0x410);
+
+			/* ISO disable */
+			writel((0x01 << (cpu + 3)), ctrl_base + 0x0C4);
+
+			/* WFI Mask */
+			val = readl(ctrl_base + 0x200);
+			val &= ~(0x1 << (cpu+28));
+			writel(val, ctrl_base + 0x200);
+
+			/* Enable core */
+			writel_relaxed((0x01 << cpu), ctrl_base + 0xf4);
+			/* Unreset */
+			writel_relaxed((0x401011 << cpu), ctrl_base + 0x414);
+		} else {
+			/* iso enable */
+			writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xC0);
+
+			/* MTCMOS */
+			writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xD4);
+
+			/* wfi mask */
+			val = readl_relaxed(ctrl_base + 0x200);
+			val |= (0x1 << (cpu+28));
+			writel_relaxed(val, ctrl_base + 0x200);
+
+			/* disable core*/
+			writel_relaxed((0x01 << cpu), ctrl_base + 0xf8);
+			/* Reset */
+			writel_relaxed((0x401011 << cpu), ctrl_base + 0x410);
+		}
+	} else if (id == HI3716_CTRL) {
+		if (enable) {
+			/* power on cpu1 */
+			val = readl_relaxed(ctrl_base + 0x1000);
+			val &=  ~(0x1 << 8);
+			val |= (0x1 << 7);
+			val &= ~(0x1 << 3);
+			writel_relaxed(val, ctrl_base + 0x1000);
+
+			/* unreset */
+			val = readl_relaxed(ctrl_base + 0x50);
+			val &= ~(0x1 << 17);
+			writel_relaxed(val, ctrl_base + 0x50);
+		} else {
+			/* power down cpu1 */
+			val = readl_relaxed(ctrl_base + 0x1000);
+			val &=  ~(0x1 << 8);
+			val |= (0x1 << 7);
+			val |= (0x1 << 3);
+			writel_relaxed(val, ctrl_base + 0x1000);
+
+			/* reset */
+			val = readl_relaxed(ctrl_base + 0x50);
+			val |= (0x1 << 17);
+			writel_relaxed(val, ctrl_base + 0x50);
+		}
+	}
+}
+
+void __init hs_hotplug_init(void)
+{
+	struct device_node *node;
+
+	node = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
+	if (node) {
+		ctrl_base = of_iomap(node, 0);
+		id = HI3716_CTRL;
+		return;
+	}
+	node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
+	if (node) {
+		ctrl_base = of_iomap(node, 0);
+		id = HI3620_CTRL;
+		return;
+	}
+}
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	/*
+	 * Turn off coherency and L1 D-cache
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, #0x40\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, #0x04\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0)
+	  : "cc");
+}
+
+void hs_cpu_die(unsigned int cpu)
+{
+	cpu_enter_lowpower();
+	hs_set_cpu_jump(cpu, phys_to_virt(0));
+	cpu_do_idle();
+
+	/* We should have never returned from idle */
+	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int hs_cpu_kill(unsigned int cpu)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+	while (hs_get_cpu_jump(cpu))
+		if (time_after(jiffies, timeout))
+			return 0;
+	hs_set_cpu(cpu, false);
+	return 1;
+}
diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c
index a76a3cc..6a08630 100644
--- a/arch/arm/mach-hi3xxx/platsmp.c
+++ b/arch/arm/mach-hi3xxx/platsmp.c
@@ -32,6 +32,7 @@ static void __init hs_smp_prepare_cpus(unsigned int max_cpus)
 
 static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
+	hs_set_cpu(cpu, true);
 	hs_set_cpu_jump(cpu, secondary_startup);
 	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 	return 0;
@@ -40,4 +41,8 @@ static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
 struct smp_operations hs_smp_ops __initdata = {
 	.smp_prepare_cpus	= hs_smp_prepare_cpus,
 	.smp_boot_secondary	= hs_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= hs_cpu_die,
+	.cpu_kill		= hs_cpu_kill,
+#endif
 };
-- 
1.8.1.2

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

* [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (8 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 09/11] ARM: hi3xxx: add hotplug support Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  2013-08-21 21:43   ` Mike Turquette
  2013-08-20  2:31 ` [PATCH v7 11/11] ARM: hi3xxx: support hi3716-dkb board Haojian Zhuang
  10 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Zhangfei Gao <zhangfei.gao@linaro.org>

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
---
 Documentation/devicetree/bindings/clock/hi3716.txt | 121 ++++++++++
 drivers/clk/Makefile                               |   2 +-
 drivers/clk/clk-hi3716.c                           | 268 +++++++++++++++++++++
 3 files changed, 390 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi3716.txt
 create mode 100644 drivers/clk/clk-hi3716.c

diff --git a/Documentation/devicetree/bindings/clock/hi3716.txt b/Documentation/devicetree/bindings/clock/hi3716.txt
new file mode 100644
index 0000000..60af61e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hi3716.txt
@@ -0,0 +1,121 @@
+Device Tree Clock bindings for hi3716
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Clock control register
+Required properties:
+- compatible : "hisilicon,clkbase"
+- reg : Address and size of clkbase.
+
+Device Clocks
+
+Device clocks are required to have one or both of the following sets of
+properties:
+
+
+Gated device clocks:
+
+Required properties:
+- compatible : "hisilicon,hi3716-clk-gate"
+- gate-reg : shall be the register offset from clkbase and enable bit, reset bit
+- clock-output-names : shall be reference name
+
+
+Mux device clocks:
+
+Required properties:
+- compatible : "hisilicon,hi3716-clk-mux"
+- mux-reg : shall be the register offset from clkbase and mux_shift mux_width
+- mux-table : shall be reg value to be choose clocks accordingly
+- clock-output-names : shall be reference name
+
+
+Fixed divisor device clocks:
+
+Required properties:
+- compatible : "hisilicon,hi3716-fixed-divider"
+- div-table : shall be divisor sequence
+- clock-output-names : shall be reference name according to divisor
+
+
+Fixed pll clocks:
+
+Required properties:
+- compatible : "hisilicon,hi3716-fixed-pll"
+- clock-frequency : shall be output clock frequence sequence
+- clock-output-names : shall be reference name according to clock-frequnce
+
+For example:
+	clkbase at f8a22000 {
+		compatible = "hisilicon,clkbase";
+		reg = <0xf8a22000 0x1000>;
+	};
+
+	osc24m: osc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24mhz";
+	};
+
+	bpll: bpll {
+		compatible = "hisilicon,hi3716-fixed-pll";
+		#clock-cells = <1>;
+		clocks = <&osc24m>;
+		clock-frequency = <1200000000>,
+				  <600000000>,
+				  <300000000>,
+				  <200000000>,
+				  <150000000>;
+		clock-output-names = "bpll_fout0",
+				     "bpll_fout1",
+				     "bpll_fout2",
+				     "bpll_fout3",
+				     "bpll_fout4";
+	};
+
+	bpll_fout0_div: bpll_fout0_div {/* 1200Mhz */
+		compatible = "hisilicon,hi3716-fixed-divider";
+		#clock-cells = <1>;
+		clocks = <&bpll 0>;
+		div-table = <3 14 25 50>;
+		clock-output-names = "fout0_400m", "fout0_86m",
+					"fout0_48m", "fout0_24m";
+	};
+
+	bpll_fout3_div: bpll_fout3_div {
+		compatible = "hisilicon,hi3716-fixed-divider";
+		#clock-cells = <1>;
+		clocks = <&bpll 3>;
+		div-table = <2 4 5 8>;
+		clock-output-names = "fout3_100m", "fout3_50m",
+					"fout3_40m", "fout3_25m";
+	};
+
+	clk_sfc_mux: clk_sfc_mux {
+		compatible = "hisilicon,hi3716-clk-mux";
+		#clock-cells = <0>;
+		/* clks: 24M 75M 100M 150M 200M */
+		clocks = <&osc24m>, <&bpll_fout2_div>,
+		       <&bpll_fout3_div 0>, <&bpll 4>, <&bpll 3>;
+
+		/* offset mux_shift mux_width */
+		mux-reg = <0x5c 8 3>;
+		/* mux reg value to choose clks */
+		mux-table = <0 7 6 4 5>;
+
+		clock-output-names = "sfc_mux";
+	};
+
+	clk_sfc: clk_sfc {
+		compatible = "hisilicon,hi3716-clk-gate";
+		#clock-cells = <0>;
+		clocks = <&clk_sfc_mux>;
+
+		/* offset, enable, reset */
+		gate-reg = <0x5c 0 4>;
+
+		clock-output-names = "sfc";
+	};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 2451ce6..b652b3d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_COMMON_CLK)	+= clk-composite.o
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
-obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3xxx.o
+obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3xxx.o clk-hi3716.o
 obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_NSPIRE)	+= clk-nspire.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs/
diff --git a/drivers/clk/clk-hi3716.c b/drivers/clk/clk-hi3716.c
new file mode 100644
index 0000000..887ffe9
--- /dev/null
+++ b/drivers/clk/clk-hi3716.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+static DEFINE_SPINLOCK(_lock);
+
+static void __iomem *clk_base;
+
+struct hi3716_clk {
+	struct		clk_gate gate;
+	void __iomem	*reg;
+	u8		reset_bit;
+};
+
+#define MAX_NUMS	10
+
+static struct hi3716_clk *to_clk_hi3716(struct clk_hw *hw)
+{
+	return container_of(hw, struct hi3716_clk, gate.hw);
+}
+
+static void __init hi3716_map_io(void)
+{
+	struct device_node *node;
+
+	if (clk_base)
+		return;
+
+	node = of_find_compatible_node(NULL, NULL, "hisilicon,clkbase");
+	if (node)
+		clk_base = of_iomap(node, 0);
+	WARN_ON(!clk_base);
+}
+
+static int hi3716_clkgate_prepare(struct clk_hw *hw)
+{
+	struct hi3716_clk *clk = to_clk_hi3716(hw);
+	unsigned long flags = 0;
+	u32 reg;
+
+	spin_lock_irqsave(&_lock, flags);
+
+	reg = readl_relaxed(clk->reg);
+	reg &= ~BIT(clk->reset_bit);
+	writel_relaxed(reg, clk->reg);
+
+	spin_unlock_irqrestore(&_lock, flags);
+
+	return 0;
+}
+
+static void hi3716_clkgate_unprepare(struct clk_hw *hw)
+{
+	struct hi3716_clk *clk = to_clk_hi3716(hw);
+	unsigned long flags = 0;
+	u32 reg;
+
+	spin_lock_irqsave(&_lock, flags);
+
+	reg = readl_relaxed(clk->reg);
+	reg |= BIT(clk->reset_bit);
+	writel_relaxed(reg, clk->reg);
+
+	spin_unlock_irqrestore(&_lock, flags);
+}
+
+static struct clk_ops hi3716_clkgate_ops = {
+	.prepare	= hi3716_clkgate_prepare,
+	.unprepare	= hi3716_clkgate_unprepare,
+};
+
+void __init hi3716_clkgate_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct hi3716_clk *p_clk;
+	struct clk_init_data init;
+	const char *parent_name;
+	u32 array[3];	/* reg, enable_bit, reset_bit */
+	int err;
+
+	hi3716_map_io();
+	err = of_property_read_u32_array(node, "gate-reg", &array[0], 3);
+	if (WARN_ON(err))
+		return;
+
+	err = of_property_read_string(node, "clock-output-names", &init.name);
+	if (WARN_ON(err))
+		return;
+
+	p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
+	if (WARN_ON(!p_clk))
+		return;
+
+	hi3716_clkgate_ops.enable = clk_gate_ops.enable;
+	hi3716_clkgate_ops.disable = clk_gate_ops.disable;
+	hi3716_clkgate_ops.is_enabled = clk_gate_ops.is_enabled;
+
+	init.ops = &hi3716_clkgate_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	p_clk->reg = p_clk->gate.reg = clk_base + array[0];
+	p_clk->gate.bit_idx = array[1];
+	p_clk->gate.flags = 0;
+	p_clk->gate.lock = &_lock;
+	p_clk->gate.hw.init = &init;
+	p_clk->reset_bit = array[2];
+
+	clk = clk_register(NULL, &p_clk->gate.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(p_clk);
+		return;
+	}
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+static void __init hi3716_clkmux_setup(struct device_node *node)
+{
+	int num = 0, err;
+	void __iomem *reg;
+	unsigned int shift, width;
+	u32 array[3];	/* reg, mux_shift, mux_width */
+	u32 *table = NULL;
+	const char *clk_name = node->name;
+	const char *parents[MAX_NUMS];
+	struct clk *clk;
+
+	hi3716_map_io();
+	err = of_property_read_string(node, "clock-output-names", &clk_name);
+	if (WARN_ON(err))
+		return;
+
+	err = of_property_read_u32_array(node, "mux-reg", &array[0], 3);
+	if (WARN_ON(err))
+		return;
+
+	reg = clk_base + array[0];
+	shift = array[1];
+	width = array[2];
+
+	while ((num < MAX_NUMS) &&
+		((parents[num] = of_clk_get_parent_name(node, num)) != NULL))
+		num++;
+	if (!num)
+		return;
+
+	table = kzalloc(sizeof(u32 *) * num, GFP_KERNEL);
+	if (WARN_ON(!table))
+		return;
+
+	err = of_property_read_u32_array(node, "mux-table", table, num);
+	if (WARN_ON(err))
+		goto err;
+
+	clk = clk_register_mux_table(NULL, clk_name, parents, num,
+			CLK_SET_RATE_PARENT, reg, shift, BIT(width) - 1,
+			0, table, &_lock);
+	if (WARN_ON(IS_ERR(clk)))
+		goto err;
+
+	clk_register_clkdev(clk, clk_name, NULL);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return;
+
+err:
+	kfree(table);
+	return;
+}
+
+static void __init hi3716_fixed_pll_setup(struct device_node *node)
+{
+	const char *clk_name, *parent_name;
+	struct clk *clks[MAX_NUMS];
+	u32 rate[MAX_NUMS];
+	struct clk_onecell_data *clk_data;
+	int i, err, nums = 0;
+
+	nums = of_property_count_strings(node, "clock-output-names");
+	if (WARN_ON((nums < 0) || (nums > MAX_NUMS)))
+		return;
+
+	err = of_property_read_u32_array(node, "clock-frequency",
+						&rate[0], nums);
+	WARN_ON(err);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	for (i = 0; i < nums; i++) {
+		err = of_property_read_string_index(node, "clock-output-names",
+				i, &clk_name);
+		WARN_ON(err);
+
+		clks[i] = clk_register_fixed_rate(NULL, clk_name,
+					parent_name, 0, rate[i]);
+		WARN_ON(IS_ERR(clks[i]));
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data) + nums * sizeof(struct clk *),
+			GFP_KERNEL);
+	if (WARN_ON(!clk_data))
+		return;
+
+	memcpy(&clk_data[1], clks, nums * sizeof(struct clk *));
+	clk_data->clks = (struct clk **)&clk_data[1];
+	clk_data->clk_num = nums;
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+void __init hi3716_fixed_divider_setup(struct device_node *node)
+{
+	const char *clk_parent;
+	const char *clk_name;
+	u32 div[MAX_NUMS];
+	struct clk *clks[MAX_NUMS];
+	struct clk_onecell_data *clk_data;
+	int err, i, nums = 0;
+
+	clk_parent = of_clk_get_parent_name(node, 0);
+
+	nums = of_property_count_strings(node, "clock-output-names");
+	if (WARN_ON((nums < 0) || (nums > MAX_NUMS)))
+		return;
+
+	err = of_property_read_u32_array(node, "div-table", &div[0], nums);
+	WARN_ON(err);
+
+	for (i = 0; i < nums; i++) {
+		err = of_property_read_string_index(node,
+				"clock-output-names", i, &clk_name);
+		WARN_ON(err);
+
+		clks[i] = clk_register_fixed_factor(NULL, clk_name,
+				clk_parent, CLK_SET_RATE_PARENT, 1, div[i]);
+		WARN_ON(IS_ERR(clks[i]));
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data) + nums * sizeof(struct clk *),
+			GFP_KERNEL);
+	if (WARN_ON(!clk_data))
+		return;
+
+	memcpy(&clk_data[1], clks, nums * sizeof(struct clk *));
+	clk_data->clks = (struct clk **)&clk_data[1];
+	clk_data->clk_num = nums;
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3716_fixed_rate, "fixed-clock", of_fixed_clk_setup)
+CLK_OF_DECLARE(hi3716_fixed_pll, "hisilicon,hi3716-fixed-pll", hi3716_fixed_pll_setup)
+CLK_OF_DECLARE(hi3716_divider, "hisilicon,hi3716-fixed-divider", hi3716_fixed_divider_setup)
+CLK_OF_DECLARE(hi3716_mux, "hisilicon,hi3716-clk-mux", hi3716_clkmux_setup)
+CLK_OF_DECLARE(hi3716_gate, "hisilicon,hi3716-clk-gate", hi3716_clkgate_setup)
-- 
1.8.1.2

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

* [PATCH v7 11/11] ARM: hi3xxx: support hi3716-dkb board
  2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
                   ` (9 preceding siblings ...)
  2013-08-20  2:31 ` [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716 Haojian Zhuang
@ 2013-08-20  2:31 ` Haojian Zhuang
  10 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Zhangfei Gao <zhangfei.gao@linaro.org>

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/hi3716-dkb.dts |  37 ++++++
 arch/arm/boot/dts/hi3716.dtsi    | 275 +++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-hi3xxx/hi3xxx.c    |   1 +
 3 files changed, 313 insertions(+)
 create mode 100644 arch/arm/boot/dts/hi3716-dkb.dts
 create mode 100644 arch/arm/boot/dts/hi3716.dtsi

diff --git a/arch/arm/boot/dts/hi3716-dkb.dts b/arch/arm/boot/dts/hi3716-dkb.dts
new file mode 100644
index 0000000..32b507b
--- /dev/null
+++ b/arch/arm/boot/dts/hi3716-dkb.dts
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "hi3716.dtsi"
+
+/ {
+	model = "Hisilicon Hi3716 Development Board";
+	compatible = "hisilicon,hi3716";
+
+	chosen {
+		bootargs = "console=ttyAMA0,115200";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>;
+	};
+
+	soc {
+		amba {
+			timer0: timer at f8002000 {
+				status = "okay";
+			};
+
+			uart0: uart at f8b00000 {
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/hi3716.dtsi b/arch/arm/boot/dts/hi3716.dtsi
new file mode 100644
index 0000000..1350d6c
--- /dev/null
+++ b/arch/arm/boot/dts/hi3716.dtsi
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&l2>;
+		};
+
+		cpu at 1 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&l2>;
+		};
+	};
+
+	gic: interrupt-controller at fc001000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		/* gic dist base, gic cpu base */
+		reg = <0xf8a01000 0x1000>, <0xf8a00100 0x100>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		device_type = "soc";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		amba {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "arm,amba-bus";
+			ranges;
+
+			timer0: timer at f8002000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0xf8002000 0x1000>;
+				/* timer00 & timer01 */
+				interrupts = <0 24 4>;
+				clocks = <&osc24m>;
+				status = "disabled";
+			};
+
+			timer1: timer at f8a29000 {
+				/*
+				 * Only used in NORMAL state, not available ins
+				 * SLOW or DOZE state.
+				 * The rate is fixed in 24MHz.
+				 */
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0xf8a29000 0x1000>;
+				/* timer10 & timer11 */
+				interrupts = <0 25 4>;
+				clocks = <&osc24m>;
+				status = "disabled";
+			};
+
+			timer2: timer at f8a2a000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0xf8a2a000 0x1000>;
+				/* timer20 & timer21 */
+				interrupts = <0 26 4>;
+				clocks = <&osc24m>;
+				status = "disabled";
+			};
+
+			timer3: timer at f8a2b000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0xf8a2b000 0x1000>;
+				/* timer30 & timer31 */
+				interrupts = <0 27 4>;
+				clocks = <&osc24m>;
+				status = "disabled";
+			};
+
+			timer4: timer at f8a81000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0xf8a81000 0x1000>;
+				/* timer30 & timer31 */
+				interrupts = <0 28 4>;
+				clocks = <&osc24m>;
+				status = "disabled";
+			};
+
+			uart0: uart at f8b00000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0xf8b00000 0x1000>;
+				interrupts = <0 49 4>;
+				clocks = <&bpll_fout0_div 1>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart1: uart at f8006000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0xf8006000 0x1000>;
+				interrupts = <0 50 4>;
+				clocks = <&bpll_fout0_div 1>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart2: uart at f8b02000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0xf8b02000 0x1000>;
+				interrupts = <0 51 4>;
+				clocks = <&bpll_fout0_div 1>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart3: uart at f8b03000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0xf8b03000 0x1000>;
+				interrupts = <0 52 4>;
+				clocks = <&bpll_fout0_div 1>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart4: uart at f8b04000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0xf8b04000 0x1000>;
+				interrupts = <0 53 4>;
+				clocks = <&bpll_fout0_div 1>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+		};
+
+		clocks {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			osc24m: osc {
+				compatible = "fixed-clock";
+				#clock-cells = <0>;
+				clock-frequency = <24000000>;
+				clock-output-names = "osc24mhz";
+			};
+
+			bpll: bpll {
+				compatible = "hisilicon,hi3716-fixed-pll";
+				#clock-cells = <1>;
+				clocks = <&osc24m>;
+				clock-frequency = <1200000000>,
+						  <600000000>,
+						  <300000000>,
+						  <200000000>,
+						  <150000000>;
+				clock-output-names = "bpll_fout0",
+						     "bpll_fout1",
+						     "bpll_fout2",
+						     "bpll_fout3",
+						     "bpll_fout4";
+			};
+
+			bpll_fout0_div: bpll_fout0_div {/* 1200Mhz */
+				compatible = "hisilicon,hi3716-fixed-divider";
+				#clock-cells = <1>;
+				clocks = <&bpll 0>;
+				div-table = <3 14 25 50>;
+				clock-output-names = "fout0_400m", "fout0_86m",
+							"fout0_48m", "fout0_24m";
+			};
+
+			bpll_fout1_div: bpll_fout1_div {
+				compatible = "hisilicon,hi3716-fixed-divider";
+				#clock-cells = <0>;
+				clocks = <&bpll 1>;
+				div-table = <10>;
+				clock-output-names = "fout1_60m";
+			};
+
+			bpll_fout2_div: bpll_fout2_div {
+				compatible = "hisilicon,hi3716-fixed-divider";
+				#clock-cells = <0>;
+				clocks = <&bpll 2>;
+				div-table = <4>;
+				clock-output-names = "fout2_75m";
+			};
+
+			bpll_fout3_div: bpll_fout3_div {
+				compatible = "hisilicon,hi3716-fixed-divider";
+				#clock-cells = <1>;
+				clocks = <&bpll 3>;
+				div-table = <2 4 5 8>;
+				clock-output-names = "fout3_100m", "fout3_50m",
+							"fout3_40m", "fout3_25m";
+			};
+
+			clk_sfc_mux: clk_sfc_mux {
+				compatible = "hisilicon,hi3716-clk-mux";
+				#clock-cells = <0>;
+				/* clks: 24M 75M 100M 150M 200M */
+				clocks = <&osc24m>, <&bpll_fout2_div>,
+				       <&bpll_fout3_div 0>, <&bpll 4>, <&bpll 3>;
+
+				/* offset mux_shift mux_width */
+				mux-reg = <0x5c 8 3>;
+				/* mux reg value to choose clks */
+				mux-table = <0 7 6 4 5>;
+
+				clock-output-names = "sfc_mux";
+			};
+
+			clk_sfc: clk_sfc {
+				compatible = "hisilicon,hi3716-clk-gate";
+				#clock-cells = <0>;
+				clocks = <&clk_sfc_mux>;
+
+				/* offset, enable, reset */
+				gate-reg = <0x5c 0 4>;
+
+				clock-output-names = "sfc";
+			};
+		};
+
+		local_timer at f8a00600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0xf8a00600 0x20>;
+			interrupts = <1 13 0xf01>;
+		};
+
+		l2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xf8a10000 0x100000>;
+			interrupts = <0 15 4>;
+			cache-unified;
+			cache-level = <2>;
+			hisilicon,l2cache-aux = <0x00050000 0xfff0ffff>;
+		};
+
+		sctrl at f8000000 {
+			compatible = "hisilicon,sctrl";
+			reg = <0xf8000000 0x1000>;
+			smp_reg = <0xc0>;
+			reboot_reg = <0x4>;
+		};
+
+		clkbase at f8a22000 {
+			compatible = "hisilicon,clkbase";
+			reg = <0xf8a22000 0x1000>;
+		};
+
+		cpuctrl at f8a22000 {
+			compatible = "hisilicon,cpuctrl";
+			reg = <0xf8a22000 0x2000>;
+		};
+	};
+};
diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
index 01ac68b..dfe3902 100644
--- a/arch/arm/mach-hi3xxx/hi3xxx.c
+++ b/arch/arm/mach-hi3xxx/hi3xxx.c
@@ -31,6 +31,7 @@ static void __init hi3xxx_timer_init(void)
 
 static const char *hs_compat[] __initdata = {
 	"hisilicon,hi3620-hi4511",
+	"hisilicon,hi3716",
 	NULL,
 };
 
-- 
1.8.1.2

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

* [PATCH v7 03/11] clk: gate: add CLK_GATE_SEPERATED_REG flag
  2013-08-20  2:31 ` [PATCH v7 03/11] clk: gate: add CLK_GATE_SEPERATED_REG flag Haojian Zhuang
@ 2013-08-21 21:18   ` Mike Turquette
  0 siblings, 0 replies; 40+ messages in thread
From: Mike Turquette @ 2013-08-21 21:18 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Haojian Zhuang (2013-08-19 19:31:05)
> In Hisilicon Hi3620 SoC, there're two kinds of clock gates.
> 
> 1. The same bit in one register controls enabling, disabling or reading status
> of the clock gate. It's the normal clock gate register.
> 
> 2. The same bit in three continuous registers control enabling,
> disabling or reading status of the clock gate. Since these three
> registers are enabling, disabling and reading status of clock gate.
> 
> Now reuse common clock gate driver to support the second case with the new
> CLK_GATE_SEPERATED_REG flag.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

Hi Haojian,

This is too implementation-specific to be pushed into the common gate
clock. Instead you should write a custom gate implementation that uses
these three registers without any flag. Your DT binding for this new
clock type should list those three register addresses via the 'reg'
property.

Regards,
Mike

> ---
>  drivers/clk/clk-gate.c       | 18 +++++++++++++++---
>  include/linux/clk-provider.h |  7 +++++++
>  2 files changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> index 790306e..5dedfb3 100644
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -58,7 +58,10 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                 if (set)
>                         reg |= BIT(gate->bit_idx);
>         } else {
> -               reg = readl(gate->reg);
> +               if (gate->flags & CLK_GATE_SEPERATED_REG)
> +                       reg = 0;
> +               else
> +                       reg = readl(gate->reg);
>  
>                 if (set)
>                         reg |= BIT(gate->bit_idx);
> @@ -66,7 +69,13 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                         reg &= ~BIT(gate->bit_idx);
>         }
>  
> -       writel(reg, gate->reg);
> +       if (gate->flags & CLK_GATE_SEPERATED_REG) {
> +               if (enable)
> +                       writel(reg, gate->reg + CLK_GATE_ENABLE_REG);
> +               else
> +                       writel(reg, gate->reg + CLK_GATE_DISABLE_REG);
> +       } else
> +               writel(reg, gate->reg);
>  
>         if (gate->lock)
>                 spin_unlock_irqrestore(gate->lock, flags);
> @@ -89,7 +98,10 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
>         u32 reg;
>         struct clk_gate *gate = to_clk_gate(hw);
>  
> -       reg = readl(gate->reg);
> +       if (gate->flags & CLK_GATE_SEPERATED_REG)
> +               reg = readl(gate->reg + CLK_GATE_STATUS_REG);
> +       else
> +               reg = readl(gate->reg);
>  
>         /* if a set bit disables this clk, flip it before masking */
>         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 9487b96..0fdc13f 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -214,6 +214,8 @@ void of_fixed_clk_setup(struct device_node *np);
>   *   of this register, and mask of gate bits are in higher 16-bit of this
>   *   register.  While setting the gate bits, higher 16-bit should also be
>   *   updated to indicate changing gate bits.
> + * CLK_GATE_SEPERATED_REG - The enable, disable & status register are three
> + *     seperated registers.
>   */
>  struct clk_gate {
>         struct clk_hw hw;
> @@ -225,6 +227,11 @@ struct clk_gate {
>  
>  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
>  #define CLK_GATE_HIWORD_MASK           BIT(1)
> +#define CLK_GATE_SEPERATED_REG         BIT(2)
> +
> +#define CLK_GATE_ENABLE_REG            (0x00)
> +#define CLK_GATE_DISABLE_REG           (0x04)
> +#define CLK_GATE_STATUS_REG            (0x08)
>  
>  extern const struct clk_ops clk_gate_ops;
>  struct clk *clk_register_gate(struct device *dev, const char *name,
> -- 
> 1.8.1.2

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

* [PATCH v7 02/11] clk: hi3xxx: add clock support
  2013-08-20  2:31 ` [PATCH v7 02/11] clk: hi3xxx: add clock support Haojian Zhuang
@ 2013-08-21 21:29   ` Mike Turquette
  2013-08-24  4:13     ` Haojian Zhuang
  0 siblings, 1 reply; 40+ messages in thread
From: Mike Turquette @ 2013-08-21 21:29 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Haojian Zhuang (2013-08-19 19:31:04)
> Add clock support with device tree on Hisilicon SoC.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Cc: Mike Turquette <mturquette@linaro.org>
> ---
>  .../devicetree/bindings/clock/hisilicon.txt        | 118 +++++++++
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/clk-hi3xxx.c                           | 272 +++++++++++++++++++++
>  3 files changed, 391 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/hisilicon.txt
>  create mode 100644 drivers/clk/clk-hi3xxx.c
> 
> diff --git a/Documentation/devicetree/bindings/clock/hisilicon.txt b/Documentation/devicetree/bindings/clock/hisilicon.txt
> new file mode 100644
> index 0000000..e8ee618
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hisilicon.txt
> @@ -0,0 +1,118 @@
> +Device Tree Clock bindings for arch-hi3xxx
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +All the mux, gate & divider are in clock container of DTS file.
> +
> +Required properties for mux clocks:
> + - compatible : shall be "hisilicon,clk-mux".
> + - clocks : shall be the input parent clock phandle for the clock. This should
> +       be the reference clock.
> + - clock-output-names : shall be reference name.
> + - #clock-cells : from common clock binding; shall be set to 0.
> + - reg : the mux register address. It should be the offset of the container.
> + - clkmux-mask : mask bits of the mux register.
> + - clkmux-table : array of mux select bits.
> +
> +Optional properties for mux clocks:
> + - clkmux-hiword-mask : indicates that the bit[31:16] are the hiword mask
> +       of mux selected bits (bit[15:0]). The bit[15:0] is valid only when
> +       bit[31:16] is set.

Instead of putting this as a flag I'm tempted to say this should be a
separate compatible string. Any thoughts from the DT experts?

> +
> +
> +
> +Required properties for gate clocks:
> + - compatible : shall be "hisilicon,clk-gate".
> + - clocks : shall be the input parent clock phandle for the clock. This should
> +       be the reference clock.
> + - clock-output-names : shall be reference name.
> + - #clock-cells : from common clock binding; shall be set to 0.
> + - reg : the mux register address. It should be the offset of the container.
> + - clkgate : bit index to control the clock gate in the gate register.
> +
> +Optional properties for gate clocks:
> + - clkgate-inverted : it indicates that setting 0 could enable the clock gate
> +       and setting 1 could disable the clock gate.
> + - clkgate-seperated-reg : it indicates that there're three continuous
> +       registers (enable, disable & status) for the same clock gate.

I responded to this in the other thread but clkgate-separated-reg is a
bad idea. You'll need your own gate clock type which handles this
instead of pushing it into the common gate implementation. Use the
existing 'reg' property to list the registers needed by this clock.

> +
> +
> +
> +Required properties for divider clocks:
> + - compatible : shall be "hisilicon,clk-div".
> + - clocks : shall be the input parent clock phandle for the clock. This should
> +       be the reference clock.
> + - clock-output-names : shall be reference name.
> + - reg : the divider register address. It should be the offset of the
> +       container.
> + - clkdiv-mask : mask bits of the divider register.
> + - clkdiv-min : the minimum divider of the clock divider.
> + - clkdiv-max : the maximum divider of the clock divider.

Are these details necessary? Do the mask, min & max values change from
clock to clock? It's nicer to have these in the driver if possible. This
looks like building a binding from a struct, which is considered bad.

> +
> +Optional properties for divider clocks:
> + - clkdiv-hiword-mask : indicates that the bit[31:16] are the hiword mask
> +       of divider selected bits (bit[15:0]). The bit[15:0] is valid only when
> +       bit[31:16] is set.

Same here. Again you might need a different compatible string for these
types of clocks.

Regards,
Mike

> +
> +
> +
> +For example:
> +       sctrl: sctrl at fc802000 {
> +               compatible = "hisilicon,sctrl";
> +               reg = <0xfc802000 0x1000>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +
> +               timer0_mux: timer0_mux {
> +                       compatible = "hisilicon,clk-mux";
> +                       #clock-cells = <0>;
> +                       clocks = <&osc32k &timerclk01>;
> +                       clock-output-names = "timer0_mux";
> +                       reg = <0>;
> +                       clkmux-mask = <0x8000>;
> +                       clkmux-table = <0 0x8000>;
> +               };
> +               uart0_mux: uart0_mux {
> +                       compatible = "hisilicon,clk-mux";
> +                       #clock-cells = <0>;
> +                       clocks = <&osc26m &pclk>;
> +                       clock-output-names = "uart0_mux";
> +                       reg = <0x100>;
> +                       clkmux-mask = <0x80>;
> +                       /* each item value */
> +                       clkmux-table = <0 0x80>;
> +                       clkmux-hiword-mask;
> +               };
> +               timclk0: timclk0 {
> +                       compatible = "hisilicon,clk-gate";
> +                       #clock-cells = <0>;
> +                       clocks = <&timer0_mux>;
> +                       clock-output-names = "timclk0";
> +                       clkgate-inverted;
> +                       reg = <0>;
> +                       clkgate = <16>;
> +               };
> +               timerclk01: timerclk01 {
> +                       compatible = "hisilicon,clk-gate";
> +                       #clock-cells = <0>;
> +                       clocks = <&timer_rclk01>;
> +                       clock-output-names = "timerclk01";
> +                       reg = <0x20>;
> +                       clkgate = <0>;
> +                       clkgate-seperated-reg;
> +               };
> +               mmc1_div: mmc1_div {
> +                       compatible = "hisilicon,clk-div";
> +                       #clock-cells = <0>;
> +                       clocks = <&mmc1_mux>;
> +                       clock-output-names = "mmc1_div";
> +                       reg = <0x108>;
> +                       clkdiv-mask = <0x1e0>;
> +                       clkdiv-min = <1>;
> +                       clkdiv-max = <16>;
> +                       clkdiv-hiword-mask;
> +               };
> +       };
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 7b11106..2451ce6 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK)      += clk-composite.o
>  # SoCs specific
>  obj-$(CONFIG_ARCH_BCM2835)     += clk-bcm2835.o
>  obj-$(CONFIG_ARCH_NOMADIK)     += clk-nomadik.o
> +obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3xxx.o
>  obj-$(CONFIG_ARCH_HIGHBANK)    += clk-highbank.o
>  obj-$(CONFIG_ARCH_NSPIRE)      += clk-nspire.o
>  obj-$(CONFIG_ARCH_MXS)         += mxs/
> diff --git a/drivers/clk/clk-hi3xxx.c b/drivers/clk/clk-hi3xxx.c
> new file mode 100644
> index 0000000..69dca7b
> --- /dev/null
> +++ b/drivers/clk/clk-hi3xxx.c
> @@ -0,0 +1,272 @@
> +/*
> + * Hisilicon Hi3xxx clock driver
> + *
> + * Copyright (c) 2012-2013 Hisilicon Limited.
> + * Copyright (c) 2012-2013 Linaro Limited.
> + *
> + * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
> + *        Xin Li <li.xin@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +struct hi3620_periclk {
> +       struct clk_hw   hw;
> +       void __iomem    *enable;        /* enable register */
> +       u32             ebits;          /* bits in enable/disable register */
> +       spinlock_t      *lock;
> +};
> +
> +static void __iomem *hi3xxx_clk_base = NULL;
> +
> +static DEFINE_SPINLOCK(hi3xxx_clk_lock);
> +
> +static const struct of_device_id hi3xxx_of_match[] = {
> +       { .compatible = "hisilicon,sctrl" },
> +};
> +
> +static void __iomem __init *hi3xxx_init_clocks(struct device_node *np)
> +{
> +       struct device_node *parent;
> +       const struct of_device_id *match;
> +       void __iomem *ret = NULL;
> +
> +       parent = of_get_parent(np);
> +       if (!parent) {
> +               pr_warn("Can't find parent node of these clocks\n");
> +               goto out;
> +       }
> +       match = of_match_node(hi3xxx_of_match, parent);
> +       if (!match) {
> +               pr_warn("Can't find the right parent\n");
> +               goto out;
> +       }
> +
> +       if (!hi3xxx_clk_base) {
> +               ret = of_iomap(parent, 0);
> +               WARN_ON(!ret);
> +               hi3xxx_clk_base = ret;
> +       } else {
> +               ret = hi3xxx_clk_base;
> +       }
> +out:
> +       return ret;
> +}
> +
> +static void __init hi3xxx_clkgate_setup(struct device_node *np)
> +{
> +       struct clk *clk;
> +       const char *clk_name, **parent_names, *name;
> +       const __be32 *prop;
> +       unsigned long flags = 0;
> +       u32 bit_idx;
> +       void __iomem *base, *reg;
> +
> +       base = hi3xxx_init_clocks(np);
> +       if (!base)
> +               goto err;
> +       if (of_property_read_string(np, "clock-output-names", &clk_name))
> +               goto err;
> +       if (of_property_read_u32(np, "clkgate", &bit_idx))
> +               goto err;
> +       prop = of_get_address(np, 0, NULL, NULL);
> +       if (!prop)
> +               goto err;
> +       reg = base + be32_to_cpu(*prop);
> +       if (of_property_read_bool(np, "clkgate-inverted"))
> +               flags |= CLK_GATE_SET_TO_DISABLE;
> +       if (of_property_read_bool(np, "clkgate-seperated-reg"))
> +               flags |= CLK_GATE_SEPERATED_REG;
> +       /* gate only has the fixed parent */
> +       parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
> +       if (!parent_names)
> +               goto err;
> +       parent_names[0] = of_clk_get_parent_name(np, 0);
> +
> +       clk = clk_register_gate(NULL, clk_name, parent_names[0], 0, reg,
> +                               (u8)bit_idx, flags, &hi3xxx_clk_lock);
> +       if (IS_ERR(clk))
> +               goto err_clk;
> +       if (!of_property_read_string(np, "clock-names", &name))
> +               clk_register_clkdev(clk, name, NULL);
> +       of_clk_add_provider(np, of_clk_src_simple_get, clk);
> +       return;
> +err_clk:
> +       kfree(parent_names);
> +err:
> +       pr_err("Fail on registering hi3xxx clkgate node.\n");
> +}
> +CLK_OF_DECLARE(hi3xxx_gate, "hisilicon,clk-gate", hi3xxx_clkgate_setup)
> +
> +static int __init hi3xxx_parse_mux(struct device_node *np,
> +                                  u8 *num_parents,
> +                                  u32 *table)
> +{
> +       int i, cnt, ret;
> +
> +       /* get the count of items in mux */
> +       for (i = 0, cnt = 0; ; i++, cnt++) {
> +               /* parent's #clock-cells property is always 0 */
> +               if (!of_parse_phandle(np, "clocks", i))
> +                       break;
> +       }
> +
> +       for (i = 0; i < cnt; i++) {
> +               if (!of_clk_get_parent_name(np, i))
> +                       return -ENOENT;
> +       }
> +       *num_parents = cnt;
> +       table = kzalloc(sizeof(u32 *) * cnt, GFP_KERNEL);
> +       if (!table)
> +               return -ENOMEM;
> +       ret = of_property_read_u32_array(np, "clkmux-table",
> +                                        table, cnt);
> +       if (ret)
> +               goto err;
> +       return 0;
> +err:
> +       kfree(table);
> +       return ret;
> +}
> +
> +static void __init hi3xxx_clkmux_setup(struct device_node *np)
> +{
> +       struct clk *clk;
> +       const char *clk_name, **parent_names = NULL;
> +       const __be32 *prop;
> +       u32 mask, *table = NULL;
> +       u8 num_parents, shift, clk_mux_flags = 0;
> +       void __iomem *reg, *base;
> +       int i, ret;
> +
> +       base = hi3xxx_init_clocks(np);
> +       if (!base)
> +               goto err;
> +       if (of_property_read_string(np, "clock-output-names", &clk_name))
> +               goto err;
> +       prop = of_get_address(np, 0, NULL, NULL);
> +       if (!prop)
> +               goto err;
> +       reg = base + be32_to_cpu(*prop);
> +       if (of_property_read_u32(np, "clkmux-mask", &mask))
> +               goto err;
> +       if (of_property_read_bool(np, "clkmux-hiword-mask"))
> +               clk_mux_flags = CLK_MUX_HIWORD_MASK;
> +
> +       ret = hi3xxx_parse_mux(np, &num_parents, table);
> +       if (ret)
> +               goto err;
> +
> +       parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL);
> +       if (!parent_names)
> +               goto err_table;
> +       for (i = 0; i < num_parents; i++)
> +               parent_names[i] = of_clk_get_parent_name(np, i);
> +
> +       shift = ffs(mask) - 1;
> +       mask = mask >> shift;
> +       clk = clk_register_mux_table(NULL, clk_name, parent_names, num_parents,
> +                                    CLK_SET_RATE_PARENT, reg, shift, mask,
> +                                    clk_mux_flags, table, &hi3xxx_clk_lock);
> +       if (IS_ERR(clk))
> +               goto err_clk;
> +       of_clk_add_provider(np, of_clk_src_simple_get, clk);
> +
> +       return;
> +err_clk:
> +       kfree(parent_names);
> +err_table:
> +       kfree(table);
> +err:
> +       pr_err("Fail on registering hi3xxx clkmux node.\n");
> +}
> +CLK_OF_DECLARE(hi3xxx_mux, "hisilicon,clk-mux", hi3xxx_clkmux_setup)
> +
> +static void __init hi3xxx_clkdiv_setup(struct device_node *np, int mode)
> +{
> +       struct clk *clk;
> +       const char *clk_name, **parent_names;
> +       const __be32 *prop;
> +       struct clk_div_table *table;
> +       unsigned int table_num;
> +       u32 min, max, mask;
> +       u8 shift, width, clk_div_flags = 0;
> +       void __iomem *reg, *base;
> +       int i;
> +
> +       base = hi3xxx_init_clocks(np);
> +       if (!base)
> +               goto err;
> +
> +       if (of_property_read_string(np, "clock-output-names", &clk_name))
> +               goto err;
> +       if (of_property_read_u32(np, "clkdiv-mask", &mask))
> +               goto err;
> +       if (of_property_read_u32(np, "clkdiv-min", &min))
> +               goto err;
> +       if (of_property_read_u32(np, "clkdiv-max", &max))
> +               goto err;
> +       if (of_property_read_bool(np, "clkdiv-hiword-mask"))
> +               clk_div_flags = CLK_DIVIDER_HIWORD_MASK;
> +
> +       prop = of_get_address(np, 0, NULL, NULL);
> +       if (!prop)
> +               goto err;
> +       reg = base + be32_to_cpu(*prop);
> +
> +       table_num = max - min + 1;
> +       table = kzalloc(sizeof(*table) * table_num, GFP_KERNEL);
> +       if (!table)
> +               goto err;
> +
> +       for (i = 0; i < table_num; i++) {
> +               table[i].div = min + i;
> +               table[i].val = table[i].div - 1;
> +       }
> +
> +       /* gate only has the fixed parent */
> +       parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
> +       if (!parent_names)
> +               goto err_par;
> +       parent_names[0] = of_clk_get_parent_name(np, 0);
> +       shift = ffs(mask) - 1;
> +       width = fls(mask) - ffs(mask) + 1;
> +       clk = clk_register_divider_table(NULL, clk_name, parent_names[0], 0,
> +                                        reg, shift, width, clk_div_flags,
> +                                        table, &hi3xxx_clk_lock);
> +       if (IS_ERR(clk))
> +               goto err_clk;
> +       of_clk_add_provider(np, of_clk_src_simple_get, clk);
> +       return;
> +err_clk:
> +       kfree(parent_names);
> +err_par:
> +       kfree(table);
> +err:
> +       pr_err("Fail on registering hi3xxx clkdiv node\n");
> +}
> +CLK_OF_DECLARE(hi3xxx_div, "hisilicon,clk-div", hi3xxx_clkdiv_setup)
> -- 
> 1.8.1.2

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

* [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716
  2013-08-20  2:31 ` [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716 Haojian Zhuang
@ 2013-08-21 21:43   ` Mike Turquette
  2013-08-22  1:19     ` zhangfei gao
  0 siblings, 1 reply; 40+ messages in thread
From: Mike Turquette @ 2013-08-21 21:43 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Haojian Zhuang (2013-08-19 19:31:12)
> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
> ---
>  Documentation/devicetree/bindings/clock/hi3716.txt | 121 ++++++++++
>  drivers/clk/Makefile                               |   2 +-
>  drivers/clk/clk-hi3716.c                           | 268 +++++++++++++++++++++
>  3 files changed, 390 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi3716.txt
>  create mode 100644 drivers/clk/clk-hi3716.c
> 
> diff --git a/Documentation/devicetree/bindings/clock/hi3716.txt b/Documentation/devicetree/bindings/clock/hi3716.txt
> new file mode 100644
> index 0000000..60af61e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi3716.txt
> @@ -0,0 +1,121 @@
> +Device Tree Clock bindings for hi3716
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Clock control register
> +Required properties:
> +- compatible : "hisilicon,clkbase"
> +- reg : Address and size of clkbase.
> +
> +Device Clocks
> +
> +Device clocks are required to have one or both of the following sets of
> +properties:
> +
> +
> +Gated device clocks:
> +
> +Required properties:
> +- compatible : "hisilicon,hi3716-clk-gate"
> +- gate-reg : shall be the register offset from clkbase and enable bit, reset bit

The 'reg' property is standard and well understood. Best not to try and
re-invent that with gate-reg.

Instead put the register address in the 'reg' property and the other
bits in separate properties.

The same goes for the *-reg properties below.

<snip>
> +static int hi3716_clkgate_prepare(struct clk_hw *hw)
> +{
> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
> +       unsigned long flags = 0;
> +       u32 reg;
> +
> +       spin_lock_irqsave(&_lock, flags);
> +
> +       reg = readl_relaxed(clk->reg);
> +       reg &= ~BIT(clk->reset_bit);
> +       writel_relaxed(reg, clk->reg);
> +
> +       spin_unlock_irqrestore(&_lock, flags);
> +
> +       return 0;
> +}
> +
> +static void hi3716_clkgate_unprepare(struct clk_hw *hw)
> +{
> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
> +       unsigned long flags = 0;
> +       u32 reg;
> +
> +       spin_lock_irqsave(&_lock, flags);
> +
> +       reg = readl_relaxed(clk->reg);
> +       reg |= BIT(clk->reset_bit);
> +       writel_relaxed(reg, clk->reg);
> +
> +       spin_unlock_irqrestore(&_lock, flags);
> +}
> +
> +static struct clk_ops hi3716_clkgate_ops = {
> +       .prepare        = hi3716_clkgate_prepare,
> +       .unprepare      = hi3716_clkgate_unprepare,
> +};

Why .prepare & .unprepare instead of .enable & .disable?

Regards,
Mike

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

* [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716
  2013-08-21 21:43   ` Mike Turquette
@ 2013-08-22  1:19     ` zhangfei gao
  2013-08-22  5:59       ` Mike Turquette
  0 siblings, 1 reply; 40+ messages in thread
From: zhangfei gao @ 2013-08-22  1:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 22, 2013 at 5:43 AM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Haojian Zhuang (2013-08-19 19:31:12)
>> From: Zhangfei Gao <zhangfei.gao@linaro.org>
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
>> ---

>> +static int hi3716_clkgate_prepare(struct clk_hw *hw)
>> +{
>> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
>> +       unsigned long flags = 0;
>> +       u32 reg;
>> +
>> +       spin_lock_irqsave(&_lock, flags);
>> +
>> +       reg = readl_relaxed(clk->reg);
>> +       reg &= ~BIT(clk->reset_bit);
>> +       writel_relaxed(reg, clk->reg);
>> +
>> +       spin_unlock_irqrestore(&_lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static void hi3716_clkgate_unprepare(struct clk_hw *hw)
>> +{
>> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
>> +       unsigned long flags = 0;
>> +       u32 reg;
>> +
>> +       spin_lock_irqsave(&_lock, flags);
>> +
>> +       reg = readl_relaxed(clk->reg);
>> +       reg |= BIT(clk->reset_bit);
>> +       writel_relaxed(reg, clk->reg);
>> +
>> +       spin_unlock_irqrestore(&_lock, flags);
>> +}
>> +
>> +static struct clk_ops hi3716_clkgate_ops = {
>> +       .prepare        = hi3716_clkgate_prepare,
>> +       .unprepare      = hi3716_clkgate_unprepare,
>> +};
>
> Why .prepare & .unprepare instead of .enable & .disable?
>
> Regards,
> Mike

Thanks  Mike for the review

the .enable & .disable is directly use clk_gate_ops.

+       hi3716_clkgate_ops.enable = clk_gate_ops.enable;
+       hi3716_clkgate_ops.disable = clk_gate_ops.disable;
+       hi3716_clkgate_ops.is_enabled = clk_gate_ops.is_enabled;
+       p_clk->gate.bit_idx = array[1];

prepare & unprepare is handle reset bit, while enable & disable is
handle enable bit.
We have to extend since clk_gate_ops does not consider prepare &
unprepare, otherwise it would be simpler.

Thanks

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

* [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716
  2013-08-22  1:19     ` zhangfei gao
@ 2013-08-22  5:59       ` Mike Turquette
  2013-08-22  7:50         ` Haojian Zhuang
  0 siblings, 1 reply; 40+ messages in thread
From: Mike Turquette @ 2013-08-22  5:59 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting zhangfei gao (2013-08-21 18:19:33)
> On Thu, Aug 22, 2013 at 5:43 AM, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting Haojian Zhuang (2013-08-19 19:31:12)
> >> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
> >> ---
> 
> >> +static int hi3716_clkgate_prepare(struct clk_hw *hw)
> >> +{
> >> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
> >> +       unsigned long flags = 0;
> >> +       u32 reg;
> >> +
> >> +       spin_lock_irqsave(&_lock, flags);
> >> +
> >> +       reg = readl_relaxed(clk->reg);
> >> +       reg &= ~BIT(clk->reset_bit);
> >> +       writel_relaxed(reg, clk->reg);
> >> +
> >> +       spin_unlock_irqrestore(&_lock, flags);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void hi3716_clkgate_unprepare(struct clk_hw *hw)
> >> +{
> >> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
> >> +       unsigned long flags = 0;
> >> +       u32 reg;
> >> +
> >> +       spin_lock_irqsave(&_lock, flags);
> >> +
> >> +       reg = readl_relaxed(clk->reg);
> >> +       reg |= BIT(clk->reset_bit);
> >> +       writel_relaxed(reg, clk->reg);
> >> +
> >> +       spin_unlock_irqrestore(&_lock, flags);
> >> +}
> >> +
> >> +static struct clk_ops hi3716_clkgate_ops = {
> >> +       .prepare        = hi3716_clkgate_prepare,
> >> +       .unprepare      = hi3716_clkgate_unprepare,
> >> +};
> >
> > Why .prepare & .unprepare instead of .enable & .disable?
> >
> > Regards,
> > Mike
> 
> Thanks  Mike for the review
> 
> the .enable & .disable is directly use clk_gate_ops.
> 
> +       hi3716_clkgate_ops.enable = clk_gate_ops.enable;
> +       hi3716_clkgate_ops.disable = clk_gate_ops.disable;
> +       hi3716_clkgate_ops.is_enabled = clk_gate_ops.is_enabled;
> +       p_clk->gate.bit_idx = array[1];
> 
> prepare & unprepare is handle reset bit, while enable & disable is
> handle enable bit.
> We have to extend since clk_gate_ops does not consider prepare &
> unprepare, otherwise it would be simpler.

I understand why you made this choice from the perspective of re-using
the existing gate-clock implementation. What I meant in my question is
whether or not handling the reset bit in the .prepare/.unprepare is the
right thing.

For instance if you called clk_enable or clk_disable from within an
interrupt handler would you want to toggle the reset bit in that
instance?

Regards,
Mike

> 
> Thanks

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

* [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716
  2013-08-22  5:59       ` Mike Turquette
@ 2013-08-22  7:50         ` Haojian Zhuang
  2013-08-22  8:16           ` Mike Turquette
  0 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-22  7:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 22 August 2013 13:59, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting zhangfei gao (2013-08-21 18:19:33)
>> On Thu, Aug 22, 2013 at 5:43 AM, Mike Turquette <mturquette@linaro.org> wrote:
>> > Quoting Haojian Zhuang (2013-08-19 19:31:12)
>> >> From: Zhangfei Gao <zhangfei.gao@linaro.org>
>> >>
>> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> >> Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
>> >> ---
>>
>> >> +static int hi3716_clkgate_prepare(struct clk_hw *hw)
>> >> +{
>> >> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
>> >> +       unsigned long flags = 0;
>> >> +       u32 reg;
>> >> +
>> >> +       spin_lock_irqsave(&_lock, flags);
>> >> +
>> >> +       reg = readl_relaxed(clk->reg);
>> >> +       reg &= ~BIT(clk->reset_bit);
>> >> +       writel_relaxed(reg, clk->reg);
>> >> +
>> >> +       spin_unlock_irqrestore(&_lock, flags);
>> >> +
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +static void hi3716_clkgate_unprepare(struct clk_hw *hw)
>> >> +{
>> >> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
>> >> +       unsigned long flags = 0;
>> >> +       u32 reg;
>> >> +
>> >> +       spin_lock_irqsave(&_lock, flags);
>> >> +
>> >> +       reg = readl_relaxed(clk->reg);
>> >> +       reg |= BIT(clk->reset_bit);
>> >> +       writel_relaxed(reg, clk->reg);
>> >> +
>> >> +       spin_unlock_irqrestore(&_lock, flags);
>> >> +}
>> >> +
>> >> +static struct clk_ops hi3716_clkgate_ops = {
>> >> +       .prepare        = hi3716_clkgate_prepare,
>> >> +       .unprepare      = hi3716_clkgate_unprepare,
>> >> +};
>> >
>> > Why .prepare & .unprepare instead of .enable & .disable?
>> >
>> > Regards,
>> > Mike
>>
>> Thanks  Mike for the review
>>
>> the .enable & .disable is directly use clk_gate_ops.
>>
>> +       hi3716_clkgate_ops.enable = clk_gate_ops.enable;
>> +       hi3716_clkgate_ops.disable = clk_gate_ops.disable;
>> +       hi3716_clkgate_ops.is_enabled = clk_gate_ops.is_enabled;
>> +       p_clk->gate.bit_idx = array[1];
>>
>> prepare & unprepare is handle reset bit, while enable & disable is
>> handle enable bit.
>> We have to extend since clk_gate_ops does not consider prepare &
>> unprepare, otherwise it would be simpler.
>
> I understand why you made this choice from the perspective of re-using
> the existing gate-clock implementation. What I meant in my question is
> whether or not handling the reset bit in the .prepare/.unprepare is the
> right thing.
>
> For instance if you called clk_enable or clk_disable from within an
> interrupt handler would you want to toggle the reset bit in that
> instance?
>

No. We don't want to access reset bit for clk_enable() & clk_disable().

We don't know what issue will occur if we always control reset & unreset with
enabling/disabling.

Regards
Haojian

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

* [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716
  2013-08-22  7:50         ` Haojian Zhuang
@ 2013-08-22  8:16           ` Mike Turquette
  0 siblings, 0 replies; 40+ messages in thread
From: Mike Turquette @ 2013-08-22  8:16 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Haojian Zhuang (2013-08-22 00:50:52)
> On 22 August 2013 13:59, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting zhangfei gao (2013-08-21 18:19:33)
> >> On Thu, Aug 22, 2013 at 5:43 AM, Mike Turquette <mturquette@linaro.org> wrote:
> >> > Quoting Haojian Zhuang (2013-08-19 19:31:12)
> >> >> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> >>
> >> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> >> Signed-off-by: Zhang Mingjun <zhang.mingjun@linaro.org>
> >> >> ---
> >>
> >> >> +static int hi3716_clkgate_prepare(struct clk_hw *hw)
> >> >> +{
> >> >> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
> >> >> +       unsigned long flags = 0;
> >> >> +       u32 reg;
> >> >> +
> >> >> +       spin_lock_irqsave(&_lock, flags);
> >> >> +
> >> >> +       reg = readl_relaxed(clk->reg);
> >> >> +       reg &= ~BIT(clk->reset_bit);
> >> >> +       writel_relaxed(reg, clk->reg);
> >> >> +
> >> >> +       spin_unlock_irqrestore(&_lock, flags);
> >> >> +
> >> >> +       return 0;
> >> >> +}
> >> >> +
> >> >> +static void hi3716_clkgate_unprepare(struct clk_hw *hw)
> >> >> +{
> >> >> +       struct hi3716_clk *clk = to_clk_hi3716(hw);
> >> >> +       unsigned long flags = 0;
> >> >> +       u32 reg;
> >> >> +
> >> >> +       spin_lock_irqsave(&_lock, flags);
> >> >> +
> >> >> +       reg = readl_relaxed(clk->reg);
> >> >> +       reg |= BIT(clk->reset_bit);
> >> >> +       writel_relaxed(reg, clk->reg);
> >> >> +
> >> >> +       spin_unlock_irqrestore(&_lock, flags);
> >> >> +}
> >> >> +
> >> >> +static struct clk_ops hi3716_clkgate_ops = {
> >> >> +       .prepare        = hi3716_clkgate_prepare,
> >> >> +       .unprepare      = hi3716_clkgate_unprepare,
> >> >> +};
> >> >
> >> > Why .prepare & .unprepare instead of .enable & .disable?
> >> >
> >> > Regards,
> >> > Mike
> >>
> >> Thanks  Mike for the review
> >>
> >> the .enable & .disable is directly use clk_gate_ops.
> >>
> >> +       hi3716_clkgate_ops.enable = clk_gate_ops.enable;
> >> +       hi3716_clkgate_ops.disable = clk_gate_ops.disable;
> >> +       hi3716_clkgate_ops.is_enabled = clk_gate_ops.is_enabled;
> >> +       p_clk->gate.bit_idx = array[1];
> >>
> >> prepare & unprepare is handle reset bit, while enable & disable is
> >> handle enable bit.
> >> We have to extend since clk_gate_ops does not consider prepare &
> >> unprepare, otherwise it would be simpler.
> >
> > I understand why you made this choice from the perspective of re-using
> > the existing gate-clock implementation. What I meant in my question is
> > whether or not handling the reset bit in the .prepare/.unprepare is the
> > right thing.
> >
> > For instance if you called clk_enable or clk_disable from within an
> > interrupt handler would you want to toggle the reset bit in that
> > instance?
> >
> 
> No. We don't want to access reset bit for clk_enable() & clk_disable().
> 
> We don't know what issue will occur if we always control reset & unreset with
> enabling/disabling.

Ok then your use of .prepare & .unprepare sounds correct to me.

Thanks,
Mike

> 
> Regards
> Haojian

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-20  2:31 ` [PATCH v7 05/11] ARM: dts: enable hi4511 " Haojian Zhuang
@ 2013-08-22 18:07   ` Kevin Hilman
  2013-08-22 18:50     ` Stephen Warren
  2013-08-24  3:59     ` Haojian Zhuang
  0 siblings, 2 replies; 40+ messages in thread
From: Kevin Hilman @ 2013-08-22 18:07 UTC (permalink / raw)
  To: linux-arm-kernel

[+ DT maintainers]

Haojian Zhuang <haojian.zhuang@linaro.org> writes:

> Enable Hisilicon Hi4511 development platform with device tree support.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

There seems to be use of several new vendor-specific bindings here that
are not documented anywhere:

hisilicon,sctrl 
hisilicon,pmctrl
hisilicon,clk-mux
hisilicon,clk-div
hisilicon,clk-gate

Not only that, the clock-related compatible properties used here are
different than the ones specificed PATCH 10/11 of this series where you
document some clock bindings.  

also...

[...]

> +/include/ "skeleton.dtsi"
> +
> +/ {
> +	aliases {
> +		serial0 = &uart0;
> +		serial1 = &uart1;
> +		serial2 = &uart2;
> +		serial3 = &uart3;
> +		serial4 = &uart4;
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu at 0 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a9";
> +			reg = <0x0>;
> +			next-level-cache = <&L2>;
> +		};
> +	};
> +
> +	osc32k: osc32k {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <32768>;
> +		clock-output-names = "osc32khz";
> +	};

...seems many of the recent users of clocks have grouped them into a
clocks {} grouping on a "simple-bus".

DT folks: is there a rule of thumb on how whether these fixed clocks
should be grouped on a simple bus?

Kevin

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-22 18:07   ` Kevin Hilman
@ 2013-08-22 18:50     ` Stephen Warren
  2013-08-24  3:52       ` Haojian Zhuang
  2013-08-24  3:59     ` Haojian Zhuang
  1 sibling, 1 reply; 40+ messages in thread
From: Stephen Warren @ 2013-08-22 18:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/22/2013 12:07 PM, Kevin Hilman wrote:
> [+ DT maintainers]
> 
> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
> 
>> Enable Hisilicon Hi4511 development platform with device tree support.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
...
>> +/include/ "skeleton.dtsi"
>> +
>> +/ {
>> +	aliases {
>> +		serial0 = &uart0;
>> +		serial1 = &uart1;
>> +		serial2 = &uart2;
>> +		serial3 = &uart3;
>> +		serial4 = &uart4;
>> +	};
>> +
>> +	cpus {
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		cpu0: cpu at 0 {
>> +			device_type = "cpu";
>> +			compatible = "arm,cortex-a9";
>> +			reg = <0x0>;
>> +			next-level-cache = <&L2>;
>> +		};
>> +	};
>> +
>> +	osc32k: osc32k {
>> +		compatible = "fixed-clock";
>> +		#clock-cells = <0>;
>> +		clock-frequency = <32768>;
>> +		clock-output-names = "osc32khz";
>> +	};
> 
> ...seems many of the recent users of clocks have grouped them into a
> clocks {} grouping on a "simple-bus".
> 
> DT folks: is there a rule of thumb on how whether these fixed clocks
> should be grouped on a simple bus?

I would expect all the clock node names to be just "clock", since the
node names should describe the type of device not their identity (i.e.
clock name).

In turn, this means that each clock node name needs to use a unit
address ("@nnn") to make them unique. In turn, this means they must have
a reg property since the unit address must match the first entry in the
reg property.

Now I assume these clocks don't have any memory-mapped IO registers, so
they would need an arbitrary reg value rather than a real one. So it
doesn't make sense to place them directly under the root DT node, since
their reg values would make no sense within the context of the
CPU-visible MMIO space that the root node describes.

In this case, it's typical to put all the clock nodes into e.g. a
/clocks node, since that node can introduce a separate numbering-space
for clocks. For example, I'd expect something like:

        clocks {
                #address-cells = <1>;
                #size-cells = <0>;

                osc32k: clock at 0 {
                        compatible = "fixed-clock";
                        reg = <0>;
                        #clock-cells = <0>;
                        clock-frequency = <32768>;
                        clock-output-names = "osc32khz";
                };

                osc26m: clock at 1 {
                        compatible = "fixed-clock";
                        reg = <1>;
                        #clock-cells = <0>;
                        clock-frequency = <26000000>;
                        clock-output-names = "osc26mhz";
                };
                ...
        };

However, it also depends on what is actually providing those clocks. If
every one of them is some standalone device on the board (e.g. a
crystal), then just dumping them all in /clocks makes sense. However, if
the clocks are provided by some on-SoC clock module, then I'd likely
expect the clocks to be contained within the DT node that represents
that clock module, which presumably does have some registers, and hence
could be a direct child of the root node. For example, I wonder if the
following is more accurate:

	sctrl: sctrl at fc802000 {
		compatible = "hisilicon,sctrl";
		reg = <0xfc802000 0x1000>;
                #address-cells = <1>;
                #size-cells = <0>;

                osc32k: clock at 0 {
                        compatible = "fixed-clock";
                        reg = <0>;
                        #clock-cells = <0>;
                        clock-frequency = <32768>;
                        clock-output-names = "osc32khz";
                };

                osc26m: clock at 1 {
                        compatible = "fixed-clock";
                        reg = <1>;
                        #clock-cells = <0>;
                        clock-frequency = <26000000>;
                        clock-output-names = "osc26mhz";
                };
                ...
        };

... since I see there are already quite a few clocks inside the sctrl node.

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-22 18:50     ` Stephen Warren
@ 2013-08-24  3:52       ` Haojian Zhuang
  2013-08-26 16:48           ` Stephen Warren
  0 siblings, 1 reply; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-24  3:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>> [+ DT maintainers]
>>
>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>
>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>
>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ...
>>> +/include/ "skeleton.dtsi"
>>> +
>>> +/ {
>>> +    aliases {
>>> +            serial0 = &uart0;
>>> +            serial1 = &uart1;
>>> +            serial2 = &uart2;
>>> +            serial3 = &uart3;
>>> +            serial4 = &uart4;
>>> +    };
>>> +
>>> +    cpus {
>>> +            #address-cells = <1>;
>>> +            #size-cells = <0>;
>>> +
>>> +            cpu0: cpu at 0 {
>>> +                    device_type = "cpu";
>>> +                    compatible = "arm,cortex-a9";
>>> +                    reg = <0x0>;
>>> +                    next-level-cache = <&L2>;
>>> +            };
>>> +    };
>>> +
>>> +    osc32k: osc32k {
>>> +            compatible = "fixed-clock";
>>> +            #clock-cells = <0>;
>>> +            clock-frequency = <32768>;
>>> +            clock-output-names = "osc32khz";
>>> +    };
>>
>> ...seems many of the recent users of clocks have grouped them into a
>> clocks {} grouping on a "simple-bus".
>>
>> DT folks: is there a rule of thumb on how whether these fixed clocks
>> should be grouped on a simple bus?
>
> I would expect all the clock node names to be just "clock", since the
> node names should describe the type of device not their identity (i.e.
> clock name).
>
> In turn, this means that each clock node name needs to use a unit
> address ("@nnn") to make them unique. In turn, this means they must have
> a reg property since the unit address must match the first entry in the
> reg property.

No, it's really bad on using a unit address. The register always contains
multiple mux or gate or divider. It would cause duplicated unit address.

I tried to use index number also. And it's also bad to append new clock nodes.
So I use the label name instead.

>
> Now I assume these clocks don't have any memory-mapped IO registers, so
> they would need an arbitrary reg value rather than a real one. So it
> doesn't make sense to place them directly under the root DT node, since
> their reg values would make no sense within the context of the
> CPU-visible MMIO space that the root node describes.
>
> In this case, it's typical to put all the clock nodes into e.g. a
> /clocks node, since that node can introduce a separate numbering-space
> for clocks. For example, I'd expect something like:
>
>         clocks {
>                 #address-cells = <1>;
>                 #size-cells = <0>;
>
>                 osc32k: clock at 0 {
>                         compatible = "fixed-clock";
>                         reg = <0>;
>                         #clock-cells = <0>;
>                         clock-frequency = <32768>;
>                         clock-output-names = "osc32khz";
>                 };
>
>                 osc26m: clock at 1 {
>                         compatible = "fixed-clock";
>                         reg = <1>;
>                         #clock-cells = <0>;
>                         clock-frequency = <26000000>;
>                         clock-output-names = "osc26mhz";
>                 };
>                 ...
>         };

Those fixed-clock doesn't contain reg property. Since it needs not to access
any clock register. It only provides the clock rate those child clock node.

>
> However, it also depends on what is actually providing those clocks. If
> every one of them is some standalone device on the board (e.g. a
> crystal), then just dumping them all in /clocks makes sense. However, if
> the clocks are provided by some on-SoC clock module, then I'd likely
> expect the clocks to be contained within the DT node that represents
> that clock module, which presumably does have some registers, and hence
> could be a direct child of the root node. For example, I wonder if the
> following is more accurate:
>
>         sctrl: sctrl at fc802000 {
>                 compatible = "hisilicon,sctrl";
>                 reg = <0xfc802000 0x1000>;
>                 #address-cells = <1>;
>                 #size-cells = <0>;
>
>                 osc32k: clock at 0 {
>                         compatible = "fixed-clock";
>                         reg = <0>;
>                         #clock-cells = <0>;
>                         clock-frequency = <32768>;
>                         clock-output-names = "osc32khz";
>                 };
>
>                 osc26m: clock at 1 {
>                         compatible = "fixed-clock";
>                         reg = <1>;
>                         #clock-cells = <0>;
>                         clock-frequency = <26000000>;
>                         clock-output-names = "osc26mhz";
>                 };
>                 ...
>         };
>
> ... since I see there are already quite a few clocks inside the sctrl node.

I can move all others clock nodes into clocks node, likes osc32k, osc26m.
Since they're not belong to sctrl register bank. And I also move all clock nodes
into a new dtsi file to make it more clearly.

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-22 18:07   ` Kevin Hilman
  2013-08-22 18:50     ` Stephen Warren
@ 2013-08-24  3:59     ` Haojian Zhuang
  1 sibling, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-24  3:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 23 August 2013 02:07, Kevin Hilman <khilman@linaro.org> wrote:
> [+ DT maintainers]
>
> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>
>> Enable Hisilicon Hi4511 development platform with device tree support.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>
> There seems to be use of several new vendor-specific bindings here that
> are not documented anywhere:
>
> hisilicon,sctrl
> hisilicon,pmctrl
> hisilicon,clk-mux
> hisilicon,clk-div
> hisilicon,clk-gate
>
Those are in clock bindings with clock patches. Since you're always
requesting those patch going through Mike's tree. I didn't pick them up
into this patch set.

> Not only that, the clock-related compatible properties used here are
> different than the ones specificed PATCH 10/11 of this series where you
> document some clock bindings.

No. #10 is only for Hi3716. It's a little different on hi3xxx. But now I dropped
this patch in my pull request.

Since there's still some comments on the whole v7 patchset, I'll update with
a v8.
>
> also...
>
> [...]
>
>> +/include/ "skeleton.dtsi"
>> +
>> +/ {
>> +     aliases {
>> +             serial0 = &uart0;
>> +             serial1 = &uart1;
>> +             serial2 = &uart2;
>> +             serial3 = &uart3;
>> +             serial4 = &uart4;
>> +     };
>> +
>> +     cpus {
>> +             #address-cells = <1>;
>> +             #size-cells = <0>;
>> +
>> +             cpu0: cpu at 0 {
>> +                     device_type = "cpu";
>> +                     compatible = "arm,cortex-a9";
>> +                     reg = <0x0>;
>> +                     next-level-cache = <&L2>;
>> +             };
>> +     };
>> +
>> +     osc32k: osc32k {
>> +             compatible = "fixed-clock";
>> +             #clock-cells = <0>;
>> +             clock-frequency = <32768>;
>> +             clock-output-names = "osc32khz";
>> +     };
>
> ...seems many of the recent users of clocks have grouped them into a
> clocks {} grouping on a "simple-bus".
>
> DT folks: is there a rule of thumb on how whether these fixed clocks
> should be grouped on a simple bus?
>
> Kevin

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

* [PATCH v7 02/11] clk: hi3xxx: add clock support
  2013-08-21 21:29   ` Mike Turquette
@ 2013-08-24  4:13     ` Haojian Zhuang
  0 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-24  4:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 22 August 2013 05:29, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Haojian Zhuang (2013-08-19 19:31:04)
>> Add clock support with device tree on Hisilicon SoC.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Cc: Mike Turquette <mturquette@linaro.org>
>> ---
>>  .../devicetree/bindings/clock/hisilicon.txt        | 118 +++++++++
>>  drivers/clk/Makefile                               |   1 +
>>  drivers/clk/clk-hi3xxx.c                           | 272 +++++++++++++++++++++
>>  3 files changed, 391 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hisilicon.txt
>>  create mode 100644 drivers/clk/clk-hi3xxx.c
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hisilicon.txt b/Documentation/devicetree/bindings/clock/hisilicon.txt
>> new file mode 100644
>> index 0000000..e8ee618
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hisilicon.txt
>> @@ -0,0 +1,118 @@
>> +Device Tree Clock bindings for arch-hi3xxx
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +All the mux, gate & divider are in clock container of DTS file.
>> +
>> +Required properties for mux clocks:
>> + - compatible : shall be "hisilicon,clk-mux".
>> + - clocks : shall be the input parent clock phandle for the clock. This should
>> +       be the reference clock.
>> + - clock-output-names : shall be reference name.
>> + - #clock-cells : from common clock binding; shall be set to 0.
>> + - reg : the mux register address. It should be the offset of the container.
>> + - clkmux-mask : mask bits of the mux register.
>> + - clkmux-table : array of mux select bits.
>> +
>> +Optional properties for mux clocks:
>> + - clkmux-hiword-mask : indicates that the bit[31:16] are the hiword mask
>> +       of mux selected bits (bit[15:0]). The bit[15:0] is valid only when
>> +       bit[31:16] is set.
>
> Instead of putting this as a flag I'm tempted to say this should be a
> separate compatible string. Any thoughts from the DT experts?
>

Since they're different divider types or mux types (with or without HIWORD) in
the same dts, it'll only make people hard to check the node with
compatible name.
So I hope to use the same compatible name with different property. It could be
easy on checking them with register table.

In this driver, I'll only use one compatible string for one clock type
on one SoC.
Since it's easier to developers on tracking with register tables.
Otherwise, they
frustrated that there're too much compatible string on the same clock
type. It only
increased unnecessary time on understanding the driver.

>> +
>> +
>> +
>> +Required properties for gate clocks:
>> + - compatible : shall be "hisilicon,clk-gate".
>> + - clocks : shall be the input parent clock phandle for the clock. This should
>> +       be the reference clock.
>> + - clock-output-names : shall be reference name.
>> + - #clock-cells : from common clock binding; shall be set to 0.
>> + - reg : the mux register address. It should be the offset of the container.
>> + - clkgate : bit index to control the clock gate in the gate register.
>> +
>> +Optional properties for gate clocks:
>> + - clkgate-inverted : it indicates that setting 0 could enable the clock gate
>> +       and setting 1 could disable the clock gate.
>> + - clkgate-seperated-reg : it indicates that there're three continuous
>> +       registers (enable, disable & status) for the same clock gate.
>
> I responded to this in the other thread but clkgate-separated-reg is a
> bad idea. You'll need your own gate clock type which handles this
> instead of pushing it into the common gate implementation. Use the
> existing 'reg' property to list the registers needed by this clock.
>
OK. I'll use my own gate clock.

>> +
>> +
>> +
>> +Required properties for divider clocks:
>> + - compatible : shall be "hisilicon,clk-div".
>> + - clocks : shall be the input parent clock phandle for the clock. This should
>> +       be the reference clock.
>> + - clock-output-names : shall be reference name.
>> + - reg : the divider register address. It should be the offset of the
>> +       container.
>> + - clkdiv-mask : mask bits of the divider register.
>> + - clkdiv-min : the minimum divider of the clock divider.
>> + - clkdiv-max : the maximum divider of the clock divider.
>
> Are these details necessary? Do the mask, min & max values change from
> clock to clock? It's nicer to have these in the driver if possible. This
> looks like building a binding from a struct, which is considered bad.
>
Since there're too much divider values for one divider, likes 32 or 64. Then I
abandon to use clkdiv-table property. Because those divider values are
continuous
ascending, I use min & max instead. It could make the node simpler.

>> +
>> +Optional properties for divider clocks:
>> + - clkdiv-hiword-mask : indicates that the bit[31:16] are the hiword mask
>> +       of divider selected bits (bit[15:0]). The bit[15:0] is valid only when
>> +       bit[31:16] is set.
>
> Same here. Again you might need a different compatible string for these
> types of clocks.

Since they're different divider types or mux types (with or without HIWORD) in
the same dts, it'll only make people hard to check the node with
compatible name.
So I hope to use the same compatible name with different property. It could be
easy on checking them with register table.

Regards
Haojian

>
> Regards,
> Mike
>

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

* Re: [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-24  3:52       ` Haojian Zhuang
@ 2013-08-26 16:48           ` Stephen Warren
  0 siblings, 0 replies; 40+ messages in thread
From: Stephen Warren @ 2013-08-26 16:48 UTC (permalink / raw)
  To: Haojian Zhuang
  Cc: Mark Rutland, devicetree, Kevin Hilman, Russell King - ARM Linux,
	Ian Campbell, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, John Stultz, grant.likely, Kumar Gala,
	Olof Johansson, Mike Turquette, tglx, linux-arm-kernel

On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>> [+ DT maintainers]
>>>
>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>
>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>
>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> ...

>>>> +    osc32k: osc32k {
>>>> +            compatible = "fixed-clock";
>>>> +            #clock-cells = <0>;
>>>> +            clock-frequency = <32768>;
>>>> +            clock-output-names = "osc32khz";
>>>> +    };
>>>
>>> ...seems many of the recent users of clocks have grouped them into a
>>> clocks {} grouping on a "simple-bus".
>>>
>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>> should be grouped on a simple bus?
>>
>> I would expect all the clock node names to be just "clock", since the
>> node names should describe the type of device not their identity (i.e.
>> clock name).
>>
>> In turn, this means that each clock node name needs to use a unit
>> address ("@nnn") to make them unique. In turn, this means they must have
>> a reg property since the unit address must match the first entry in the
>> reg property.
> 
> No, it's really bad on using a unit address. The register always contains
> multiple mux or gate or divider. It would cause duplicated unit address.

There shouldn't be multiple nodes with identical reg values; if that's
happening, then it seems like the mapping of nodes to HW is incorrect.

Each HW block should have 1 DT node. That way, the reg values won't collide.

> I tried to use index number also. And it's also bad to append new clock nodes.
> So I use the label name instead.
> 
>> Now I assume these clocks don't have any memory-mapped IO registers, so
>> they would need an arbitrary reg value rather than a real one. So it
>> doesn't make sense to place them directly under the root DT node, since
>> their reg values would make no sense within the context of the
>> CPU-visible MMIO space that the root node describes.
>>
>> In this case, it's typical to put all the clock nodes into e.g. a
>> /clocks node, since that node can introduce a separate numbering-space
>> for clocks. For example, I'd expect something like:
>>
>>         clocks {
>>                 #address-cells = <1>;
>>                 #size-cells = <0>;
>>
>>                 osc32k: clock@0 {
>>                         compatible = "fixed-clock";
>>                         reg = <0>;
...
>>                 osc26m: clock@1 {
>>                         compatible = "fixed-clock";
>>                         reg = <1>;
...

> Those fixed-clock doesn't contain reg property. Since it needs not to access
> any clock register. It only provides the clock rate those child clock node.

Inside the clocks node, the reg property is just a dummy value.

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
@ 2013-08-26 16:48           ` Stephen Warren
  0 siblings, 0 replies; 40+ messages in thread
From: Stephen Warren @ 2013-08-26 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>> [+ DT maintainers]
>>>
>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>
>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>
>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> ...

>>>> +    osc32k: osc32k {
>>>> +            compatible = "fixed-clock";
>>>> +            #clock-cells = <0>;
>>>> +            clock-frequency = <32768>;
>>>> +            clock-output-names = "osc32khz";
>>>> +    };
>>>
>>> ...seems many of the recent users of clocks have grouped them into a
>>> clocks {} grouping on a "simple-bus".
>>>
>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>> should be grouped on a simple bus?
>>
>> I would expect all the clock node names to be just "clock", since the
>> node names should describe the type of device not their identity (i.e.
>> clock name).
>>
>> In turn, this means that each clock node name needs to use a unit
>> address ("@nnn") to make them unique. In turn, this means they must have
>> a reg property since the unit address must match the first entry in the
>> reg property.
> 
> No, it's really bad on using a unit address. The register always contains
> multiple mux or gate or divider. It would cause duplicated unit address.

There shouldn't be multiple nodes with identical reg values; if that's
happening, then it seems like the mapping of nodes to HW is incorrect.

Each HW block should have 1 DT node. That way, the reg values won't collide.

> I tried to use index number also. And it's also bad to append new clock nodes.
> So I use the label name instead.
> 
>> Now I assume these clocks don't have any memory-mapped IO registers, so
>> they would need an arbitrary reg value rather than a real one. So it
>> doesn't make sense to place them directly under the root DT node, since
>> their reg values would make no sense within the context of the
>> CPU-visible MMIO space that the root node describes.
>>
>> In this case, it's typical to put all the clock nodes into e.g. a
>> /clocks node, since that node can introduce a separate numbering-space
>> for clocks. For example, I'd expect something like:
>>
>>         clocks {
>>                 #address-cells = <1>;
>>                 #size-cells = <0>;
>>
>>                 osc32k: clock at 0 {
>>                         compatible = "fixed-clock";
>>                         reg = <0>;
...
>>                 osc26m: clock at 1 {
>>                         compatible = "fixed-clock";
>>                         reg = <1>;
...

> Those fixed-clock doesn't contain reg property. Since it needs not to access
> any clock register. It only provides the clock rate those child clock node.

Inside the clocks node, the reg property is just a dummy value.

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

* [PATCH v7 08/11] ARM: hi3xxx: add smp support
  2013-08-20  2:31 ` [PATCH v7 08/11] ARM: hi3xxx: add smp support Haojian Zhuang
@ 2013-08-28  2:12   ` Olof Johansson
  2013-08-28 11:53     ` zhangfei gao
  0 siblings, 1 reply; 40+ messages in thread
From: Olof Johansson @ 2013-08-28  2:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Some comments below.

On Tue, Aug 20, 2013 at 10:31:10AM +0800, Haojian Zhuang wrote:
> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> 
> Enable SMP support on hi3xxx platform
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Tested-by: Zhang Mingjun <zhang.mingjun@linaro.org>
> Tested-by: Li Xin <li.xin@linaro.org>
> ---
>  .../bindings/arm/hisilicon/hisilicon.txt           | 47 ++++++++++++++++
>  arch/arm/boot/dts/hi3620.dtsi                      | 28 +++++++++-
>  arch/arm/boot/dts/hi4511.dts                       |  2 +-
>  arch/arm/mach-hi3xxx/Kconfig                       |  2 +
>  arch/arm/mach-hi3xxx/Makefile                      |  3 +-
>  arch/arm/mach-hi3xxx/core.h                        | 14 +++++
>  arch/arm/mach-hi3xxx/hi3xxx.c                      |  5 ++
>  arch/arm/mach-hi3xxx/platsmp.c                     | 43 ++++++++++++++
>  arch/arm/mach-hi3xxx/system.c                      | 65 ++++++++++++++++++++++
>  9 files changed, 206 insertions(+), 3 deletions(-)
>  create mode 100644 arch/arm/mach-hi3xxx/core.h
>  create mode 100644 arch/arm/mach-hi3xxx/platsmp.c
>  create mode 100644 arch/arm/mach-hi3xxx/system.c
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 3be60c8..4cc5c57 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -8,3 +8,50 @@ Required root node properties:
>  Hi4511 Board
>  Required root node properties:
>  	- compatible = "hisilicon,hi3620-hi4511";
> +
> +
> +Hisilicon sctrl resiter

Resiter seems like odd naming here.

> +
> +Required properties:
> +- compatible : "hisilicon,sctrl"
> +- reg : Address and size of sysctrl.

sysctrl or sctrl? sysctrl isn't really too long, might as well use that.

> +
> +Optional properties:
> +- smp_reg : offset in sysctrl for notifying slave cpu booting
> +		cpu 1, reg;
> +		cpu 2, reg + 0x4;
> +		cpu 3, reg + 0x8;
> +		If reg value is not zero, cpun exit wfi and go
> +- resume_reg : offset in sysctrl for notifying cpu0 when resume
> +- reset_reg : offset in sysctrl for system reset

Underscores are usually not used in properties, you use dashes instead.

Anyway, I suggest defining those as the different cells in a regular 'reg'
property instead.

> +
> +Example:
> +	hi3716:
> +	sctrl at f8000000 {

Labels are usually not done on a separate line before.

Common node names would be more clear-text than this. Maybe "system-controller"
in this case.


> +		compatible = "hisilicon,sctrl";
> +		reg = <0xf8000000 0x1000>;
> +		smp_reg = <0xc0>;
> +		reboot_reg = <0x4>;
> +	};
> +
> +	hi3620:
> +	sctrl at fc802000 {
> +		compatible = "hisilicon,sctrl";
> +		reg = <0xfc802000 0x1000>;
> +		smp_reg = <0x31c>;
> +		resume_reg = <0x308>;
> +		reboot_reg = <0x4>;
> +	};
> +
> +Hi3716 cpuctrl register
> +Required properties:
> +- compatible : "hisilicon,cpuctrl"
> +- reg : Address and size of cpuctrl.
> +
> +Hi3716 specific cpuctrl register, control hotplug info etc.

Controlling hotplug _info_? Seems like odd wording here.

> +Example:
> +	hi3716:
> +	cpuctrl at f8a22000 {
> +		compatible = "hisilicon,cpuctrl";
> +		reg = <0xf8a22000 0x2000>;
> +	};
> diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
> index 39fa37f..ee81192 100644
> --- a/arch/arm/boot/dts/hi3620.dtsi
> +++ b/arch/arm/boot/dts/hi3620.dtsi
> @@ -32,6 +32,24 @@
>  			reg = <0x0>;
>  			next-level-cache = <&L2>;
>  		};
> +		cpu1: cpu at 1 {

Do you need labels here? I don't think these are referred to as phandles
anywhere?

> +			compatible = "arm,cortex-a9";
> +			device_type = "cpu";
> +			reg = <1>;
> +			next-level-cache = <&L2>;
> +		};
> +		cpu2: cpu at 2 {
> +			compatible = "arm,cortex-a9";
> +			device_type = "cpu";
> +			reg = <2>;
> +			next-level-cache = <&L2>;
> +		};
> +		cpu3: cpu at 3 {
> +			compatible = "arm,cortex-a9";
> +			device_type = "cpu";
> +			reg = <3>;
> +			next-level-cache = <&L2>;
> +		};
>  	};
>  
>  	osc32k: osc32k {
> @@ -130,7 +148,9 @@
>  			reg = <0xfc802000 0x1000>;
>  			#address-cells = <1>;
>  			#size-cells = <0>;
> -
> +			smp_reg = <0x31c>;
> +			resume_reg = <0x308>;
> +			reboot_reg = <0x4>;
>  
>  			timer0_mux: timer0_mux {
>  				compatible = "hisilicon,clk-mux";
> @@ -1242,6 +1262,12 @@
>  			status = "disabled";
>  		};
>  
> +		timer5: timer at fc000600 {
> +			compatible = "arm,cortex-a9-twd-timer";
> +			reg = <0xfc000600 0x20>;
> +			interrupts = <1 13 0xf01>;
> +		};
> +
>  		uart0: uart at fcb00000 {
>  			compatible = "arm,pl011", "arm,primecell";
>  			reg = <0xfcb00000 0x1000>;
> diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
> index 7e67564..c9fd329 100644
> --- a/arch/arm/boot/dts/hi4511.dts
> +++ b/arch/arm/boot/dts/hi4511.dts
> @@ -15,7 +15,7 @@
>  	compatible = "hisilicon,hi3620-hi4511";
>  
>  	chosen {
> -		bootargs = "console=ttyAMA0,115200 root=/dev/ram0 earlyprintk";
> +		bootargs = "console=ttyAMA0,115200 root=/dev/ram0 nr_cpus=4 earlyprintk";

nr_cpus should not be needed on the command line.

>  	};
>  
>  	memory {
> diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig
> index 68bd26c..d2e7d57 100644
> --- a/arch/arm/mach-hi3xxx/Kconfig
> +++ b/arch/arm/mach-hi3xxx/Kconfig
> @@ -6,6 +6,8 @@ config ARCH_HI3xxx
>  	select CACHE_L2X0
>  	select CLKSRC_OF
>  	select GENERIC_CLOCKEVENTS
> +	select HAVE_ARM_SCU
> +	select HAVE_SMP
>  	select PINCTRL
>  	select PINCTRL_SINGLE
>  	help
> diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
> index d68ebb3..0917f1c 100644
> --- a/arch/arm/mach-hi3xxx/Makefile
> +++ b/arch/arm/mach-hi3xxx/Makefile
> @@ -2,4 +2,5 @@
>  # Makefile for Hisilicon Hi36xx/Hi37xx processors line
>  #
>  
> -obj-y	+= hi3xxx.o
> +obj-y	+= hi3xxx.o system.o
> +obj-$(CONFIG_SMP)		+= platsmp.o
> diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h
> new file mode 100644
> index 0000000..2cfd643
> --- /dev/null
> +++ b/arch/arm/mach-hi3xxx/core.h
> @@ -0,0 +1,14 @@
> +#ifndef __HISILICON_CORE_H
> +#define __HISILICON_CORE_H
> +
> +#include <linux/init.h>

I don't think you need linux/init.h here?

> +#include <linux/reboot.h>
> +
> +extern void hs_set_cpu_jump(int cpu, void *jump_addr);
> +extern int hs_get_cpu_jump(int cpu);
> +extern void secondary_startup(void);
> +extern void hs_map_io(void);
> +extern void hs_restart(enum reboot_mode, const char *cmd);
> +extern struct smp_operations hs_smp_ops;
> +
> +#endif
> diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
> index e7c54bc..567a0d5 100644
> --- a/arch/arm/mach-hi3xxx/hi3xxx.c
> +++ b/arch/arm/mach-hi3xxx/hi3xxx.c
> @@ -19,8 +19,11 @@
>  #include <asm/mach/arch.h>
>  #include <asm/mach/map.h>
>  
> +#include "core.h"
> +
>  static void __init hi3xxx_timer_init(void)
>  {
> +	hs_map_io();
>  	of_clk_init(NULL);
>  	clocksource_of_init();
>  }
> @@ -33,4 +36,6 @@ static const char *hs_compat[] __initdata = {
>  DT_MACHINE_START(HI3xxx, "Hisilicon Hi36xx/Hi37xx (Flattened Device Tree)")
>  	.init_time	= hi3xxx_timer_init,
>  	.dt_compat	= hs_compat,
> +	.smp		= smp_ops(hs_smp_ops),
> +	.restart	= hs_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c
> new file mode 100644
> index 0000000..a76a3cc
> --- /dev/null
> +++ b/arch/arm/mach-hi3xxx/platsmp.c
> @@ -0,0 +1,43 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +#include <linux/smp.h>
> +#include <linux/io.h>
> +#include <asm/smp_scu.h>
> +
> +#include "core.h"
> +
> +static void __init hs_smp_prepare_cpus(unsigned int max_cpus)
> +{
> +	unsigned long base;
> +	void __iomem *scu_base;
> +
> +	if (scu_a9_has_base()) {
> +		base = scu_a9_get_base();
> +		scu_base = ioremap(base, SZ_4K);
> +		if (!scu_base) {
> +			pr_err("ioremap(scu_base) failed\n");
> +			return;
> +		}
> +		scu_enable(scu_base);
> +		iounmap(scu_base);
> +	}
> +}
> +
> +static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
> +{
> +	hs_set_cpu_jump(cpu, secondary_startup);
> +	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
> +	return 0;
> +}
> +
> +struct smp_operations hs_smp_ops __initdata = {
> +	.smp_prepare_cpus	= hs_smp_prepare_cpus,
> +	.smp_boot_secondary	= hs_boot_secondary,
> +};
> diff --git a/arch/arm/mach-hi3xxx/system.c b/arch/arm/mach-hi3xxx/system.c
> new file mode 100644
> index 0000000..51bb247
> --- /dev/null
> +++ b/arch/arm/mach-hi3xxx/system.c
> @@ -0,0 +1,65 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +
> +#include <asm/proc-fns.h>
> +#include <asm/smp_plat.h>
> +
> +#include "core.h"
> +
> +static void __iomem *hs_sctrl_base;
> +static int hs_smp_reg;
> +static int hs_resume_reg;
> +static int hs_reboot_reg;
> +
> +void hs_map_io(void)
> +{
> +	struct device_node *np;
> +
> +	np = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
> +	if (np) {
> +		hs_sctrl_base = of_iomap(np, 0);
> +		if (!hs_sctrl_base)
> +			pr_err("of_iomap(sctrl_base) failed\n");
> +		of_property_read_u32(np, "smp_reg", &hs_smp_reg);
> +		of_property_read_u32(np, "resume_reg", &hs_resume_reg);
> +		of_property_read_u32(np, "reboot_reg", &hs_reboot_reg);
> +	}
> +}
> +
> +void hs_set_cpu_jump(int cpu, void *jump_addr)
> +{
> +	int offset = hs_smp_reg;
> +
> +	cpu = cpu_logical_map(cpu);
> +	if (cpu > 0)
> +		offset +=  0x04 * (cpu - 1);
> +	writel_relaxed(virt_to_phys(jump_addr), hs_sctrl_base + offset);
> +}
> +
> +int hs_get_cpu_jump(int cpu)
> +{
> +	int offset = hs_smp_reg;
> +
> +	cpu = cpu_logical_map(cpu);
> +	if (cpu > 0)
> +		offset +=  0x04 * (cpu - 1);
> +	return readl_relaxed(hs_sctrl_base + offset);
> +}
> +
> +void hs_restart(enum reboot_mode mode, const char *cmd)
> +{
> +	writel_relaxed(0xdeadbeef, hs_sctrl_base + hs_reboot_reg);
> +
> +	while (1)
> +		cpu_do_idle();
> +}
> +
> -- 
> 1.8.1.2
> 

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

* Re: [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-26 16:48           ` Stephen Warren
@ 2013-08-28  2:17             ` Haojian Zhuang
  -1 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-28  2:17 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Mark Rutland, devicetree, Kevin Hilman, Russell King - ARM Linux,
	Ian Campbell, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, John Stultz, grant.likely, Kumar Gala,
	Olof Johansson, Mike Turquette, tglx, linux-arm-kernel

On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>> [+ DT maintainers]
>>>>
>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>
>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>
>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>> ...
>
>>>>> +    osc32k: osc32k {
>>>>> +            compatible = "fixed-clock";
>>>>> +            #clock-cells = <0>;
>>>>> +            clock-frequency = <32768>;
>>>>> +            clock-output-names = "osc32khz";
>>>>> +    };
>>>>
>>>> ...seems many of the recent users of clocks have grouped them into a
>>>> clocks {} grouping on a "simple-bus".
>>>>
>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>> should be grouped on a simple bus?
>>>
>>> I would expect all the clock node names to be just "clock", since the
>>> node names should describe the type of device not their identity (i.e.
>>> clock name).
>>>
>>> In turn, this means that each clock node name needs to use a unit
>>> address ("@nnn") to make them unique. In turn, this means they must have
>>> a reg property since the unit address must match the first entry in the
>>> reg property.
>>
>> No, it's really bad on using a unit address. The register always contains
>> multiple mux or gate or divider. It would cause duplicated unit address.
>
> There shouldn't be multiple nodes with identical reg values; if that's
> happening, then it seems like the mapping of nodes to HW is incorrect.
>
> Each HW block should have 1 DT node. That way, the reg values won't collide.
>

At here, I emphasize each clock node is one clock node. They are organized in
tree. The same register integrates multiple clock gate/clock mux/clock divider.
If each clock node is depend on reg, maybe it's not easy to read and the clock
driver will be more complex.

>> I tried to use index number also. And it's also bad to append new clock nodes.
>> So I use the label name instead.
>>
>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>> they would need an arbitrary reg value rather than a real one. So it
>>> doesn't make sense to place them directly under the root DT node, since
>>> their reg values would make no sense within the context of the
>>> CPU-visible MMIO space that the root node describes.
>>>
>>> In this case, it's typical to put all the clock nodes into e.g. a
>>> /clocks node, since that node can introduce a separate numbering-space
>>> for clocks. For example, I'd expect something like:
>>>
>>>         clocks {
>>>                 #address-cells = <1>;
>>>                 #size-cells = <0>;
>>>
>>>                 osc32k: clock@0 {
>>>                         compatible = "fixed-clock";
>>>                         reg = <0>;
> ...
>>>                 osc26m: clock@1 {
>>>                         compatible = "fixed-clock";
>>>                         reg = <1>;
> ...
>
>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>> any clock register. It only provides the clock rate those child clock node.
>
> Inside the clocks node, the reg property is just a dummy value.

Is a dummy value helpful? I don't think so.

Regards
Haojian

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
@ 2013-08-28  2:17             ` Haojian Zhuang
  0 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-28  2:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>> [+ DT maintainers]
>>>>
>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>
>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>
>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>> ...
>
>>>>> +    osc32k: osc32k {
>>>>> +            compatible = "fixed-clock";
>>>>> +            #clock-cells = <0>;
>>>>> +            clock-frequency = <32768>;
>>>>> +            clock-output-names = "osc32khz";
>>>>> +    };
>>>>
>>>> ...seems many of the recent users of clocks have grouped them into a
>>>> clocks {} grouping on a "simple-bus".
>>>>
>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>> should be grouped on a simple bus?
>>>
>>> I would expect all the clock node names to be just "clock", since the
>>> node names should describe the type of device not their identity (i.e.
>>> clock name).
>>>
>>> In turn, this means that each clock node name needs to use a unit
>>> address ("@nnn") to make them unique. In turn, this means they must have
>>> a reg property since the unit address must match the first entry in the
>>> reg property.
>>
>> No, it's really bad on using a unit address. The register always contains
>> multiple mux or gate or divider. It would cause duplicated unit address.
>
> There shouldn't be multiple nodes with identical reg values; if that's
> happening, then it seems like the mapping of nodes to HW is incorrect.
>
> Each HW block should have 1 DT node. That way, the reg values won't collide.
>

At here, I emphasize each clock node is one clock node. They are organized in
tree. The same register integrates multiple clock gate/clock mux/clock divider.
If each clock node is depend on reg, maybe it's not easy to read and the clock
driver will be more complex.

>> I tried to use index number also. And it's also bad to append new clock nodes.
>> So I use the label name instead.
>>
>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>> they would need an arbitrary reg value rather than a real one. So it
>>> doesn't make sense to place them directly under the root DT node, since
>>> their reg values would make no sense within the context of the
>>> CPU-visible MMIO space that the root node describes.
>>>
>>> In this case, it's typical to put all the clock nodes into e.g. a
>>> /clocks node, since that node can introduce a separate numbering-space
>>> for clocks. For example, I'd expect something like:
>>>
>>>         clocks {
>>>                 #address-cells = <1>;
>>>                 #size-cells = <0>;
>>>
>>>                 osc32k: clock at 0 {
>>>                         compatible = "fixed-clock";
>>>                         reg = <0>;
> ...
>>>                 osc26m: clock at 1 {
>>>                         compatible = "fixed-clock";
>>>                         reg = <1>;
> ...
>
>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>> any clock register. It only provides the clock rate those child clock node.
>
> Inside the clocks node, the reg property is just a dummy value.

Is a dummy value helpful? I don't think so.

Regards
Haojian

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

* [PATCH v7 09/11] ARM: hi3xxx: add hotplug support
  2013-08-20  2:31 ` [PATCH v7 09/11] ARM: hi3xxx: add hotplug support Haojian Zhuang
@ 2013-08-28  2:21   ` Olof Johansson
  2013-08-28 11:45     ` zhangfei gao
  0 siblings, 1 reply; 40+ messages in thread
From: Olof Johansson @ 2013-08-28  2:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Some comments below.

On Tue, Aug 20, 2013 at 10:31:11AM +0800, Haojian Zhuang wrote:
> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> 
> Enable hotplug support on hi3xxx platform
> 
> How to test:
> cat proc/interrupts
> echo 0 > /sys/devices/system/cpu/cpuX/online
> cat proc/interrupts
> echo 1 > /sys/devices/system/cpu/cpuX/online
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Tested-by: Zhang Mingjun <zhang.mingjun@linaro.org>
> ---
>  arch/arm/mach-hi3xxx/Makefile  |   1 +
>  arch/arm/mach-hi3xxx/core.h    |   5 ++
>  arch/arm/mach-hi3xxx/hi3xxx.c  |   1 +
>  arch/arm/mach-hi3xxx/hotplug.c | 154 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-hi3xxx/platsmp.c |   5 ++
>  5 files changed, 166 insertions(+)
>  create mode 100644 arch/arm/mach-hi3xxx/hotplug.c
> 
> diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
> index 0917f1c..c597cbf 100644
> --- a/arch/arm/mach-hi3xxx/Makefile
> +++ b/arch/arm/mach-hi3xxx/Makefile
> @@ -4,3 +4,4 @@
>  
>  obj-y	+= hi3xxx.o system.o
>  obj-$(CONFIG_SMP)		+= platsmp.o
> +obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
> diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h
> index 2cfd643..c2ce35d 100644
> --- a/arch/arm/mach-hi3xxx/core.h
> +++ b/arch/arm/mach-hi3xxx/core.h
> @@ -11,4 +11,9 @@ extern void hs_map_io(void);
>  extern void hs_restart(enum reboot_mode, const char *cmd);
>  extern struct smp_operations hs_smp_ops;
>  
> +extern void __init hs_hotplug_init(void);
> +extern void hs_cpu_die(unsigned int cpu);
> +extern int hs_cpu_kill(unsigned int cpu);
> +extern void hs_set_cpu(int cpu, bool enable);
> +
>  #endif
> diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c
> index 567a0d5..01ac68b 100644
> --- a/arch/arm/mach-hi3xxx/hi3xxx.c
> +++ b/arch/arm/mach-hi3xxx/hi3xxx.c
> @@ -24,6 +24,7 @@
>  static void __init hi3xxx_timer_init(void)
>  {
>  	hs_map_io();
> +	hs_hotplug_init();
>  	of_clk_init(NULL);
>  	clocksource_of_init();
>  }
> diff --git a/arch/arm/mach-hi3xxx/hotplug.c b/arch/arm/mach-hi3xxx/hotplug.c
> new file mode 100644
> index 0000000..c67f8a2
> --- /dev/null
> +++ b/arch/arm/mach-hi3xxx/hotplug.c
> @@ -0,0 +1,154 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +#include <linux/cpu.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <asm/cacheflush.h>
> +#include <asm/smp_plat.h>
> +#include "core.h"
> +
> +enum {
> +	HI3620_CTRL,
> +	HI3716_CTRL,
> +};
> +
> +static void __iomem *ctrl_base;
> +static int id;
> +
> +void hs_set_cpu(int cpu, bool enable)
> +{
> +	u32 val = 0;
> +
> +	if (!ctrl_base)
> +		return;
> +
> +	if (id == HI3620_CTRL) {
> +		if (enable) {
> +			/* MTCMOS */
> +			writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xD0);

0xD0 should be 0xd0 (we usually don't use all-caps hex)

> +			writel_relaxed((0x1011 << cpu), ctrl_base + 0x414);
> +			writel_relaxed((0x401011 << cpu), ctrl_base + 0x410);

You can skip the outermost parens here.

These numbers look pretty magic. Can you make it slightly easier for someone
reading the code to figure out what's going on?

> +			/* ISO disable */
> +			writel((0x01 << (cpu + 3)), ctrl_base + 0x0C4);

0x0C4 should be 0xc4. Also, it's clearer if you use 0x8 << cpu  instead.


> +
> +			/* WFI Mask */
> +			val = readl(ctrl_base + 0x200);
> +			val &= ~(0x1 << (cpu+28));

Same here, don't use cpu + 28, modify the constant instead. Same for the other
occurrances below.

> +			writel(val, ctrl_base + 0x200);
> +
> +			/* Enable core */
> +			writel_relaxed((0x01 << cpu), ctrl_base + 0xf4);
> +			/* Unreset */
> +			writel_relaxed((0x401011 << cpu), ctrl_base + 0x414);
> +		} else {
> +			/* iso enable */
> +			writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xC0);
> +
> +			/* MTCMOS */
> +			writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xD4);
> +
> +			/* wfi mask */
> +			val = readl_relaxed(ctrl_base + 0x200);
> +			val |= (0x1 << (cpu+28));
> +			writel_relaxed(val, ctrl_base + 0x200);
> +
> +			/* disable core*/
> +			writel_relaxed((0x01 << cpu), ctrl_base + 0xf8);
> +			/* Reset */
> +			writel_relaxed((0x401011 << cpu), ctrl_base + 0x410);
> +		}
> +	} else if (id == HI3716_CTRL) {
> +		if (enable) {
> +			/* power on cpu1 */
> +			val = readl_relaxed(ctrl_base + 0x1000);
> +			val &=  ~(0x1 << 8);
> +			val |= (0x1 << 7);
> +			val &= ~(0x1 << 3);
> +			writel_relaxed(val, ctrl_base + 0x1000);
> +
> +			/* unreset */
> +			val = readl_relaxed(ctrl_base + 0x50);
> +			val &= ~(0x1 << 17);
> +			writel_relaxed(val, ctrl_base + 0x50);
> +		} else {
> +			/* power down cpu1 */
> +			val = readl_relaxed(ctrl_base + 0x1000);
> +			val &=  ~(0x1 << 8);
> +			val |= (0x1 << 7);
> +			val |= (0x1 << 3);
> +			writel_relaxed(val, ctrl_base + 0x1000);
> +
> +			/* reset */
> +			val = readl_relaxed(ctrl_base + 0x50);
> +			val |= (0x1 << 17);
> +			writel_relaxed(val, ctrl_base + 0x50);
> +		}
> +	}

So the function above really shares no code path between the different SoCs.
Instead of doing it all in nested if/else bodies, please split it up in two
functions, one for each SoC. You can still keep the enable/disable paths under
if/else though.

> +}
> +
> +void __init hs_hotplug_init(void)
> +{
> +	struct device_node *node;
> +
> +	node = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
> +	if (node) {
> +		ctrl_base = of_iomap(node, 0);
> +		id = HI3716_CTRL;

You should use something more specific than just hisilicon,cpuctrl here, if
it's truly tied to the SoC (i.e. this ID here).

hisilicon,hi3716-cpuctrl seems appropriate. Note that the bindings need
to be revised for this.

> +		return;
> +	}
> +	node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
> +	if (node) {
> +		ctrl_base = of_iomap(node, 0);
> +		id = HI3620_CTRL;

Same here.

> +		return;
> +	}
> +}
> +
> +static inline void cpu_enter_lowpower(void)
> +{
> +	unsigned int v;
> +
> +	flush_cache_all();
> +	asm volatile(
> +	/*
> +	 * Turn off coherency and L1 D-cache
> +	 */

Move the comment up above the asm volatile

> +	"	mrc	p15, 0, %0, c1, c0, 1\n"
> +	"	bic	%0, %0, #0x40\n"
> +	"	mcr	p15, 0, %0, c1, c0, 1\n"
> +	"	mrc	p15, 0, %0, c1, c0, 0\n"
> +	"	bic	%0, %0, #0x04\n"
> +	"	mcr	p15, 0, %0, c1, c0, 0\n"
> +	  : "=&r" (v)
> +	  : "r" (0)
> +	  : "cc");
> +}
> +
> +void hs_cpu_die(unsigned int cpu)
> +{
> +	cpu_enter_lowpower();
> +	hs_set_cpu_jump(cpu, phys_to_virt(0));
> +	cpu_do_idle();
> +
> +	/* We should have never returned from idle */
> +	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
> +}
> +
> +int hs_cpu_kill(unsigned int cpu)
> +{
> +	unsigned long timeout = jiffies + msecs_to_jiffies(50);
> +
> +	while (hs_get_cpu_jump(cpu))
> +		if (time_after(jiffies, timeout))
> +			return 0;
> +	hs_set_cpu(cpu, false);
> +	return 1;
> +}
> diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c
> index a76a3cc..6a08630 100644
> --- a/arch/arm/mach-hi3xxx/platsmp.c
> +++ b/arch/arm/mach-hi3xxx/platsmp.c
> @@ -32,6 +32,7 @@ static void __init hs_smp_prepare_cpus(unsigned int max_cpus)
>  
>  static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
>  {
> +	hs_set_cpu(cpu, true);
>  	hs_set_cpu_jump(cpu, secondary_startup);
>  	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
>  	return 0;
> @@ -40,4 +41,8 @@ static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
>  struct smp_operations hs_smp_ops __initdata = {
>  	.smp_prepare_cpus	= hs_smp_prepare_cpus,
>  	.smp_boot_secondary	= hs_boot_secondary,
> +#ifdef CONFIG_HOTPLUG_CPU
> +	.cpu_die		= hs_cpu_die,
> +	.cpu_kill		= hs_cpu_kill,
> +#endif
>  };
> -- 
> 1.8.1.2
> 

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

* [PATCH v7 09/11] ARM: hi3xxx: add hotplug support
  2013-08-28  2:21   ` Olof Johansson
@ 2013-08-28 11:45     ` zhangfei gao
  0 siblings, 0 replies; 40+ messages in thread
From: zhangfei gao @ 2013-08-28 11:45 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Olof

Thanks for the good suggestion.
All the comments make sense, will update in new version.

>> +void hs_set_cpu(int cpu, bool enable)
>> +{
>> +     u32 val = 0;
>> +
>> +     if (!ctrl_base)
>> +             return;
>> +
>> +     if (id == HI3620_CTRL) {
>> +             if (enable) {
>> +                     /* MTCMOS */
>> +                     writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xD0);
>
> 0xD0 should be 0xd0 (we usually don't use all-caps hex)
>
>> +                     writel_relaxed((0x1011 << cpu), ctrl_base + 0x414);
>> +                     writel_relaxed((0x401011 << cpu), ctrl_base + 0x410);
>
> You can skip the outermost parens here.
>
> These numbers look pretty magic. Can you make it slightly easier for someone
> reading the code to figure out what's going on?
>
>> +                     /* ISO disable */
>> +                     writel((0x01 << (cpu + 3)), ctrl_base + 0x0C4);
>
> 0x0C4 should be 0xc4. Also, it's clearer if you use 0x8 << cpu  instead.
>
>
>> +
>> +                     /* WFI Mask */
>> +                     val = readl(ctrl_base + 0x200);
>> +                     val &= ~(0x1 << (cpu+28));
>
> Same here, don't use cpu + 28, modify the constant instead. Same for the other
> occurrances below.
>
>> +                     writel(val, ctrl_base + 0x200);
>> +
>> +                     /* Enable core */
>> +                     writel_relaxed((0x01 << cpu), ctrl_base + 0xf4);
>> +                     /* Unreset */
>> +                     writel_relaxed((0x401011 << cpu), ctrl_base + 0x414);
>> +             } else {
>> +                     /* iso enable */
>> +                     writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xC0);
>> +
>> +                     /* MTCMOS */
>> +                     writel_relaxed((0x01 << (cpu + 3)), ctrl_base + 0xD4);
>> +
>> +                     /* wfi mask */
>> +                     val = readl_relaxed(ctrl_base + 0x200);
>> +                     val |= (0x1 << (cpu+28));
>> +                     writel_relaxed(val, ctrl_base + 0x200);
>> +
>> +                     /* disable core*/
>> +                     writel_relaxed((0x01 << cpu), ctrl_base + 0xf8);
>> +                     /* Reset */
>> +                     writel_relaxed((0x401011 << cpu), ctrl_base + 0x410);
>> +             }
>> +     } else if (id == HI3716_CTRL) {
>> +             if (enable) {
>> +                     /* power on cpu1 */
>> +                     val = readl_relaxed(ctrl_base + 0x1000);
>> +                     val &=  ~(0x1 << 8);
>> +                     val |= (0x1 << 7);
>> +                     val &= ~(0x1 << 3);
>> +                     writel_relaxed(val, ctrl_base + 0x1000);
>> +
>> +                     /* unreset */
>> +                     val = readl_relaxed(ctrl_base + 0x50);
>> +                     val &= ~(0x1 << 17);
>> +                     writel_relaxed(val, ctrl_base + 0x50);
>> +             } else {
>> +                     /* power down cpu1 */
>> +                     val = readl_relaxed(ctrl_base + 0x1000);
>> +                     val &=  ~(0x1 << 8);
>> +                     val |= (0x1 << 7);
>> +                     val |= (0x1 << 3);
>> +                     writel_relaxed(val, ctrl_base + 0x1000);
>> +
>> +                     /* reset */
>> +                     val = readl_relaxed(ctrl_base + 0x50);
>> +                     val |= (0x1 << 17);
>> +                     writel_relaxed(val, ctrl_base + 0x50);
>> +             }
>> +     }
>
> So the function above really shares no code path between the different SoCs.
> Instead of doing it all in nested if/else bodies, please split it up in two
> functions, one for each SoC. You can still keep the enable/disable paths under
> if/else though.
>
>> +}
>> +
>> +void __init hs_hotplug_init(void)
>> +{
>> +     struct device_node *node;
>> +
>> +     node = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
>> +     if (node) {
>> +             ctrl_base = of_iomap(node, 0);
>> +             id = HI3716_CTRL;
>
> You should use something more specific than just hisilicon,cpuctrl here, if
> it's truly tied to the SoC (i.e. this ID here).
>
> hisilicon,hi3716-cpuctrl seems appropriate. Note that the bindings need
> to be revised for this.
>
>> +             return;
>> +     }
>> +     node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
>> +     if (node) {
>> +             ctrl_base = of_iomap(node, 0);
>> +             id = HI3620_CTRL;
>
> Same here.

Will use "hisilicon,hi3716-cpuctrl", which is specific to hi3716,
and we use this as flag to indicate hi3716 soc

Will use "hisilicon,sysctrl", however, it exists on both hi3620 and hi3716.
So use as a flag of hi3620 after check hi3716.

>
>> +             return;
>> +     }
>> +}
>> +
>> +static inline void cpu_enter_lowpower(void)
>> +{
>> +     unsigned int v;
>> +
>> +     flush_cache_all();
>> +     asm volatile(
>> +     /*
>> +      * Turn off coherency and L1 D-cache
>> +      */
>
> Move the comment up above the asm volatile
>

Thanks

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

* [PATCH v7 08/11] ARM: hi3xxx: add smp support
  2013-08-28  2:12   ` Olof Johansson
@ 2013-08-28 11:53     ` zhangfei gao
  2013-08-28 17:19       ` Olof Johansson
  0 siblings, 1 reply; 40+ messages in thread
From: zhangfei gao @ 2013-08-28 11:53 UTC (permalink / raw)
  To: linux-arm-kernel

Thanks Olof, will update with your comments.

>>
>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> index 3be60c8..4cc5c57 100644
>> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> @@ -8,3 +8,50 @@ Required root node properties:
>>  Hi4511 Board
>>  Required root node properties:
>>       - compatible = "hisilicon,hi3620-hi4511";
>> +
>> +
>> +Hisilicon sctrl resiter
>
> Resiter seems like odd naming here.
>
>> +
>> +Required properties:
>> +- compatible : "hisilicon,sctrl"
>> +- reg : Address and size of sysctrl.
>
> sysctrl or sctrl? sysctrl isn't really too long, might as well use that.
>
>> +
>> +Optional properties:
>> +- smp_reg : offset in sysctrl for notifying slave cpu booting
>> +             cpu 1, reg;
>> +             cpu 2, reg + 0x4;
>> +             cpu 3, reg + 0x8;
>> +             If reg value is not zero, cpun exit wfi and go
>> +- resume_reg : offset in sysctrl for notifying cpu0 when resume
>> +- reset_reg : offset in sysctrl for system reset
>
> Underscores are usually not used in properties, you use dashes instead.
>
> Anyway, I suggest defining those as the different cells in a regular 'reg'
> property instead.

Will update with

Required properties:
- compatible : "hisilicon,sysctrl"
- reg : Register address and size

Optional properties:
- smp-off : offset in sysctrl for notifying slave cpu booting
                cpu 1, reg;
                cpu 2, reg + 0x4;
                cpu 3, reg + 0x8;
                If reg value is not zero, cpun exit wfi and go
- resume-off : offset in sysctrl for notifying cpu0 when resume
- reboot-off : offset in sysctrl for system reboot

>
>> +
>> +Example:
>> +     hi3716:
>> +     sctrl at f8000000 {
>
> Labels are usually not done on a separate line before.
>
> Common node names would be more clear-text than this. Maybe "system-controller"
> in this case.

will update with
   sysctrl: system-controller at f8000000 {
                compatible = "hisilicon,sysctrl";
                reg = <0xf8000000 0x1000>;
                smp-off = <0xc0>;
                reboot-off = <0x4>;
        };


>
>
>> +             compatible = "hisilicon,sctrl";
>> +             reg = <0xf8000000 0x1000>;
>> +             smp_reg = <0xc0>;
>> +             reboot_reg = <0x4>;
>> +     };
>> +
>> +     hi3620:
>> +     sctrl at fc802000 {
>> +             compatible = "hisilicon,sctrl";
>> +             reg = <0xfc802000 0x1000>;
>> +             smp_reg = <0x31c>;
>> +             resume_reg = <0x308>;
>> +             reboot_reg = <0x4>;
>> +     };
>> +
>> +Hi3716 cpuctrl register
>> +Required properties:
>> +- compatible : "hisilicon,cpuctrl"
>> +- reg : Address and size of cpuctrl.
>> +
>> +Hi3716 specific cpuctrl register, control hotplug info etc.
>
> Controlling hotplug _info_? Seems like odd wording here.
Update to
Hi3716 cpuctrl register
Hi3716 specific cpuctrl register, control power & clock of cpu and module.

>
>> +Example:
>> +     hi3716:
>> +     cpuctrl at f8a22000 {
>> +             compatible = "hisilicon,cpuctrl";
>> +             reg = <0xf8a22000 0x2000>;
>> +     };
>> diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
>> index 39fa37f..ee81192 100644
>> --- a/arch/arm/boot/dts/hi3620.dtsi
>> +++ b/arch/arm/boot/dts/hi3620.dtsi
>> @@ -32,6 +32,24 @@
>>                       reg = <0x0>;
>>                       next-level-cache = <&L2>;
>>               };
>> +             cpu1: cpu at 1 {
>
> Do you need labels here? I don't think these are referred to as phandles
> anywhere?
>
>> +                     compatible = "arm,cortex-a9";
>> +                     device_type = "cpu";
>> +                     reg = <1>;
>> +                     next-level-cache = <&L2>;
>> +             };
>> +             cpu2: cpu at 2 {
>> +                     compatible = "arm,cortex-a9";
>> +                     device_type = "cpu";
>> +                     reg = <2>;
>> +                     next-level-cache = <&L2>;
>> +             };
>> +             cpu3: cpu at 3 {
>> +                     compatible = "arm,cortex-a9";
>> +                     device_type = "cpu";
>> +                     reg = <3>;
>> +                     next-level-cache = <&L2>;
>> +             };
>>       };
>>
>>       osc32k: osc32k {
>> @@ -130,7 +148,9 @@
>>                       reg = <0xfc802000 0x1000>;
>>                       #address-cells = <1>;
>>                       #size-cells = <0>;
>> -
>> +                     smp_reg = <0x31c>;
>> +                     resume_reg = <0x308>;
>> +                     reboot_reg = <0x4>;
>>
>>                       timer0_mux: timer0_mux {
>>                               compatible = "hisilicon,clk-mux";
>> @@ -1242,6 +1262,12 @@
>>                       status = "disabled";
>>               };
>>
>> +             timer5: timer at fc000600 {
>> +                     compatible = "arm,cortex-a9-twd-timer";
>> +                     reg = <0xfc000600 0x20>;
>> +                     interrupts = <1 13 0xf01>;
>> +             };
>> +
>>               uart0: uart at fcb00000 {
>>                       compatible = "arm,pl011", "arm,primecell";
>>                       reg = <0xfcb00000 0x1000>;
>> diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
>> index 7e67564..c9fd329 100644
>> --- a/arch/arm/boot/dts/hi4511.dts
>> +++ b/arch/arm/boot/dts/hi4511.dts
>> @@ -15,7 +15,7 @@
>>       compatible = "hisilicon,hi3620-hi4511";
>>
>>       chosen {
>> -             bootargs = "console=ttyAMA0,115200 root=/dev/ram0 earlyprintk";
>> +             bootargs = "console=ttyAMA0,115200 root=/dev/ram0 nr_cpus=4 earlyprintk";
>
> nr_cpus should not be needed on the command line.
>
>>       };
>>
>>       memory {
>> diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig
>> index 68bd26c..d2e7d57 100644
>> --- a/arch/arm/mach-hi3xxx/Kconfig
>> +++ b/arch/arm/mach-hi3xxx/Kconfig
>> @@ -6,6 +6,8 @@ config ARCH_HI3xxx
>>       select CACHE_L2X0
>>       select CLKSRC_OF
>>       select GENERIC_CLOCKEVENTS
>> +     select HAVE_ARM_SCU
>> +     select HAVE_SMP
>>       select PINCTRL
>>       select PINCTRL_SINGLE
>>       help
>> diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile
>> index d68ebb3..0917f1c 100644
>> --- a/arch/arm/mach-hi3xxx/Makefile
>> +++ b/arch/arm/mach-hi3xxx/Makefile
>> @@ -2,4 +2,5 @@
>>  # Makefile for Hisilicon Hi36xx/Hi37xx processors line
>>  #
>>
>> -obj-y        += hi3xxx.o
>> +obj-y        += hi3xxx.o system.o
>> +obj-$(CONFIG_SMP)            += platsmp.o
>> diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h
>> new file mode 100644
>> index 0000000..2cfd643
>> --- /dev/null
>> +++ b/arch/arm/mach-hi3xxx/core.h
>> @@ -0,0 +1,14 @@
>> +#ifndef __HISILICON_CORE_H
>> +#define __HISILICON_CORE_H
>> +
>> +#include <linux/init.h>
>
> I don't think you need linux/init.h here?
>
Thanks, definitely true.

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

* Re: [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-28  2:17             ` Haojian Zhuang
@ 2013-08-28 14:20               ` Stephen Warren
  -1 siblings, 0 replies; 40+ messages in thread
From: Stephen Warren @ 2013-08-28 14:20 UTC (permalink / raw)
  To: Haojian Zhuang
  Cc: Mark Rutland, devicetree, Kevin Hilman, Russell King - ARM Linux,
	Ian Campbell, Arnd Bergmann, Linus Walleij, Rob Herring,
	Pawel Moll, John Stultz, grant.likely, Kumar Gala,
	Olof Johansson, Mike Turquette, tglx, linux-arm-kernel

On 08/27/2013 08:17 PM, Haojian Zhuang wrote:
> On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>>> [+ DT maintainers]
>>>>>
>>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>>
>>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>>
>>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>>> ...
>>
>>>>>> +    osc32k: osc32k {
>>>>>> +            compatible = "fixed-clock";
>>>>>> +            #clock-cells = <0>;
>>>>>> +            clock-frequency = <32768>;
>>>>>> +            clock-output-names = "osc32khz";
>>>>>> +    };
>>>>>
>>>>> ...seems many of the recent users of clocks have grouped them into a
>>>>> clocks {} grouping on a "simple-bus".
>>>>>
>>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>>> should be grouped on a simple bus?
>>>>
>>>> I would expect all the clock node names to be just "clock", since the
>>>> node names should describe the type of device not their identity (i.e.
>>>> clock name).
>>>>
>>>> In turn, this means that each clock node name needs to use a unit
>>>> address ("@nnn") to make them unique. In turn, this means they must have
>>>> a reg property since the unit address must match the first entry in the
>>>> reg property.
>>>
>>> No, it's really bad on using a unit address. The register always contains
>>> multiple mux or gate or divider. It would cause duplicated unit address.
>>
>> There shouldn't be multiple nodes with identical reg values; if that's
>> happening, then it seems like the mapping of nodes to HW is incorrect.
>>
>> Each HW block should have 1 DT node. That way, the reg values won't collide.
> 
> At here, I emphasize each clock node is one clock node. They are organized in
> tree. The same register integrates multiple clock gate/clock mux/clock divider.
> If each clock node is depend on reg, maybe it's not easy to read and the clock
> driver will be more complex.

If there's a single HW block (or single register) that provides multiple
clocks, there should be a single DT node and a single device that
provides multiple clocks.

>>> I tried to use index number also. And it's also bad to append new clock nodes.
>>> So I use the label name instead.
>>>
>>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>>> they would need an arbitrary reg value rather than a real one. So it
>>>> doesn't make sense to place them directly under the root DT node, since
>>>> their reg values would make no sense within the context of the
>>>> CPU-visible MMIO space that the root node describes.
>>>>
>>>> In this case, it's typical to put all the clock nodes into e.g. a
>>>> /clocks node, since that node can introduce a separate numbering-space
>>>> for clocks. For example, I'd expect something like:
>>>>
>>>>         clocks {
>>>>                 #address-cells = <1>;
>>>>                 #size-cells = <0>;
>>>>
>>>>                 osc32k: clock@0 {
>>>>                         compatible = "fixed-clock";
>>>>                         reg = <0>;
>> ...
>>>>                 osc26m: clock@1 {
>>>>                         compatible = "fixed-clock";
>>>>                         reg = <1>;
>> ...
>>
>>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>>> any clock register. It only provides the clock rate those child clock node.
>>
>> Inside the clocks node, the reg property is just a dummy value.
> 
> Is a dummy value helpful? I don't think so.

It's not a matter of whether it's helpful; it's just how DT works.

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
@ 2013-08-28 14:20               ` Stephen Warren
  0 siblings, 0 replies; 40+ messages in thread
From: Stephen Warren @ 2013-08-28 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2013 08:17 PM, Haojian Zhuang wrote:
> On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>>> [+ DT maintainers]
>>>>>
>>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>>
>>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>>
>>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>>> ...
>>
>>>>>> +    osc32k: osc32k {
>>>>>> +            compatible = "fixed-clock";
>>>>>> +            #clock-cells = <0>;
>>>>>> +            clock-frequency = <32768>;
>>>>>> +            clock-output-names = "osc32khz";
>>>>>> +    };
>>>>>
>>>>> ...seems many of the recent users of clocks have grouped them into a
>>>>> clocks {} grouping on a "simple-bus".
>>>>>
>>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>>> should be grouped on a simple bus?
>>>>
>>>> I would expect all the clock node names to be just "clock", since the
>>>> node names should describe the type of device not their identity (i.e.
>>>> clock name).
>>>>
>>>> In turn, this means that each clock node name needs to use a unit
>>>> address ("@nnn") to make them unique. In turn, this means they must have
>>>> a reg property since the unit address must match the first entry in the
>>>> reg property.
>>>
>>> No, it's really bad on using a unit address. The register always contains
>>> multiple mux or gate or divider. It would cause duplicated unit address.
>>
>> There shouldn't be multiple nodes with identical reg values; if that's
>> happening, then it seems like the mapping of nodes to HW is incorrect.
>>
>> Each HW block should have 1 DT node. That way, the reg values won't collide.
> 
> At here, I emphasize each clock node is one clock node. They are organized in
> tree. The same register integrates multiple clock gate/clock mux/clock divider.
> If each clock node is depend on reg, maybe it's not easy to read and the clock
> driver will be more complex.

If there's a single HW block (or single register) that provides multiple
clocks, there should be a single DT node and a single device that
provides multiple clocks.

>>> I tried to use index number also. And it's also bad to append new clock nodes.
>>> So I use the label name instead.
>>>
>>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>>> they would need an arbitrary reg value rather than a real one. So it
>>>> doesn't make sense to place them directly under the root DT node, since
>>>> their reg values would make no sense within the context of the
>>>> CPU-visible MMIO space that the root node describes.
>>>>
>>>> In this case, it's typical to put all the clock nodes into e.g. a
>>>> /clocks node, since that node can introduce a separate numbering-space
>>>> for clocks. For example, I'd expect something like:
>>>>
>>>>         clocks {
>>>>                 #address-cells = <1>;
>>>>                 #size-cells = <0>;
>>>>
>>>>                 osc32k: clock at 0 {
>>>>                         compatible = "fixed-clock";
>>>>                         reg = <0>;
>> ...
>>>>                 osc26m: clock at 1 {
>>>>                         compatible = "fixed-clock";
>>>>                         reg = <1>;
>> ...
>>
>>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>>> any clock register. It only provides the clock rate those child clock node.
>>
>> Inside the clocks node, the reg property is just a dummy value.
> 
> Is a dummy value helpful? I don't think so.

It's not a matter of whether it's helpful; it's just how DT works.

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

* Re: [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-28 14:20               ` Stephen Warren
@ 2013-08-28 15:15                 ` Haojian Zhuang
  -1 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-28 15:15 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Mark Rutland, devicetree, Kevin Hilman, Russell King - ARM Linux,
	Ian Campbell, Arnd Bergmann, Linus Walleij, Rob Herring,
	Grant Likely, Pawel Moll, John Stultz, Kumar Gala,
	Olof Johansson, Mike Turquette, tglx, linux-arm-kernel

On 28 August 2013 22:20, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2013 08:17 PM, Haojian Zhuang wrote:
>> On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>>>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>>>> [+ DT maintainers]
>>>>>>
>>>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>>>
>>>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>>>
>>>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>>>> ...
>>>
>>>>>>> +    osc32k: osc32k {
>>>>>>> +            compatible = "fixed-clock";
>>>>>>> +            #clock-cells = <0>;
>>>>>>> +            clock-frequency = <32768>;
>>>>>>> +            clock-output-names = "osc32khz";
>>>>>>> +    };
>>>>>>
>>>>>> ...seems many of the recent users of clocks have grouped them into a
>>>>>> clocks {} grouping on a "simple-bus".
>>>>>>
>>>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>>>> should be grouped on a simple bus?
>>>>>
>>>>> I would expect all the clock node names to be just "clock", since the
>>>>> node names should describe the type of device not their identity (i.e.
>>>>> clock name).
>>>>>
>>>>> In turn, this means that each clock node name needs to use a unit
>>>>> address ("@nnn") to make them unique. In turn, this means they must have
>>>>> a reg property since the unit address must match the first entry in the
>>>>> reg property.
>>>>
>>>> No, it's really bad on using a unit address. The register always contains
>>>> multiple mux or gate or divider. It would cause duplicated unit address.
>>>
>>> There shouldn't be multiple nodes with identical reg values; if that's
>>> happening, then it seems like the mapping of nodes to HW is incorrect.
>>>
>>> Each HW block should have 1 DT node. That way, the reg values won't collide.
>>
>> At here, I emphasize each clock node is one clock node. They are organized in
>> tree. The same register integrates multiple clock gate/clock mux/clock divider.
>> If each clock node is depend on reg, maybe it's not easy to read and the clock
>> driver will be more complex.
>
> If there's a single HW block (or single register) that provides multiple
> clocks, there should be a single DT node and a single device that
> provides multiple clocks.
>
>>>> I tried to use index number also. And it's also bad to append new clock nodes.
>>>> So I use the label name instead.
>>>>
>>>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>>>> they would need an arbitrary reg value rather than a real one. So it
>>>>> doesn't make sense to place them directly under the root DT node, since
>>>>> their reg values would make no sense within the context of the
>>>>> CPU-visible MMIO space that the root node describes.
>>>>>
>>>>> In this case, it's typical to put all the clock nodes into e.g. a
>>>>> /clocks node, since that node can introduce a separate numbering-space
>>>>> for clocks. For example, I'd expect something like:
>>>>>
>>>>>         clocks {
>>>>>                 #address-cells = <1>;
>>>>>                 #size-cells = <0>;
>>>>>
>>>>>                 osc32k: clock@0 {
>>>>>                         compatible = "fixed-clock";
>>>>>                         reg = <0>;
>>> ...
>>>>>                 osc26m: clock@1 {
>>>>>                         compatible = "fixed-clock";
>>>>>                         reg = <1>;
>>> ...
>>>
>>>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>>>> any clock register. It only provides the clock rate those child clock node.
>>>
>>> Inside the clocks node, the reg property is just a dummy value.
>>
>> Is a dummy value helpful? I don't think so.
>
> It's not a matter of whether it's helpful; it's just how DT works.
>
>

I copied some texts from device tree spec (Page 87. file name:
Power_ePAPER_APPROVED_v1.0.pdf).

    Node and property definitions
    Device tree nodes are defined with a node name and unit address
with braces marking the start and
    end of the node definition. They may be preceded by a label.

    [label:] node-name[@unit-address] {
        [properties definitions]
        [child nodes]
    }

We can see that "unit-address" is optional.

I also copied some texts from $LINUX/Documentation/devicetree/usage-model.txt

     Structurally, the DT is a tree, or acyclic graph with named nodes, and
     nodes may have an arbitrary number of named properties encapsulating
     arbitrary data.  A mechanism also exists to create arbitrary
     links from one node to another outside of the natural tree structure.

     Conceptually, a common set of usage conventions, called 'bindings',
     is defined for how data should appear in the tree to describe typical
     hardware characteristics including data busses, interrupt lines, GPIO
     connections, and peripheral devices.

I define each clock as one node although multiple clocks share one
register, because it could
share clock driver as much as possible. Whether they're sharing one
register or not, they
can be distinguished by clock types. I think that encapsulating them
into one single
node could only make clock driver complex. Sometimes one clock is
using a single register,
and sometime some clocks are sharing a single register. If the clock
driver wants to support
both, it needs to add more logic to check. And I don't think that
abstracting clock breaks
any law in DT.

Regards
Haojian

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
@ 2013-08-28 15:15                 ` Haojian Zhuang
  0 siblings, 0 replies; 40+ messages in thread
From: Haojian Zhuang @ 2013-08-28 15:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 28 August 2013 22:20, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2013 08:17 PM, Haojian Zhuang wrote:
>> On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>>>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>>>> [+ DT maintainers]
>>>>>>
>>>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>>>
>>>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>>>
>>>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>>>> ...
>>>
>>>>>>> +    osc32k: osc32k {
>>>>>>> +            compatible = "fixed-clock";
>>>>>>> +            #clock-cells = <0>;
>>>>>>> +            clock-frequency = <32768>;
>>>>>>> +            clock-output-names = "osc32khz";
>>>>>>> +    };
>>>>>>
>>>>>> ...seems many of the recent users of clocks have grouped them into a
>>>>>> clocks {} grouping on a "simple-bus".
>>>>>>
>>>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>>>> should be grouped on a simple bus?
>>>>>
>>>>> I would expect all the clock node names to be just "clock", since the
>>>>> node names should describe the type of device not their identity (i.e.
>>>>> clock name).
>>>>>
>>>>> In turn, this means that each clock node name needs to use a unit
>>>>> address ("@nnn") to make them unique. In turn, this means they must have
>>>>> a reg property since the unit address must match the first entry in the
>>>>> reg property.
>>>>
>>>> No, it's really bad on using a unit address. The register always contains
>>>> multiple mux or gate or divider. It would cause duplicated unit address.
>>>
>>> There shouldn't be multiple nodes with identical reg values; if that's
>>> happening, then it seems like the mapping of nodes to HW is incorrect.
>>>
>>> Each HW block should have 1 DT node. That way, the reg values won't collide.
>>
>> At here, I emphasize each clock node is one clock node. They are organized in
>> tree. The same register integrates multiple clock gate/clock mux/clock divider.
>> If each clock node is depend on reg, maybe it's not easy to read and the clock
>> driver will be more complex.
>
> If there's a single HW block (or single register) that provides multiple
> clocks, there should be a single DT node and a single device that
> provides multiple clocks.
>
>>>> I tried to use index number also. And it's also bad to append new clock nodes.
>>>> So I use the label name instead.
>>>>
>>>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>>>> they would need an arbitrary reg value rather than a real one. So it
>>>>> doesn't make sense to place them directly under the root DT node, since
>>>>> their reg values would make no sense within the context of the
>>>>> CPU-visible MMIO space that the root node describes.
>>>>>
>>>>> In this case, it's typical to put all the clock nodes into e.g. a
>>>>> /clocks node, since that node can introduce a separate numbering-space
>>>>> for clocks. For example, I'd expect something like:
>>>>>
>>>>>         clocks {
>>>>>                 #address-cells = <1>;
>>>>>                 #size-cells = <0>;
>>>>>
>>>>>                 osc32k: clock at 0 {
>>>>>                         compatible = "fixed-clock";
>>>>>                         reg = <0>;
>>> ...
>>>>>                 osc26m: clock at 1 {
>>>>>                         compatible = "fixed-clock";
>>>>>                         reg = <1>;
>>> ...
>>>
>>>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>>>> any clock register. It only provides the clock rate those child clock node.
>>>
>>> Inside the clocks node, the reg property is just a dummy value.
>>
>> Is a dummy value helpful? I don't think so.
>
> It's not a matter of whether it's helpful; it's just how DT works.
>
>

I copied some texts from device tree spec (Page 87. file name:
Power_ePAPER_APPROVED_v1.0.pdf).

    Node and property definitions
    Device tree nodes are defined with a node name and unit address
with braces marking the start and
    end of the node definition. They may be preceded by a label.

    [label:] node-name[@unit-address] {
        [properties definitions]
        [child nodes]
    }

We can see that "unit-address" is optional.

I also copied some texts from $LINUX/Documentation/devicetree/usage-model.txt

     Structurally, the DT is a tree, or acyclic graph with named nodes, and
     nodes may have an arbitrary number of named properties encapsulating
     arbitrary data.  A mechanism also exists to create arbitrary
     links from one node to another outside of the natural tree structure.

     Conceptually, a common set of usage conventions, called 'bindings',
     is defined for how data should appear in the tree to describe typical
     hardware characteristics including data busses, interrupt lines, GPIO
     connections, and peripheral devices.

I define each clock as one node although multiple clocks share one
register, because it could
share clock driver as much as possible. Whether they're sharing one
register or not, they
can be distinguished by clock types. I think that encapsulating them
into one single
node could only make clock driver complex. Sometimes one clock is
using a single register,
and sometime some clocks are sharing a single register. If the clock
driver wants to support
both, it needs to add more logic to check. And I don't think that
abstracting clock breaks
any law in DT.

Regards
Haojian

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

* Re: [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
  2013-08-28 15:15                 ` Haojian Zhuang
@ 2013-08-28 15:45                   ` Stephen Warren
  -1 siblings, 0 replies; 40+ messages in thread
From: Stephen Warren @ 2013-08-28 15:45 UTC (permalink / raw)
  To: Haojian Zhuang
  Cc: Mark Rutland, devicetree, Kevin Hilman, Russell King - ARM Linux,
	Ian Campbell, Arnd Bergmann, Linus Walleij, Rob Herring,
	Grant Likely, Pawel Moll, John Stultz, Kumar Gala,
	Olof Johansson, Mike Turquette, tglx, linux-arm-kernel

On 08/28/2013 09:15 AM, Haojian Zhuang wrote:
> On 28 August 2013 22:20, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/27/2013 08:17 PM, Haojian Zhuang wrote:
>>> On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>>>>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>>>>> [+ DT maintainers]
>>>>>>>
>>>>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>>>>
>>>>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>>>>
>>>>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>>>>> ...
>>>>
>>>>>>>> +    osc32k: osc32k {
>>>>>>>> +            compatible = "fixed-clock";
>>>>>>>> +            #clock-cells = <0>;
>>>>>>>> +            clock-frequency = <32768>;
>>>>>>>> +            clock-output-names = "osc32khz";
>>>>>>>> +    };
>>>>>>>
>>>>>>> ...seems many of the recent users of clocks have grouped them into a
>>>>>>> clocks {} grouping on a "simple-bus".
>>>>>>>
>>>>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>>>>> should be grouped on a simple bus?
>>>>>>
>>>>>> I would expect all the clock node names to be just "clock", since the
>>>>>> node names should describe the type of device not their identity (i.e.
>>>>>> clock name).
>>>>>>
>>>>>> In turn, this means that each clock node name needs to use a unit
>>>>>> address ("@nnn") to make them unique. In turn, this means they must have
>>>>>> a reg property since the unit address must match the first entry in the
>>>>>> reg property.
>>>>>
>>>>> No, it's really bad on using a unit address. The register always contains
>>>>> multiple mux or gate or divider. It would cause duplicated unit address.
>>>>
>>>> There shouldn't be multiple nodes with identical reg values; if that's
>>>> happening, then it seems like the mapping of nodes to HW is incorrect.
>>>>
>>>> Each HW block should have 1 DT node. That way, the reg values won't collide.
>>>
>>> At here, I emphasize each clock node is one clock node. They are organized in
>>> tree. The same register integrates multiple clock gate/clock mux/clock divider.
>>> If each clock node is depend on reg, maybe it's not easy to read and the clock
>>> driver will be more complex.
>>
>> If there's a single HW block (or single register) that provides multiple
>> clocks, there should be a single DT node and a single device that
>> provides multiple clocks.
>>
>>>>> I tried to use index number also. And it's also bad to append new clock nodes.
>>>>> So I use the label name instead.
>>>>>
>>>>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>>>>> they would need an arbitrary reg value rather than a real one. So it
>>>>>> doesn't make sense to place them directly under the root DT node, since
>>>>>> their reg values would make no sense within the context of the
>>>>>> CPU-visible MMIO space that the root node describes.
>>>>>>
>>>>>> In this case, it's typical to put all the clock nodes into e.g. a
>>>>>> /clocks node, since that node can introduce a separate numbering-space
>>>>>> for clocks. For example, I'd expect something like:
>>>>>>
>>>>>>         clocks {
>>>>>>                 #address-cells = <1>;
>>>>>>                 #size-cells = <0>;
>>>>>>
>>>>>>                 osc32k: clock@0 {
>>>>>>                         compatible = "fixed-clock";
>>>>>>                         reg = <0>;
>>>> ...
>>>>>>                 osc26m: clock@1 {
>>>>>>                         compatible = "fixed-clock";
>>>>>>                         reg = <1>;
>>>> ...
>>>>
>>>>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>>>>> any clock register. It only provides the clock rate those child clock node.
>>>>
>>>> Inside the clocks node, the reg property is just a dummy value.
>>>
>>> Is a dummy value helpful? I don't think so.
>>
>> It's not a matter of whether it's helpful; it's just how DT works.
>>
>>
> 
> I copied some texts from device tree spec (Page 87. file name:
> Power_ePAPER_APPROVED_v1.0.pdf).
> 
>     Node and property definitions
>     Device tree nodes are defined with a node name and unit address
> with braces marking the start and
>     end of the node definition. They may be preceded by a label.
> 
>     [label:] node-name[@unit-address] {
>         [properties definitions]
>         [child nodes]
>     }
> 
> We can see that "unit-address" is optional.

It's optional syntactically, yes.

But,

a) Nodes must be named after their type, not their identity, so then you
end up with multiple nodes named "clock", all/many of which are children
of the same parent.

b) Nodes must have unique names within their parent, so you can
unambiguously specify which node you're accessing.

If (b) is not satisfied by node name alone, adding the unit address to
the node name is the way you make it unique.

> I also copied some texts from $LINUX/Documentation/devicetree/usage-model.txt
> 
>      Structurally, the DT is a tree, or acyclic graph with named nodes, and
>      nodes may have an arbitrary number of named properties encapsulating
>      arbitrary data.  A mechanism also exists to create arbitrary
>      links from one node to another outside of the natural tree structure.
> 
>      Conceptually, a common set of usage conventions, called 'bindings',
>      is defined for how data should appear in the tree to describe typical
>      hardware characteristics including data busses, interrupt lines, GPIO
>      connections, and peripheral devices.
> 
> I define each clock as one node although multiple clocks share one
> register, because it could
> share clock driver as much as possible. Whether they're sharing one
> register or not, they
> can be distinguished by clock types. I think that encapsulating them
> into one single
> node could only make clock driver complex. Sometimes one clock is
> using a single register,
> and sometime some clocks are sharing a single register. If the clock
> driver wants to support
> both, it needs to add more logic to check. And I don't think that
> abstracting clock breaks
> any law in DT.

The DT structure should be driven purely by the HW structure. The driver
structure should have no influence over the DT structure. If there's a
single HW module that exposes N clocks, there should be a single DT node
that's a clock provider, which uses #clock-cells>0 to identify the
clocks that consumers use.

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

* [PATCH v7 05/11] ARM: dts: enable hi4511 with device tree
@ 2013-08-28 15:45                   ` Stephen Warren
  0 siblings, 0 replies; 40+ messages in thread
From: Stephen Warren @ 2013-08-28 15:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/28/2013 09:15 AM, Haojian Zhuang wrote:
> On 28 August 2013 22:20, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/27/2013 08:17 PM, Haojian Zhuang wrote:
>>> On 27 August 2013 00:48, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 08/23/2013 09:52 PM, Haojian Zhuang wrote:
>>>>> On 23 August 2013 02:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>> On 08/22/2013 12:07 PM, Kevin Hilman wrote:
>>>>>>> [+ DT maintainers]
>>>>>>>
>>>>>>> Haojian Zhuang <haojian.zhuang@linaro.org> writes:
>>>>>>>
>>>>>>>> Enable Hisilicon Hi4511 development platform with device tree support.
>>>>>>>>
>>>>>>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>>>>> ...
>>>>
>>>>>>>> +    osc32k: osc32k {
>>>>>>>> +            compatible = "fixed-clock";
>>>>>>>> +            #clock-cells = <0>;
>>>>>>>> +            clock-frequency = <32768>;
>>>>>>>> +            clock-output-names = "osc32khz";
>>>>>>>> +    };
>>>>>>>
>>>>>>> ...seems many of the recent users of clocks have grouped them into a
>>>>>>> clocks {} grouping on a "simple-bus".
>>>>>>>
>>>>>>> DT folks: is there a rule of thumb on how whether these fixed clocks
>>>>>>> should be grouped on a simple bus?
>>>>>>
>>>>>> I would expect all the clock node names to be just "clock", since the
>>>>>> node names should describe the type of device not their identity (i.e.
>>>>>> clock name).
>>>>>>
>>>>>> In turn, this means that each clock node name needs to use a unit
>>>>>> address ("@nnn") to make them unique. In turn, this means they must have
>>>>>> a reg property since the unit address must match the first entry in the
>>>>>> reg property.
>>>>>
>>>>> No, it's really bad on using a unit address. The register always contains
>>>>> multiple mux or gate or divider. It would cause duplicated unit address.
>>>>
>>>> There shouldn't be multiple nodes with identical reg values; if that's
>>>> happening, then it seems like the mapping of nodes to HW is incorrect.
>>>>
>>>> Each HW block should have 1 DT node. That way, the reg values won't collide.
>>>
>>> At here, I emphasize each clock node is one clock node. They are organized in
>>> tree. The same register integrates multiple clock gate/clock mux/clock divider.
>>> If each clock node is depend on reg, maybe it's not easy to read and the clock
>>> driver will be more complex.
>>
>> If there's a single HW block (or single register) that provides multiple
>> clocks, there should be a single DT node and a single device that
>> provides multiple clocks.
>>
>>>>> I tried to use index number also. And it's also bad to append new clock nodes.
>>>>> So I use the label name instead.
>>>>>
>>>>>> Now I assume these clocks don't have any memory-mapped IO registers, so
>>>>>> they would need an arbitrary reg value rather than a real one. So it
>>>>>> doesn't make sense to place them directly under the root DT node, since
>>>>>> their reg values would make no sense within the context of the
>>>>>> CPU-visible MMIO space that the root node describes.
>>>>>>
>>>>>> In this case, it's typical to put all the clock nodes into e.g. a
>>>>>> /clocks node, since that node can introduce a separate numbering-space
>>>>>> for clocks. For example, I'd expect something like:
>>>>>>
>>>>>>         clocks {
>>>>>>                 #address-cells = <1>;
>>>>>>                 #size-cells = <0>;
>>>>>>
>>>>>>                 osc32k: clock at 0 {
>>>>>>                         compatible = "fixed-clock";
>>>>>>                         reg = <0>;
>>>> ...
>>>>>>                 osc26m: clock at 1 {
>>>>>>                         compatible = "fixed-clock";
>>>>>>                         reg = <1>;
>>>> ...
>>>>
>>>>> Those fixed-clock doesn't contain reg property. Since it needs not to access
>>>>> any clock register. It only provides the clock rate those child clock node.
>>>>
>>>> Inside the clocks node, the reg property is just a dummy value.
>>>
>>> Is a dummy value helpful? I don't think so.
>>
>> It's not a matter of whether it's helpful; it's just how DT works.
>>
>>
> 
> I copied some texts from device tree spec (Page 87. file name:
> Power_ePAPER_APPROVED_v1.0.pdf).
> 
>     Node and property definitions
>     Device tree nodes are defined with a node name and unit address
> with braces marking the start and
>     end of the node definition. They may be preceded by a label.
> 
>     [label:] node-name[@unit-address] {
>         [properties definitions]
>         [child nodes]
>     }
> 
> We can see that "unit-address" is optional.

It's optional syntactically, yes.

But,

a) Nodes must be named after their type, not their identity, so then you
end up with multiple nodes named "clock", all/many of which are children
of the same parent.

b) Nodes must have unique names within their parent, so you can
unambiguously specify which node you're accessing.

If (b) is not satisfied by node name alone, adding the unit address to
the node name is the way you make it unique.

> I also copied some texts from $LINUX/Documentation/devicetree/usage-model.txt
> 
>      Structurally, the DT is a tree, or acyclic graph with named nodes, and
>      nodes may have an arbitrary number of named properties encapsulating
>      arbitrary data.  A mechanism also exists to create arbitrary
>      links from one node to another outside of the natural tree structure.
> 
>      Conceptually, a common set of usage conventions, called 'bindings',
>      is defined for how data should appear in the tree to describe typical
>      hardware characteristics including data busses, interrupt lines, GPIO
>      connections, and peripheral devices.
> 
> I define each clock as one node although multiple clocks share one
> register, because it could
> share clock driver as much as possible. Whether they're sharing one
> register or not, they
> can be distinguished by clock types. I think that encapsulating them
> into one single
> node could only make clock driver complex. Sometimes one clock is
> using a single register,
> and sometime some clocks are sharing a single register. If the clock
> driver wants to support
> both, it needs to add more logic to check. And I don't think that
> abstracting clock breaks
> any law in DT.

The DT structure should be driven purely by the HW structure. The driver
structure should have no influence over the DT structure. If there's a
single HW module that exposes N clocks, there should be a single DT node
that's a clock provider, which uses #clock-cells>0 to identify the
clocks that consumers use.

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

* [PATCH v7 08/11] ARM: hi3xxx: add smp support
  2013-08-28 11:53     ` zhangfei gao
@ 2013-08-28 17:19       ` Olof Johansson
  2013-08-29  1:54         ` zhangfei
  0 siblings, 1 reply; 40+ messages in thread
From: Olof Johansson @ 2013-08-28 17:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 28, 2013 at 07:53:03PM +0800, zhangfei gao wrote:
> Thanks Olof, will update with your comments.
> 
> >>
> >> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> >> index 3be60c8..4cc5c57 100644
> >> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> >> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> >> @@ -8,3 +8,50 @@ Required root node properties:
> >>  Hi4511 Board
> >>  Required root node properties:
> >>       - compatible = "hisilicon,hi3620-hi4511";
> >> +
> >> +
> >> +Hisilicon sctrl resiter
> >
> > Resiter seems like odd naming here.
> >
> >> +
> >> +Required properties:
> >> +- compatible : "hisilicon,sctrl"
> >> +- reg : Address and size of sysctrl.
> >
> > sysctrl or sctrl? sysctrl isn't really too long, might as well use that.
> >
> >> +
> >> +Optional properties:
> >> +- smp_reg : offset in sysctrl for notifying slave cpu booting
> >> +             cpu 1, reg;
> >> +             cpu 2, reg + 0x4;
> >> +             cpu 3, reg + 0x8;
> >> +             If reg value is not zero, cpun exit wfi and go
> >> +- resume_reg : offset in sysctrl for notifying cpu0 when resume
> >> +- reset_reg : offset in sysctrl for system reset
> >
> > Underscores are usually not used in properties, you use dashes instead.
> >
> > Anyway, I suggest defining those as the different cells in a regular 'reg'
> > property instead.
> 
> Will update with
> 
> Required properties:
> - compatible : "hisilicon,sysctrl"
> - reg : Register address and size
> 
> Optional properties:
> - smp-off : offset in sysctrl for notifying slave cpu booting
>                 cpu 1, reg;
>                 cpu 2, reg + 0x4;
>                 cpu 3, reg + 0x8;
>                 If reg value is not zero, cpun exit wfi and go
> - resume-off : offset in sysctrl for notifying cpu0 when resume
> - reboot-off : offset in sysctrl for system reboot

Unabbreviated "offset" would be better than "off" here.

Do you even need this in the device tree? Do you have different implementations
of this IP that has the same programming model but just with a couple of
different offsets?


-Olof

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

* [PATCH v7 08/11] ARM: hi3xxx: add smp support
  2013-08-28 17:19       ` Olof Johansson
@ 2013-08-29  1:54         ` zhangfei
  0 siblings, 0 replies; 40+ messages in thread
From: zhangfei @ 2013-08-29  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 13-08-29 01:19 AM, Olof Johansson wrote:
> On Wed, Aug 28, 2013 at 07:53:03PM +0800, zhangfei gao wrote:
>> Thanks Olof, will update with your comments.
>>
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>>>> index 3be60c8..4cc5c57 100644
>>>> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>>>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>>>> @@ -8,3 +8,50 @@ Required root node properties:
>>>>   Hi4511 Board
>>>>   Required root node properties:
>>>>        - compatible = "hisilicon,hi3620-hi4511";
>>>> +
>>>> +
>>>> +Hisilicon sctrl resiter
>>>
>>> Resiter seems like odd naming here.
>>>
>>>> +
>>>> +Required properties:
>>>> +- compatible : "hisilicon,sctrl"
>>>> +- reg : Address and size of sysctrl.
>>>
>>> sysctrl or sctrl? sysctrl isn't really too long, might as well use that.
>>>
>>>> +
>>>> +Optional properties:
>>>> +- smp_reg : offset in sysctrl for notifying slave cpu booting
>>>> +             cpu 1, reg;
>>>> +             cpu 2, reg + 0x4;
>>>> +             cpu 3, reg + 0x8;
>>>> +             If reg value is not zero, cpun exit wfi and go
>>>> +- resume_reg : offset in sysctrl for notifying cpu0 when resume
>>>> +- reset_reg : offset in sysctrl for system reset
>>>
>>> Underscores are usually not used in properties, you use dashes instead.
>>>
>>> Anyway, I suggest defining those as the different cells in a regular 'reg'
>>> property instead.
>>
>> Will update with
>>
>> Required properties:
>> - compatible : "hisilicon,sysctrl"
>> - reg : Register address and size
>>
>> Optional properties:
>> - smp-off : offset in sysctrl for notifying slave cpu booting
>>                  cpu 1, reg;
>>                  cpu 2, reg + 0x4;
>>                  cpu 3, reg + 0x8;
>>                  If reg value is not zero, cpun exit wfi and go
>> - resume-off : offset in sysctrl for notifying cpu0 when resume
>> - reboot-off : offset in sysctrl for system reboot
>
> Unabbreviated "offset" would be better than "off" here.

:(
Have updated with off in Haojian's v9, since find such vector in 
/Document/devicetree
Do I need update to offset?
Will update to offset if there are newer version.

>
> Do you even need this in the device tree? Do you have different implementations
> of this IP that has the same programming model but just with a couple of
> different offsets?

Yes, they are different offsets value in hi3716 and hi3620.
Same implementation, only different offset value in different soc.

Thanks

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

end of thread, other threads:[~2013-08-29  1:54 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-20  2:31 [PATCH v7 00/11] Enable Hisilicon Hi3620 SoC Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 01/11] ARM: debug: support debug ll on hisilicon soc Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 02/11] clk: hi3xxx: add clock support Haojian Zhuang
2013-08-21 21:29   ` Mike Turquette
2013-08-24  4:13     ` Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 03/11] clk: gate: add CLK_GATE_SEPERATED_REG flag Haojian Zhuang
2013-08-21 21:18   ` Mike Turquette
2013-08-20  2:31 ` [PATCH v7 04/11] ARM: hi3xxx: add board support with device tree Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 05/11] ARM: dts: enable hi4511 " Haojian Zhuang
2013-08-22 18:07   ` Kevin Hilman
2013-08-22 18:50     ` Stephen Warren
2013-08-24  3:52       ` Haojian Zhuang
2013-08-26 16:48         ` Stephen Warren
2013-08-26 16:48           ` Stephen Warren
2013-08-28  2:17           ` Haojian Zhuang
2013-08-28  2:17             ` Haojian Zhuang
2013-08-28 14:20             ` Stephen Warren
2013-08-28 14:20               ` Stephen Warren
2013-08-28 15:15               ` Haojian Zhuang
2013-08-28 15:15                 ` Haojian Zhuang
2013-08-28 15:45                 ` Stephen Warren
2013-08-28 15:45                   ` Stephen Warren
2013-08-24  3:59     ` Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 06/11] ARM: config: enable hi3xxx in multi_v7_defconfig Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 07/11] ARM: config: add defconfig for Hi3xxx Haojian Zhuang
2013-08-20  2:31 ` [PATCH v7 08/11] ARM: hi3xxx: add smp support Haojian Zhuang
2013-08-28  2:12   ` Olof Johansson
2013-08-28 11:53     ` zhangfei gao
2013-08-28 17:19       ` Olof Johansson
2013-08-29  1:54         ` zhangfei
2013-08-20  2:31 ` [PATCH v7 09/11] ARM: hi3xxx: add hotplug support Haojian Zhuang
2013-08-28  2:21   ` Olof Johansson
2013-08-28 11:45     ` zhangfei gao
2013-08-20  2:31 ` [PATCH v7 10/11] ARM: hi3xxx: add clk-hi3716 Haojian Zhuang
2013-08-21 21:43   ` Mike Turquette
2013-08-22  1:19     ` zhangfei gao
2013-08-22  5:59       ` Mike Turquette
2013-08-22  7:50         ` Haojian Zhuang
2013-08-22  8:16           ` Mike Turquette
2013-08-20  2:31 ` [PATCH v7 11/11] ARM: hi3xxx: support hi3716-dkb board Haojian Zhuang

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.