linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Build and support rk3036 SoC platform
@ 2015-09-17  8:28 Xing Zheng
  2015-09-17  8:28 ` [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts Xing Zheng
                   ` (9 more replies)
  0 siblings, 10 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-17  8:28 UTC (permalink / raw)
  To: heiko
  Cc: linux-rockchip, Xing Zheng, Russell King, Michael Turquette,
	Alessandro Zummo, devicetree, Stephen Boyd, linux-gpio,
	Linus Walleij, Alexandre Belloni, Kumar Gala, linux-kernel,
	Ian Campbell, Rob Herring, Pawel Moll, rtc-linux, Mark Rutland,
	linux-clk, linux-arm-kernel


Hi,
we need to support rk3036 soc platform via upstream, there are
3 primary parts for the initial release of minimum system: dts,
pinctrl, and clock tree for rk3036, and additional, add a rtc
hym8563 patch to fix initial invaild, we can use these startup
and run to init processs.

Thanks.

changed in v2:
- based on v1, add clock controller documentation
- enable timer5 startup
- add smp for cpu1
- initial set time for rtc-hym8563

changes since v1:
- add dts, pinctrl and clock tree for rk3036 soc platform

The patchset (9):
9) rtc: hym8563: make sure hym8563 can be normal work
8) ARM: rockchip: add support smp for rk3036
7) rockchip: make sure timer5 is enabled on rk3036 platforms
6) pinctrl: rockchip: add support for the rk3036
5) dt-bindings: add documentation of rk3036 clock controller
4) clk: rockchip: add new clock type and controller for rk3036
3) clk: rockchip: add clock controller for rk3036
2) clk: rockchip: add dt-binding header for rk3036
1) ARM: dts: rockchip: add core rk3036 dts


Changes in v2:
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>

Xing Zheng (9):
  ARM: dts: rockchip: add core rk3036 dts
  clk: rockchip: add dt-binding header for rk3036
  clk: rockchip: add clock controller for rk3036
  clk: rockchip: add new clock type and controller for rk3036
  dt-bindings: add documentation of rk3036 clock controller
  pinctrl: rockchip: add support for the rk3036
  rockchip: make sure timer5 is enabled on rk3036 platforms
  ARM: rockchip: add support smp for rk3036
  rtc: hym8563: make sure hym8563 can be normal work

 .../bindings/clock/rockchip,rk3036-cru.txt         |   60 +++
 .../bindings/pinctrl/rockchip,pinctrl.txt          |    1 +
 arch/arm/boot/dts/Makefile                         |    1 +
 arch/arm/boot/dts/rk3036-sdk.dts                   |   62 +++
 arch/arm/boot/dts/rk3036.dtsi                      |  381 +++++++++++++++
 arch/arm/mach-rockchip/platsmp.c                   |  121 +++++
 arch/arm/mach-rockchip/rockchip.c                  |   22 +
 drivers/clk/rockchip/Makefile                      |    1 +
 drivers/clk/rockchip/clk-pll.c                     |  262 +++++++++-
 drivers/clk/rockchip/clk-rk3036.c                  |  504 ++++++++++++++++++++
 drivers/clk/rockchip/clk.h                         |   30 ++
 drivers/pinctrl/pinctrl-rockchip.c                 |   17 +
 drivers/rtc/rtc-hym8563.c                          |   93 ++++
 include/dt-bindings/clock/rk3036-cru.h             |  198 ++++++++
 14 files changed, 1752 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
 create mode 100644 arch/arm/boot/dts/rk3036-sdk.dts
 create mode 100644 arch/arm/boot/dts/rk3036.dtsi
 create mode 100644 drivers/clk/rockchip/clk-rk3036.c
 create mode 100644 include/dt-bindings/clock/rk3036-cru.h

-- 
1.7.9.5



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

* [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
@ 2015-09-17  8:28 ` Xing Zheng
  2015-09-17  9:18   ` Heiko Stübner
  2015-09-17  8:28 ` [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036 Xing Zheng
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17  8:28 UTC (permalink / raw)
  To: heiko
  Cc: linux-rockchip, Xing Zheng, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, devicetree,
	linux-arm-kernel, linux-kernel

Initial release for rk3036, node definitions rk3036 sdk board.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 arch/arm/boot/dts/Makefile       |    1 +
 arch/arm/boot/dts/rk3036-sdk.dts |   62 +++++++
 arch/arm/boot/dts/rk3036.dtsi    |  381 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 444 insertions(+)
 create mode 100644 arch/arm/boot/dts/rk3036-sdk.dts
 create mode 100644 arch/arm/boot/dts/rk3036.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d39ce4b..48260c4 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -502,6 +502,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3066a-bqcurie2.dtb \
 	rk3066a-marsboard.dtb \
 	rk3066a-rayeager.dtb \
+	rk3036-sdk.dtb \
 	rk3188-radxarock.dtb \
 	rk3288-evb-act8846.dtb \
 	rk3288-evb-rk808.dtb \
diff --git a/arch/arm/boot/dts/rk3036-sdk.dts b/arch/arm/boot/dts/rk3036-sdk.dts
new file mode 100644
index 0000000..9187f93
--- /dev/null
+++ b/arch/arm/boot/dts/rk3036-sdk.dts
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c)  2015 Xing Zheng <zhengxing@rock-chips.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ *  Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "rk3036.dtsi"
+
+/ {
+	model = "SDK-RK3036";
+	compatible = "sdk,sdk-rk3036", "rockchip,rk3036";
+};
+
+&i2c1 {
+	status = "okay";
+
+        hym8563: hym8563@51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+	};
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
new file mode 100644
index 0000000..b7459c0
--- /dev/null
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -0,0 +1,381 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3036-cru.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "rockchip,rk3036";
+
+	interrupt-parent = <&gic>;
+
+	aliases {
+		i2c1 = &i2c1;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x40000000>;
+	};
+
+        arm-pmu {
+                compatible = "arm,cortex-a7-pmu";
+                interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+                             <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+                interrupt-affinity = <&cpu0>, <&cpu1>;
+        };
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "rockchip,rk3036-smp";
+
+		cpu0: cpu@f00 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0xf00>;
+			operating-points = <
+				/* KHz    uV */
+				 816000 1000000
+			>;
+			#cooling-cells = <2>; /* min followed by max */
+			clock-latency = <40000>;
+			clocks = <&cru ARMCLK>;
+			resets = <&cru SRST_CORE0>;
+		};
+		cpu1: cpu@f01 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0xf01>;
+			resets = <&cru SRST_CORE1>;
+		};
+	};
+
+	amba {
+		compatible = "arm,amba-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+                pdma: pdma@20078000 {
+                        compatible = "arm,pl330", "arm,primecell";
+                        reg = <0x20078000 0x4000>;
+                        interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                        #dma-cells = <1>;
+                        clocks = <&cru ACLK_DMAC2>;
+                        clock-names = "apb_pclk";
+                };
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		arm,cpu-registers-not-fw-configured;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		clock-frequency = <24000000>;
+	};
+
+	cru: clock-controller@20000000 {
+		compatible = "rockchip,rk3036-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		assigned-clocks = <&cru PLL_GPLL>;
+		assigned-clock-rates = <594000000>;
+	};
+
+	uart0: serial@20060000 {
+		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
+		reg = <0x20060000 0x100>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+	};
+
+	uart1: serial@20064000 {
+		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
+		reg = <0x20064000 0x100>;
+		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer>;
+	};
+
+	uart2: serial@20068000 {
+		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
+		reg = <0x20068000 0x100>;
+		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2_xfer>;
+	};
+
+	pwm0: pwm@20050000 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050000 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm1: pwm@20050010 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050010 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm2: pwm@20050020 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050020 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm3: pwm@20050030 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050030 0x10>;
+		#pwm-cells = <2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	sram: sram@10080000 {
+		compatible = "rockchip,rk3036-smp-sram", "mmio-sram";
+		reg = <0x10080000 0x2000>;
+	};
+
+	gic: interrupt-controller@10139000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0x10139000 0x1000>,
+		      <0x1013a000 0x1000>,
+		      <0x1013c000 0x2000>,
+		      <0x1013e000 0x2000>;
+		interrupts = <GIC_PPI 9 0xf04>;
+	};
+
+	grf: syscon@20008000 {
+		compatible = "rockchip,rk3036-grf", "syscon";
+		reg = <0x20008000 0x1000>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3036-pinctrl";
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio0@2007c000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2007c000 0x100>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1@20080000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20080000 0x100>;
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio2@20084000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20084000 0x100>;
+			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <0 16 RK_FUNC_1 &pcfg_pull_none>,
+						<0 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <0 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <0 19 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <2 22 RK_FUNC_1 &pcfg_pull_none>,
+						<2 23 RK_FUNC_1 &pcfg_pull_none>;
+			};
+			/* no rts / cts for uart1 */
+		};
+
+                uart2 {
+                        uart2_xfer: uart2-xfer {
+                                rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_none>,
+                                                <1 19 RK_FUNC_2 &pcfg_pull_none>;
+                        };
+                        /* no rts / cts for uart2 */
+                };
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins = <0 1 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins = <0 1 2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3 {
+			pwm3_pin: pwm3-pin {
+				rockchip,pins = <0 27 1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>,
+						<0 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+	};
+
+	i2c1: i2c@20056000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0x20056000 0x1000>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		status = "disabled";
+	};
+};
-- 
1.7.9.5



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

* [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
  2015-09-17  8:28 ` [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts Xing Zheng
@ 2015-09-17  8:28 ` Xing Zheng
  2015-09-17  9:25   ` Heiko Stübner
  2015-09-17  8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller " Xing Zheng
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17  8:28 UTC (permalink / raw)
  To: heiko
  Cc: linux-rockchip, Xing Zheng, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, linux-kernel, devicetree

Add the dt-bindings header for the rk3036, that gets shared between
the clock controller and the clock references in the dts.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 include/dt-bindings/clock/rk3036-cru.h |  198 ++++++++++++++++++++++++++++++++
 1 file changed, 198 insertions(+)
 create mode 100644 include/dt-bindings/clock/rk3036-cru.h

diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h
new file mode 100644
index 0000000..b0033ef
--- /dev/null
+++ b/include/dt-bindings/clock/rk3036-cru.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
+
+/* core clocks */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_GPLL		3
+#define ARMCLK			4
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU		64
+#define SCLK_SPI		65
+#define SCLK_SDMMC		68
+#define SCLK_SDIO		69
+#define SCLK_EMMC		71
+#define SCLK_NANDC		76
+#define SCLK_UART0		77
+#define SCLK_UART1		78
+#define SCLK_UART2		79
+#define SCLK_I2S		82
+#define SCLK_SPDIF		83
+#define SCLK_TIMER0		85
+#define SCLK_TIMER1		86
+#define SCLK_TIMER2		87
+#define SCLK_TIMER3		88
+#define SCLK_OTGPHY0		93
+#define SCLK_OTGPHY1		94
+#define SCLK_LCDC		100
+#define SCLK_HDMI		109
+#define SCLK_HEVC		111
+#define SCLK_I2S_OUT		113
+#define SCLK_SDMMC_DRV		114
+#define SCLK_SDIO_DRV		115
+#define SCLK_EMMC_DRV		117
+#define SCLK_SDMMC_SAMPLE	118
+#define SCLK_SDIO_SAMPLE	119
+#define SCLK_EMMC_SAMPLE	121
+#define SCLK_PVTM_CORE          123
+#define SCLK_PVTM_GPU           124
+#define SCLK_PVTM_VIDEO         125
+#define SCLK_MAC		151
+#define SCLK_MACREF		152
+#define SCLK_SFC		160
+
+#define DCLK_LCDC		190
+
+/* aclk gates */
+#define ACLK_DMAC2		194
+#define ACLK_LCDC		197
+#define ACLK_VIO		203
+#define ACLK_VCODEC		208
+#define ACLK_CPU		209
+#define ACLK_PERI		210
+
+/* pclk gates */
+#define PCLK_GPIO0		320
+#define PCLK_GPIO1		321
+#define PCLK_GPIO2		322
+#define PCLK_GRF		329
+#define PCLK_I2C0		332
+#define PCLK_I2C1		333
+#define PCLK_I2C2		334
+#define PCLK_SPI		338
+#define PCLK_UART0		341
+#define PCLK_UART1		342
+#define PCLK_UART2		343
+#define PCLK_PWM		350
+#define PCLK_TIMER		353
+#define PCLK_HDMI		360
+#define PCLK_CPU		362
+#define PCLK_PERI		363
+#define PCLK_DDRUPCTL		364
+#define PCLK_WDT		368
+
+/* hclk gates */
+#define HCLK_OTG0		449
+#define HCLK_OTG1		450
+#define HCLK_NANDC		453
+#define HCLK_SDMMC		456
+#define HCLK_SDIO		457
+#define HCLK_EMMC		459
+#define HCLK_I2S		462
+#define HCLK_LCDC		465
+#define HCLK_ROM		467
+#define HCLK_VIO_BUS		472
+#define HCLK_VCODEC		476
+#define HCLK_CPU		477
+#define HCLK_PERI		478
+
+#define CLK_NR_CLKS		(HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0		0
+#define SRST_CORE1		1
+#define SRST_CORE0_DBG		4
+#define SRST_CORE1_DBG		5
+#define SRST_CORE0_POR		8
+#define SRST_CORE1_POR		9
+#define SRST_L2C		12
+#define SRST_TOPDBG		13
+#define SRST_STRC_SYS_A		14
+#define SRST_PD_CORE_NIU	15
+
+#define SRST_TIMER2		16
+#define SRST_CPUSYS_H		17
+#define SRST_AHB2APB_H		19
+#define SRST_TIMER3		20
+#define SRST_INTMEM		21
+#define SRST_ROM		22
+#define SRST_PERI_NIU		23
+#define SRST_I2S		24
+#define SRST_DDR_PLL		25
+#define SRST_GPU_DLL		26
+#define SRST_TIMER0		27
+#define SRST_TIMER1		28
+#define SRST_CORE_DLL		29
+#define SRST_EFUSE_P		30
+#define SRST_ACODEC_P		31
+
+#define SRST_GPIO0		32
+#define SRST_GPIO1		33
+#define SRST_GPIO2		34
+#define SRST_UART0		39
+#define SRST_UART1		40
+#define SRST_UART2		41
+#define SRST_I2C0		43
+#define SRST_I2C1		44
+#define SRST_I2C2		45
+#define SRST_SFC		47
+
+#define SRST_PWM0		48
+#define SRST_DAP		51
+#define SRST_DAP_SYS		52
+#define SRST_GRF		55
+#define SRST_PERIPHSYS_A	57
+#define SRST_PERIPHSYS_H	58
+#define SRST_PERIPHSYS_P	59
+#define SRST_CPU_PERI		61
+#define SRST_EMEM_PERI		62
+#define SRST_USB_PERI		63
+
+#define SRST_DMA2		64
+#define SRST_MAC		66
+#define SRST_NANDC		68
+#define SRST_USBOTG0		69
+#define SRST_OTGC0		71
+#define SRST_USBOTG1		72
+#define SRST_OTGC1		74
+#define SRST_DDRMSCH		79
+
+#define SRST_MMC0		81
+#define SRST_SDIO		82
+#define SRST_EMMC		83
+#define SRST_SPI0		84
+#define SRST_WDT		86
+#define SRST_DDRPHY		88
+#define SRST_DDRPHY_P		89
+#define SRST_DDRCTRL		90
+#define SRST_DDRCTRL_P		91
+
+#define SRST_HDMI_P		96
+#define SRST_VIO_BUS_H		99
+#define SRST_UTMI0		103
+#define SRST_UTMI1		104
+#define SRST_USBPOR		105
+
+#define SRST_VCODEC_A		112
+#define SRST_VCODEC_H		113
+#define SRST_VIO1_A		114
+#define SRST_HEVC		115
+#define SRST_VCODEC_NIU_A	116
+#define SRST_LCDC1_A		117
+#define SRST_LCDC1_H		118
+#define SRST_LCDC1_D		119
+#define SRST_GPU		120
+#define SRST_GPU_NIU_A		122
+
+#define SRST_DBG_P		131
+
+#endif
-- 
1.7.9.5



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

* [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
  2015-09-17  8:28 ` [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts Xing Zheng
  2015-09-17  8:28 ` [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036 Xing Zheng
@ 2015-09-17  8:28 ` Xing Zheng
  2015-09-17  9:47   ` Heiko Stübner
  2015-09-17  8:28 ` [PATCH v2 4/9] clk: rockchip: add new clock type and " Xing Zheng
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17  8:28 UTC (permalink / raw)
  To: heiko
  Cc: linux-rockchip, Xing Zheng, Michael Turquette, Stephen Boyd,
	linux-kernel, linux-clk, linux-arm-kernel

Add the clock tree definition for the new rk3036 SoC.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 drivers/clk/rockchip/Makefile     |    1 +
 drivers/clk/rockchip/clk-rk3036.c |  504 +++++++++++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h        |   30 +++
 3 files changed, 535 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-rk3036.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index b27edd6..d599829 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -10,6 +10,7 @@ obj-y	+= clk-inverter.o
 obj-y	+= clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
+obj-y	+= clk-rk3036.o
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3288.o
 obj-y	+= clk-rk3368.o
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
new file mode 100644
index 0000000..724d467
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3036.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk3036-cru.h>
+#include "clk.h"
+
+enum rk3036_plls {
+	apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk3036_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+	RK3036_PLL_RATE(0, 1, 0, 1, 1, 1, 0),
+	{ /* sentinel */ },
+};
+
+#define RK3036_DIV_CPU_MASK		0x1f
+#define RK3036_DIV_CPU_SHIFT		8
+
+#define RK3036_DIV_PERI_MASK		0xf
+#define RK3036_DIV_PERI_SHIFT		0
+#define RK3036_DIV_ACLK_MASK		0x7
+#define RK3036_DIV_ACLK_SHIFT		4
+#define RK3036_DIV_HCLK_MASK		0x3
+#define RK3036_DIV_HCLK_SHIFT		8
+#define RK3036_DIV_PCLK_MASK		0x7
+#define RK3036_DIV_PCLK_SHIFT		12
+
+#define RK3036_CLKSEL1(_core_periph_div)					\
+	{									\
+		.reg = RK2928_CLKSEL_CON(1),					\
+		.val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK,	\
+				RK3036_DIV_PERI_SHIFT)				\
+	}
+
+#define RK3036_CPUCLK_RATE(_prate, _core_periph_div)			\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3036_CLKSEL1(_core_periph_div),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata = {
+	RK3036_CPUCLK_RATE(816000000, 4),
+	RK3036_CPUCLK_RATE(600000000, 4),
+	RK3036_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
+	.core_reg = RK2928_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 7,
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin24m" };
+
+PNAME(mux_armclk_p)		= { "apll", "gpll_armclk" };
+PNAME(mux_busclk_p)		= { "apll", "dpll_cpu", "gpll_cpu" };
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_pll_src_3plls_p)	= { "apll", "dpll", "gpll" };
+PNAME(mux_timer_p)		= { "xin24m", "pclk_peri_src" };
+
+PNAME(mux_pll_src_apll_gpll_dpll_usb480m_p)	= { "apll", "gpll", "dpll" "usb480m" };
+
+PNAME(mux_mmc_src_p)	= { "apll", "gpll", "dpll", "xin24m" };
+PNAME(mux_i2s_pre_p)	= { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_clkout_p)	= { "i2s_pre", "xin12m" };
+PNAME(mux_spdif_p)	= { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_uart0_p)	= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)	= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)	= { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_mac_p)	= { "mac_pll_src", "ext_gmac" };
+PNAME(mux_dclk_p)	= { "dclk_lcdc", "dclk_hdmi_src" };
+
+static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
+		     RK2928_MODE_CON, 0, 10, 0, rk3036_pll_rates),
+	[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
+		     RK2928_MODE_CON, 4, 10, 0, NULL),
+	[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
+		     RK2928_MODE_CON, 12, 10, ROCKCHIP_PLL_SYNC_RATE, rk3036_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 1
+	 */
+
+	/* PD_CORE */
+	GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	/* PD_DDR */
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+
+	/* PD_CORE */
+	COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_core_pre", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+
+	/* PD_CPU (BUS) */
+	GATE(0, "dpll_cpu", "dpll", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(0, "gpll_cpu", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_busclk_p, 0,
+			RK2928_CLKSEL_CON(0), 14, 2, MFLAGS, 8, 5, DFLAGS),
+	GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 4, GFLAGS),
+
+	/* PD_PERI */
+	COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 1, GFLAGS),
+	/* pclk_peri_src is soure for timers */
+	DIV(0, "pclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	GATE(PCLK_PERI, "pclk_peri", "pclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 3, GFLAGS),
+	/* hclk_peri_src is soure for sclk_macref_out */
+	DIV(0, "hclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	GATE(HCLK_PERI, "hclk_peri", "hclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 2, GFLAGS),
+
+	/* PD_TIMER */
+	COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 4, 1, DFLAGS,
+			RK2928_CLKGATE_CON(1), 0, GFLAGS),
+	COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 5, 1, DFLAGS,
+			RK2928_CLKGATE_CON(1), 1, GFLAGS),
+	COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 6, 1, DFLAGS,
+			RK2928_CLKGATE_CON(2), 4, GFLAGS),
+	COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 7, 1, DFLAGS,
+			RK2928_CLKGATE_CON(2), 5, GFLAGS),
+
+	/* PD_UART */
+	MUX(0, "uart_pll_clk", mux_pll_src_apll_gpll_dpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(13), 10, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(17), 0,
+			RK2928_CLKGATE_CON(1), 9, GFLAGS),
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(18), 0,
+			RK2928_CLKGATE_CON(1), 11, GFLAGS),
+	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(19), 0,
+			RK2928_CLKGATE_CON(1), 13, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+
+	/* PD_VIDEO */
+	COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 11, GFLAGS),
+
+	COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 6, GFLAGS),
+
+	/* PD_VIO */
+	COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 4, GFLAGS),
+	COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(0), 11, GFLAGS),
+	COMPOSITE(DCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+
+	/* MMC */
+	COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 8, 2, DFLAGS,
+			RK2928_CLKGATE_CON(2), 11, GFLAGS),
+	DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0,
+			RK2928_CLKSEL_CON(11), 0, 7, DFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 10, 2, DFLAGS,
+			RK2928_CLKGATE_CON(2), 13, GFLAGS),
+	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+			RK2928_CLKSEL_CON(11), 8, 7, DFLAGS),
+
+	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 14, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3036_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3036_SDMMC_CON1, 0),
+
+	MMC(SCLK_SDIO_DRV,    "sdio_drv",    "sclk_sdio", RK3036_SDIO_CON0, 1),
+	MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3036_SDIO_CON1, 0),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3036_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3036_EMMC_CON1,  0),
+
+	/* I2S */
+	COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(3), 14, 1, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(7), 0,
+			RK2928_CLKGATE_CON(0), 10, GFLAGS),
+	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_clkout", mux_i2s_clkout_p, 0,
+			RK2928_CLKSEL_CON(4), 12, 1, MFLAGS,
+			RK2928_CLKGATE_CON(0), 13, GFLAGS),
+	GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT,
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+
+	COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
+			RK2928_CLKSEL_CON(9), 0,
+			RK2928_CLKGATE_CON(2), 12, GFLAGS),
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
+			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+
+	GATE(0, "hsicphy12m_xin12m", "xin12m", 0,
+			RK2928_CLKGATE_CON(1), 5, GFLAGS),
+
+	COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+
+	COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 9, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 4, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_gpll_dpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 5, GFLAGS),
+
+	/* MAC */
+	COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS),
+	/* for clk_mac_ref & clk_mac_refout */
+	MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(21), 3, 1, MFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0,
+			RK2928_CLKSEL_CON(21), 9, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 6, GFLAGS),
+
+	/* HDMI */
+	/* total clks: pin_sys_clk / pin_sck / pin_mclk / pin_vclk / pin_vclk_pllref */
+	/* the same with dclk_lcdc */
+	COMPOSITE(0, "dclk_hdmi_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+	/* hdmi dclk from dclk_lcdc directly */
+	MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0,
+			RK2928_CLKSEL_CON(31), 0, 1, MFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	/* aclk_cpu gates */
+	GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS),
+	GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS),
+
+	/* hclk_cpu gates */
+	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS),
+
+	/* pclk_cpu gates */
+	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
+	GATE(ACLK_VCODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
+	GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
+
+	/* aclk_vio gates */
+	GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", 0,
+			RK2928_CLKGATE_CON(6), 13, GFLAGS),
+	GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0,
+			RK2928_CLKGATE_CON(9), 6, GFLAGS),
+
+	GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0,
+			RK2928_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0,
+			RK2928_CLKGATE_CON(9), 5, GFLAGS),
+
+	/* aclk_video gates */
+	GATE(HCLK_LCDC, "hclk_vcodec", "hclk_disp_pre", 0,
+			RK2928_CLKGATE_CON(3), 12, GFLAGS),
+
+	/* xin24m gates */
+	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS),
+
+	/* aclk_peri gates */
+	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS),
+	GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS),
+	GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS),
+
+	/* hclk_peri gates */
+	GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
+	GATE(0, "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
+	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
+	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS),
+	GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 13, GFLAGS),
+	GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+	GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS),
+	GATE(0, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS),
+
+	/* pclk_peri gates */
+	GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS),
+	GATE(PCLK_TIMER, "pclk_timer0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
+	GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
+	GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+};
+
+static const char *const rk3036_critical_clocks[] __initconst = {
+	"aclk_cpu",
+	"aclk_peri",
+	"hclk_peri",
+	"pclk_peri",
+};
+
+static void __init rk3036_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock usb480m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock ddrphy: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
+					"aclk_vcodec", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
+					"hclk_peri_src", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	rockchip_clk_register_plls(rk3036_pll_clks,
+				   ARRAY_SIZE(rk3036_pll_clks),
+				   -1);
+	rockchip_clk_register_branches(rk3036_clk_branches,
+				  ARRAY_SIZE(rk3036_clk_branches));
+	rockchip_clk_protect_critical(rk3036_critical_clocks,
+				      ARRAY_SIZE(rk3036_critical_clocks));
+
+	rockchip_clk_register_armclk(ARMCLK, "armclk",
+			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
+			ARRAY_SIZE(rk3036_cpuclk_rates));
+
+	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
+}
+CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index dc8ecb2..6603c07 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -2,6 +2,9 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
  * based on
  *
  * samsung/clk.h
@@ -40,6 +43,13 @@ struct clk;
 #define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON		0x134
 
+#define RK3036_SDMMC_CON0		0x144
+#define RK3036_SDMMC_CON1		0x148
+#define RK3036_SDIO_CON0		0x14c
+#define RK3036_SDIO_CON1		0x150
+#define RK3036_EMMC_CON0		0x154
+#define RK3036_EMMC_CON1		0x158
+
 #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
 #define RK3288_MODE_CON			0x50
 #define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
@@ -75,6 +85,7 @@ struct clk;
 
 enum rockchip_pll_type {
 	pll_rk3066,
+	pll_rk3036,
 };
 
 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
@@ -95,12 +106,31 @@ enum rockchip_pll_type {
 	.nb = _nb,						\
 }
 
+#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
+			_postdiv2, _dsmpd, _frac)		\
+{								\
+	.rate	= _rate##U,					\
+	.fbdiv = _fbdiv,					\
+	.postdiv1 = _postdiv1,					\
+	.refdiv = _refdiv,					\
+	.postdiv2 = _postdiv2,					\
+	.dsmpd = _dsmpd,					\
+	.frac = _frac,						\
+}
+
 struct rockchip_pll_rate_table {
 	unsigned long rate;
 	unsigned int nr;
 	unsigned int nf;
 	unsigned int no;
 	unsigned int nb;
+	/* for RK3036 */
+	unsigned int fbdiv;
+	unsigned int postdiv1;
+	unsigned int refdiv;
+	unsigned int postdiv2;
+	unsigned int dsmpd;
+	unsigned int frac;
 };
 
 /**
-- 
1.7.9.5



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

* [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (2 preceding siblings ...)
  2015-09-17  8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller " Xing Zheng
@ 2015-09-17  8:28 ` Xing Zheng
  2015-09-17  9:54   ` Heiko Stübner
  2015-09-22 22:41   ` Stephen Boyd
  2015-09-17  9:59 ` [PATCH v2 0/9] Build and support rk3036 SoC platform Heiko Stübner
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-17  8:28 UTC (permalink / raw)
  To: heiko
  Cc: linux-rockchip, Xing Zheng, Michael Turquette, Stephen Boyd,
	linux-clk, linux-arm-kernel, linux-kernel

The rk3036's pll and clock are different with base on the rk3066(rk3188,
rk3288, rk3368 use it), there are different adjust foctors and control
registers, so these should be independent and separate from the series
of rk3066s.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 drivers/clk/rockchip/clk-pll.c |  262 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 261 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 7737a1d..25b066a 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -2,6 +2,9 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
  * 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
@@ -19,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
+#include <linux/clk.h>
 #include "clk.h"
 
 #define PLL_MODE_MASK		0x3
@@ -306,6 +310,256 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
 	}
 }
 
+/**
+ * PLL used in RK3036
+ */
+
+#define RK3036_PLLCON(i)			(i * 0x4)
+#define RK3036_PLLCON0_FBDIV_MASK		0xfff
+#define RK3036_PLLCON0_FBDIV_SHIFT		0
+#define RK3036_PLLCON0_POSTDIV1_MASK		0x7
+#define RK3036_PLLCON0_POSTDIV1_SHIFT		12
+#define RK3036_PLLCON1_REFDIV_MASK		0x3f
+#define RK3036_PLLCON1_REFDIV_SHIFT		0
+#define RK3036_PLLCON1_POSTDIV2_MASK		0x7
+#define RK3036_PLLCON1_POSTDIV2_SHIFT		6
+#define RK3036_PLLCON1_DSMPD_MASK		0x1
+#define RK3036_PLLCON1_DSMPD_SHIFT		12
+#define RK3036_PLLCON2_FRAC_MASK		0xffffff
+#define RK3036_PLLCON2_FRAC_SHIFT		0
+
+#define RK3036_PLLCON1_PWRDOWN			(1 << 13)
+#define RK3036_PLLCON1_LOCK_STATUS		(1 << 10)
+
+static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+	u32 pllcon;
+	int delay = 24000000;
+
+	/* poll check the lock status in rk3036 xPLLCON1 */
+	while (delay > 0) {
+		pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
+		if (pllcon & RK3036_PLLCON1_LOCK_STATUS)
+			return 0;
+
+		delay--;
+	}
+
+	pr_err("%s: timeout waiting for pll to lock\n", __func__);
+	return -ETIMEDOUT;
+}
+
+static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
+	u64 rate64 = prate;
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
+	fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT) & RK3036_PLLCON0_FBDIV_MASK);
+	postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT) & RK3036_PLLCON0_POSTDIV1_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
+	refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT) & RK3036_PLLCON1_REFDIV_MASK);
+	postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT) & RK3036_PLLCON1_POSTDIV2_MASK);
+	dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT) & RK3036_PLLCON1_DSMPD_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+	frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT) & RK3036_PLLCON2_FRAC_MASK);
+
+	rate64 *= fbdiv;
+	do_div(rate64, refdiv);
+
+	if (dsmpd == 0) {
+		/* fractional mode */
+		u64 frac_rate64 = prate * frac;
+
+		do_div(frac_rate64, refdiv);
+		rate64 += frac_rate64 >> 24;
+	}
+
+	do_div(rate64, postdiv1);
+	do_div(rate64, postdiv2);
+
+	return (unsigned long)rate64;
+}
+
+static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate);
+	struct regmap *grf = rockchip_clk_get_grf();
+	struct clk_mux *pll_mux = &pll->pll_mux;
+	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+	u32 pllcon;
+	int rate_change_remuxed = 0;
+	int cur_parent;
+	int ret;
+
+	if (IS_ERR(grf)) {
+		pr_debug("%s: grf regmap not available, aborting rate change\n",
+			 __func__);
+		return PTR_ERR(grf);
+	}
+
+	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
+		 __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+
+	/* Get required rate settings from table */
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		__func__, rate->rate,
+		rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, rate->dsmpd, rate->frac);
+
+	cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+	if (cur_parent == PLL_MODE_NORM) {
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+		rate_change_remuxed = 1;
+	}
+
+	/* update pll values */
+	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
+					  RK3036_PLLCON0_FBDIV_SHIFT) |
+		       HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK,
+					     RK3036_PLLCON0_POSTDIV1_SHIFT),
+		       pll->reg_base + RK3036_PLLCON(0));
+
+	writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK,
+						   RK3036_PLLCON1_REFDIV_SHIFT) |
+		       HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK,
+						     RK3036_PLLCON1_POSTDIV2_SHIFT) |
+		       HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK,
+						  RK3036_PLLCON1_DSMPD_SHIFT),
+		       pll->reg_base + RK3036_PLLCON(1));
+
+	/* GPLL CON2 is not HIWORD_MASK */
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+	pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);
+	pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
+	writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
+
+	/* wait for the pll to lock */
+	ret = rockchip_rk3036_pll_wait_lock(pll);
+	if (ret) {
+		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
+			__func__, old_rate);
+		rockchip_rk3036_pll_set_rate(hw, old_rate, prate);
+	}
+
+	if (rate_change_remuxed)
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+	return ret;
+}
+
+static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3036_PLLCON(1));
+
+	return 0;
+}
+
+static void rockchip_rk3036_pll_disable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
+			     RK3036_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3036_PLLCON(1));
+}
+
+static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));
+
+	return !(pllcon & RK3036_PLLCON1_PWRDOWN);
+}
+
+static void rockchip_rk3036_pll_init(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
+	unsigned long drate;
+	u32 pllcon;
+
+	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+		return;
+
+	drate = clk_hw_get_rate(hw);
+	rate = rockchip_get_pll_settings(pll, drate);
+
+	/* when no rate setting for the current rate, rely on clk_set_rate */
+	if (!rate)
+		return;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
+	fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT) & RK3036_PLLCON0_FBDIV_MASK);
+	postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT) & RK3036_PLLCON0_POSTDIV1_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
+	refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT) & RK3036_PLLCON1_REFDIV_MASK);
+	postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT) & RK3036_PLLCON1_POSTDIV2_MASK);
+	dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT) & RK3036_PLLCON1_DSMPD_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+	frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT) & RK3036_PLLCON2_FRAC_MASK);
+
+	pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk), drate);
+	pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac);
+	pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, rate->dsmpd, rate->frac);
+
+	if (rate->fbdiv != fbdiv || rate->postdiv1 != postdiv1 || rate->refdiv != refdiv ||
+		rate->postdiv2 != postdiv2 || rate->dsmpd != dsmpd || rate->frac != frac) {
+		struct clk *parent = clk_get_parent(hw->clk);
+		unsigned long prate;
+
+		if (!parent) {
+			pr_warn("%s: parent of %s not available\n",
+				__func__, __clk_get_name(hw->clk));
+			return;
+		}
+
+		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
+			 __func__, __clk_get_name(hw->clk));
+		prate = clk_get_rate(parent);
+		rockchip_rk3036_pll_set_rate(hw, drate, prate);
+	}
+}
+
+static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
+	.recalc_rate = rockchip_rk3036_pll_recalc_rate,
+	.enable = rockchip_rk3036_pll_enable,
+	.disable = rockchip_rk3036_pll_disable,
+	.is_enabled = rockchip_rk3036_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
+	.recalc_rate = rockchip_rk3036_pll_recalc_rate,
+	.round_rate = rockchip_pll_round_rate,
+	.set_rate = rockchip_rk3036_pll_set_rate,
+	.enable = rockchip_rk3036_pll_enable,
+	.disable = rockchip_rk3036_pll_disable,
+	.is_enabled = rockchip_rk3036_pll_is_enabled,
+	.init = rockchip_rk3036_pll_init,
+};
+
 static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
 	.recalc_rate = rockchip_rk3066_pll_recalc_rate,
 	.enable = rockchip_rk3066_pll_enable,
@@ -363,7 +617,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
 	pll_mux->lock = lock;
 	pll_mux->hw.init = &init;
 
-	if (pll_type == pll_rk3066)
+	if (pll_type == pll_rk3066 || pll_type == pll_rk3036)
 		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
 
 	/* the actual muxing is xin24m, pll-output, xin32k */
@@ -414,6 +668,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
 		else
 			init.ops = &rockchip_rk3066_pll_clk_ops;
 		break;
+	case pll_rk3036:
+		if (!pll->rate_table)
+			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
+		else
+			init.ops = &rockchip_rk3036_pll_clk_ops;
+		break;
 	default:
 		pr_warn("%s: Unknown pll type for pll clk %s\n",
 			__func__, name);
-- 
1.7.9.5



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

* Re: [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts
  2015-09-17  8:28 ` [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts Xing Zheng
@ 2015-09-17  9:18   ` Heiko Stübner
  2015-09-24  2:18     ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17  9:18 UTC (permalink / raw)
  To: Xing Zheng
  Cc: linux-rockchip, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Russell King, devicetree,
	linux-arm-kernel, linux-kernel

Am Donnerstag, 17. September 2015, 16:28:52 schrieb Xing Zheng:
> Initial release for rk3036, node definitions rk3036 sdk board.
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  arch/arm/boot/dts/Makefile       |    1 +
>  arch/arm/boot/dts/rk3036-sdk.dts |   62 +++++++
>  arch/arm/boot/dts/rk3036.dtsi    |  381
> ++++++++++++++++++++++++++++++++++++++ 3 files changed, 444 insertions(+)
>  create mode 100644 arch/arm/boot/dts/rk3036-sdk.dts
>  create mode 100644 arch/arm/boot/dts/rk3036.dtsi
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index d39ce4b..48260c4 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -502,6 +502,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
>  	rk3066a-bqcurie2.dtb \
>  	rk3066a-marsboard.dtb \
>  	rk3066a-rayeager.dtb \
> +	rk3036-sdk.dtb \

ordering ... please put the rk3036 above rk3066 boards


>  	rk3188-radxarock.dtb \
>  	rk3288-evb-act8846.dtb \
>  	rk3288-evb-rk808.dtb \
> diff --git a/arch/arm/boot/dts/rk3036-sdk.dts
> b/arch/arm/boot/dts/rk3036-sdk.dts new file mode 100644
> index 0000000..9187f93
> --- /dev/null
> +++ b/arch/arm/boot/dts/rk3036-sdk.dts

or "rk3036-evb.dts"? What is the actual board named?

> @@ -0,0 +1,62 @@
> +/*
> + * Copyright (c)  2015 Xing Zheng <zhengxing@rock-chips.com>

this probably wants a Rockchip copyright notice?


> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This file 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 file 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.
> + *
> + *  Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +/dts-v1/;
> +
> +#include "rk3036.dtsi"
> +
> +/ {
> +	model = "SDK-RK3036";
> +	compatible = "sdk,sdk-rk3036", "rockchip,rk3036";

	model = "Rockchip RK3036-SDK";
	compatible = "rockchip,rk3036-sdk", "rockchip,rk3036";

or

	model = "Rockchip RK3036 Evaluation board";
	compatible = "rockchip,rk3036-evb", "rockchip,rk3036";

depending on what the real board is labeled


> +};
> +
> +&i2c1 {
> +	status = "okay";
> +
> +        hym8563: hym8563@51 {
> +		compatible = "haoyu,hym8563";
> +		reg = <0x51>;
> +		#clock-cells = <0>;
> +		clock-frequency = <32768>;
> +		clock-output-names = "xin32k";
> +	};
> +};
> \ No newline at end of file

missing newline as stated above


> diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
> new file mode 100644
> index 0000000..b7459c0
> --- /dev/null
> +++ b/arch/arm/boot/dts/rk3036.dtsi
> @@ -0,0 +1,381 @@
> +/*
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This file 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 file 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.
> + *
> + * Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/pinctrl/rockchip.h>
> +#include <dt-bindings/clock/rk3036-cru.h>
> +#include "skeleton.dtsi"

in general, please sort nodes by register address, so for example

	interrupt-controller@10139000
should be before
	clock-controller@20000000

same for all other nodes

> +
> +/ {
> +	compatible = "rockchip,rk3036";
> +
> +	interrupt-parent = <&gic>;
> +
> +	aliases {
> +		i2c1 = &i2c1;
> +		serial0 = &uart0;
> +		serial1 = &uart1;
> +		serial2 = &uart2;
> +	};
> +
> +	memory {
> +		device_type = "memory";
> +		reg = <0x60000000 0x40000000>;

ordering is possible ... to ease readability I try to keep this as

compatible = ...
reg = ...
[other properties sorted alphabetically]
status = ...

> +	};
> +
> +        arm-pmu {
> +                compatible = "arm,cortex-a7-pmu";
> +                interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
> +                             <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
> +                interrupt-affinity = <&cpu0>, <&cpu1>;
> +        };

tabs, not spaces please


> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		enable-method = "rockchip,rk3036-smp";

this enable method is not yet defined, please don't add it until actual smp is 
accepted


> +
> +		cpu0: cpu@f00 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a7";
> +			reg = <0xf00>;
> +			operating-points = <
> +				/* KHz    uV */
> +				 816000 1000000
> +			>;
> +			#cooling-cells = <2>; /* min followed by max */

again, not yet defined thermal handling, so the #cooling-cells should stay out 
for now


> +			clock-latency = <40000>;
> +			clocks = <&cru ARMCLK>;
> +			resets = <&cru SRST_CORE0>;
> +		};
> +		cpu1: cpu@f01 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a7";
> +			reg = <0xf01>;
> +			resets = <&cru SRST_CORE1>;
> +		};
> +	};
> +
> +	amba {
> +		compatible = "arm,amba-bus";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +                pdma: pdma@20078000 {
> +                        compatible = "arm,pl330", "arm,primecell";
> +                        reg = <0x20078000 0x4000>;
> +                        interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
> +                                     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
> +                        #dma-cells = <1>;
> +                        clocks = <&cru ACLK_DMAC2>;
> +                        clock-names = "apb_pclk";
> +                };

again tabs please

> +	};
> +
> +	xin24m: oscillator {
> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "xin24m";
> +		#clock-cells = <0>;
> +	};
> +
> +	timer {
> +		compatible = "arm,armv7-timer";
> +		arm,cpu-registers-not-fw-configured;
> +		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | 
IRQ_TYPE_LEVEL_HIGH)>,
> +			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, +	
		 
>    <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, +			    
> <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
> +		clock-frequency = <24000000>;
> +	};
> +
> +	cru: clock-controller@20000000 {
> +		compatible = "rockchip,rk3036-cru";
> +		reg = <0x20000000 0x1000>;
> +		rockchip,grf = <&grf>;
> +		#clock-cells = <1>;
> +		#reset-cells = <1>;
> +		assigned-clocks = <&cru PLL_GPLL>;
> +		assigned-clock-rates = <594000000>;
> +	};
> +
> +	uart0: serial@20060000 {
> +		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
> +		reg = <0x20060000 0x100>;
> +		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
> +		reg-shift = <2>;
> +		reg-io-width = <4>;
> +		clock-frequency = <24000000>;
> +		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
> +		clock-names = "baudclk", "apb_pclk";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;

status = "disabled" and then in the board.dts a

&uart0 {
	status = "okay";
};

not everybody will want to use uart0 ... same is true for the other two uarts.


> +	};
> +
> +	uart1: serial@20064000 {
> +		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
> +		reg = <0x20064000 0x100>;
> +		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
> +		reg-shift = <2>;
> +		reg-io-width = <4>;
> +		clock-frequency = <24000000>;
> +		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
> +		clock-names = "baudclk", "apb_pclk";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&uart1_xfer>;
> +	};
> +
> +	uart2: serial@20068000 {
> +		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
> +		reg = <0x20068000 0x100>;
> +		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
> +		reg-shift = <2>;
> +		reg-io-width = <4>;
> +		clock-frequency = <24000000>;
> +		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
> +		clock-names = "baudclk", "apb_pclk";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&uart2_xfer>;
> +	};
> +
> +	pwm0: pwm@20050000 {
> +		compatible = "rockchip,rk2928-pwm";

		compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm";

rk2928-pwm matches now, but if we find issues we can simply create the rk3036-
pwm in the driver without needing to change the dts

> +		reg = <0x20050000 0x10>;
> +		#pwm-cells = <3>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pwm0_pin>;
> +		clocks = <&cru PCLK_PWM>;
> +		clock-names = "pwm";
> +		status = "disabled";
> +	};
> +
> +	pwm1: pwm@20050010 {
> +		compatible = "rockchip,rk2928-pwm";
> +		reg = <0x20050010 0x10>;
> +		#pwm-cells = <3>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pwm1_pin>;
> +		clocks = <&cru PCLK_PWM>;
> +		clock-names = "pwm";
> +		status = "disabled";
> +	};
> +
> +	pwm2: pwm@20050020 {
> +		compatible = "rockchip,rk2928-pwm";
> +		reg = <0x20050020 0x10>;
> +		#pwm-cells = <3>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pwm2_pin>;
> +		clocks = <&cru PCLK_PWM>;
> +		clock-names = "pwm";
> +		status = "disabled";
> +	};
> +
> +	pwm3: pwm@20050030 {
> +		compatible = "rockchip,rk2928-pwm";
> +		reg = <0x20050030 0x10>;
> +		#pwm-cells = <2>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pwm3_pin>;
> +		clocks = <&cru PCLK_PWM>;
> +		clock-names = "pwm";
> +		status = "disabled";
> +	};
> +
> +	sram: sram@10080000 {
> +		compatible = "rockchip,rk3036-smp-sram", "mmio-sram";
> +		reg = <0x10080000 0x2000>;
> +	};
> +
> +	gic: interrupt-controller@10139000 {
> +		compatible = "arm,gic-400";
> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		#address-cells = <0>;
> +
> +		reg = <0x10139000 0x1000>,
> +		      <0x1013a000 0x1000>,
> +		      <0x1013c000 0x2000>,
> +		      <0x1013e000 0x2000>;
> +		interrupts = <GIC_PPI 9 0xf04>;
> +	};
> +
> +	grf: syscon@20008000 {
> +		compatible = "rockchip,rk3036-grf", "syscon";
> +		reg = <0x20008000 0x1000>;
> +	};
> +
> +	pinctrl: pinctrl {
> +		compatible = "rockchip,rk3036-pinctrl";
> +		rockchip,grf = <&grf>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +		gpio0: gpio0@2007c000 {
> +			compatible = "rockchip,gpio-bank";
> +			reg = <0x2007c000 0x100>;
> +			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&cru PCLK_GPIO0>;
> +
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +		};
> +
> +		gpio1: gpio1@20080000 {
> +			compatible = "rockchip,gpio-bank";
> +			reg = <0x20080000 0x100>;
> +			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&cru PCLK_GPIO1>;
> +
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +		};
> +
> +		gpio2: gpio2@20084000 {
> +			compatible = "rockchip,gpio-bank";
> +			reg = <0x20084000 0x100>;
> +			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&cru PCLK_GPIO2>;
> +
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +		};
> +
> +		pcfg_pull_up: pcfg-pull-up {
> +			bias-pull-up;
> +		};
> +
> +		pcfg_pull_down: pcfg-pull-down {
> +			bias-pull-down;
> +		};
> +
> +		pcfg_pull_none: pcfg-pull-none {
> +			bias-disable;
> +		};
> +
> +		uart0 {
> +			uart0_xfer: uart0-xfer {
> +				rockchip,pins = <0 16 RK_FUNC_1 &pcfg_pull_none>,

pcfg_pull_up for the rx-pin?

> +						<0 17 RK_FUNC_1 &pcfg_pull_none>;
> +			};
> +
> +			uart0_cts: uart0-cts {
> +				rockchip,pins = <0 18 RK_FUNC_1 &pcfg_pull_none>;
> +			};

pcfg_pull_up again?
see ARM: dts: rockchip: pull up cts lines on rk3288 
(https://lkml.org/lkml/2015/9/2/612) for comparison


> +
> +			uart0_rts: uart0-rts {
> +				rockchip,pins = <0 19 RK_FUNC_1 &pcfg_pull_none>;
> +			};
> +		};
> +
> +		uart1 {
> +			uart1_xfer: uart1-xfer {
> +				rockchip,pins = <2 22 RK_FUNC_1 &pcfg_pull_none>,
> +						<2 23 RK_FUNC_1 &pcfg_pull_none>;
> +			};
> +			/* no rts / cts for uart1 */
> +		};
> +
> +                uart2 {
> +                        uart2_xfer: uart2-xfer {
> +                                rockchip,pins = <1 18 RK_FUNC_2
> &pcfg_pull_none>, +                                                <1 19
> RK_FUNC_2 &pcfg_pull_none>; +                        };
> +                        /* no rts / cts for uart2 */
> +                };

tabs please

> +
> +		pwm0 {
> +			pwm0_pin: pwm0-pin {
> +				rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
> +			};
> +		};
> +
> +		pwm1 {
> +			pwm1_pin: pwm1-pin {
> +				rockchip,pins = <0 1 RK_FUNC_2 &pcfg_pull_none>;
> +			};
> +		};
> +
> +		pwm2 {
> +			pwm2_pin: pwm2-pin {
> +				rockchip,pins = <0 1 2 &pcfg_pull_none>;
> +			};
> +		};
> +
> +		pwm3 {
> +			pwm3_pin: pwm3-pin {
> +				rockchip,pins = <0 27 1 &pcfg_pull_none>;
> +			};
> +		};
> +
> +		i2c1 {
> +			i2c1_xfer: i2c1-xfer {
> +				rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>,
> +						<0 3 RK_FUNC_1 &pcfg_pull_none>;
> +			};
> +		};
> +	};
> +
> +	i2c1: i2c@20056000 {
> +		compatible = "rockchip,rk3288-i2c";
> +		reg = <0x20056000 0x1000>;
> +		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clock-names = "i2c";
> +		clocks = <&cru PCLK_I2C1>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c1_xfer>;
> +		status = "disabled";
> +	};
> +};


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

* Re: [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036
  2015-09-17  8:28 ` [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036 Xing Zheng
@ 2015-09-17  9:25   ` Heiko Stübner
  2015-09-24  2:17     ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17  9:25 UTC (permalink / raw)
  To: Xing Zheng
  Cc: linux-rockchip, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, linux-kernel, devicetree

Am Donnerstag, 17. September 2015, 16:28:53 schrieb Xing Zheng:
> Add the dt-bindings header for the rk3036, that gets shared between
> the clock controller and the clock references in the dts.
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  include/dt-bindings/clock/rk3036-cru.h |  198
> ++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+)
>  create mode 100644 include/dt-bindings/clock/rk3036-cru.h
> 
> diff --git a/include/dt-bindings/clock/rk3036-cru.h
> b/include/dt-bindings/clock/rk3036-cru.h new file mode 100644
> index 0000000..b0033ef
> --- /dev/null
> +++ b/include/dt-bindings/clock/rk3036-cru.h
> @@ -0,0 +1,198 @@
> +/*
> + * Copyright (c) 2014 MundoReader S.L.
> + * Author: Heiko Stuebner <heiko@sntech.de>

you can probably drop that copyright line ... I didn't do anything here ;-)

> + *
> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
> + * Author: Xing Zheng <zhengxing@rock-chips.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
> +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
> +
> +/* core clocks */
> +#define PLL_APLL		1
> +#define PLL_DPLL		2
> +#define PLL_GPLL		3
> +#define ARMCLK			4
> +
> +/* sclk gates (special clocks) */

you have a lot of gaps in the numbering ... intentional?


otherwise
Reviewed-by: Heiko Stuebner <heiko@sntech.de>

> +#define SCLK_GPU		64
> +#define SCLK_SPI		65
> +#define SCLK_SDMMC		68
> +#define SCLK_SDIO		69
> +#define SCLK_EMMC		71
> +#define SCLK_NANDC		76
> +#define SCLK_UART0		77
> +#define SCLK_UART1		78
> +#define SCLK_UART2		79
> +#define SCLK_I2S		82
> +#define SCLK_SPDIF		83
> +#define SCLK_TIMER0		85
> +#define SCLK_TIMER1		86
> +#define SCLK_TIMER2		87
> +#define SCLK_TIMER3		88
> +#define SCLK_OTGPHY0		93
> +#define SCLK_OTGPHY1		94
> +#define SCLK_LCDC		100
> +#define SCLK_HDMI		109
> +#define SCLK_HEVC		111
> +#define SCLK_I2S_OUT		113
> +#define SCLK_SDMMC_DRV		114
> +#define SCLK_SDIO_DRV		115
> +#define SCLK_EMMC_DRV		117
> +#define SCLK_SDMMC_SAMPLE	118
> +#define SCLK_SDIO_SAMPLE	119
> +#define SCLK_EMMC_SAMPLE	121
> +#define SCLK_PVTM_CORE          123
> +#define SCLK_PVTM_GPU           124
> +#define SCLK_PVTM_VIDEO         125
> +#define SCLK_MAC		151
> +#define SCLK_MACREF		152
> +#define SCLK_SFC		160
> +
> +#define DCLK_LCDC		190
> +
> +/* aclk gates */
> +#define ACLK_DMAC2		194
> +#define ACLK_LCDC		197
> +#define ACLK_VIO		203
> +#define ACLK_VCODEC		208
> +#define ACLK_CPU		209
> +#define ACLK_PERI		210
> +
> +/* pclk gates */
> +#define PCLK_GPIO0		320
> +#define PCLK_GPIO1		321
> +#define PCLK_GPIO2		322
> +#define PCLK_GRF		329
> +#define PCLK_I2C0		332
> +#define PCLK_I2C1		333
> +#define PCLK_I2C2		334
> +#define PCLK_SPI		338
> +#define PCLK_UART0		341
> +#define PCLK_UART1		342
> +#define PCLK_UART2		343
> +#define PCLK_PWM		350
> +#define PCLK_TIMER		353
> +#define PCLK_HDMI		360
> +#define PCLK_CPU		362
> +#define PCLK_PERI		363
> +#define PCLK_DDRUPCTL		364
> +#define PCLK_WDT		368
> +
> +/* hclk gates */
> +#define HCLK_OTG0		449
> +#define HCLK_OTG1		450
> +#define HCLK_NANDC		453
> +#define HCLK_SDMMC		456
> +#define HCLK_SDIO		457
> +#define HCLK_EMMC		459
> +#define HCLK_I2S		462
> +#define HCLK_LCDC		465
> +#define HCLK_ROM		467
> +#define HCLK_VIO_BUS		472
> +#define HCLK_VCODEC		476
> +#define HCLK_CPU		477
> +#define HCLK_PERI		478
> +
> +#define CLK_NR_CLKS		(HCLK_PERI + 1)
> +
> +/* soft-reset indices */
> +#define SRST_CORE0		0
> +#define SRST_CORE1		1
> +#define SRST_CORE0_DBG		4
> +#define SRST_CORE1_DBG		5
> +#define SRST_CORE0_POR		8
> +#define SRST_CORE1_POR		9
> +#define SRST_L2C		12
> +#define SRST_TOPDBG		13
> +#define SRST_STRC_SYS_A		14
> +#define SRST_PD_CORE_NIU	15
> +
> +#define SRST_TIMER2		16
> +#define SRST_CPUSYS_H		17
> +#define SRST_AHB2APB_H		19
> +#define SRST_TIMER3		20
> +#define SRST_INTMEM		21
> +#define SRST_ROM		22
> +#define SRST_PERI_NIU		23
> +#define SRST_I2S		24
> +#define SRST_DDR_PLL		25
> +#define SRST_GPU_DLL		26
> +#define SRST_TIMER0		27
> +#define SRST_TIMER1		28
> +#define SRST_CORE_DLL		29
> +#define SRST_EFUSE_P		30
> +#define SRST_ACODEC_P		31
> +
> +#define SRST_GPIO0		32
> +#define SRST_GPIO1		33
> +#define SRST_GPIO2		34
> +#define SRST_UART0		39
> +#define SRST_UART1		40
> +#define SRST_UART2		41
> +#define SRST_I2C0		43
> +#define SRST_I2C1		44
> +#define SRST_I2C2		45
> +#define SRST_SFC		47
> +
> +#define SRST_PWM0		48
> +#define SRST_DAP		51
> +#define SRST_DAP_SYS		52
> +#define SRST_GRF		55
> +#define SRST_PERIPHSYS_A	57
> +#define SRST_PERIPHSYS_H	58
> +#define SRST_PERIPHSYS_P	59
> +#define SRST_CPU_PERI		61
> +#define SRST_EMEM_PERI		62
> +#define SRST_USB_PERI		63
> +
> +#define SRST_DMA2		64
> +#define SRST_MAC		66
> +#define SRST_NANDC		68
> +#define SRST_USBOTG0		69
> +#define SRST_OTGC0		71
> +#define SRST_USBOTG1		72
> +#define SRST_OTGC1		74
> +#define SRST_DDRMSCH		79
> +
> +#define SRST_MMC0		81
> +#define SRST_SDIO		82
> +#define SRST_EMMC		83
> +#define SRST_SPI0		84
> +#define SRST_WDT		86
> +#define SRST_DDRPHY		88
> +#define SRST_DDRPHY_P		89
> +#define SRST_DDRCTRL		90
> +#define SRST_DDRCTRL_P		91
> +
> +#define SRST_HDMI_P		96
> +#define SRST_VIO_BUS_H		99
> +#define SRST_UTMI0		103
> +#define SRST_UTMI1		104
> +#define SRST_USBPOR		105
> +
> +#define SRST_VCODEC_A		112
> +#define SRST_VCODEC_H		113
> +#define SRST_VIO1_A		114
> +#define SRST_HEVC		115
> +#define SRST_VCODEC_NIU_A	116
> +#define SRST_LCDC1_A		117
> +#define SRST_LCDC1_H		118
> +#define SRST_LCDC1_D		119
> +#define SRST_GPU		120
> +#define SRST_GPU_NIU_A		122
> +
> +#define SRST_DBG_P		131
> +
> +#endif


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

* Re: [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036
  2015-09-17  8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller " Xing Zheng
@ 2015-09-17  9:47   ` Heiko Stübner
  2015-09-24  3:04     ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17  9:47 UTC (permalink / raw)
  To: Xing Zheng
  Cc: linux-rockchip, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-clk, linux-arm-kernel

Hi,

Am Donnerstag, 17. September 2015, 16:28:54 schrieb Xing Zheng:
> Add the clock tree definition for the new rk3036 SoC.
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>

missing a dt-bindings document in a separate patch. See "dt-bindings: add 
documentation of rk3668 clock controller" 
(http://lists.infradead.org/pipermail/linux-rockchip/2015-July/003396.html) 
for comparison.


> ---
> 
> Changes in v2: None
> 
>  drivers/clk/rockchip/Makefile     |    1 +
>  drivers/clk/rockchip/clk-rk3036.c |  504
> +++++++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h        |  
> 30 +++
>  3 files changed, 535 insertions(+)
>  create mode 100644 drivers/clk/rockchip/clk-rk3036.c
> 
> diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
> index b27edd6..d599829 100644
> --- a/drivers/clk/rockchip/Makefile
> +++ b/drivers/clk/rockchip/Makefile
> @@ -10,6 +10,7 @@ obj-y	+= clk-inverter.o
>  obj-y	+= clk-mmc-phase.o
>  obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
> 
> +obj-y	+= clk-rk3036.o
>  obj-y	+= clk-rk3188.o
>  obj-y	+= clk-rk3288.o
>  obj-y	+= clk-rk3368.o
> diff --git a/drivers/clk/rockchip/clk-rk3036.c
> b/drivers/clk/rockchip/clk-rk3036.c new file mode 100644
> index 0000000..724d467
> --- /dev/null
> +++ b/drivers/clk/rockchip/clk-rk3036.c
> @@ -0,0 +1,504 @@
> +/*
> + * Copyright (c) 2014 MundoReader S.L.
> + * Author: Heiko Stuebner <heiko@sntech.de>
> + *
> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
> + * Author: Xing Zheng <zhengxing@rock-chips.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/syscore_ops.h>
> +#include <dt-bindings/clock/rk3036-cru.h>
> +#include "clk.h"
> +
> +enum rk3036_plls {
> +	apll, dpll, gpll,
> +};
> +
> +static struct rockchip_pll_rate_table rk3036_pll_rates[] = {
> +	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
> +	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
> +	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
> +	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
> +	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
> +	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
> +	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
> +	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
> +	RK3036_PLL_RATE(0, 1, 0, 1, 1, 1, 0),

you shouldn't need a "0" rate entry I guess


> +	{ /* sentinel */ },
> +};
> +
> +#define RK3036_DIV_CPU_MASK		0x1f
> +#define RK3036_DIV_CPU_SHIFT		8
> +
> +#define RK3036_DIV_PERI_MASK		0xf
> +#define RK3036_DIV_PERI_SHIFT		0
> +#define RK3036_DIV_ACLK_MASK		0x7
> +#define RK3036_DIV_ACLK_SHIFT		4
> +#define RK3036_DIV_HCLK_MASK		0x3
> +#define RK3036_DIV_HCLK_SHIFT		8
> +#define RK3036_DIV_PCLK_MASK		0x7
> +#define RK3036_DIV_PCLK_SHIFT		12
> +
> +#define RK3036_CLKSEL1(_core_periph_div)					\
> +	{									\
> +		.reg = RK2928_CLKSEL_CON(1),					\
> +		.val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK,	\
> +				RK3036_DIV_PERI_SHIFT)				\
> +	}
> +
> +#define RK3036_CPUCLK_RATE(_prate, _core_periph_div)			\
> +	{								\
> +		.prate = _prate,					\
> +		.divs = {						\
> +			RK3036_CLKSEL1(_core_periph_div),		\
> +		},							\
> +	}
> +
> +static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata =
> { +	RK3036_CPUCLK_RATE(816000000, 4),
> +	RK3036_CPUCLK_RATE(600000000, 4),
> +	RK3036_CPUCLK_RATE(312000000, 4),
> +};
> +
> +static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
> +	.core_reg = RK2928_CLKSEL_CON(0),
> +	.div_core_shift = 0,
> +	.div_core_mask = 0x1f,
> +	.mux_core_shift = 7,
> +};
> +
> +PNAME(mux_pll_p)		= { "xin24m", "xin24m" };

looks like you overlooked the divider? Like

DIV(0, "xin24m_plldiv", "xin24m", 0,
		RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),

PNAME(mux_pll_p)		= { "xin24m_plldiv", "xin24m" };

> +
> +PNAME(mux_armclk_p)		= { "apll", "gpll_armclk" };
> +PNAME(mux_busclk_p)		= { "apll", "dpll_cpu", "gpll_cpu" };

[...]

> +	/*
> +	 * Clock-Architecture Diagram 3
> +	 */
> +
> +	/* aclk_cpu gates */
> +	GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(4), 12, GFLAGS), +	GATE(0, "aclk_strc_sys", "aclk_cpu",
> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS), +
> +	/* hclk_cpu gates */
> +	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(5), 6, GFLAGS), +
> +	/* pclk_cpu gates */
> +	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(5), 4, GFLAGS), +	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl",
> "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), +	GATE(ACLK_VCODEC,
> "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
> +	GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8,
> GFLAGS), +
> +	/* aclk_vio gates */
> +	GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", 0,
> +			RK2928_CLKGATE_CON(6), 13, GFLAGS),
> +	GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0,
> +			RK2928_CLKGATE_CON(9), 6, GFLAGS),
> +
> +	GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0,
> +			RK2928_CLKGATE_CON(6), 12, GFLAGS),
> +	GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0,
> +			RK2928_CLKGATE_CON(9), 5, GFLAGS),
> +
> +	/* aclk_video gates */
> +	GATE(HCLK_LCDC, "hclk_vcodec", "hclk_disp_pre", 0,
> +			RK2928_CLKGATE_CON(3), 12, GFLAGS),

in big gate-block from diagram 3, please stick to the one-line format, like 
the rest of the gates here (diagram3 only)

> +
> +	/* xin24m gates */
> +	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0,
> RK2928_CLKGATE_CON(10), 0, GFLAGS), +	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu",
> "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS), +
> +	/* aclk_peri gates */
> +	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(4), 3, GFLAGS), +	GATE(0, "aclk_cpu_peri", "aclk_peri",
> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), +	GATE(ACLK_DMAC2,
> "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), +	GATE(0,
> "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15,
> GFLAGS), +
> +	/* hclk_peri gates */
> +	GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(4), 0, GFLAGS), +	GATE(0, "hclk_usb_peri", "hclk_peri",
> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS), +	GATE(0,
> "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9),
> 14, GFLAGS), +	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0,
> RK2928_CLKGATE_CON(5), 9, GFLAGS), +	GATE(HCLK_SDMMC, "hclk_sdmmc",
> "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS), +	GATE(HCLK_SDIO,
> "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
> +	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0,
> GFLAGS), +	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(5), 13, GFLAGS), +	GATE(HCLK_OTG1, "hclk_otg1",
> "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 13, GFLAGS),
> +	GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(7), 2, GFLAGS), +	GATE(0, "hclk_sfc", "hclk_peri",
> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), +	GATE(0,
> "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15,
> GFLAGS), +
> +	/* pclk_peri gates */
> +	GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED,
> RK2928_CLKGATE_CON(4), 1, GFLAGS), +	GATE(0, "pclk_efuse", "pclk_peri",
> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), +	GATE(PCLK_TIMER,
> "pclk_timer0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
> +	GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10,
> GFLAGS), +	GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0,
> RK2928_CLKGATE_CON(7), 12, GFLAGS), +	GATE(PCLK_WDT, "pclk_wdt",
> "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), +	GATE(PCLK_UART0,
> "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
> +	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1,
> GFLAGS), +	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0,
> RK2928_CLKGATE_CON(8), 2, GFLAGS), +	GATE(PCLK_I2C0, "pclk_i2c0",
> "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), +	GATE(PCLK_I2C1,
> "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
> +	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6,
> GFLAGS), +	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0,
> RK2928_CLKGATE_CON(8), 9, GFLAGS), +	GATE(PCLK_GPIO1, "pclk_gpio1",
> "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), +	GATE(PCLK_GPIO2,
> "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), +};
> +
> +static const char *const rk3036_critical_clocks[] __initconst = {
> +	"aclk_cpu",
> +	"aclk_peri",
> +	"hclk_peri",
> +	"pclk_peri",
> +};
> +
> +static void __init rk3036_clk_init(struct device_node *np)
> +{
> +	void __iomem *reg_base;
> +	struct clk *clk;
> +
> +	reg_base = of_iomap(np, 0);
> +	if (!reg_base) {
> +		pr_err("%s: could not map cru region\n", __func__);
> +		return;
> +	}
> +
> +	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
> +
> +	/* xin12m is created by an cru-internal divider */
> +	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
> +	if (IS_ERR(clk))
> +		pr_warn("%s: could not register clock xin12m: %ld\n",
> +			__func__, PTR_ERR(clk));
> +
> +	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> +	if (IS_ERR(clk))
> +		pr_warn("%s: could not register clock usb480m: %ld\n",
> +			__func__, PTR_ERR(clk));
> +
> +	clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
> +	if (IS_ERR(clk))
> +		pr_warn("%s: could not register clock ddrphy: %ld\n",
> +			__func__, PTR_ERR(clk));
> +
> +	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
> +					"aclk_vcodec", 0, 1, 4);
> +	if (IS_ERR(clk))
> +		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
> +			__func__, PTR_ERR(clk));
> +
> +	clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
> +					"hclk_peri_src", 0, 1, 2);
> +	if (IS_ERR(clk))
> +		pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
> +			__func__, PTR_ERR(clk));
> +
> +	rockchip_clk_register_plls(rk3036_pll_clks,
> +				   ARRAY_SIZE(rk3036_pll_clks),
> +				   -1);
> +	rockchip_clk_register_branches(rk3036_clk_branches,
> +				  ARRAY_SIZE(rk3036_clk_branches));
> +	rockchip_clk_protect_critical(rk3036_critical_clocks,
> +				      ARRAY_SIZE(rk3036_critical_clocks));
> +
> +	rockchip_clk_register_armclk(ARMCLK, "armclk",
> +			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
> +			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
> +			ARRAY_SIZE(rk3036_cpuclk_rates));
> +
> +	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
> +				  ROCKCHIP_SOFTRST_HIWORD_MASK);
> +
> +	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
> +}
> +CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
> diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
> index dc8ecb2..6603c07 100644
> --- a/drivers/clk/rockchip/clk.h
> +++ b/drivers/clk/rockchip/clk.h
> @@ -2,6 +2,9 @@
>   * Copyright (c) 2014 MundoReader S.L.
>   * Author: Heiko Stuebner <heiko@sntech.de>
>   *
> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
> + * Author: Xing Zheng <zhengxing@rock-chips.com>
> + *
>   * based on
>   *
>   * samsung/clk.h
> @@ -40,6 +43,13 @@ struct clk;
>  #define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
>  #define RK2928_MISC_CON		0x134
> 
> +#define RK3036_SDMMC_CON0		0x144
> +#define RK3036_SDMMC_CON1		0x148
> +#define RK3036_SDIO_CON0		0x14c
> +#define RK3036_SDIO_CON1		0x150
> +#define RK3036_EMMC_CON0		0x154
> +#define RK3036_EMMC_CON1		0x158
> +
>  #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
>  #define RK3288_MODE_CON			0x50
>  #define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
> @@ -75,6 +85,7 @@ struct clk;
> 
>  enum rockchip_pll_type {
>  	pll_rk3066,
> +	pll_rk3036,

this should be part of the addition of the pll type (your patch4, and should 
be reordered accordingly)

Also please all 3036 before the 3066 entry


>  };
> 
>  #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
> @@ -95,12 +106,31 @@ enum rockchip_pll_type {
>  	.nb = _nb,						\
>  }
> 
> +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
> +			_postdiv2, _dsmpd, _frac)		\
> +{								\
> +	.rate	= _rate##U,					\
> +	.fbdiv = _fbdiv,					\
> +	.postdiv1 = _postdiv1,					\
> +	.refdiv = _refdiv,					\
> +	.postdiv2 = _postdiv2,					\
> +	.dsmpd = _dsmpd,					\
> +	.frac = _frac,						\
> +}
> +
>  struct rockchip_pll_rate_table {
>  	unsigned long rate;
>  	unsigned int nr;
>  	unsigned int nf;
>  	unsigned int no;
>  	unsigned int nb;
> +	/* for RK3036 */
> +	unsigned int fbdiv;
> +	unsigned int postdiv1;
> +	unsigned int refdiv;
> +	unsigned int postdiv2;
> +	unsigned int dsmpd;
> +	unsigned int frac;

same for these 2 ... should be part of the pll addition itself

>  };
> 
>  /**


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

* Re: [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-17  8:28 ` [PATCH v2 4/9] clk: rockchip: add new clock type and " Xing Zheng
@ 2015-09-17  9:54   ` Heiko Stübner
  2015-09-22 22:41   ` Stephen Boyd
  1 sibling, 0 replies; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17  9:54 UTC (permalink / raw)
  To: Xing Zheng
  Cc: linux-rockchip, Michael Turquette, Stephen Boyd, linux-clk,
	linux-arm-kernel, linux-kernel

Hi,

Am Donnerstag, 17. September 2015, 16:28:55 schrieb Xing Zheng:
> The rk3036's pll and clock are different with base on the rk3066(rk3188,
> rk3288, rk3368 use it), there are different adjust foctors and control
> registers, so these should be independent and separate from the series
> of rk3066s.
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  drivers/clk/rockchip/clk-pll.c |  262
> +++++++++++++++++++++++++++++++++++++++- 1 file changed, 261 insertions(+),
> 1 deletion(-)
> 
> diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
> index 7737a1d..25b066a 100644
> --- a/drivers/clk/rockchip/clk-pll.c
> +++ b/drivers/clk/rockchip/clk-pll.c
> @@ -2,6 +2,9 @@
>   * Copyright (c) 2014 MundoReader S.L.
>   * Author: Heiko Stuebner <heiko@sntech.de>
>   *
> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
> + * Author: Xing Zheng <zhengxing@rock-chips.com>
> + *
>   * 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
> @@ -19,6 +22,7 @@
>  #include <linux/delay.h>
>  #include <linux/clk-provider.h>
>  #include <linux/regmap.h>
> +#include <linux/clk.h>
>  #include "clk.h"
> 
>  #define PLL_MODE_MASK		0x3
> @@ -306,6 +310,256 @@ static void rockchip_rk3066_pll_init(struct clk_hw
> *hw) }
>  }
> 
> +/**
> + * PLL used in RK3036
> + */
> +
> +#define RK3036_PLLCON(i)			(i * 0x4)
> +#define RK3036_PLLCON0_FBDIV_MASK		0xfff
> +#define RK3036_PLLCON0_FBDIV_SHIFT		0
> +#define RK3036_PLLCON0_POSTDIV1_MASK		0x7
> +#define RK3036_PLLCON0_POSTDIV1_SHIFT		12
> +#define RK3036_PLLCON1_REFDIV_MASK		0x3f
> +#define RK3036_PLLCON1_REFDIV_SHIFT		0
> +#define RK3036_PLLCON1_POSTDIV2_MASK		0x7
> +#define RK3036_PLLCON1_POSTDIV2_SHIFT		6
> +#define RK3036_PLLCON1_DSMPD_MASK		0x1
> +#define RK3036_PLLCON1_DSMPD_SHIFT		12
> +#define RK3036_PLLCON2_FRAC_MASK		0xffffff
> +#define RK3036_PLLCON2_FRAC_SHIFT		0
> +
> +#define RK3036_PLLCON1_PWRDOWN			(1 << 13)
> +#define RK3036_PLLCON1_LOCK_STATUS		(1 << 10)
> +
> +static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll)
> +{
> +	u32 pllcon;
> +	int delay = 24000000;
> +
> +	/* poll check the lock status in rk3036 xPLLCON1 */
> +	while (delay > 0) {
> +		pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
> +		if (pllcon & RK3036_PLLCON1_LOCK_STATUS)
> +			return 0;
> +
> +		delay--;
> +	}
> +
> +	pr_err("%s: timeout waiting for pll to lock\n", __func__);
> +	return -ETIMEDOUT;
> +}

Just saw that you responded to this in the v1 thread.

I don't necessarily object to this new lock function ... but if both the 
PLLCON1 and GRF_SOC_STATUS0 register provide the same information, I'd prefer 
to use the already existing solution.

[...]

> @@ -363,7 +617,7 @@ struct clk *rockchip_clk_register_pll(enum
> rockchip_pll_type pll_type, pll_mux->lock = lock;
>  	pll_mux->hw.init = &init;
> 
> -	if (pll_type == pll_rk3066)
> +	if (pll_type == pll_rk3066 || pll_type == pll_rk3036)

ordering please :-) (3036 before 3066)

>  		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
> 
>  	/* the actual muxing is xin24m, pll-output, xin32k */
> @@ -414,6 +668,12 @@ struct clk *rockchip_clk_register_pll(enum
> rockchip_pll_type pll_type, else
>  			init.ops = &rockchip_rk3066_pll_clk_ops;
>  		break;
> +	case pll_rk3036:
> +		if (!pll->rate_table)
> +			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
> +		else
> +			init.ops = &rockchip_rk3036_pll_clk_ops;
> +		break;

same here, 3036 before 3066 please


>  	default:
>  		pr_warn("%s: Unknown pll type for pll clk %s\n",
>  			__func__, name);


apart from these small issues, this looks great :-)


Thanks
Heiko

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

* Re: [PATCH v2 0/9] Build and support rk3036 SoC platform
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (3 preceding siblings ...)
  2015-09-17  8:28 ` [PATCH v2 4/9] clk: rockchip: add new clock type and " Xing Zheng
@ 2015-09-17  9:59 ` Heiko Stübner
  2015-09-17 10:32 ` [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller Xing Zheng
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17  9:59 UTC (permalink / raw)
  To: Xing Zheng
  Cc: linux-rockchip, Russell King, Michael Turquette,
	Alessandro Zummo, devicetree, Stephen Boyd, linux-gpio,
	Linus Walleij, Alexandre Belloni, Kumar Gala, linux-kernel,
	Ian Campbell, Rob Herring, Pawel Moll, rtc-linux, Mark Rutland,
	linux-clk, linux-arm-kernel

Hi,

Am Donnerstag, 17. September 2015, 16:28:51 schrieb Xing Zheng:
> we need to support rk3036 soc platform via upstream, there are
> 3 primary parts for the initial release of minimum system: dts,
> pinctrl, and clock tree for rk3036, and additional, add a rtc
> hym8563 patch to fix initial invaild, we can use these startup
> and run to init processs.
> 
> Thanks.
> 
> changed in v2:
> - based on v1, add clock controller documentation
> - enable timer5 startup
> - add smp for cpu1
> - initial set time for rtc-hym8563
> 
> changes since v1:
> - add dts, pinctrl and clock tree for rk3036 soc platform
> 
> The patchset (9):
> 9) rtc: hym8563: make sure hym8563 can be normal work
> 8) ARM: rockchip: add support smp for rk3036
> 7) rockchip: make sure timer5 is enabled on rk3036 platforms
> 6) pinctrl: rockchip: add support for the rk3036
> 5) dt-bindings: add documentation of rk3036 clock controller
> 4) clk: rockchip: add new clock type and controller for rk3036
> 3) clk: rockchip: add clock controller for rk3036
> 2) clk: rockchip: add dt-binding header for rk3036
> 1) ARM: dts: rockchip: add core rk3036 dts
> 
> 
> Changes in v2:
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> 
> Xing Zheng (9):
>   ARM: dts: rockchip: add core rk3036 dts
>   clk: rockchip: add dt-binding header for rk3036
>   clk: rockchip: add clock controller for rk3036
>   clk: rockchip: add new clock type and controller for rk3036
>   dt-bindings: add documentation of rk3036 clock controller
>   pinctrl: rockchip: add support for the rk3036
>   rockchip: make sure timer5 is enabled on rk3036 platforms
>   ARM: rockchip: add support smp for rk3036
>   rtc: hym8563: make sure hym8563 can be normal work

am I missing some patches? I only got patches 1-4.

Anyway, you should reorder a bit

- whatever other patches are necessary before
- dt-bindings: add documentation of rk3036 clock controller
- clk: rockchip: add dt-binding header for rk3036
- clk: rockchip: add new pll type for rk3036
-  clk: rockchip: add clock controller for rk3036
- ARM: dts: rockchip: add core rk3036 dts

The dts patch for example depends on the clock-header, so it really should 
come after its addition.


Heiko

> 
>  .../bindings/clock/rockchip,rk3036-cru.txt         |   60 +++
>  .../bindings/pinctrl/rockchip,pinctrl.txt          |    1 +
>  arch/arm/boot/dts/Makefile                         |    1 +
>  arch/arm/boot/dts/rk3036-sdk.dts                   |   62 +++
>  arch/arm/boot/dts/rk3036.dtsi                      |  381 +++++++++++++++
>  arch/arm/mach-rockchip/platsmp.c                   |  121 +++++
>  arch/arm/mach-rockchip/rockchip.c                  |   22 +
>  drivers/clk/rockchip/Makefile                      |    1 +
>  drivers/clk/rockchip/clk-pll.c                     |  262 +++++++++-
>  drivers/clk/rockchip/clk-rk3036.c                  |  504
> ++++++++++++++++++++ drivers/clk/rockchip/clk.h                         |  
> 30 ++
>  drivers/pinctrl/pinctrl-rockchip.c                 |   17 +
>  drivers/rtc/rtc-hym8563.c                          |   93 ++++
>  include/dt-bindings/clock/rk3036-cru.h             |  198 ++++++++
>  14 files changed, 1752 insertions(+), 1 deletion(-)
>  create mode 100644
> Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt create mode
> 100644 arch/arm/boot/dts/rk3036-sdk.dts
>  create mode 100644 arch/arm/boot/dts/rk3036.dtsi
>  create mode 100644 drivers/clk/rockchip/clk-rk3036.c
>  create mode 100644 include/dt-bindings/clock/rk3036-cru.h


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

* [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (4 preceding siblings ...)
  2015-09-17  9:59 ` [PATCH v2 0/9] Build and support rk3036 SoC platform Heiko Stübner
@ 2015-09-17 10:32 ` Xing Zheng
  2015-09-17 15:09   ` Heiko Stübner
  2015-09-17 10:34 ` [PATCH v2 6/9] pinctrl: rockchip: add support for the rk3036 Xing Zheng
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17 10:32 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	zhengxing, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

Add the devicetree binding for the cru on the rk3036 which quite similar
structured as previous clock controllers.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 .../bindings/clock/rockchip,rk3036-cru.txt         |   60 ++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt

diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
new file mode 100644
index 0000000..ac3037a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
@@ -0,0 +1,60 @@
+* Rockchip RK3036 Clock and Reset Unit
+
+The RK3036 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3036-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3036-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_vip" - external VIP clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+
+Example: Clock controller node:
+
+	cru: cru@20000000 {
+		compatible = "rockchip,rk3036-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial@20060000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x20060000 0x100>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART0>;
+	};
-- 
1.7.9.5



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

* [PATCH v2 6/9] pinctrl: rockchip: add support for the rk3036
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (5 preceding siblings ...)
  2015-09-17 10:32 ` [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller Xing Zheng
@ 2015-09-17 10:34 ` Xing Zheng
  2015-09-17 12:47   ` Heiko Stübner
  2015-09-17 10:37 ` [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms Xing Zheng
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17 10:34 UTC (permalink / raw)
  To: heiko
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	zhengxing, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, linus.walleij, linux-gpio

Add new type for rk3036 and many parts of pinctrl rk3036 are similar
with rk2928's.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 .../bindings/pinctrl/rockchip,pinctrl.txt          |    1 +
 drivers/pinctrl/pinctrl-rockchip.c                 |   17 +++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
index 391ef4b..c73f2bb 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
@@ -22,6 +22,7 @@ Required properties for iomux controller:
   - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
 		       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
 		       "rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
+		       "rockchip,rk3036-pinctrl"
   - rockchip,grf: phandle referencing a syscon providing the
 	 "general register files"
 
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index c5246c0..9c49510 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -2089,6 +2089,21 @@ static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3036_pin_banks[] = {
+	PIN_BANK(0, 32, "gpio0"),
+	PIN_BANK(1, 32, "gpio1"),
+	PIN_BANK(2, 32, "gpio2"),
+};
+
+static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
+		.pin_banks		= rk3036_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3036_pin_banks),
+		.label			= "RK3036-GPIO",
+		.type			= RK2928,
+		.grf_mux_offset		= 0xa8,
+		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
+};
+
 static struct rockchip_pin_bank rk3066a_pin_banks[] = {
 	PIN_BANK(0, 32, "gpio0"),
 	PIN_BANK(1, 32, "gpio1"),
@@ -2207,6 +2222,8 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
 	{ .compatible = "rockchip,rk2928-pinctrl",
 		.data = (void *)&rk2928_pin_ctrl },
+	{ .compatible = "rockchip,rk3036-pinctrl",
+		.data = (void *)&rk3036_pin_ctrl },
 	{ .compatible = "rockchip,rk3066a-pinctrl",
 		.data = (void *)&rk3066a_pin_ctrl },
 	{ .compatible = "rockchip,rk3066b-pinctrl",
-- 
1.7.9.5



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

* [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (6 preceding siblings ...)
  2015-09-17 10:34 ` [PATCH v2 6/9] pinctrl: rockchip: add support for the rk3036 Xing Zheng
@ 2015-09-17 10:37 ` Xing Zheng
  2015-09-17 15:05   ` Heiko Stübner
  2015-09-17 10:38 ` [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036 Xing Zheng
  2015-09-17 10:39 ` [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work Xing Zheng
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17 10:37 UTC (permalink / raw)
  To: heiko; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel, zhengxing

The timer5 supplies the architected timer and thus as has to run when
the system clocksource and clockevents drivers are registered.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 arch/arm/mach-rockchip/rockchip.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index b6cf3b4..937047f 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -32,6 +32,8 @@
 #define RK3288_GRF_SOC_CON0 0x244
 #define RK3288_TIMER6_7_PHYS 0xff810000
 
+#define RK3036_TIMER5_PHYS 0x200440a0
+
 static void __init rockchip_timer_init(void)
 {
 	if (of_machine_is_compatible("rockchip,rk3288")) {
@@ -64,6 +66,25 @@ static void __init rockchip_timer_init(void)
 			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
 		else
 			pr_err("rockchip: could not get grf syscon\n");
+	} else if (of_machine_is_compatible("rockchip,rk3036")) {
+		void __iomem *reg_base;
+
+		/*
+		 * Most/all uboot versions for rk3036 don't enable timer5
+		 * which is needed for the architected timer to work.
+		 * So make sure it is running during early boot.
+		 */
+		reg_base = ioremap(RK3036_TIMER5_PHYS, SZ_16K);
+		if (reg_base) {
+			writel(0, reg_base + 0x10);
+			writel(0xffffffff, reg_base);
+			writel(0xffffffff, reg_base + 0x04);
+			writel(1, reg_base + 0x10);
+			dsb();
+			iounmap(reg_base);
+		} else {
+			pr_err("rockchip: could not map timer5 registers\n");
+		}
 	}
 
 	of_clk_init(NULL);
@@ -79,6 +100,7 @@ static void __init rockchip_dt_init(void)
 
 static const char * const rockchip_board_dt_compat[] = {
 	"rockchip,rk2928",
+	"rockchip,rk3036",
 	"rockchip,rk3066a",
 	"rockchip,rk3066b",
 	"rockchip,rk3188",
-- 
1.7.9.5



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

* [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (7 preceding siblings ...)
  2015-09-17 10:37 ` [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms Xing Zheng
@ 2015-09-17 10:38 ` Xing Zheng
  2015-09-17 20:15   ` Heiko Stübner
  2015-09-17 10:39 ` [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work Xing Zheng
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17 10:38 UTC (permalink / raw)
  To: heiko; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel, zhengxing

The rk3036 is dual-core soc, we can use this patch to enable cpu1
enter boot secondary, and hotplug(online/offline).

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

Changes in v2: None

 arch/arm/mach-rockchip/platsmp.c |  121 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 3e7a4b7..14218eb 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -34,6 +34,8 @@
 
 static void __iomem *scu_base_addr;
 static void __iomem *sram_base_addr;
+static void __iomem *cru_base_addr;
+
 static int ncores;
 
 #define PMU_PWRDN_CON		0x08
@@ -41,6 +43,8 @@ static int ncores;
 
 #define PMU_PWRDN_SCU		4
 
+#define RK3036_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
+
 static struct regmap *pmu;
 
 static int pmu_power_domain_is_on(int pd)
@@ -184,6 +188,7 @@ static int __init rockchip_smp_prepare_sram(struct device_node *node)
 	}
 
 	rsize = resource_size(&res);
+
 	if (rsize < trampoline_sz) {
 		pr_err("%s: reserved block with size 0x%x is to small for trampoline size 0x%x\n",
 		       __func__, rsize, trampoline_sz);
@@ -350,3 +355,119 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 };
 
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
+
+/* for rk3036 */
+
+static int rk3036_set_power_domain(int pd, bool on)
+{
+	/* there are 2cpus on rk3036 soc, we just need to be care cpu1 */
+	if (pd != 1)
+		return 0;
+
+	if (on)
+		writel_relaxed(0x20000, cru_base_addr + RK3036_SOFTRST_CON(0));
+	else
+		writel_relaxed(0x20002, cru_base_addr + RK3036_SOFTRST_CON(0));
+
+	dsb();
+
+	return 0;
+}
+
+static void __init rk3036_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *node;
+	unsigned int l2ctlr;
+	unsigned int i, cpu;
+
+	/* get cru_base_addr */
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3036-cru");
+	if (!node) {
+		pr_err("%s: could not find cru dt node\n", __func__);
+		return;
+	}
+
+	cru_base_addr = of_iomap(node, 0);
+	if (!cru_base_addr) {
+		pr_err("%s: could not map cru registers\n", __func__);
+		return;
+	}
+
+	/* get sram_base_addr */
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3036-smp-sram");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	sram_base_addr = of_iomap(node, 0);
+	if (!sram_base_addr) {
+		pr_err("%s: could not map sram registers\n", __func__);
+		return;
+	}
+
+	/* get ncores */
+	asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
+	ncores = ((l2ctlr >> 24) & 0x3) + 1;
+	cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 0);
+
+	/* Make sure that all cores except the first are really off */
+	for (i = 1; i < ncores; i++)
+		rk3036_set_power_domain(0 + i, false);
+}
+
+static int rk3036_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	if (cpu >= ncores) {
+		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
+			__func__, cpu, ncores);
+		return -ENXIO;
+	}
+
+	/* start the core */
+	rk3036_set_power_domain(0 + cpu, true);
+
+	/*
+	 * We need to wait a moment after soft reset CPUx on rk3036,
+	 * otherwise, CPUx will startup failed.
+	 */
+	udelay(10);
+	writel(virt_to_phys(secondary_startup), sram_base_addr + 8);
+	writel(0xDEADBEAF, sram_base_addr + 4);
+	dsb_sev();
+
+	return 0;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int rk3066_cpu_kill(unsigned int cpu)
+{
+	/*
+	 * We need a delay here to ensure that the dying CPU can finish
+	 * executing v7_coherency_exit() and reach the WFI/WFE state
+	 * prior to having the power domain disabled.
+	 */
+	mdelay(1);
+
+	rk3036_set_power_domain(0 + cpu, false);
+
+	return 1;
+}
+
+static void rk3066_cpu_die(unsigned int cpu)
+{
+	v7_exit_coherency_flush(louis);
+	while (1)
+		cpu_do_idle();
+}
+#endif
+
+static struct smp_operations rk3036_smp_ops __initdata = {
+	.smp_prepare_cpus	= rk3036_smp_prepare_cpus,
+	.smp_boot_secondary	= rk3036_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_kill		= rk3066_cpu_kill,
+	.cpu_die		= rk3066_cpu_die,
+#endif
+};
+CPU_METHOD_OF_DECLARE(rk3036_smp, "rockchip,rk3036-smp", &rk3036_smp_ops);
-- 
1.7.9.5



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

* [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work
  2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
                   ` (8 preceding siblings ...)
  2015-09-17 10:38 ` [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036 Xing Zheng
@ 2015-09-17 10:39 ` Xing Zheng
  2015-09-17 12:07   ` Heiko Stübner
  9 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-17 10:39 UTC (permalink / raw)
  To: heiko; +Cc: a.zummo, alexandre.belloni, rtc-linux, linux-kernel, zhengxing

The rtc hym8563 maybe failed to register if first startup or rtc
powerdown:
[    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
[    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
[    1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available
[    1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware clock

We can set initial time for rtc and register it:
[    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
[    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01 00:02:00 UTC (946684920)

---

Changes in v2:
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>

 drivers/rtc/rtc-hym8563.c |   93 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index 097325d..ea37fdf 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -83,6 +83,8 @@
 
 #define HYM8563_TMR_CNT		0x0f
 
+#define HYM8563_RTC_SECTION_LEN	0x07
+
 struct hym8563 {
 	struct i2c_client	*client;
 	struct rtc_device	*rtc;
@@ -527,9 +529,77 @@ static int hym8563_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
 
+static int hym8563_set_time(struct i2c_client *client, struct rtc_time *tm)
+{
+	u8 regs[HYM8563_RTC_SECTION_LEN] = {0};
+	u8 mon_day;
+	int ret = 0;
+
+	dev_dbg(&client->dev, "%s -- %4d-%02d-%02d(%d) %02d:%02d:%02d\n", __func__,
+		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	mon_day = rtc_month_days((tm->tm_mon), tm->tm_year + 1900);
+
+	if (tm->tm_sec >= 60 || tm->tm_sec < 0)
+		regs[0x00] = bin2bcd(0x00);
+	else
+		regs[0x00] = bin2bcd(tm->tm_sec);
+
+	if (tm->tm_min >= 60 || tm->tm_min < 0)
+		regs[0x01] = bin2bcd(0x00);
+	else
+		regs[0x01] = bin2bcd(tm->tm_min);
+
+	if (tm->tm_hour >= 24 || tm->tm_hour < 0)
+		regs[0x02] = bin2bcd(0x00);
+	else
+		regs[0x02] = bin2bcd(tm->tm_hour);
+
+	if ((tm->tm_mday) > mon_day)
+		regs[0x03] = bin2bcd(mon_day);
+	else if ((tm->tm_mday) > 0)
+		regs[0x03] = bin2bcd(tm->tm_mday);
+	else if ((tm->tm_mday) <= 0)
+		regs[0x03] = bin2bcd(0x01);
+
+	if (tm->tm_year >= 200)
+		regs[0x06] = bin2bcd(99);
+	else if (tm->tm_year >= 100)
+		regs[0x06] = bin2bcd(tm->tm_year - 100);
+	else if (tm->tm_year >= 0) {
+		regs[0x06] = bin2bcd(tm->tm_year);
+		regs[0x05] |= 0x80;
+	} else {
+		regs[0x06] = bin2bcd(0);
+		regs[0x05] |= 0x80;
+	}
+
+	regs[0x04] = bin2bcd(tm->tm_wday);
+	regs[0x05] = (regs[0x05] & 0x80) | (bin2bcd(tm->tm_mon + 1) & 0x7F);
+
+	ret = i2c_smbus_write_byte_data(client, HYM8563_SEC, *regs);
+	if (ret < 0) {
+		dev_err(&client->dev, "%s: error writing i2c data %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int hym8563_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct rtc_time tm_read, tm = {
+		.tm_sec = 0,
+		.tm_min = 0,
+		.tm_hour = 12,
+		.tm_mday = 1,
+		.tm_mon = 0,
+		.tm_year = 111,
+		.tm_wday = 6,
+	};
 	struct hym8563 *hym8563;
 	int ret;
 
@@ -562,6 +632,7 @@ static int hym8563_probe(struct i2c_client *client,
 
 	/* check state of calendar information */
 	ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
+
 	if (ret < 0)
 		return ret;
 
@@ -569,6 +640,28 @@ static int hym8563_probe(struct i2c_client *client,
 	dev_dbg(&client->dev, "rtc information is %s\n",
 		hym8563->valid ? "valid" : "invalid");
 
+	if (!hym8563->valid) {
+		ret = hym8563_set_time(client, &tm);
+		if (ret < 0) {
+			dev_err(&client->dev, "rtc set time failed, %d\n", ret);
+			return ret;
+		}
+
+		hym8563->valid = true;
+	}
+
+	/* read current time */
+	ret = hym8563_rtc_read_time(&client->dev, &tm_read);
+	if (ret < 0) {
+		dev_err(&client->dev, "rtc read time failed, %d\n", ret);
+		return ret;
+	}
+
+	dev_dbg(&client->dev, "tm_sec = %d, tm_min = %d, tm_hour = %d,tm_mday = %d\n",
+		tm_read.tm_sec, tm_read.tm_min, tm_read.tm_hour, tm_read.tm_mday);
+	dev_dbg(&client->dev, "tm_mon = %d, tm_year = %d, tm_wday = %d\n",
+		tm_read.tm_mon, tm_read.tm_year, tm_read.tm_wday);
+
 	hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
 						&hym8563_rtc_ops, THIS_MODULE);
 	if (IS_ERR(hym8563->rtc))
-- 
1.7.9.5



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

* Re: [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work
  2015-09-17 10:39 ` [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work Xing Zheng
@ 2015-09-17 12:07   ` Heiko Stübner
  2015-09-17 12:31     ` Alexandre Belloni
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17 12:07 UTC (permalink / raw)
  To: Xing Zheng; +Cc: a.zummo, alexandre.belloni, rtc-linux, linux-kernel

Am Donnerstag, 17. September 2015, 18:39:28 schrieb Xing Zheng:
> The rtc hym8563 maybe failed to register if first startup or rtc
> powerdown:
> [    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
> [    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0 [ 
>   1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available [
>    1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware
> clock
> 
> We can set initial time for rtc and register it:
> [    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
> [    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01
> 00:02:00 UTC (946684920)

hmm, not setting a false date was actually intentional when I did the driver.

In my mind it is better to shout and keep programs from using wrong values 
than to set some arbitary date and let programs silently use this wrong value.


But I guess we'll let the rtc maintainers decide what is actually the better 
approach.


Heiko

> 
> ---
> 
> Changes in v2:
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> 
>  drivers/rtc/rtc-hym8563.c |   93
> +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93
> insertions(+)
> 
> diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
> index 097325d..ea37fdf 100644
> --- a/drivers/rtc/rtc-hym8563.c
> +++ b/drivers/rtc/rtc-hym8563.c
> @@ -83,6 +83,8 @@
> 
>  #define HYM8563_TMR_CNT		0x0f
> 
> +#define HYM8563_RTC_SECTION_LEN	0x07
> +
>  struct hym8563 {
>  	struct i2c_client	*client;
>  	struct rtc_device	*rtc;
> @@ -527,9 +529,77 @@ static int hym8563_resume(struct device *dev)
> 
>  static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
> 
> +static int hym8563_set_time(struct i2c_client *client, struct rtc_time *tm)
> +{
> +	u8 regs[HYM8563_RTC_SECTION_LEN] = {0};
> +	u8 mon_day;
> +	int ret = 0;
> +
> +	dev_dbg(&client->dev, "%s -- %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
> __func__, +		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm-
>tm_wday,
> +		tm->tm_hour, tm->tm_min, tm->tm_sec);
> +
> +	mon_day = rtc_month_days((tm->tm_mon), tm->tm_year + 1900);
> +
> +	if (tm->tm_sec >= 60 || tm->tm_sec < 0)
> +		regs[0x00] = bin2bcd(0x00);
> +	else
> +		regs[0x00] = bin2bcd(tm->tm_sec);
> +
> +	if (tm->tm_min >= 60 || tm->tm_min < 0)
> +		regs[0x01] = bin2bcd(0x00);
> +	else
> +		regs[0x01] = bin2bcd(tm->tm_min);
> +
> +	if (tm->tm_hour >= 24 || tm->tm_hour < 0)
> +		regs[0x02] = bin2bcd(0x00);
> +	else
> +		regs[0x02] = bin2bcd(tm->tm_hour);
> +
> +	if ((tm->tm_mday) > mon_day)
> +		regs[0x03] = bin2bcd(mon_day);
> +	else if ((tm->tm_mday) > 0)
> +		regs[0x03] = bin2bcd(tm->tm_mday);
> +	else if ((tm->tm_mday) <= 0)
> +		regs[0x03] = bin2bcd(0x01);
> +
> +	if (tm->tm_year >= 200)
> +		regs[0x06] = bin2bcd(99);
> +	else if (tm->tm_year >= 100)
> +		regs[0x06] = bin2bcd(tm->tm_year - 100);
> +	else if (tm->tm_year >= 0) {
> +		regs[0x06] = bin2bcd(tm->tm_year);
> +		regs[0x05] |= 0x80;
> +	} else {
> +		regs[0x06] = bin2bcd(0);
> +		regs[0x05] |= 0x80;
> +	}
> +
> +	regs[0x04] = bin2bcd(tm->tm_wday);
> +	regs[0x05] = (regs[0x05] & 0x80) | (bin2bcd(tm->tm_mon + 1) & 0x7F);
> +
> +	ret = i2c_smbus_write_byte_data(client, HYM8563_SEC, *regs);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "%s: error writing i2c data %d\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int hym8563_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
> +	struct rtc_time tm_read, tm = {
> +		.tm_sec = 0,
> +		.tm_min = 0,
> +		.tm_hour = 12,
> +		.tm_mday = 1,
> +		.tm_mon = 0,
> +		.tm_year = 111,
> +		.tm_wday = 6,
> +	};
>  	struct hym8563 *hym8563;
>  	int ret;
> 
> @@ -562,6 +632,7 @@ static int hym8563_probe(struct i2c_client *client,
> 
>  	/* check state of calendar information */
>  	ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
> +
>  	if (ret < 0)
>  		return ret;
> 
> @@ -569,6 +640,28 @@ static int hym8563_probe(struct i2c_client *client,
>  	dev_dbg(&client->dev, "rtc information is %s\n",
>  		hym8563->valid ? "valid" : "invalid");
> 
> +	if (!hym8563->valid) {
> +		ret = hym8563_set_time(client, &tm);
> +		if (ret < 0) {
> +			dev_err(&client->dev, "rtc set time failed, %d\n", ret);
> +			return ret;
> +		}
> +
> +		hym8563->valid = true;
> +	}
> +
> +	/* read current time */
> +	ret = hym8563_rtc_read_time(&client->dev, &tm_read);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "rtc read time failed, %d\n", ret);
> +		return ret;
> +	}
> +
> +	dev_dbg(&client->dev, "tm_sec = %d, tm_min = %d, tm_hour = %d,tm_mday =
> %d\n", +		tm_read.tm_sec, tm_read.tm_min, tm_read.tm_hour,
> tm_read.tm_mday); +	dev_dbg(&client->dev, "tm_mon = %d, tm_year = %d,
> tm_wday = %d\n", +		tm_read.tm_mon, tm_read.tm_year, tm_read.tm_wday);
> +
>  	hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
>  						&hym8563_rtc_ops, THIS_MODULE);
>  	if (IS_ERR(hym8563->rtc))


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

* Re: [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work
  2015-09-17 12:07   ` Heiko Stübner
@ 2015-09-17 12:31     ` Alexandre Belloni
  2015-09-17 12:44       ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Alexandre Belloni @ 2015-09-17 12:31 UTC (permalink / raw)
  To: Heiko Stübner; +Cc: Xing Zheng, a.zummo, rtc-linux, linux-kernel

Hi,

On 17/09/2015 at 14:07:47 +0200, Heiko Stübner wrote :
> Am Donnerstag, 17. September 2015, 18:39:28 schrieb Xing Zheng:
> > The rtc hym8563 maybe failed to register if first startup or rtc
> > powerdown:
> > [    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
> > [    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0 [ 
> >   1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available [
> >    1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware
> > clock
> > 
> > We can set initial time for rtc and register it:
> > [    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
> > [    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01
> > 00:02:00 UTC (946684920)
> 
> hmm, not setting a false date was actually intentional when I did the driver.
> 
> In my mind it is better to shout and keep programs from using wrong values 
> than to set some arbitary date and let programs silently use this wrong value.
> 

Indeed, I find it worse to set a wrong value instead of returning an
error. Userspace has to define its policy when reading the time fails.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* Re: [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work
  2015-09-17 12:31     ` Alexandre Belloni
@ 2015-09-17 12:44       ` Xing Zheng
  0 siblings, 0 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-17 12:44 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Heiko Stübner, a.zummo, rtc-linux, linux-kernel

On 2015年09月17日 20:31, Alexandre Belloni wrote:
> Hi,
>
> On 17/09/2015 at 14:07:47 +0200, Heiko Stübner wrote :
>> Am Donnerstag, 17. September 2015, 18:39:28 schrieb Xing Zheng:
>>> The rtc hym8563 maybe failed to register if first startup or rtc
>>> powerdown:
>>> [    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
>>> [    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0 [
>>>    1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available [
>>>     1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware
>>> clock
>>>
>>> We can set initial time for rtc and register it:
>>> [    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
>>> [    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01
>>> 00:02:00 UTC (946684920)
>> hmm, not setting a false date was actually intentional when I did the driver.
>>
>> In my mind it is better to shout and keep programs from using wrong values
>> than to set some arbitary date and let programs silently use this wrong value.
>>
> Indeed, I find it worse to set a wrong value instead of returning an
> error. Userspace has to define its policy when reading the time fails.
>
OK, I got it, this patch will be abandoned at next version.
Thanks.


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

* Re: [PATCH v2 6/9] pinctrl: rockchip: add support for the rk3036
  2015-09-17 10:34 ` [PATCH v2 6/9] pinctrl: rockchip: add support for the rk3036 Xing Zheng
@ 2015-09-17 12:47   ` Heiko Stübner
  0 siblings, 0 replies; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17 12:47 UTC (permalink / raw)
  To: Xing Zheng
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	linus.walleij, linux-gpio

Am Donnerstag, 17. September 2015, 18:34:20 schrieb Xing Zheng:
> Add new type for rk3036 and many parts of pinctrl rk3036 are similar
> with rk2928's.
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>

very nice that the rk3036 pin-controller works with already established 
infrastructure :-)

Reviewed-by: Heiko Stuebner <heiko@sntech.de>

> ---
> 
> Changes in v2: None
> 
>  .../bindings/pinctrl/rockchip,pinctrl.txt          |    1 +
>  drivers/pinctrl/pinctrl-rockchip.c                 |   17 +++++++++++++++++
> 2 files changed, 18 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
> b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt index
> 391ef4b..c73f2bb 100644
> --- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
> @@ -22,6 +22,7 @@ Required properties for iomux controller:
>    - compatible: one of "rockchip,rk2928-pinctrl",
> "rockchip,rk3066a-pinctrl" "rockchip,rk3066b-pinctrl",
> "rockchip,rk3188-pinctrl"
>  		       "rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
> +		       "rockchip,rk3036-pinctrl"
>    - rockchip,grf: phandle referencing a syscon providing the
>  	 "general register files"
> 
> diff --git a/drivers/pinctrl/pinctrl-rockchip.c
> b/drivers/pinctrl/pinctrl-rockchip.c index c5246c0..9c49510 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.c
> +++ b/drivers/pinctrl/pinctrl-rockchip.c
> @@ -2089,6 +2089,21 @@ static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
>  		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
>  };
> 
> +static struct rockchip_pin_bank rk3036_pin_banks[] = {
> +	PIN_BANK(0, 32, "gpio0"),
> +	PIN_BANK(1, 32, "gpio1"),
> +	PIN_BANK(2, 32, "gpio2"),
> +};
> +
> +static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
> +		.pin_banks		= rk3036_pin_banks,
> +		.nr_banks		= ARRAY_SIZE(rk3036_pin_banks),
> +		.label			= "RK3036-GPIO",
> +		.type			= RK2928,
> +		.grf_mux_offset		= 0xa8,
> +		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
> +};
> +
>  static struct rockchip_pin_bank rk3066a_pin_banks[] = {
>  	PIN_BANK(0, 32, "gpio0"),
>  	PIN_BANK(1, 32, "gpio1"),
> @@ -2207,6 +2222,8 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
>  static const struct of_device_id rockchip_pinctrl_dt_match[] = {
>  	{ .compatible = "rockchip,rk2928-pinctrl",
>  		.data = (void *)&rk2928_pin_ctrl },
> +	{ .compatible = "rockchip,rk3036-pinctrl",
> +		.data = (void *)&rk3036_pin_ctrl },
>  	{ .compatible = "rockchip,rk3066a-pinctrl",
>  		.data = (void *)&rk3066a_pin_ctrl },
>  	{ .compatible = "rockchip,rk3066b-pinctrl",


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

* Re: [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms
  2015-09-17 10:37 ` [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms Xing Zheng
@ 2015-09-17 15:05   ` Heiko Stübner
  2015-09-28 12:25     ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17 15:05 UTC (permalink / raw)
  To: Xing Zheng; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel

Am Donnerstag, 17. September 2015, 18:37:24 schrieb Xing Zheng:
> The timer5 supplies the architected timer and thus as has to run when
> the system clocksource and clockevents drivers are registered.

please kindly ask the people doing uboot development to do this in uboot 
itself in future socs :-) - for example Simon's rk3288 mainline uboot does 
this correctly.


> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  arch/arm/mach-rockchip/rockchip.c |   22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/arch/arm/mach-rockchip/rockchip.c
> b/arch/arm/mach-rockchip/rockchip.c index b6cf3b4..937047f 100644
> --- a/arch/arm/mach-rockchip/rockchip.c
> +++ b/arch/arm/mach-rockchip/rockchip.c
> @@ -32,6 +32,8 @@
>  #define RK3288_GRF_SOC_CON0 0x244
>  #define RK3288_TIMER6_7_PHYS 0xff810000
> 
> +#define RK3036_TIMER5_PHYS 0x200440a0
> +

#define RK3036_TIMER_PHYS 0x20044000
--> the actual base address of the timer block

As it looks like that we'll need to duplicate that timer init at least for the 
rk3036 and the timer ip in question is actually the same on both, please split 
out the actual work into a separate function like

static void rockchip_init_arch_timer_supply(resource_size_t phys, int offs)
{
		reg_base = ioremap(phys, SZ_16K);
		if (reg_base) {
			writel(0, reg_base + offs + 0x10);
			writel(0xffffffff, reg_base + offs);
			writel(0xffffffff, reg_base + offs + 0x04);
			writel(1, reg_base + offs + 0x10);
			dsb();
			iounmap(reg_base);
		} else {
			pr_err("rockchip: could not map timer registers\n");
		}
}

>  static void __init rockchip_timer_init(void)
>  {
>  	if (of_machine_is_compatible("rockchip,rk3288")) {
> @@ -64,6 +66,25 @@ static void __init rockchip_timer_init(void)

for the rk3288 exchange the timer init against
rockchip_init_arch_timer_supply(RK3288_TIMER6_7_PHYS, 0x20);


>  			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
>  		else
>  			pr_err("rockchip: could not get grf syscon\n");
> +	} else if (of_machine_is_compatible("rockchip,rk3036")) {
> +		void __iomem *reg_base;
> +
> +		/*
> +		 * Most/all uboot versions for rk3036 don't enable timer5
> +		 * which is needed for the architected timer to work.
> +		 * So make sure it is running during early boot.
> +		 */
> +		reg_base = ioremap(RK3036_TIMER5_PHYS, SZ_16K);
> +		if (reg_base) {
> +			writel(0, reg_base + 0x10);
> +			writel(0xffffffff, reg_base);
> +			writel(0xffffffff, reg_base + 0x04);
> +			writel(1, reg_base + 0x10);
> +			dsb();
> +			iounmap(reg_base);
> +		} else {
> +			pr_err("rockchip: could not map timer5 registers\n");
> +		}

rockchip_init_arch_timer_supply(RK3036_TIMER_PHYS, 0xa0);

>  	}
> 
>  	of_clk_init(NULL);
> @@ -79,6 +100,7 @@ static void __init rockchip_dt_init(void)
> 
>  static const char * const rockchip_board_dt_compat[] = {
>  	"rockchip,rk2928",
> +	"rockchip,rk3036",
>  	"rockchip,rk3066a",
>  	"rockchip,rk3066b",
>  	"rockchip,rk3188",


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

* Re: [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller
  2015-09-17 10:32 ` [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller Xing Zheng
@ 2015-09-17 15:09   ` Heiko Stübner
  2015-09-24  3:42     ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17 15:09 UTC (permalink / raw)
  To: Xing Zheng
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel

Am Donnerstag, 17. September 2015, 18:32:49 schrieb Xing Zheng:
> Add the devicetree binding for the cru on the rk3036 which quite similar
> structured as previous clock controllers.
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  .../bindings/clock/rockchip,rk3036-cru.txt         |   60
> ++++++++++++++++++++ 1 file changed, 60 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
> b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt new file
> mode 100644
> index 0000000..ac3037a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
> @@ -0,0 +1,60 @@
> +* Rockchip RK3036 Clock and Reset Unit
> +
> +The RK3036 clock controller generates and supplies clock to various
> +controllers within the SoC and also implements a reset controller for SoC
> +peripherals.
> +
> +Required Properties:
> +
> +- compatible: should be "rockchip,rk3036-cru"
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +- #clock-cells: should be 1.
> +- #reset-cells: should be 1.
> +
> +Optional Properties:
> +
> +- rockchip,grf: phandle to the syscon managing the "general register files"
> +  If missing pll rates are not changable, due to the missing pll lock
> status. +
> +Each clock is assigned an identifier and client nodes can use this
> identifier +to specify the clock which they consume. All available clocks
> are defined as +preprocessor macros in the dt-bindings/clock/rk3036-cru.h
> headers and can be +used in device tree sources. Similar macros exist for
> the reset sources in +these files.
> +
> +External clocks:
> +
> +There are several clocks that are generated outside the SoC. It is expected
> +that they are defined using standard clock bindings with following
> +clock-output-names:
> + - "xin24m" - crystal input - required,
> + - "xin32k" - rtc clock - optional,

The rk3036 does not seem to use a rtc clock, so this should probably go away

> + - "ext_i2s" - external I2S clock - optional,

> + - "ext_hsadc" - external HSADC clock - optional,
> + - "ext_vip" - external VIP clock - optional,
> + - "ext_isp" - external ISP clock - optional,
> + - "ext_jtag" - external JTAG clock - optional
There do not seem to exist external clock sources for hsadc, vip, isp and jtag 
in your clock tree?

missing here:
- ext_gmac

> +
> +Example: Clock controller node:
> +
> +	cru: cru@20000000 {
> +		compatible = "rockchip,rk3036-cru";
> +		reg = <0x20000000 0x1000>;
> +		rockchip,grf = <&grf>;
> +
> +		#clock-cells = <1>;
> +		#reset-cells = <1>;
> +	};
> +
> +Example: UART controller node that consumes the clock generated by the
> clock +  controller:
> +
> +	uart0: serial@20060000 {
> +		compatible = "snps,dw-apb-uart";
> +		reg = <0x20060000 0x100>;
> +		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
> +		reg-shift = <2>;
> +		reg-io-width = <4>;
> +		clocks = <&cru SCLK_UART0>;
> +	};


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

* Re: [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036
  2015-09-17 10:38 ` [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036 Xing Zheng
@ 2015-09-17 20:15   ` Heiko Stübner
  2015-09-28 11:50     ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-17 20:15 UTC (permalink / raw)
  To: Xing Zheng; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel

Am Donnerstag, 17. September 2015, 18:38:06 schrieb Xing Zheng:
> The rk3036 is dual-core soc, we can use this patch to enable cpu1
> enter boot secondary, and hotplug(online/offline).
> 
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  arch/arm/mach-rockchip/platsmp.c |  121
> ++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+)
> 
> diff --git a/arch/arm/mach-rockchip/platsmp.c
> b/arch/arm/mach-rockchip/platsmp.c index 3e7a4b7..14218eb 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -34,6 +34,8 @@
> 
>  static void __iomem *scu_base_addr;
>  static void __iomem *sram_base_addr;
> +static void __iomem *cru_base_addr;
> +
>  static int ncores;
> 
>  #define PMU_PWRDN_CON		0x08
> @@ -41,6 +43,8 @@ static int ncores;
> 
>  #define PMU_PWRDN_SCU		4
> 
> +#define RK3036_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
> +
>  static struct regmap *pmu;
> 
>  static int pmu_power_domain_is_on(int pd)
> @@ -184,6 +188,7 @@ static int __init rockchip_smp_prepare_sram(struct
> device_node *node) }
> 
>  	rsize = resource_size(&res);
> +
>  	if (rsize < trampoline_sz) {
>  		pr_err("%s: reserved block with size 0x%x is to small for trampoline 
size
> 0x%x\n", __func__, rsize, trampoline_sz);
> @@ -350,3 +355,119 @@ static struct smp_operations rockchip_smp_ops
> __initdata = { };
> 
>  CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp",
> &rockchip_smp_ops); +
> +/* for rk3036 */
> +
> +static int rk3036_set_power_domain(int pd, bool on)
> +{
> +	/* there are 2cpus on rk3036 soc, we just need to be care cpu1 */
> +	if (pd != 1)
> +		return 0;
> +
> +	if (on)
> +		writel_relaxed(0x20000, cru_base_addr + RK3036_SOFTRST_CON(0));
> +	else
> +		writel_relaxed(0x20002, cru_base_addr + RK3036_SOFTRST_CON(0));

this is definitly the wrong way. The reset handling is the same as on the 
rk3288 - so you can use the regular reset mechanism like the other socs and 
should definitly _never_ write to the cru directly.

The only visible difference is that you cannot control the power-domains of 
the cpu cores. Its sibling the rk3128 seems to have controllable power domains 
again.

I'm still pondering how to make this future proof...


Heiko

> +
> +	dsb();
> +
> +	return 0;
> +}
> +
> +static void __init rk3036_smp_prepare_cpus(unsigned int max_cpus)
> +{
> +	struct device_node *node;
> +	unsigned int l2ctlr;
> +	unsigned int i, cpu;
> +
> +	/* get cru_base_addr */
> +	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3036-cru");
> +	if (!node) {
> +		pr_err("%s: could not find cru dt node\n", __func__);
> +		return;
> +	}
> +
> +	cru_base_addr = of_iomap(node, 0);
> +	if (!cru_base_addr) {
> +		pr_err("%s: could not map cru registers\n", __func__);
> +		return;
> +	}
> +
> +	/* get sram_base_addr */
> +	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3036-smp-sram");
> +	if (!node) {
> +		pr_err("%s: could not find sram dt node\n", __func__);
> +		return;
> +	}
> +
> +	sram_base_addr = of_iomap(node, 0);
> +	if (!sram_base_addr) {
> +		pr_err("%s: could not map sram registers\n", __func__);
> +		return;
> +	}
> +
> +	/* get ncores */
> +	asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
> +	ncores = ((l2ctlr >> 24) & 0x3) + 1;
> +	cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 0);
> +
> +	/* Make sure that all cores except the first are really off */
> +	for (i = 1; i < ncores; i++)
> +		rk3036_set_power_domain(0 + i, false);
> +}
> +
> +static int rk3036_boot_secondary(unsigned int cpu, struct task_struct
> *idle) +{
> +	if (cpu >= ncores) {
> +		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
> +			__func__, cpu, ncores);
> +		return -ENXIO;
> +	}
> +
> +	/* start the core */
> +	rk3036_set_power_domain(0 + cpu, true);
> +
> +	/*
> +	 * We need to wait a moment after soft reset CPUx on rk3036,
> +	 * otherwise, CPUx will startup failed.
> +	 */
> +	udelay(10);
> +	writel(virt_to_phys(secondary_startup), sram_base_addr + 8);
> +	writel(0xDEADBEAF, sram_base_addr + 4);
> +	dsb_sev();
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_HOTPLUG_CPU
> +static int rk3066_cpu_kill(unsigned int cpu)
> +{
> +	/*
> +	 * We need a delay here to ensure that the dying CPU can finish
> +	 * executing v7_coherency_exit() and reach the WFI/WFE state
> +	 * prior to having the power domain disabled.
> +	 */
> +	mdelay(1);
> +
> +	rk3036_set_power_domain(0 + cpu, false);
> +
> +	return 1;
> +}
> +
> +static void rk3066_cpu_die(unsigned int cpu)
> +{
> +	v7_exit_coherency_flush(louis);
> +	while (1)
> +		cpu_do_idle();
> +}
> +#endif
> +
> +static struct smp_operations rk3036_smp_ops __initdata = {
> +	.smp_prepare_cpus	= rk3036_smp_prepare_cpus,
> +	.smp_boot_secondary	= rk3036_boot_secondary,
> +#ifdef CONFIG_HOTPLUG_CPU
> +	.cpu_kill		= rk3066_cpu_kill,
> +	.cpu_die		= rk3066_cpu_die,
> +#endif
> +};
> +CPU_METHOD_OF_DECLARE(rk3036_smp, "rockchip,rk3036-smp", &rk3036_smp_ops);


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

* Re: [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-17  8:28 ` [PATCH v2 4/9] clk: rockchip: add new clock type and " Xing Zheng
  2015-09-17  9:54   ` Heiko Stübner
@ 2015-09-22 22:41   ` Stephen Boyd
  2015-09-22 22:58     ` Heiko Stübner
  1 sibling, 1 reply; 37+ messages in thread
From: Stephen Boyd @ 2015-09-22 22:41 UTC (permalink / raw)
  To: Xing Zheng
  Cc: heiko, linux-rockchip, Michael Turquette, linux-clk,
	linux-arm-kernel, linux-kernel

On 09/17, Xing Zheng wrote:
> +
> +static void rockchip_rk3036_pll_init(struct clk_hw *hw)

init ops are "discouraged". Could we do this through assigned
rates instead?

> +{
> +	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
> +	const struct rockchip_pll_rate_table *rate;
> +	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
> +	unsigned long drate;
> +	u32 pllcon;
> +
> +	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
> +		return;

I don't understand what this one does though. This check isn't in
the set rate ops.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-22 22:41   ` Stephen Boyd
@ 2015-09-22 22:58     ` Heiko Stübner
  2015-09-22 23:19       ` Stephen Boyd
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-22 22:58 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Xing Zheng, linux-rockchip, Michael Turquette, linux-clk,
	linux-arm-kernel, linux-kernel

Hi Stephen,

Am Dienstag, 22. September 2015, 15:41:25 schrieb Stephen Boyd:
> On 09/17, Xing Zheng wrote:
> > +
> > +static void rockchip_rk3036_pll_init(struct clk_hw *hw)
> 
> init ops are "discouraged". Could we do this through assigned
> rates instead?

really? According to Mike that was a valid use-case when we looked for an 
initial place for that on the rk3288 :-) .


> > +{
> > +	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
> > +	const struct rockchip_pll_rate_table *rate;
> > +	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
> > +	unsigned long drate;
> > +	u32 pllcon;
> > +
> > +	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
> > +		return;
> 
> I don't understand what this one does though. This check isn't in
> the set rate ops.

And it shouldn't be :-)

The issue this whole thing is trying to solve is aligning the pll settings 
which what we have in the rate table, not what the bootloader set.

For example the bootloader could set up a pll at 594MHz with one set of 
parameters and after some time - when you don't want to exchange bootloaders 
on shipping devices anymore - it comes to light that a different set of 
parameters for the same frequency produces for example a more stable hdmi 
signal [I think that was the main reason for the initial change].

So we're not changing the frequency x -> y, which could be easily done [and is 
done already] via assigned-rates, but instead
	x {params a,b,c} -> x {params d,e,f}
so the rate itself stays the same, only the frequency generation is adapted.

As for the ROCKCHIP_PLL_SYNC_RATE param, we of course don't want to sync the 
ddr-pll for example for obvious hang-reasons.


Heiko

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

* Re: [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-22 22:58     ` Heiko Stübner
@ 2015-09-22 23:19       ` Stephen Boyd
  2015-09-30 23:32         ` Heiko Stübner
  0 siblings, 1 reply; 37+ messages in thread
From: Stephen Boyd @ 2015-09-22 23:19 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Xing Zheng, linux-rockchip, Michael Turquette, linux-clk,
	linux-arm-kernel, linux-kernel

On 09/23, Heiko Stübner wrote:
> Hi Stephen,
> 
> Am Dienstag, 22. September 2015, 15:41:25 schrieb Stephen Boyd:
> > On 09/17, Xing Zheng wrote:
> > > +
> > > +static void rockchip_rk3036_pll_init(struct clk_hw *hw)
> > 
> > init ops are "discouraged". Could we do this through assigned
> > rates instead?
> 
> really? According to Mike that was a valid use-case when we looked for an 
> initial place for that on the rk3288 :-) .

A comment in clk.c indicates init ops are discouraged. Maybe this
is a valid use-case on other platforms so it was allowed, but
pretty much every time we see a new init op we have to think
about it and justify it. Hooray!

> 
> 
> > > +{
> > > +	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
> > > +	const struct rockchip_pll_rate_table *rate;
> > > +	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
> > > +	unsigned long drate;
> > > +	u32 pllcon;
> > > +
> > > +	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
> > > +		return;
> > 
> > I don't understand what this one does though. This check isn't in
> > the set rate ops.
> 
> And it shouldn't be :-)
> 
> The issue this whole thing is trying to solve is aligning the pll settings 
> which what we have in the rate table, not what the bootloader set.
> 
> For example the bootloader could set up a pll at 594MHz with one set of 
> parameters and after some time - when you don't want to exchange bootloaders 
> on shipping devices anymore - it comes to light that a different set of 
> parameters for the same frequency produces for example a more stable hdmi 
> signal [I think that was the main reason for the initial change].
> 
> So we're not changing the frequency x -> y, which could be easily done [and is 
> done already] via assigned-rates, but instead
> 	x {params a,b,c} -> x {params d,e,f}
> so the rate itself stays the same, only the frequency generation is adapted.

Ok. It would be nice if this sort of information was made into a
comment and put in the code. Or at least the commit text for the
change.

And is there any reason that we need to get the parent clock and
parent rate to align the PLL settings? It would be nice if we
avoided using clk_* APIs in here, by extracting the pll set rate
code into another function that we can call from init to make the
values the same without all the fallback to old rates, etc.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036
  2015-09-17  9:25   ` Heiko Stübner
@ 2015-09-24  2:17     ` Xing Zheng
  0 siblings, 0 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-24  2:17 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: linux-rockchip, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, linux-kernel, devicetree

On 2015年09月17日 17:25, Heiko Stübner wrote:
> Am Donnerstag, 17. September 2015, 16:28:53 schrieb Xing Zheng:
>> Add the dt-bindings header for the rk3036, that gets shared between
>> the clock controller and the clock references in the dts.
>>
>> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
>> ---
>>
>> Changes in v2: None
>>
>>   include/dt-bindings/clock/rk3036-cru.h |  198
>> ++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+)
>>   create mode 100644 include/dt-bindings/clock/rk3036-cru.h
>>
>> diff --git a/include/dt-bindings/clock/rk3036-cru.h
>> b/include/dt-bindings/clock/rk3036-cru.h new file mode 100644
>> index 0000000..b0033ef
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/rk3036-cru.h
>> @@ -0,0 +1,198 @@
>> +/*
>> + * Copyright (c) 2014 MundoReader S.L.
>> + * Author: Heiko Stuebner<heiko@sntech.de>
> you can probably drop that copyright line ... I didn't do anything here ;-)
OK, done. :)
>
>> + *
>> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
>> + * Author: Xing Zheng<zhengxing@rock-chips.com>
>> + *
>> + * 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.
>> + */
>> +
>> +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
>> +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
>> +
>> +/* core clocks */
>> +#define PLL_APLL		1
>> +#define PLL_DPLL		2
>> +#define PLL_GPLL		3
>> +#define ARMCLK			4
>> +
>> +/* sclk gates (special clocks) */
> you have a lot of gaps in the numbering ... intentional?
Oh, I think I referenced to "rk3288-cru.h" and cut some useless 
numbering from it for rk3036
>
> otherwise
> Reviewed-by: Heiko Stuebner<heiko@sntech.de>
Done.
>> +#define SCLK_GPU		64
>> +#define SCLK_SPI		65
>> +#define SCLK_SDMMC		68
>> +#define SCLK_SDIO		69
>> +#define SCLK_EMMC		71
>> +#define SCLK_NANDC		76
>> +#define SCLK_UART0		77
>> +#define SCLK_UART1		78
>> +#define SCLK_UART2		79
>> +#define SCLK_I2S		82
>> +#define SCLK_SPDIF		83
>> +#define SCLK_TIMER0		85
>> +#define SCLK_TIMER1		86
>> +#define SCLK_TIMER2		87
>> +#define SCLK_TIMER3		88
>> +#define SCLK_OTGPHY0		93
>> +#define SCLK_OTGPHY1		94
>> +#define SCLK_LCDC		100
>> +#define SCLK_HDMI		109
>> +#define SCLK_HEVC		111
>> +#define SCLK_I2S_OUT		113
>> +#define SCLK_SDMMC_DRV		114
>> +#define SCLK_SDIO_DRV		115
>> +#define SCLK_EMMC_DRV		117
>> +#define SCLK_SDMMC_SAMPLE	118
>> +#define SCLK_SDIO_SAMPLE	119
>> +#define SCLK_EMMC_SAMPLE	121
>> +#define SCLK_PVTM_CORE          123
>> +#define SCLK_PVTM_GPU           124
>> +#define SCLK_PVTM_VIDEO         125
>> +#define SCLK_MAC		151
>> +#define SCLK_MACREF		152
>> +#define SCLK_SFC		160
>> +
>> +#define DCLK_LCDC		190
>> +
>> +/* aclk gates */
>> +#define ACLK_DMAC2		194
>> +#define ACLK_LCDC		197
>> +#define ACLK_VIO		203
>> +#define ACLK_VCODEC		208
>> +#define ACLK_CPU		209
>> +#define ACLK_PERI		210
>> +
>> +/* pclk gates */
>> +#define PCLK_GPIO0		320
>> +#define PCLK_GPIO1		321
>> +#define PCLK_GPIO2		322
>> +#define PCLK_GRF		329
>> +#define PCLK_I2C0		332
>> +#define PCLK_I2C1		333
>> +#define PCLK_I2C2		334
>> +#define PCLK_SPI		338
>> +#define PCLK_UART0		341
>> +#define PCLK_UART1		342
>> +#define PCLK_UART2		343
>> +#define PCLK_PWM		350
>> +#define PCLK_TIMER		353
>> +#define PCLK_HDMI		360
>> +#define PCLK_CPU		362
>> +#define PCLK_PERI		363
>> +#define PCLK_DDRUPCTL		364
>> +#define PCLK_WDT		368
>> +
>> +/* hclk gates */
>> +#define HCLK_OTG0		449
>> +#define HCLK_OTG1		450
>> +#define HCLK_NANDC		453
>> +#define HCLK_SDMMC		456
>> +#define HCLK_SDIO		457
>> +#define HCLK_EMMC		459
>> +#define HCLK_I2S		462
>> +#define HCLK_LCDC		465
>> +#define HCLK_ROM		467
>> +#define HCLK_VIO_BUS		472
>> +#define HCLK_VCODEC		476
>> +#define HCLK_CPU		477
>> +#define HCLK_PERI		478
>> +
>> +#define CLK_NR_CLKS		(HCLK_PERI + 1)
>> +
>> +/* soft-reset indices */
>> +#define SRST_CORE0		0
>> +#define SRST_CORE1		1
>> +#define SRST_CORE0_DBG		4
>> +#define SRST_CORE1_DBG		5
>> +#define SRST_CORE0_POR		8
>> +#define SRST_CORE1_POR		9
>> +#define SRST_L2C		12
>> +#define SRST_TOPDBG		13
>> +#define SRST_STRC_SYS_A		14
>> +#define SRST_PD_CORE_NIU	15
>> +
>> +#define SRST_TIMER2		16
>> +#define SRST_CPUSYS_H		17
>> +#define SRST_AHB2APB_H		19
>> +#define SRST_TIMER3		20
>> +#define SRST_INTMEM		21
>> +#define SRST_ROM		22
>> +#define SRST_PERI_NIU		23
>> +#define SRST_I2S		24
>> +#define SRST_DDR_PLL		25
>> +#define SRST_GPU_DLL		26
>> +#define SRST_TIMER0		27
>> +#define SRST_TIMER1		28
>> +#define SRST_CORE_DLL		29
>> +#define SRST_EFUSE_P		30
>> +#define SRST_ACODEC_P		31
>> +
>> +#define SRST_GPIO0		32
>> +#define SRST_GPIO1		33
>> +#define SRST_GPIO2		34
>> +#define SRST_UART0		39
>> +#define SRST_UART1		40
>> +#define SRST_UART2		41
>> +#define SRST_I2C0		43
>> +#define SRST_I2C1		44
>> +#define SRST_I2C2		45
>> +#define SRST_SFC		47
>> +
>> +#define SRST_PWM0		48
>> +#define SRST_DAP		51
>> +#define SRST_DAP_SYS		52
>> +#define SRST_GRF		55
>> +#define SRST_PERIPHSYS_A	57
>> +#define SRST_PERIPHSYS_H	58
>> +#define SRST_PERIPHSYS_P	59
>> +#define SRST_CPU_PERI		61
>> +#define SRST_EMEM_PERI		62
>> +#define SRST_USB_PERI		63
>> +
>> +#define SRST_DMA2		64
>> +#define SRST_MAC		66
>> +#define SRST_NANDC		68
>> +#define SRST_USBOTG0		69
>> +#define SRST_OTGC0		71
>> +#define SRST_USBOTG1		72
>> +#define SRST_OTGC1		74
>> +#define SRST_DDRMSCH		79
>> +
>> +#define SRST_MMC0		81
>> +#define SRST_SDIO		82
>> +#define SRST_EMMC		83
>> +#define SRST_SPI0		84
>> +#define SRST_WDT		86
>> +#define SRST_DDRPHY		88
>> +#define SRST_DDRPHY_P		89
>> +#define SRST_DDRCTRL		90
>> +#define SRST_DDRCTRL_P		91
>> +
>> +#define SRST_HDMI_P		96
>> +#define SRST_VIO_BUS_H		99
>> +#define SRST_UTMI0		103
>> +#define SRST_UTMI1		104
>> +#define SRST_USBPOR		105
>> +
>> +#define SRST_VCODEC_A		112
>> +#define SRST_VCODEC_H		113
>> +#define SRST_VIO1_A		114
>> +#define SRST_HEVC		115
>> +#define SRST_VCODEC_NIU_A	116
>> +#define SRST_LCDC1_A		117
>> +#define SRST_LCDC1_H		118
>> +#define SRST_LCDC1_D		119
>> +#define SRST_GPU		120
>> +#define SRST_GPU_NIU_A		122
>> +
>> +#define SRST_DBG_P		131
>> +
>> +#endif
>
>
>



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

* Re: [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts
  2015-09-17  9:18   ` Heiko Stübner
@ 2015-09-24  2:18     ` Xing Zheng
  0 siblings, 0 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-24  2:18 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: linux-rockchip, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Russell King, devicetree,
	linux-arm-kernel, linux-kernel

On 2015年09月17日 17:18, Heiko Stübner wrote:
> Am Donnerstag, 17. September 2015, 16:28:52 schrieb Xing Zheng:
>> Initial release for rk3036, node definitions rk3036 sdk board.
>>
>> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
>> ---
>>
>> Changes in v2: None
>>
>>   arch/arm/boot/dts/Makefile       |    1 +
>>   arch/arm/boot/dts/rk3036-sdk.dts |   62 +++++++
>>   arch/arm/boot/dts/rk3036.dtsi    |  381
>> ++++++++++++++++++++++++++++++++++++++ 3 files changed, 444 insertions(+)
>>   create mode 100644 arch/arm/boot/dts/rk3036-sdk.dts
>>   create mode 100644 arch/arm/boot/dts/rk3036.dtsi
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index d39ce4b..48260c4 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -502,6 +502,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
>>   	rk3066a-bqcurie2.dtb \
>>   	rk3066a-marsboard.dtb \
>>   	rk3066a-rayeager.dtb \
>> +	rk3036-sdk.dtb \
> ordering ... please put the rk3036 above rk3066 boards
Done.
>
>>   	rk3188-radxarock.dtb \
>>   	rk3288-evb-act8846.dtb \
>>   	rk3288-evb-rk808.dtb \
>> diff --git a/arch/arm/boot/dts/rk3036-sdk.dts
>> b/arch/arm/boot/dts/rk3036-sdk.dts new file mode 100644
>> index 0000000..9187f93
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/rk3036-sdk.dts
> or "rk3036-evb.dts"? What is the actual board named?
Done, use rk3036-evb.dts
>> @@ -0,0 +1,62 @@
>> +/*
>> + * Copyright (c)  2015 Xing Zheng<zhengxing@rock-chips.com>
> this probably wants a Rockchip copyright notice?
Yes, remove this notice.
>> + *
>> + * This file is dual-licensed: you can use it either under the terms
>> + * of the GPL or the X11 license, at your option. Note that this dual
>> + * licensing only applies to this file, and not this project as a
>> + * whole.
>> + *
>> + *  a) This file 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 file 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.
>> + *
>> + *  Or, alternatively,
>> + *
>> + *  b) Permission is hereby granted, free of charge, to any person
>> + *     obtaining a copy of this software and associated documentation
>> + *     files (the "Software"), to deal in the Software without
>> + *     restriction, including without limitation the rights to use,
>> + *     copy, modify, merge, publish, distribute, sublicense, and/or
>> + *     sell copies of the Software, and to permit persons to whom the
>> + *     Software is furnished to do so, subject to the following
>> + *     conditions:
>> + *
>> + *     The above copyright notice and this permission notice shall be
>> + *     included in all copies or substantial portions of the Software.
>> + *
>> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
>> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + *     OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +/dts-v1/;
>> +
>> +#include "rk3036.dtsi"
>> +
>> +/ {
>> +	model = "SDK-RK3036";
>> +	compatible = "sdk,sdk-rk3036", "rockchip,rk3036";
> 	model = "Rockchip RK3036-SDK";
> 	compatible = "rockchip,rk3036-sdk", "rockchip,rk3036";
>
> or
>
> 	model = "Rockchip RK3036 Evaluation board";
> 	compatible = "rockchip,rk3036-evb", "rockchip,rk3036";
>
> depending on what the real board is labeled
Done.
>> +};
>> +
>> +&i2c1 {
>> +	status = "okay";
>> +
>> +        hym8563: hym8563@51 {
>> +		compatible = "haoyu,hym8563";
>> +		reg =<0x51>;
>> +		#clock-cells =<0>;
>> +		clock-frequency =<32768>;
>> +		clock-output-names = "xin32k";
>> +	};
>> +};
>> \ No newline at end of file
> missing newline as stated above
Done.
>> diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
>> new file mode 100644
>> index 0000000..b7459c0
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/rk3036.dtsi
>> @@ -0,0 +1,381 @@
>> +/*
>> + * This file is dual-licensed: you can use it either under the terms
>> + * of the GPL or the X11 license, at your option. Note that this dual
>> + * licensing only applies to this file, and not this project as a
>> + * whole.
>> + *
>> + *  a) This file 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 file 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.
>> + *
>> + * Or, alternatively,
>> + *
>> + *  b) Permission is hereby granted, free of charge, to any person
>> + *     obtaining a copy of this software and associated documentation
>> + *     files (the "Software"), to deal in the Software without
>> + *     restriction, including without limitation the rights to use,
>> + *     copy, modify, merge, publish, distribute, sublicense, and/or
>> + *     sell copies of the Software, and to permit persons to whom the
>> + *     Software is furnished to do so, subject to the following
>> + *     conditions:
>> + *
>> + *     The above copyright notice and this permission notice shall be
>> + *     included in all copies or substantial portions of the Software.
>> + *
>> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
>> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + *     OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +#include<dt-bindings/gpio/gpio.h>
>> +#include<dt-bindings/interrupt-controller/irq.h>
>> +#include<dt-bindings/interrupt-controller/arm-gic.h>
>> +#include<dt-bindings/pinctrl/rockchip.h>
>> +#include<dt-bindings/clock/rk3036-cru.h>
>> +#include "skeleton.dtsi"
> in general, please sort nodes by register address, so for example
>
> 	interrupt-controller@10139000
> should be before
> 	clock-controller@20000000
>
> same for all other nodes
Done.
>> +
>> +/ {
>> +	compatible = "rockchip,rk3036";
>> +
>> +	interrupt-parent =<&gic>;
>> +
>> +	aliases {
>> +		i2c1 =&i2c1;
>> +		serial0 =&uart0;
>> +		serial1 =&uart1;
>> +		serial2 =&uart2;
>> +	};
>> +
>> +	memory {
>> +		device_type = "memory";
>> +		reg =<0x60000000 0x40000000>;
> ordering is possible ... to ease readability I try to keep this as
>
> compatible = ...
> reg = ...
> [other properties sorted alphabetically]
> status = ...
Done.
>> +	};
>> +
>> +        arm-pmu {
>> +                compatible = "arm,cortex-a7-pmu";
>> +                interrupts =<GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
>> +<GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
>> +                interrupt-affinity =<&cpu0>,<&cpu1>;
>> +        };
> tabs, not spaces please
Done.
>> +
>> +	cpus {
>> +		#address-cells =<1>;
>> +		#size-cells =<0>;
>> +		enable-method = "rockchip,rk3036-smp";
> this enable method is not yet defined, please don't add it until actual smp is
> accepted
Done, removed it on this patch.
>> +
>> +		cpu0: cpu@f00 {
>> +			device_type = "cpu";
>> +			compatible = "arm,cortex-a7";
>> +			reg =<0xf00>;
>> +			operating-points =<
>> +				/* KHz    uV */
>> +				 816000 1000000
>> +			>;
>> +			#cooling-cells =<2>; /* min followed by max */
> again, not yet defined thermal handling, so the #cooling-cells should stay out
> for now
Done, removed it.
>> +			clock-latency =<40000>;
>> +			clocks =<&cru ARMCLK>;
>> +			resets =<&cru SRST_CORE0>;
>> +		};
>> +		cpu1: cpu@f01 {
>> +			device_type = "cpu";
>> +			compatible = "arm,cortex-a7";
>> +			reg =<0xf01>;
>> +			resets =<&cru SRST_CORE1>;
>> +		};
>> +	};
>> +
>> +	amba {
>> +		compatible = "arm,amba-bus";
>> +		#address-cells =<1>;
>> +		#size-cells =<1>;
>> +		ranges;
>> +
>> +                pdma: pdma@20078000 {
>> +                        compatible = "arm,pl330", "arm,primecell";
>> +                        reg =<0x20078000 0x4000>;
>> +                        interrupts =<GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
>> +<GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
>> +                        #dma-cells =<1>;
>> +                        clocks =<&cru ACLK_DMAC2>;
>> +                        clock-names = "apb_pclk";
>> +                };
> again tabs please
Done.
>> +	};
>> +
>> +	xin24m: oscillator {
>> +		compatible = "fixed-clock";
>> +		clock-frequency =<24000000>;
>> +		clock-output-names = "xin24m";
>> +		#clock-cells =<0>;
>> +	};
>> +
>> +	timer {
>> +		compatible = "arm,armv7-timer";
>> +		arm,cpu-registers-not-fw-configured;
>> +		interrupts =<GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
> IRQ_TYPE_LEVEL_HIGH)>,
>> +			<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, +	
> 		
>>     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, +			
>> <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>> +		clock-frequency =<24000000>;
>> +	};
>> +
>> +	cru: clock-controller@20000000 {
>> +		compatible = "rockchip,rk3036-cru";
>> +		reg =<0x20000000 0x1000>;
>> +		rockchip,grf =<&grf>;
>> +		#clock-cells =<1>;
>> +		#reset-cells =<1>;
>> +		assigned-clocks =<&cru PLL_GPLL>;
>> +		assigned-clock-rates =<594000000>;
>> +	};
>> +
>> +	uart0: serial@20060000 {
>> +		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
>> +		reg =<0x20060000 0x100>;
>> +		interrupts =<GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
>> +		reg-shift =<2>;
>> +		reg-io-width =<4>;
>> +		clock-frequency =<24000000>;
>> +		clocks =<&cru SCLK_UART0>,<&cru PCLK_UART0>;
>> +		clock-names = "baudclk", "apb_pclk";
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&uart0_xfer&uart0_cts&uart0_rts>;
> status = "disabled" and then in the board.dts a
>
> &uart0 {
> 	status = "okay";
> };
>
> not everybody will want to use uart0 ... same is true for the other two uarts.
Done.
>> +	};
>> +
>> +	uart1: serial@20064000 {
>> +		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
>> +		reg =<0x20064000 0x100>;
>> +		interrupts =<GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
>> +		reg-shift =<2>;
>> +		reg-io-width =<4>;
>> +		clock-frequency =<24000000>;
>> +		clocks =<&cru SCLK_UART1>,<&cru PCLK_UART1>;
>> +		clock-names = "baudclk", "apb_pclk";
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&uart1_xfer>;
>> +	};
>> +
>> +	uart2: serial@20068000 {
>> +		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
>> +		reg =<0x20068000 0x100>;
>> +		interrupts =<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
>> +		reg-shift =<2>;
>> +		reg-io-width =<4>;
>> +		clock-frequency =<24000000>;
>> +		clocks =<&cru SCLK_UART2>,<&cru PCLK_UART2>;
>> +		clock-names = "baudclk", "apb_pclk";
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&uart2_xfer>;
>> +	};
>> +
>> +	pwm0: pwm@20050000 {
>> +		compatible = "rockchip,rk2928-pwm";
> 		compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm";
>
> rk2928-pwm matches now, but if we find issues we can simply create the rk3036-
> pwm in the driver without needing to change the dts
Done.
>> +		reg =<0x20050000 0x10>;
>> +		#pwm-cells =<3>;
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&pwm0_pin>;
>> +		clocks =<&cru PCLK_PWM>;
>> +		clock-names = "pwm";
>> +		status = "disabled";
>> +	};
>> +
>> +	pwm1: pwm@20050010 {
>> +		compatible = "rockchip,rk2928-pwm";
>> +		reg =<0x20050010 0x10>;
>> +		#pwm-cells =<3>;
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&pwm1_pin>;
>> +		clocks =<&cru PCLK_PWM>;
>> +		clock-names = "pwm";
>> +		status = "disabled";
>> +	};
>> +
>> +	pwm2: pwm@20050020 {
>> +		compatible = "rockchip,rk2928-pwm";
>> +		reg =<0x20050020 0x10>;
>> +		#pwm-cells =<3>;
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&pwm2_pin>;
>> +		clocks =<&cru PCLK_PWM>;
>> +		clock-names = "pwm";
>> +		status = "disabled";
>> +	};
>> +
>> +	pwm3: pwm@20050030 {
>> +		compatible = "rockchip,rk2928-pwm";
>> +		reg =<0x20050030 0x10>;
>> +		#pwm-cells =<2>;
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&pwm3_pin>;
>> +		clocks =<&cru PCLK_PWM>;
>> +		clock-names = "pwm";
>> +		status = "disabled";
>> +	};
>> +
>> +	sram: sram@10080000 {
>> +		compatible = "rockchip,rk3036-smp-sram", "mmio-sram";
>> +		reg =<0x10080000 0x2000>;
>> +	};
>> +
>> +	gic: interrupt-controller@10139000 {
>> +		compatible = "arm,gic-400";
>> +		interrupt-controller;
>> +		#interrupt-cells =<3>;
>> +		#address-cells =<0>;
>> +
>> +		reg =<0x10139000 0x1000>,
>> +		<0x1013a000 0x1000>,
>> +		<0x1013c000 0x2000>,
>> +		<0x1013e000 0x2000>;
>> +		interrupts =<GIC_PPI 9 0xf04>;
>> +	};
>> +
>> +	grf: syscon@20008000 {
>> +		compatible = "rockchip,rk3036-grf", "syscon";
>> +		reg =<0x20008000 0x1000>;
>> +	};
>> +
>> +	pinctrl: pinctrl {
>> +		compatible = "rockchip,rk3036-pinctrl";
>> +		rockchip,grf =<&grf>;
>> +		#address-cells =<1>;
>> +		#size-cells =<1>;
>> +		ranges;
>> +
>> +		gpio0: gpio0@2007c000 {
>> +			compatible = "rockchip,gpio-bank";
>> +			reg =<0x2007c000 0x100>;
>> +			interrupts =<GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
>> +			clocks =<&cru PCLK_GPIO0>;
>> +
>> +			gpio-controller;
>> +			#gpio-cells =<2>;
>> +
>> +			interrupt-controller;
>> +			#interrupt-cells =<2>;
>> +		};
>> +
>> +		gpio1: gpio1@20080000 {
>> +			compatible = "rockchip,gpio-bank";
>> +			reg =<0x20080000 0x100>;
>> +			interrupts =<GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
>> +			clocks =<&cru PCLK_GPIO1>;
>> +
>> +			gpio-controller;
>> +			#gpio-cells =<2>;
>> +
>> +			interrupt-controller;
>> +			#interrupt-cells =<2>;
>> +		};
>> +
>> +		gpio2: gpio2@20084000 {
>> +			compatible = "rockchip,gpio-bank";
>> +			reg =<0x20084000 0x100>;
>> +			interrupts =<GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
>> +			clocks =<&cru PCLK_GPIO2>;
>> +
>> +			gpio-controller;
>> +			#gpio-cells =<2>;
>> +
>> +			interrupt-controller;
>> +			#interrupt-cells =<2>;
>> +		};
>> +
>> +		pcfg_pull_up: pcfg-pull-up {
>> +			bias-pull-up;
>> +		};
>> +
>> +		pcfg_pull_down: pcfg-pull-down {
>> +			bias-pull-down;
>> +		};
>> +
>> +		pcfg_pull_none: pcfg-pull-none {
>> +			bias-disable;
>> +		};
>> +
>> +		uart0 {
>> +			uart0_xfer: uart0-xfer {
>> +				rockchip,pins =<0 16 RK_FUNC_1&pcfg_pull_none>,
> pcfg_pull_up for the rx-pin?
Done
>> +						<0 17 RK_FUNC_1&pcfg_pull_none>;
>> +			};
>> +
>> +			uart0_cts: uart0-cts {
>> +				rockchip,pins =<0 18 RK_FUNC_1&pcfg_pull_none>;
>> +			};
> pcfg_pull_up again?
> see ARM: dts: rockchip: pull up cts lines on rk3288
> (https://lkml.org/lkml/2015/9/2/612) for comparison
Yes, they should be pull up.
>
>> +
>> +			uart0_rts: uart0-rts {
>> +				rockchip,pins =<0 19 RK_FUNC_1&pcfg_pull_none>;
>> +			};
>> +		};
>> +
>> +		uart1 {
>> +			uart1_xfer: uart1-xfer {
>> +				rockchip,pins =<2 22 RK_FUNC_1&pcfg_pull_none>,
>> +						<2 23 RK_FUNC_1&pcfg_pull_none>;
>> +			};
>> +			/* no rts / cts for uart1 */
>> +		};
>> +
>> +                uart2 {
>> +                        uart2_xfer: uart2-xfer {
>> +                                rockchip,pins =<1 18 RK_FUNC_2
>> &pcfg_pull_none>, +<1 19
>> RK_FUNC_2&pcfg_pull_none>; +                        };
>> +                        /* no rts / cts for uart2 */
>> +                };
> tabs please
Sorry, done.
>> +
>> +		pwm0 {
>> +			pwm0_pin: pwm0-pin {
>> +				rockchip,pins =<0 0 RK_FUNC_2&pcfg_pull_none>;
>> +			};
>> +		};
>> +
>> +		pwm1 {
>> +			pwm1_pin: pwm1-pin {
>> +				rockchip,pins =<0 1 RK_FUNC_2&pcfg_pull_none>;
>> +			};
>> +		};
>> +
>> +		pwm2 {
>> +			pwm2_pin: pwm2-pin {
>> +				rockchip,pins =<0 1 2&pcfg_pull_none>;
>> +			};
>> +		};
>> +
>> +		pwm3 {
>> +			pwm3_pin: pwm3-pin {
>> +				rockchip,pins =<0 27 1&pcfg_pull_none>;
>> +			};
>> +		};
>> +
>> +		i2c1 {
>> +			i2c1_xfer: i2c1-xfer {
>> +				rockchip,pins =<0 2 RK_FUNC_1&pcfg_pull_none>,
>> +						<0 3 RK_FUNC_1&pcfg_pull_none>;
>> +			};
>> +		};
>> +	};
>> +
>> +	i2c1: i2c@20056000 {
>> +		compatible = "rockchip,rk3288-i2c";
>> +		reg =<0x20056000 0x1000>;
>> +		interrupts =<GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
>> +		#address-cells =<1>;
>> +		#size-cells =<0>;
>> +		clock-names = "i2c";
>> +		clocks =<&cru PCLK_I2C1>;
>> +		pinctrl-names = "default";
>> +		pinctrl-0 =<&i2c1_xfer>;
>> +		status = "disabled";
>> +	};
>> +};
>
Thanks.



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

* Re: [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036
  2015-09-17  9:47   ` Heiko Stübner
@ 2015-09-24  3:04     ` Xing Zheng
  2015-09-24  3:31       ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-24  3:04 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: linux-rockchip, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-clk, linux-arm-kernel

On 2015年09月17日 17:47, Heiko Stübner wrote:
> Hi,
>
> Am Donnerstag, 17. September 2015, 16:28:54 schrieb Xing Zheng:
>> Add the clock tree definition for the new rk3036 SoC.
>>
>> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
> missing a dt-bindings document in a separate patch. See "dt-bindings: add
> documentation of rk3668 clock controller"
> (http://lists.infradead.org/pipermail/linux-rockchip/2015-July/003396.html)
> for comparison.
Yes, I sent a dt-bindings document in patch 5:
"dt-bindings: add documentation of rk3036 clock controller",
and I think I will adjust the order of document before "Add the clock 
tree..."
for rk3036.

>> ---
>>
>> Changes in v2: None
>>
>>   drivers/clk/rockchip/Makefile     |    1 +
>>   drivers/clk/rockchip/clk-rk3036.c |  504
>> +++++++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h        |
>> 30 +++
>>   3 files changed, 535 insertions(+)
>>   create mode 100644 drivers/clk/rockchip/clk-rk3036.c
>>
>> diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
>> index b27edd6..d599829 100644
>> --- a/drivers/clk/rockchip/Makefile
>> +++ b/drivers/clk/rockchip/Makefile
>> @@ -10,6 +10,7 @@ obj-y	+= clk-inverter.o
>>   obj-y	+= clk-mmc-phase.o
>>   obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
>>
>> +obj-y	+= clk-rk3036.o
>>   obj-y	+= clk-rk3188.o
>>   obj-y	+= clk-rk3288.o
>>   obj-y	+= clk-rk3368.o
>> diff --git a/drivers/clk/rockchip/clk-rk3036.c
>> b/drivers/clk/rockchip/clk-rk3036.c new file mode 100644
>> index 0000000..724d467
>> --- /dev/null
>> +++ b/drivers/clk/rockchip/clk-rk3036.c
>> @@ -0,0 +1,504 @@
>> +/*
>> + * Copyright (c) 2014 MundoReader S.L.
>> + * Author: Heiko Stuebner<heiko@sntech.de>
>> + *
>> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
>> + * Author: Xing Zheng<zhengxing@rock-chips.com>
>> + *
>> + * 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.
>> + */
>> +
>> +#include<linux/clk-provider.h>
>> +#include<linux/of.h>
>> +#include<linux/of_address.h>
>> +#include<linux/syscore_ops.h>
>> +#include<dt-bindings/clock/rk3036-cru.h>
>> +#include "clk.h"
>> +
>> +enum rk3036_plls {
>> +	apll, dpll, gpll,
>> +};
>> +
>> +static struct rockchip_pll_rate_table rk3036_pll_rates[] = {
>> +	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
>> +	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
>> +	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
>> +	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
>> +	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
>> +	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
>> +	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
>> +	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
>> +	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
>> +	RK3036_PLL_RATE(0, 1, 0, 1, 1, 1, 0),
> you shouldn't need a "0" rate entry I guess
Done.
>> +	{ /* sentinel */ },
>> +};
>> +
>> +#define RK3036_DIV_CPU_MASK		0x1f
>> +#define RK3036_DIV_CPU_SHIFT		8
>> +
>> +#define RK3036_DIV_PERI_MASK		0xf
>> +#define RK3036_DIV_PERI_SHIFT		0
>> +#define RK3036_DIV_ACLK_MASK		0x7
>> +#define RK3036_DIV_ACLK_SHIFT		4
>> +#define RK3036_DIV_HCLK_MASK		0x3
>> +#define RK3036_DIV_HCLK_SHIFT		8
>> +#define RK3036_DIV_PCLK_MASK		0x7
>> +#define RK3036_DIV_PCLK_SHIFT		12
>> +
>> +#define RK3036_CLKSEL1(_core_periph_div)					\
>> +	{									\
>> +		.reg = RK2928_CLKSEL_CON(1),					\
>> +		.val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK,	\
>> +				RK3036_DIV_PERI_SHIFT)				\
>> +	}
>> +
>> +#define RK3036_CPUCLK_RATE(_prate, _core_periph_div)			\
>> +	{								\
>> +		.prate = _prate,					\
>> +		.divs = {						\
>> +			RK3036_CLKSEL1(_core_periph_div),		\
>> +		},							\
>> +	}
>> +
>> +static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata =
>> { +	RK3036_CPUCLK_RATE(816000000, 4),
>> +	RK3036_CPUCLK_RATE(600000000, 4),
>> +	RK3036_CPUCLK_RATE(312000000, 4),
>> +};
>> +
>> +static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
>> +	.core_reg = RK2928_CLKSEL_CON(0),
>> +	.div_core_shift = 0,
>> +	.div_core_mask = 0x1f,
>> +	.mux_core_shift = 7,
>> +};
>> +
>> +PNAME(mux_pll_p)		= { "xin24m", "xin24m" };
> looks like you overlooked the divider? Like
>
> DIV(0, "xin24m_plldiv", "xin24m", 0,
> 		RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),
>
> PNAME(mux_pll_p)		= { "xin24m_plldiv", "xin24m" };
Did I? There are not xin24m_plldiv and CRU_CLKSEL_CON4 register in my 
rk3036 TRM...
>> +
>> +PNAME(mux_armclk_p)		= { "apll", "gpll_armclk" };
>> +PNAME(mux_busclk_p)		= { "apll", "dpll_cpu", "gpll_cpu" };
> [...]
>
>> +	/*
>> +	 * Clock-Architecture Diagram 3
>> +	 */
>> +
>> +	/* aclk_cpu gates */
>> +	GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(4), 12, GFLAGS), +	GATE(0, "aclk_strc_sys", "aclk_cpu",
>> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS), +
>> +	/* hclk_cpu gates */
>> +	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(5), 6, GFLAGS), +
>> +	/* pclk_cpu gates */
>> +	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(5), 4, GFLAGS), +	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl",
>> "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), +	GATE(ACLK_VCODEC,
>> "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
>> +	GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8,
>> GFLAGS), +
>> +	/* aclk_vio gates */
>> +	GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", 0,
>> +			RK2928_CLKGATE_CON(6), 13, GFLAGS),
>> +	GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0,
>> +			RK2928_CLKGATE_CON(9), 6, GFLAGS),
>> +
>> +	GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0,
>> +			RK2928_CLKGATE_CON(6), 12, GFLAGS),
>> +	GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0,
>> +			RK2928_CLKGATE_CON(9), 5, GFLAGS),
>> +
>> +	/* aclk_video gates */
>> +	GATE(HCLK_LCDC, "hclk_vcodec", "hclk_disp_pre", 0,
>> +			RK2928_CLKGATE_CON(3), 12, GFLAGS),
> in big gate-block from diagram 3, please stick to the one-line format, like
> the rest of the gates here (diagram3 only)
Done.
>> +
>> +	/* xin24m gates */
>> +	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0,
>> RK2928_CLKGATE_CON(10), 0, GFLAGS), +	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu",
>> "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS), +
>> +	/* aclk_peri gates */
>> +	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(4), 3, GFLAGS), +	GATE(0, "aclk_cpu_peri", "aclk_peri",
>> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), +	GATE(ACLK_DMAC2,
>> "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), +	GATE(0,
>> "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15,
>> GFLAGS), +
>> +	/* hclk_peri gates */
>> +	GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(4), 0, GFLAGS), +	GATE(0, "hclk_usb_peri", "hclk_peri",
>> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS), +	GATE(0,
>> "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9),
>> 14, GFLAGS), +	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0,
>> RK2928_CLKGATE_CON(5), 9, GFLAGS), +	GATE(HCLK_SDMMC, "hclk_sdmmc",
>> "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS), +	GATE(HCLK_SDIO,
>> "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
>> +	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0,
>> GFLAGS), +	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(5), 13, GFLAGS), +	GATE(HCLK_OTG1, "hclk_otg1",
>> "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 13, GFLAGS),
>> +	GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(7), 2, GFLAGS), +	GATE(0, "hclk_sfc", "hclk_peri",
>> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), +	GATE(0,
>> "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15,
>> GFLAGS), +
>> +	/* pclk_peri gates */
>> +	GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED,
>> RK2928_CLKGATE_CON(4), 1, GFLAGS), +	GATE(0, "pclk_efuse", "pclk_peri",
>> CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), +	GATE(PCLK_TIMER,
>> "pclk_timer0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
>> +	GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10,
>> GFLAGS), +	GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0,
>> RK2928_CLKGATE_CON(7), 12, GFLAGS), +	GATE(PCLK_WDT, "pclk_wdt",
>> "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), +	GATE(PCLK_UART0,
>> "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
>> +	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1,
>> GFLAGS), +	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0,
>> RK2928_CLKGATE_CON(8), 2, GFLAGS), +	GATE(PCLK_I2C0, "pclk_i2c0",
>> "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), +	GATE(PCLK_I2C1,
>> "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
>> +	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6,
>> GFLAGS), +	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0,
>> RK2928_CLKGATE_CON(8), 9, GFLAGS), +	GATE(PCLK_GPIO1, "pclk_gpio1",
>> "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), +	GATE(PCLK_GPIO2,
>> "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), +};
>> +
>> +static const char *const rk3036_critical_clocks[] __initconst = {
>> +	"aclk_cpu",
>> +	"aclk_peri",
>> +	"hclk_peri",
>> +	"pclk_peri",
>> +};
>> +
>> +static void __init rk3036_clk_init(struct device_node *np)
>> +{
>> +	void __iomem *reg_base;
>> +	struct clk *clk;
>> +
>> +	reg_base = of_iomap(np, 0);
>> +	if (!reg_base) {
>> +		pr_err("%s: could not map cru region\n", __func__);
>> +		return;
>> +	}
>> +
>> +	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
>> +
>> +	/* xin12m is created by an cru-internal divider */
>> +	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
>> +	if (IS_ERR(clk))
>> +		pr_warn("%s: could not register clock xin12m: %ld\n",
>> +			__func__, PTR_ERR(clk));
>> +
>> +	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
>> +	if (IS_ERR(clk))
>> +		pr_warn("%s: could not register clock usb480m: %ld\n",
>> +			__func__, PTR_ERR(clk));
>> +
>> +	clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
>> +	if (IS_ERR(clk))
>> +		pr_warn("%s: could not register clock ddrphy: %ld\n",
>> +			__func__, PTR_ERR(clk));
>> +
>> +	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
>> +					"aclk_vcodec", 0, 1, 4);
>> +	if (IS_ERR(clk))
>> +		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
>> +			__func__, PTR_ERR(clk));
>> +
>> +	clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
>> +					"hclk_peri_src", 0, 1, 2);
>> +	if (IS_ERR(clk))
>> +		pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
>> +			__func__, PTR_ERR(clk));
>> +
>> +	rockchip_clk_register_plls(rk3036_pll_clks,
>> +				   ARRAY_SIZE(rk3036_pll_clks),
>> +				   -1);
>> +	rockchip_clk_register_branches(rk3036_clk_branches,
>> +				  ARRAY_SIZE(rk3036_clk_branches));
>> +	rockchip_clk_protect_critical(rk3036_critical_clocks,
>> +				      ARRAY_SIZE(rk3036_critical_clocks));
>> +
>> +	rockchip_clk_register_armclk(ARMCLK, "armclk",
>> +			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
>> +			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
>> +			ARRAY_SIZE(rk3036_cpuclk_rates));
>> +
>> +	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
>> +				  ROCKCHIP_SOFTRST_HIWORD_MASK);
>> +
>> +	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
>> +}
>> +CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
>> diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
>> index dc8ecb2..6603c07 100644
>> --- a/drivers/clk/rockchip/clk.h
>> +++ b/drivers/clk/rockchip/clk.h
>> @@ -2,6 +2,9 @@
>>    * Copyright (c) 2014 MundoReader S.L.
>>    * Author: Heiko Stuebner<heiko@sntech.de>
>>    *
>> + * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
>> + * Author: Xing Zheng<zhengxing@rock-chips.com>
>> + *
>>    * based on
>>    *
>>    * samsung/clk.h
>> @@ -40,6 +43,13 @@ struct clk;
>>   #define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
>>   #define RK2928_MISC_CON		0x134
>>
>> +#define RK3036_SDMMC_CON0		0x144
>> +#define RK3036_SDMMC_CON1		0x148
>> +#define RK3036_SDIO_CON0		0x14c
>> +#define RK3036_SDIO_CON1		0x150
>> +#define RK3036_EMMC_CON0		0x154
>> +#define RK3036_EMMC_CON1		0x158
>> +
>>   #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
>>   #define RK3288_MODE_CON			0x50
>>   #define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
>> @@ -75,6 +85,7 @@ struct clk;
>>
>>   enum rockchip_pll_type {
>>   	pll_rk3066,
>> +	pll_rk3036,
> this should be part of the addition of the pll type (your patch4, and should
> be reordered accordingly)
>
> Also please all 3036 before the 3066 entry
OK, done.
>>   };
>>
>>   #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
>> @@ -95,12 +106,31 @@ enum rockchip_pll_type {
>>   	.nb = _nb,						\
>>   }
>>
>> +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
>> +			_postdiv2, _dsmpd, _frac)		\
>> +{								\
>> +	.rate	= _rate##U,					\
>> +	.fbdiv = _fbdiv,					\
>> +	.postdiv1 = _postdiv1,					\
>> +	.refdiv = _refdiv,					\
>> +	.postdiv2 = _postdiv2,					\
>> +	.dsmpd = _dsmpd,					\
>> +	.frac = _frac,						\
>> +}
>> +
>>   struct rockchip_pll_rate_table {
>>   	unsigned long rate;
>>   	unsigned int nr;
>>   	unsigned int nf;
>>   	unsigned int no;
>>   	unsigned int nb;
>> +	/* for RK3036 */
>> +	unsigned int fbdiv;
>> +	unsigned int postdiv1;
>> +	unsigned int refdiv;
>> +	unsigned int postdiv2;
>> +	unsigned int dsmpd;
>> +	unsigned int frac;
> same for these 2 ... should be part of the pll addition itself
Done.
>
>>   };
>>
>>   /**
Thanks.


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

* Re: [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036
  2015-09-24  3:04     ` Xing Zheng
@ 2015-09-24  3:31       ` Xing Zheng
  2015-10-07 10:24         ` Heiko Stuebner
  0 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-24  3:31 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: linux-rockchip, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-clk, linux-arm-kernel

On 2015年09月24日 11:04, Xing Zheng wrote:
>>>
>>>   #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)    \
>>> @@ -95,12 +106,31 @@ enum rockchip_pll_type {
>>>       .nb = _nb,                        \
>>>   }
>>>
>>> +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,    \
>>> +            _postdiv2, _dsmpd, _frac)        \
>>> +{                                \
>>> +    .rate    = _rate##U,                    \
>>> +    .fbdiv = _fbdiv,                    \
>>> +    .postdiv1 = _postdiv1,                    \
>>> +    .refdiv = _refdiv,                    \
>>> +    .postdiv2 = _postdiv2,                    \
>>> +    .dsmpd = _dsmpd,                    \
>>> +    .frac = _frac,                        \
>>> +}
>>> +
>>>   struct rockchip_pll_rate_table {
>>>       unsigned long rate;
>>>       unsigned int nr;
>>>       unsigned int nf;
>>>       unsigned int no;
>>>       unsigned int nb;
>>> +    /* for RK3036 */
>>> +    unsigned int fbdiv;
>>> +    unsigned int postdiv1;
>>> +    unsigned int refdiv;
>>> +    unsigned int postdiv2;
>>> +    unsigned int dsmpd;
>>> +    unsigned int frac;
>> same for these 2 ... should be part of the pll addition itself
>   };
> Done.
>
Sorry, I have one question:
The "struct rockchip_pll_rate_table" is called in "rockchip/clk-pll.c" 
on many functions, I think I could add a struct like:
struct rk3036_pll_rate_table {
     unsigned int fbdiv;
     unsigned int postdiv1;
     unsigned int refdiv;
     unsigned int postdiv2;
     unsigned int dsmpd;
     unsigned int frac;
};
but, it will add many redundancy codes in "rockchip/clk-pll.c" just for 
call "struct rk3036_pll_rate_table".

Thanks.



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

* Re: [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller
  2015-09-17 15:09   ` Heiko Stübner
@ 2015-09-24  3:42     ` Xing Zheng
  0 siblings, 0 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-24  3:42 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel

On 2015年09月17日 23:09, Heiko Stübner wrote:
> Am Donnerstag, 17. September 2015, 18:32:49 schrieb Xing Zheng:
>> Add the devicetree binding for the cru on the rk3036 which quite similar
>> structured as previous clock controllers.
>>
>> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
>> ---
>>
>> Changes in v2: None
>>
>>   .../bindings/clock/rockchip,rk3036-cru.txt         |   60
>> ++++++++++++++++++++ 1 file changed, 60 insertions(+)
>>   create mode 100644
>> Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
>> b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt new file
>> mode 100644
>> index 0000000..ac3037a
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
>> @@ -0,0 +1,60 @@
>> +* Rockchip RK3036 Clock and Reset Unit
>> +
>> +The RK3036 clock controller generates and supplies clock to various
>> +controllers within the SoC and also implements a reset controller for SoC
>> +peripherals.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be "rockchip,rk3036-cru"
>> +- reg: physical base address of the controller and length of memory mapped
>> +  region.
>> +- #clock-cells: should be 1.
>> +- #reset-cells: should be 1.
>> +
>> +Optional Properties:
>> +
>> +- rockchip,grf: phandle to the syscon managing the "general register files"
>> +  If missing pll rates are not changable, due to the missing pll lock
>> status. +
>> +Each clock is assigned an identifier and client nodes can use this
>> identifier +to specify the clock which they consume. All available clocks
>> are defined as +preprocessor macros in the dt-bindings/clock/rk3036-cru.h
>> headers and can be +used in device tree sources. Similar macros exist for
>> the reset sources in +these files.
>> +
>> +External clocks:
>> +
>> +There are several clocks that are generated outside the SoC. It is expected
>> +that they are defined using standard clock bindings with following
>> +clock-output-names:
>> + - "xin24m" - crystal input - required,
>> + - "xin32k" - rtc clock - optional,
> The rk3036 does not seem to use a rtc clock, so this should probably go away
Done.
>> + - "ext_i2s" - external I2S clock - optional,
>> + - "ext_hsadc" - external HSADC clock - optional,
>> + - "ext_vip" - external VIP clock - optional,
>> + - "ext_isp" - external ISP clock - optional,
>> + - "ext_jtag" - external JTAG clock - optional
> There do not seem to exist external clock sources for hsadc, vip, isp and jtag
> in your clock tree?
>
> missing here:
> - ext_gmac
Yes, done.
>> +
>> +Example: Clock controller node:
>> +
>> +	cru: cru@20000000 {
>> +		compatible = "rockchip,rk3036-cru";
>> +		reg =<0x20000000 0x1000>;
>> +		rockchip,grf =<&grf>;
>> +
>> +		#clock-cells =<1>;
>> +		#reset-cells =<1>;
>> +	};
>> +
>> +Example: UART controller node that consumes the clock generated by the
>> clock +  controller:
>> +
>> +	uart0: serial@20060000 {
>> +		compatible = "snps,dw-apb-uart";
>> +		reg =<0x20060000 0x100>;
>> +		interrupts =<GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
>> +		reg-shift =<2>;
>> +		reg-io-width =<4>;
>> +		clocks =<&cru SCLK_UART0>;
>> +	};
Thanks.


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

* Re: [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036
  2015-09-17 20:15   ` Heiko Stübner
@ 2015-09-28 11:50     ` Xing Zheng
  0 siblings, 0 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-28 11:50 UTC (permalink / raw)
  To: Heiko Stübner; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel

On 2015年09月18日 04:15, Heiko Stübner wrote:
> Am Donnerstag, 17. September 2015, 18:38:06 schrieb Xing Zheng:
>> The rk3036 is dual-core soc, we can use this patch to enable cpu1
>> enter boot secondary, and hotplug(online/offline).
>>
>> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
>> ---
>>
>> Changes in v2: None
>>
>>   arch/arm/mach-rockchip/platsmp.c |  121
>> ++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/platsmp.c
>> b/arch/arm/mach-rockchip/platsmp.c index 3e7a4b7..14218eb 100644
>> --- a/arch/arm/mach-rockchip/platsmp.c
>> +++ b/arch/arm/mach-rockchip/platsmp.c
>> @@ -34,6 +34,8 @@
>>
>>   static void __iomem *scu_base_addr;
>>   static void __iomem *sram_base_addr;
>> +static void __iomem *cru_base_addr;
>> +
>>   static int ncores;
>>
>>   #define PMU_PWRDN_CON		0x08
>> @@ -41,6 +43,8 @@ static int ncores;
>>
>>   #define PMU_PWRDN_SCU		4
>>
>> +#define RK3036_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
>> +
>>   static struct regmap *pmu;
>>
>>   static int pmu_power_domain_is_on(int pd)
>> @@ -184,6 +188,7 @@ static int __init rockchip_smp_prepare_sram(struct
>> device_node *node) }
>>
>>   	rsize = resource_size(&res);
>> +
>>   	if (rsize<  trampoline_sz) {
>>   		pr_err("%s: reserved block with size 0x%x is to small for trampoline
> size
>> 0x%x\n", __func__, rsize, trampoline_sz);
>> @@ -350,3 +355,119 @@ static struct smp_operations rockchip_smp_ops
>> __initdata = { };
>>
>>   CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp",
>> &rockchip_smp_ops); +
>> +/* for rk3036 */
>> +
>> +static int rk3036_set_power_domain(int pd, bool on)
>> +{
>> +	/* there are 2cpus on rk3036 soc, we just need to be care cpu1 */
>> +	if (pd != 1)
>> +		return 0;
>> +
>> +	if (on)
>> +		writel_relaxed(0x20000, cru_base_addr + RK3036_SOFTRST_CON(0));
>> +	else
>> +		writel_relaxed(0x20002, cru_base_addr + RK3036_SOFTRST_CON(0));
> this is definitly the wrong way. The reset handling is the same as on the
> rk3288 - so you can use the regular reset mechanism like the other socs and
> should definitly _never_ write to the cru directly.
>
> The only visible difference is that you cannot control the power-domains of
> the cpu cores. Its sibling the rk3128 seems to have controllable power domains
> again.
>
> I'm still pondering how to make this future proof...
>
>
> Heiko
OK, I tried add the regular reset mechanism like the rk3288.
Yes, then, there are something need to continue to improve.

Thanks.
>
>> +
>> +	dsb();
>> +
>> +	return 0;
>> +}
>> +
>> +static void __init rk3036_smp_prepare_cpus(unsigned int max_cpus)
>> +{
>> +	struct device_node *node;
>> +	unsigned int l2ctlr;
>> +	unsigned int i, cpu;
>> +
>> +	/* get cru_base_addr */
>> +	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3036-cru");
>> +	if (!node) {
>> +		pr_err("%s: could not find cru dt node\n", __func__);
>> +		return;
>> +	}
>> +
>> +	cru_base_addr = of_iomap(node, 0);
>> +	if (!cru_base_addr) {
>> +		pr_err("%s: could not map cru registers\n", __func__);
>> +		return;
>> +	}
>> +
>> +	/* get sram_base_addr */
>> +	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3036-smp-sram");
>> +	if (!node) {
>> +		pr_err("%s: could not find sram dt node\n", __func__);
>> +		return;
>> +	}
>> +
>> +	sram_base_addr = of_iomap(node, 0);
>> +	if (!sram_base_addr) {
>> +		pr_err("%s: could not map sram registers\n", __func__);
>> +		return;
>> +	}
>> +
>> +	/* get ncores */
>> +	asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
>> +	ncores = ((l2ctlr>>  24)&  0x3) + 1;
>> +	cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 0);
>> +
>> +	/* Make sure that all cores except the first are really off */
>> +	for (i = 1; i<  ncores; i++)
>> +		rk3036_set_power_domain(0 + i, false);
>> +}
>> +
>> +static int rk3036_boot_secondary(unsigned int cpu, struct task_struct
>> *idle) +{
>> +	if (cpu>= ncores) {
>> +		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
>> +			__func__, cpu, ncores);
>> +		return -ENXIO;
>> +	}
>> +
>> +	/* start the core */
>> +	rk3036_set_power_domain(0 + cpu, true);
>> +
>> +	/*
>> +	 * We need to wait a moment after soft reset CPUx on rk3036,
>> +	 * otherwise, CPUx will startup failed.
>> +	 */
>> +	udelay(10);
>> +	writel(virt_to_phys(secondary_startup), sram_base_addr + 8);
>> +	writel(0xDEADBEAF, sram_base_addr + 4);
>> +	dsb_sev();
>> +
>> +	return 0;
>> +}
>> +
>> +#ifdef CONFIG_HOTPLUG_CPU
>> +static int rk3066_cpu_kill(unsigned int cpu)
>> +{
>> +	/*
>> +	 * We need a delay here to ensure that the dying CPU can finish
>> +	 * executing v7_coherency_exit() and reach the WFI/WFE state
>> +	 * prior to having the power domain disabled.
>> +	 */
>> +	mdelay(1);
>> +
>> +	rk3036_set_power_domain(0 + cpu, false);
>> +
>> +	return 1;
>> +}
>> +
>> +static void rk3066_cpu_die(unsigned int cpu)
>> +{
>> +	v7_exit_coherency_flush(louis);
>> +	while (1)
>> +		cpu_do_idle();
>> +}
>> +#endif
>> +
>> +static struct smp_operations rk3036_smp_ops __initdata = {
>> +	.smp_prepare_cpus	= rk3036_smp_prepare_cpus,
>> +	.smp_boot_secondary	= rk3036_boot_secondary,
>> +#ifdef CONFIG_HOTPLUG_CPU
>> +	.cpu_kill		= rk3066_cpu_kill,
>> +	.cpu_die		= rk3066_cpu_die,
>> +#endif
>> +};
>> +CPU_METHOD_OF_DECLARE(rk3036_smp, "rockchip,rk3036-smp",&rk3036_smp_ops);



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

* Re: [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms
  2015-09-17 15:05   ` Heiko Stübner
@ 2015-09-28 12:25     ` Xing Zheng
  2015-09-28 12:44       ` Heiko Stübner
  0 siblings, 1 reply; 37+ messages in thread
From: Xing Zheng @ 2015-09-28 12:25 UTC (permalink / raw)
  To: Heiko Stübner; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel

On 2015年09月17日 23:05, Heiko Stübner wrote:
> Am Donnerstag, 17. September 2015, 18:37:24 schrieb Xing Zheng:
>> The timer5 supplies the architected timer and thus as has to run when
>> the system clocksource and clockevents drivers are registered.
> please kindly ask the people doing uboot development to do this in uboot
> itself in future socs :-) - for example Simon's rk3288 mainline uboot does
> this correctly.
OK, I will ask the engineer who is doing uboot whether needs to add
this patch. So I will remove it from the patchset v3 of "Build and support
rk3036 SoC platform".

Thanks.
>> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
>> ---
>>
>> Changes in v2: None
>>
>>   arch/arm/mach-rockchip/rockchip.c |   22 ++++++++++++++++++++++
>>   1 file changed, 22 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> b/arch/arm/mach-rockchip/rockchip.c index b6cf3b4..937047f 100644
>> --- a/arch/arm/mach-rockchip/rockchip.c
>> +++ b/arch/arm/mach-rockchip/rockchip.c
>> @@ -32,6 +32,8 @@
>>   #define RK3288_GRF_SOC_CON0 0x244
>>   #define RK3288_TIMER6_7_PHYS 0xff810000
>>
>> +#define RK3036_TIMER5_PHYS 0x200440a0
>> +
> #define RK3036_TIMER_PHYS 0x20044000
> -->  the actual base address of the timer block
>
> As it looks like that we'll need to duplicate that timer init at least for the
> rk3036 and the timer ip in question is actually the same on both, please split
> out the actual work into a separate function like
>
> static void rockchip_init_arch_timer_supply(resource_size_t phys, int offs)
> {
> 		reg_base = ioremap(phys, SZ_16K);
> 		if (reg_base) {
> 			writel(0, reg_base + offs + 0x10);
> 			writel(0xffffffff, reg_base + offs);
> 			writel(0xffffffff, reg_base + offs + 0x04);
> 			writel(1, reg_base + offs + 0x10);
> 			dsb();
> 			iounmap(reg_base);
> 		} else {
> 			pr_err("rockchip: could not map timer registers\n");
> 		}
> }
Done.
>
>>   static void __init rockchip_timer_init(void)
>>   {
>>   	if (of_machine_is_compatible("rockchip,rk3288")) {
>> @@ -64,6 +66,25 @@ static void __init rockchip_timer_init(void)
> for the rk3288 exchange the timer init against
> rockchip_init_arch_timer_supply(RK3288_TIMER6_7_PHYS, 0x20);
Done.
>>   			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
>>   		else
>>   			pr_err("rockchip: could not get grf syscon\n");
>> +	} else if (of_machine_is_compatible("rockchip,rk3036")) {
>> +		void __iomem *reg_base;
>> +
>> +		/*
>> +		 * Most/all uboot versions for rk3036 don't enable timer5
>> +		 * which is needed for the architected timer to work.
>> +		 * So make sure it is running during early boot.
>> +		 */
>> +		reg_base = ioremap(RK3036_TIMER5_PHYS, SZ_16K);
>> +		if (reg_base) {
>> +			writel(0, reg_base + 0x10);
>> +			writel(0xffffffff, reg_base);
>> +			writel(0xffffffff, reg_base + 0x04);
>> +			writel(1, reg_base + 0x10);
>> +			dsb();
>> +			iounmap(reg_base);
>> +		} else {
>> +			pr_err("rockchip: could not map timer5 registers\n");
>> +		}
> rockchip_init_arch_timer_supply(RK3036_TIMER_PHYS, 0xa0);
Done.
>>   	}
>>
>>   	of_clk_init(NULL);
>> @@ -79,6 +100,7 @@ static void __init rockchip_dt_init(void)
>>
>>   static const char * const rockchip_board_dt_compat[] = {
>>   	"rockchip,rk2928",
>> +	"rockchip,rk3036",
>>   	"rockchip,rk3066a",
>>   	"rockchip,rk3066b",
>>   	"rockchip,rk3188",
>


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

* Re: [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms
  2015-09-28 12:25     ` Xing Zheng
@ 2015-09-28 12:44       ` Heiko Stübner
  2015-09-28 12:53         ` Xing Zheng
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-28 12:44 UTC (permalink / raw)
  To: Xing Zheng; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel

Hi,

Am Montag, 28. September 2015, 20:25:07 schrieb Xing Zheng:
> On 2015年09月17日 23:05, Heiko Stübner wrote:
> > Am Donnerstag, 17. September 2015, 18:37:24 schrieb Xing Zheng:
> >> The timer5 supplies the architected timer and thus as has to run when
> >> the system clocksource and clockevents drivers are registered.
> > 
> > please kindly ask the people doing uboot development to do this in uboot
> > itself in future socs :-) - for example Simon's rk3288 mainline uboot does
> > this correctly.
> 
> OK, I will ask the engineer who is doing uboot whether needs to add
> this patch. So I will remove it from the patchset v3 of "Build and support
> rk3036 SoC platform".

No, I really only meant try to make people get this right in the future :-).

For the rk3036 there are probably already devices on the market with uboots 
sporting that issue. So it's ok to have this in here now, it's just to make 
sure it gets really fixed in future socs.


Heiko



> 
> Thanks.
> 
> >> Signed-off-by: Xing Zheng<zhengxing@rock-chips.com>
> >> ---
> >> 
> >> Changes in v2: None
> >> 
> >>   arch/arm/mach-rockchip/rockchip.c |   22 ++++++++++++++++++++++
> >>   1 file changed, 22 insertions(+)
> >> 
> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >> b/arch/arm/mach-rockchip/rockchip.c index b6cf3b4..937047f 100644
> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> @@ -32,6 +32,8 @@
> >> 
> >>   #define RK3288_GRF_SOC_CON0 0x244
> >>   #define RK3288_TIMER6_7_PHYS 0xff810000
> >> 
> >> +#define RK3036_TIMER5_PHYS 0x200440a0
> >> +
> > 
> > #define RK3036_TIMER_PHYS 0x20044000
> > -->  the actual base address of the timer block
> > 
> > As it looks like that we'll need to duplicate that timer init at least for
> > the rk3036 and the timer ip in question is actually the same on both,
> > please split out the actual work into a separate function like
> > 
> > static void rockchip_init_arch_timer_supply(resource_size_t phys, int
> > offs)
> > {
> > 
> > 		reg_base = ioremap(phys, SZ_16K);
> > 		if (reg_base) {
> > 		
> > 			writel(0, reg_base + offs + 0x10);
> > 			writel(0xffffffff, reg_base + offs);
> > 			writel(0xffffffff, reg_base + offs + 0x04);
> > 			writel(1, reg_base + offs + 0x10);
> > 			dsb();
> > 			iounmap(reg_base);
> > 		
> > 		} else {
> > 		
> > 			pr_err("rockchip: could not map timer registers\n");
> > 		
> > 		}
> > 
> > }
> 
> Done.
> 
> >>   static void __init rockchip_timer_init(void)
> >>   {
> >>   
> >>   	if (of_machine_is_compatible("rockchip,rk3288")) {
> >> 
> >> @@ -64,6 +66,25 @@ static void __init rockchip_timer_init(void)
> > 
> > for the rk3288 exchange the timer init against
> > rockchip_init_arch_timer_supply(RK3288_TIMER6_7_PHYS, 0x20);
> 
> Done.
> 
> >>   			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
> >>   		
> >>   		else
> >>   		
> >>   			pr_err("rockchip: could not get grf syscon\n");
> >> 
> >> +	} else if (of_machine_is_compatible("rockchip,rk3036")) {
> >> +		void __iomem *reg_base;
> >> +
> >> +		/*
> >> +		 * Most/all uboot versions for rk3036 don't enable timer5
> >> +		 * which is needed for the architected timer to work.
> >> +		 * So make sure it is running during early boot.
> >> +		 */
> >> +		reg_base = ioremap(RK3036_TIMER5_PHYS, SZ_16K);
> >> +		if (reg_base) {
> >> +			writel(0, reg_base + 0x10);
> >> +			writel(0xffffffff, reg_base);
> >> +			writel(0xffffffff, reg_base + 0x04);
> >> +			writel(1, reg_base + 0x10);
> >> +			dsb();
> >> +			iounmap(reg_base);
> >> +		} else {
> >> +			pr_err("rockchip: could not map timer5 registers\n");
> >> +		}
> > 
> > rockchip_init_arch_timer_supply(RK3036_TIMER_PHYS, 0xa0);
> 
> Done.
> 
> >>   	}
> >>   	
> >>   	of_clk_init(NULL);
> >> 
> >> @@ -79,6 +100,7 @@ static void __init rockchip_dt_init(void)
> >> 
> >>   static const char * const rockchip_board_dt_compat[] = {
> >>   
> >>   	"rockchip,rk2928",
> >> 
> >> +	"rockchip,rk3036",
> >> 
> >>   	"rockchip,rk3066a",
> >>   	"rockchip,rk3066b",
> >>   	"rockchip,rk3188",


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

* Re: [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms
  2015-09-28 12:44       ` Heiko Stübner
@ 2015-09-28 12:53         ` Xing Zheng
  0 siblings, 0 replies; 37+ messages in thread
From: Xing Zheng @ 2015-09-28 12:53 UTC (permalink / raw)
  To: Heiko Stübner; +Cc: linux, linux-arm-kernel, linux-rockchip, linux-kernel

On 2015年09月28日 20:44, Heiko Stübner wrote:
> Hi,
>
> Am Montag, 28. September 2015, 20:25:07 schrieb Xing Zheng:
>> On 2015年09月17日 23:05, Heiko Stübner wrote:
>>> Am Donnerstag, 17. September 2015, 18:37:24 schrieb Xing Zheng:
>>>> The timer5 supplies the architected timer and thus as has to run when
>>>> the system clocksource and clockevents drivers are registered.
>>> please kindly ask the people doing uboot development to do this in uboot
>>> itself in future socs :-) - for example Simon's rk3288 mainline uboot does
>>> this correctly.
>> OK, I will ask the engineer who is doing uboot whether needs to add
>> this patch. So I will remove it from the patchset v3 of "Build and support
>> rk3036 SoC platform".
> No, I really only meant try to make people get this right in the future :-).
>
> For the rk3036 there are probably already devices on the market with uboots
> sporting that issue. So it's ok to have this in here now, it's just to make
> sure it gets really fixed in future socs.
>
>
> Heiko
>
>
OK, I got it.

Thank you. :)


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

* Re: [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-22 23:19       ` Stephen Boyd
@ 2015-09-30 23:32         ` Heiko Stübner
  2015-10-01  0:51           ` Stephen Boyd
  0 siblings, 1 reply; 37+ messages in thread
From: Heiko Stübner @ 2015-09-30 23:32 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Xing Zheng, linux-rockchip, Michael Turquette, linux-clk,
	linux-arm-kernel, linux-kernel

Hi Stephen,

Am Dienstag, 22. September 2015, 16:19:00 schrieb Stephen Boyd:
> On 09/23, Heiko Stübner wrote:
> > Am Dienstag, 22. September 2015, 15:41:25 schrieb Stephen Boyd:
> > > On 09/17, Xing Zheng wrote:
> > > > +
> > > > +static void rockchip_rk3036_pll_init(struct clk_hw *hw)
> > > 
> > > init ops are "discouraged". Could we do this through assigned
> > > rates instead?
> > 
> > really? According to Mike that was a valid use-case when we looked for an
> > initial place for that on the rk3288 :-) .
> 
> A comment in clk.c indicates init ops are discouraged. Maybe this
> is a valid use-case on other platforms so it was allowed, but
> pretty much every time we see a new init op we have to think
> about it and justify it. Hooray!

for the rk3288-variant Mike said
"Looks good to me. I think rk3xxx might be the first user of the .init
callback!" [0]
so it looks like he was convinced of our reasoning at the time :-) .


[0] http://lists.infradead.org/pipermail/linux-rockchip/2014-November/001570.html


> > > > +{
> > > > +	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
> > > > +	const struct rockchip_pll_rate_table *rate;
> > > > +	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
> > > > +	unsigned long drate;
> > > > +	u32 pllcon;
> > > > +
> > > > +	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
> > > > +		return;
> > > 
> > > I don't understand what this one does though. This check isn't in
> > > the set rate ops.
> > 
> > And it shouldn't be :-)
> > 
> > The issue this whole thing is trying to solve is aligning the pll settings
> > which what we have in the rate table, not what the bootloader set.
> > 
> > For example the bootloader could set up a pll at 594MHz with one set of
> > parameters and after some time - when you don't want to exchange
> > bootloaders on shipping devices anymore - it comes to light that a
> > different set of parameters for the same frequency produces for example a
> > more stable hdmi signal [I think that was the main reason for the initial
> > change].
> > 
> > So we're not changing the frequency x -> y, which could be easily done
> > [and is done already] via assigned-rates, but instead
> > 
> > 	x {params a,b,c} -> x {params d,e,f}
> > 
> > so the rate itself stays the same, only the frequency generation is
> > adapted.
> Ok. It would be nice if this sort of information was made into a
> comment and put in the code. Or at least the commit text for the
> change.
> 
> And is there any reason that we need to get the parent clock and
> parent rate to align the PLL settings?
> It would be nice if we
> avoided using clk_* APIs in here, by extracting the pll set rate
> code into another function that we can call from init to make the
> values the same without all the fallback to old rates, etc.

I guess you want Xing Zheng to change his pll code somewhat like the
following, right? While starting off as proof-of-concept, that change
below actually does work quite nicely on rk3288 boards.

---------------- 8< --------------------
From: Heiko Stuebner <heiko@sntech.de>
Subject: [PATCH] clk: rockchip: don't use clk_ APIs in the pll init-callback

Separate the update of pll registers from the actual set_rate function
so that the init callback does not need to access clk-API functions.

As we now have separated the getting and setting of the pll parameters
we can also directly use these new functions in other places too.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/clk/rockchip/clk-pll.c | 135 ++++++++++++++++++++++-------------------
 1 file changed, 74 insertions(+), 61 deletions(-)

diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 7737a1d..4881eb8 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -126,11 +126,32 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
 #define RK3066_PLLCON3_PWRDOWN		(1 << 1)
 #define RK3066_PLLCON3_BYPASS		(1 << 0)
 
+static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll,
+					struct rockchip_pll_rate_table *rate)
+{
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
+	rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT)
+				& RK3066_PLLCON0_NR_MASK) + 1;
+	rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT)
+				& RK3066_PLLCON0_OD_MASK) + 1;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
+	rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT)
+				& RK3066_PLLCON1_NF_MASK) + 1;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
+	rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT)
+				& RK3066_PLLCON2_NB_MASK) + 1;
+}
+
 static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
 						     unsigned long prate)
 {
 	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	u64 nf, nr, no, rate64 = prate;
+	struct rockchip_pll_rate_table cur;
+	u64 rate64 = prate;
 	u32 pllcon;
 
 	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
@@ -140,53 +161,31 @@ static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
 		return prate;
 	}
 
-	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
-	nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK;
-
-	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
-	nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK;
-	no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK;
+	rockchip_rk3066_pll_get_params(pll, &cur);
 
-	rate64 *= (nf + 1);
-	do_div(rate64, nr + 1);
-	do_div(rate64, no + 1);
+	rate64 *= cur.nf;
+	do_div(rate64, cur.nr);
+	do_div(rate64, cur.no);
 
 	return (unsigned long)rate64;
 }
 
-static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
-					unsigned long prate)
+static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll,
+				const struct rockchip_pll_rate_table *rate)
 {
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	const struct rockchip_pll_rate_table *rate;
-	unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
-	struct regmap *grf = rockchip_clk_get_grf();
-	struct clk_mux *pll_mux = &pll->pll_mux;
 	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+	struct clk_mux *pll_mux = &pll->pll_mux;
+	struct rockchip_pll_rate_table cur;
 	int rate_change_remuxed = 0;
 	int cur_parent;
 	int ret;
 
-	if (IS_ERR(grf)) {
-		pr_debug("%s: grf regmap not available, aborting rate change\n",
-			 __func__);
-		return PTR_ERR(grf);
-	}
-
-	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
-		 __func__, clk_hw_get_name(hw), old_rate, drate, prate);
-
-	/* Get required rate settings from table */
-	rate = rockchip_get_pll_settings(pll, drate);
-	if (!rate) {
-		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-			drate, clk_hw_get_name(hw));
-		return -EINVAL;
-	}
-
 	pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
 		 __func__, rate->rate, rate->nr, rate->no, rate->nf);
 
+	rockchip_rk3066_pll_get_params(pll, &cur);
+	cur.rate = 0;
+
 	cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
 	if (cur_parent == PLL_MODE_NORM) {
 		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
@@ -219,9 +218,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 	/* wait for the pll to lock */
 	ret = rockchip_pll_wait_lock(pll);
 	if (ret) {
-		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
-			__func__, old_rate);
-		rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
+		pr_warn("%s: pll update unsucessful, trying to restore old params\n",
+			__func__);
+		rockchip_rk3066_pll_set_params(pll, &cur);
 	}
 
 	if (rate_change_remuxed)
@@ -230,6 +229,34 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 	return ret;
 }
 
+static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
+	struct regmap *grf = rockchip_clk_get_grf();
+
+	if (IS_ERR(grf)) {
+		pr_debug("%s: grf regmap not available, aborting rate change\n",
+			 __func__);
+		return PTR_ERR(grf);
+	}
+
+	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
+		 __func__, clk_hw_get_name(hw), old_rate, drate, prate);
+
+	/* Get required rate settings from table */
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, clk_hw_get_name(hw));
+		return -EINVAL;
+	}
+
+	return rockchip_rk3066_pll_set_params(pll, rate);
+}
+
 static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
 {
 	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
@@ -261,9 +288,8 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
 {
 	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
 	const struct rockchip_pll_rate_table *rate;
-	unsigned int nf, nr, no, nb;
+	struct rockchip_pll_rate_table cur;
 	unsigned long drate;
-	u32 pllcon;
 
 	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
 		return;
@@ -275,34 +301,21 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
 	if (!rate)
 		return;
 
-	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
-	nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1;
-	no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1;
-
-	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
-	nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
-
-	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
-	nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1;
+	rockchip_rk3066_pll_get_params(pll, &cur);
 
 	pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
-		 __func__, clk_hw_get_name(hw), drate, rate->nr, nr,
-		rate->no, no, rate->nf, nf, rate->nb, nb);
-	if (rate->nr != nr || rate->no != no || rate->nf != nf
-					     || rate->nb != nb) {
-		struct clk_hw *parent = clk_hw_get_parent(hw);
-		unsigned long prate;
-
-		if (!parent) {
-			pr_warn("%s: parent of %s not available\n",
-				__func__, clk_hw_get_name(hw));
+		 __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr,
+		 rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
+	if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf
+						     || rate->nb != cur.nb) {
+		struct regmap *grf = rockchip_clk_get_grf();
+
+		if (IS_ERR(grf))
 			return;
-		}
 
 		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
 			 __func__, clk_hw_get_name(hw));
-		prate = clk_hw_get_rate(parent);
-		rockchip_rk3066_pll_set_rate(hw, drate, prate);
+		rockchip_rk3066_pll_set_params(pll, rate);
 	}
 }
 
-- 
2.5.3
---------------- 8< --------------------

Heiko

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

* Re: [PATCH v2 4/9] clk: rockchip: add new clock type and controller for rk3036
  2015-09-30 23:32         ` Heiko Stübner
@ 2015-10-01  0:51           ` Stephen Boyd
  0 siblings, 0 replies; 37+ messages in thread
From: Stephen Boyd @ 2015-10-01  0:51 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Xing Zheng, linux-rockchip, Michael Turquette, linux-clk,
	linux-arm-kernel, linux-kernel

On 10/01, Heiko Stübner wrote:
> Hi Stephen,
> 
> Am Dienstag, 22. September 2015, 16:19:00 schrieb Stephen Boyd:
> > On 09/23, Heiko Stübner wrote:
> > > Am Dienstag, 22. September 2015, 15:41:25 schrieb Stephen Boyd:
> > > > On 09/17, Xing Zheng wrote:
> > > > > +{
> > > > > +	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
> > > > > +	const struct rockchip_pll_rate_table *rate;
> > > > > +	unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac;
> > > > > +	unsigned long drate;
> > > > > +	u32 pllcon;
> > > > > +
> > > > > +	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
> > > > > +		return;
> > > > 
> > > > I don't understand what this one does though. This check isn't in
> > > > the set rate ops.
> > > 
> > > And it shouldn't be :-)
> > > 
> > > The issue this whole thing is trying to solve is aligning the pll settings
> > > which what we have in the rate table, not what the bootloader set.
> > > 
> > > For example the bootloader could set up a pll at 594MHz with one set of
> > > parameters and after some time - when you don't want to exchange
> > > bootloaders on shipping devices anymore - it comes to light that a
> > > different set of parameters for the same frequency produces for example a
> > > more stable hdmi signal [I think that was the main reason for the initial
> > > change].
> > > 
> > > So we're not changing the frequency x -> y, which could be easily done
> > > [and is done already] via assigned-rates, but instead
> > > 
> > > 	x {params a,b,c} -> x {params d,e,f}
> > > 
> > > so the rate itself stays the same, only the frequency generation is
> > > adapted.
> > Ok. It would be nice if this sort of information was made into a
> > comment and put in the code. Or at least the commit text for the
> > change.
> > 
> > And is there any reason that we need to get the parent clock and
> > parent rate to align the PLL settings?
> > It would be nice if we
> > avoided using clk_* APIs in here, by extracting the pll set rate
> > code into another function that we can call from init to make the
> > values the same without all the fallback to old rates, etc.
> 
> I guess you want Xing Zheng to change his pll code somewhat like the
> following, right? While starting off as proof-of-concept, that change
> below actually does work quite nicely on rk3288 boards.
> 
> ---------------- 8< --------------------
> From: Heiko Stuebner <heiko@sntech.de>
> Subject: [PATCH] clk: rockchip: don't use clk_ APIs in the pll init-callback
> 
> Separate the update of pll registers from the actual set_rate function
> so that the init callback does not need to access clk-API functions.
> 
> As we now have separated the getting and setting of the pll parameters
> we can also directly use these new functions in other places too.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>

Yep, it looks much better this way.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036
  2015-09-24  3:31       ` Xing Zheng
@ 2015-10-07 10:24         ` Heiko Stuebner
  0 siblings, 0 replies; 37+ messages in thread
From: Heiko Stuebner @ 2015-10-07 10:24 UTC (permalink / raw)
  To: Xing Zheng
  Cc: linux-rockchip, Michael Turquette, Stephen Boyd, linux-kernel,
	linux-clk, linux-arm-kernel

Hi,

Am Donnerstag, 24. September 2015, 11:31:58 schrieb Xing Zheng:
> On 2015年09月24日 11:04, Xing Zheng wrote:
> >>>   #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)    \
> >>> 
> >>> @@ -95,12 +106,31 @@ enum rockchip_pll_type {
> >>> 
> >>>       .nb = _nb,                        \
> >>>   
> >>>   }
> >>> 
> >>> +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,    \
> >>> +            _postdiv2, _dsmpd, _frac)        \
> >>> +{                                \
> >>> +    .rate    = _rate##U,                    \
> >>> +    .fbdiv = _fbdiv,                    \
> >>> +    .postdiv1 = _postdiv1,                    \
> >>> +    .refdiv = _refdiv,                    \
> >>> +    .postdiv2 = _postdiv2,                    \
> >>> +    .dsmpd = _dsmpd,                    \
> >>> +    .frac = _frac,                        \
> >>> +}
> >>> +
> >>> 
> >>>   struct rockchip_pll_rate_table {
> >>>   
> >>>       unsigned long rate;
> >>>       unsigned int nr;
> >>>       unsigned int nf;
> >>>       unsigned int no;
> >>>       unsigned int nb;
> >>> 
> >>> +    /* for RK3036 */
> >>> +    unsigned int fbdiv;
> >>> +    unsigned int postdiv1;
> >>> +    unsigned int refdiv;
> >>> +    unsigned int postdiv2;
> >>> +    unsigned int dsmpd;
> >>> +    unsigned int frac;
> >> 
> >> same for these 2 ... should be part of the pll addition itself
> >> 
> >   };
> > 
> > Done.
> 
> Sorry, I have one question:
> The "struct rockchip_pll_rate_table" is called in "rockchip/clk-pll.c"
> on many functions, I think I could add a struct like:
> struct rk3036_pll_rate_table {
>      unsigned int fbdiv;
>      unsigned int postdiv1;
>      unsigned int refdiv;
>      unsigned int postdiv2;
>      unsigned int dsmpd;
>      unsigned int frac;
> };
> but, it will add many redundancy codes in "rockchip/clk-pll.c" just for
> call "struct rk3036_pll_rate_table".


One possible solution may be to cast to void* in the general functions, so 
have sturct rk3066_pll_rate_table, rk3036_pll_rate_table, have 
rockchip_clk_register_pll and friends handle it as void* and then only have 
the rockchip_rk3066_pll_* functions as well as the clk-rkxxxx.c use them as 
their actual type, as they know which they need.


Heiko


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

end of thread, other threads:[~2015-10-07 14:56 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-17  8:28 [PATCH v2 0/9] Build and support rk3036 SoC platform Xing Zheng
2015-09-17  8:28 ` [PATCH v2 1/9] ARM: dts: rockchip: add core rk3036 dts Xing Zheng
2015-09-17  9:18   ` Heiko Stübner
2015-09-24  2:18     ` Xing Zheng
2015-09-17  8:28 ` [PATCH v2 2/9] clk: rockchip: add dt-binding header for rk3036 Xing Zheng
2015-09-17  9:25   ` Heiko Stübner
2015-09-24  2:17     ` Xing Zheng
2015-09-17  8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller " Xing Zheng
2015-09-17  9:47   ` Heiko Stübner
2015-09-24  3:04     ` Xing Zheng
2015-09-24  3:31       ` Xing Zheng
2015-10-07 10:24         ` Heiko Stuebner
2015-09-17  8:28 ` [PATCH v2 4/9] clk: rockchip: add new clock type and " Xing Zheng
2015-09-17  9:54   ` Heiko Stübner
2015-09-22 22:41   ` Stephen Boyd
2015-09-22 22:58     ` Heiko Stübner
2015-09-22 23:19       ` Stephen Boyd
2015-09-30 23:32         ` Heiko Stübner
2015-10-01  0:51           ` Stephen Boyd
2015-09-17  9:59 ` [PATCH v2 0/9] Build and support rk3036 SoC platform Heiko Stübner
2015-09-17 10:32 ` [PATCH v2 5/9] dt-bindings: add documentation of rk3036 clock controller Xing Zheng
2015-09-17 15:09   ` Heiko Stübner
2015-09-24  3:42     ` Xing Zheng
2015-09-17 10:34 ` [PATCH v2 6/9] pinctrl: rockchip: add support for the rk3036 Xing Zheng
2015-09-17 12:47   ` Heiko Stübner
2015-09-17 10:37 ` [PATCH v2 7/9] rockchip: make sure timer5 is enabled on rk3036 platforms Xing Zheng
2015-09-17 15:05   ` Heiko Stübner
2015-09-28 12:25     ` Xing Zheng
2015-09-28 12:44       ` Heiko Stübner
2015-09-28 12:53         ` Xing Zheng
2015-09-17 10:38 ` [PATCH v2 8/9] ARM: rockchip: add support smp for rk3036 Xing Zheng
2015-09-17 20:15   ` Heiko Stübner
2015-09-28 11:50     ` Xing Zheng
2015-09-17 10:39 ` [PATCH v2 9/9] rtc: hym8563: make sure hym8563 can be normal work Xing Zheng
2015-09-17 12:07   ` Heiko Stübner
2015-09-17 12:31     ` Alexandre Belloni
2015-09-17 12:44       ` Xing Zheng

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