* [PATCH v2 0/9] Build and support rk3036 SoC platform
@ 2015-09-17 8:28 Xing Zheng
2015-09-17 8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036 Xing Zheng
` (2 more replies)
0 siblings, 3 replies; 14+ 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] 14+ 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 ` 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
2015-09-17 9:59 ` [PATCH v2 0/9] Build and support rk3036 SoC platform Heiko Stübner
2 siblings, 1 reply; 14+ 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] 14+ 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
2015-09-17 8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036 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
2 siblings, 2 replies; 14+ 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] 14+ 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 for rk3036 Xing Zheng
@ 2015-09-17 9:47 ` Heiko Stübner
2015-09-24 3:04 ` Xing Zheng
0 siblings, 1 reply; 14+ 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] 14+ 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; 14+ 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] 14+ 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
2015-09-17 8:28 ` [PATCH v2 3/9] clk: rockchip: add clock controller for rk3036 Xing Zheng
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
2 siblings, 0 replies; 14+ 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] 14+ 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; 14+ 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] 14+ 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; 14+ 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] 14+ 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; 14+ 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] 14+ 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; 14+ 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] 14+ 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; 14+ 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] 14+ 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; 14+ 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=FCbner 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)
> > >=20
> > > init ops are "discouraged". Could we do this through assigned
> > > rates instead?
> >=20
> > really? According to Mike that was a valid use-case when we looked =
for an
> > initial place for that on the rk3288 :-) .
>=20
> 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/0=
01570.html
> > > > +{
> > > > +=09struct rockchip_clk_pll *pll =3D to_rockchip_clk_pll(hw);
> > > > +=09const struct rockchip_pll_rate_table *rate;
> > > > +=09unsigned int fbdiv, postdiv1, refdiv, postdiv2, dsmpd, frac=
;
> > > > +=09unsigned long drate;
> > > > +=09u32 pllcon;
> > > > +
> > > > +=09if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
> > > > +=09=09return;
> > >=20
> > > I don't understand what this one does though. This check isn't in=
> > > the set rate ops.
> >=20
> > And it shouldn't be :-)
> >=20
> > The issue this whole thing is trying to solve is aligning the pll s=
ettings
> > which what we have in the rate table, not what the bootloader set.
> >=20
> > For example the bootloader could set up a pll at 594MHz with one se=
t 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 exa=
mple a
> > more stable hdmi signal [I think that was the main reason for the i=
nitial
> > change].
> >=20
> > So we're not changing the frequency x -> y, which could be easily d=
one
> > [and is done already] via assigned-rates, but instead
> >=20
> > =09x {params a,b,c} -> x {params d,e,f}
> >=20
> > 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.
>=20
> 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-cal=
lback
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=09=09(1 << 1)
#define RK3066_PLLCON3_BYPASS=09=09(1 << 0)
=20
+static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pl=
l,
+=09=09=09=09=09struct rockchip_pll_rate_table *rate)
+{
+=09u32 pllcon;
+
+=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
+=09rate->nr =3D ((pllcon >> RK3066_PLLCON0_NR_SHIFT)
+=09=09=09=09& RK3066_PLLCON0_NR_MASK) + 1;
+=09rate->no =3D ((pllcon >> RK3066_PLLCON0_OD_SHIFT)
+=09=09=09=09& RK3066_PLLCON0_OD_MASK) + 1;
+
+=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
+=09rate->nf =3D ((pllcon >> RK3066_PLLCON1_NF_SHIFT)
+=09=09=09=09& RK3066_PLLCON1_NF_MASK) + 1;
+
+=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
+=09rate->nb =3D ((pllcon >> RK3066_PLLCON2_NB_SHIFT)
+=09=09=09=09& RK3066_PLLCON2_NB_MASK) + 1;
+}
+
static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw=
,
=09=09=09=09=09=09 unsigned long prate)
{
=09struct rockchip_clk_pll *pll =3D to_rockchip_clk_pll(hw);
-=09u64 nf, nr, no, rate64 =3D prate;
+=09struct rockchip_pll_rate_table cur;
+=09u64 rate64 =3D prate;
=09u32 pllcon;
=20
=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
@@ -140,53 +161,31 @@ static unsigned long rockchip_rk3066_pll_recalc_r=
ate(struct clk_hw *hw,
=09=09return prate;
=09}
=20
-=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
-=09nf =3D (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK=
;
-
-=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
-=09nr =3D (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK=
;
-=09no =3D (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK=
;
+=09rockchip_rk3066_pll_get_params(pll, &cur);
=20
-=09rate64 *=3D (nf + 1);
-=09do_div(rate64, nr + 1);
-=09do_div(rate64, no + 1);
+=09rate64 *=3D cur.nf;
+=09do_div(rate64, cur.nr);
+=09do_div(rate64, cur.no);
=20
=09return (unsigned long)rate64;
}
=20
-static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned lo=
ng drate,
-=09=09=09=09=09unsigned long prate)
+static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll=
,
+=09=09=09=09const struct rockchip_pll_rate_table *rate)
{
-=09struct rockchip_clk_pll *pll =3D to_rockchip_clk_pll(hw);
-=09const struct rockchip_pll_rate_table *rate;
-=09unsigned long old_rate =3D rockchip_rk3066_pll_recalc_rate(hw, prat=
e);
-=09struct regmap *grf =3D rockchip_clk_get_grf();
-=09struct clk_mux *pll_mux =3D &pll->pll_mux;
=09const struct clk_ops *pll_mux_ops =3D pll->pll_mux_ops;
+=09struct clk_mux *pll_mux =3D &pll->pll_mux;
+=09struct rockchip_pll_rate_table cur;
=09int rate_change_remuxed =3D 0;
=09int cur_parent;
=09int ret;
=20
-=09if (IS_ERR(grf)) {
-=09=09pr_debug("%s: grf regmap not available, aborting rate change\n",=
-=09=09=09 __func__);
-=09=09return PTR_ERR(grf);
-=09}
-
-=09pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu=
\n",
-=09=09 __func__, clk_hw_get_name(hw), old_rate, drate, prate);
-
-=09/* Get required rate settings from table */
-=09rate =3D rockchip_get_pll_settings(pll, drate);
-=09if (!rate) {
-=09=09pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-=09=09=09drate, clk_hw_get_name(hw));
-=09=09return -EINVAL;
-=09}
-
=09pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
=09=09 __func__, rate->rate, rate->nr, rate->no, rate->nf);
=20
+=09rockchip_rk3066_pll_get_params(pll, &cur);
+=09cur.rate =3D 0;
+
=09cur_parent =3D pll_mux_ops->get_parent(&pll_mux->hw);
=09if (cur_parent =3D=3D PLL_MODE_NORM) {
=09=09pll_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,
=09/* wait for the pll to lock */
=09ret =3D rockchip_pll_wait_lock(pll);
=09if (ret) {
-=09=09pr_warn("%s: pll did not lock, trying to restore old rate %lu\n"=
,
-=09=09=09__func__, old_rate);
-=09=09rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
+=09=09pr_warn("%s: pll update unsucessful, trying to restore old param=
s\n",
+=09=09=09__func__);
+=09=09rockchip_rk3066_pll_set_params(pll, &cur);
=09}
=20
=09if (rate_change_remuxed)
@@ -230,6 +229,34 @@ static int rockchip_rk3066_pll_set_rate(struct clk=
_hw *hw, unsigned long drate,
=09return ret;
}
=20
+static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned lo=
ng drate,
+=09=09=09=09=09unsigned long prate)
+{
+=09struct rockchip_clk_pll *pll =3D to_rockchip_clk_pll(hw);
+=09const struct rockchip_pll_rate_table *rate;
+=09unsigned long old_rate =3D rockchip_rk3066_pll_recalc_rate(hw, prat=
e);
+=09struct regmap *grf =3D rockchip_clk_get_grf();
+
+=09if (IS_ERR(grf)) {
+=09=09pr_debug("%s: grf regmap not available, aborting rate change\n",=
+=09=09=09 __func__);
+=09=09return PTR_ERR(grf);
+=09}
+
+=09pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu=
\n",
+=09=09 __func__, clk_hw_get_name(hw), old_rate, drate, prate);
+
+=09/* Get required rate settings from table */
+=09rate =3D rockchip_get_pll_settings(pll, drate);
+=09if (!rate) {
+=09=09pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+=09=09=09drate, clk_hw_get_name(hw));
+=09=09return -EINVAL;
+=09}
+
+=09return rockchip_rk3066_pll_set_params(pll, rate);
+}
+
static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
{
=09struct rockchip_clk_pll *pll =3D to_rockchip_clk_pll(hw);
@@ -261,9 +288,8 @@ static void rockchip_rk3066_pll_init(struct clk_hw =
*hw)
{
=09struct rockchip_clk_pll *pll =3D to_rockchip_clk_pll(hw);
=09const struct rockchip_pll_rate_table *rate;
-=09unsigned int nf, nr, no, nb;
+=09struct rockchip_pll_rate_table cur;
=09unsigned long drate;
-=09u32 pllcon;
=20
=09if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
=09=09return;
@@ -275,34 +301,21 @@ static void rockchip_rk3066_pll_init(struct clk_h=
w *hw)
=09if (!rate)
=09=09return;
=20
-=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
-=09nr =3D ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MAS=
K) + 1;
-=09no =3D ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MAS=
K) + 1;
-
-=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
-=09nf =3D ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MAS=
K) + 1;
-
-=09pllcon =3D readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
-=09nb =3D ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MAS=
K) + 1;
+=09rockchip_rk3066_pll_get_params(pll, &cur);
=20
=09pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:=
%d)\n",
-=09=09 __func__, clk_hw_get_name(hw), drate, rate->nr, nr,
-=09=09rate->no, no, rate->nf, nf, rate->nb, nb);
-=09if (rate->nr !=3D nr || rate->no !=3D no || rate->nf !=3D nf
-=09=09=09=09=09 || rate->nb !=3D nb) {
-=09=09struct clk_hw *parent =3D clk_hw_get_parent(hw);
-=09=09unsigned long prate;
-
-=09=09if (!parent) {
-=09=09=09pr_warn("%s: parent of %s not available\n",
-=09=09=09=09__func__, clk_hw_get_name(hw));
+=09=09 __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr,
+=09=09 rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
+=09if (rate->nr !=3D cur.nr || rate->no !=3D cur.no || rate->nf !=3D c=
ur.nf
+=09=09=09=09=09=09 || rate->nb !=3D cur.nb) {
+=09=09struct regmap *grf =3D rockchip_clk_get_grf();
+
+=09=09if (IS_ERR(grf))
=09=09=09return;
-=09=09}
=20
=09=09pr_debug("%s: pll %s: rate params do not match rate table, adjus=
ting\n",
=09=09=09 __func__, clk_hw_get_name(hw));
-=09=09prate =3D clk_hw_get_rate(parent);
-=09=09rockchip_rk3066_pll_set_rate(hw, drate, prate);
+=09=09rockchip_rk3066_pll_set_params(pll, rate);
=09}
}
=20
--=20
2.5.3
---------------- 8< --------------------
Heiko
^ permalink raw reply related [flat|nested] 14+ 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; 14+ 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] 14+ 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; 14+ 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=E5=B9=B409=E6=9C=8824=E6=97=A5 11:04, Xing Zheng wrote:
> >>> #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
> >>>=20
> >>> @@ -95,12 +106,31 @@ enum rockchip_pll_type {
> >>>=20
> >>> .nb =3D _nb, \
> >>> =20
> >>> }
> >>>=20
> >>> +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
> >>> + _postdiv2, _dsmpd, _frac) \
> >>> +{ \
> >>> + .rate =3D _rate##U, \
> >>> + .fbdiv =3D _fbdiv, \
> >>> + .postdiv1 =3D _postdiv1, \
> >>> + .refdiv =3D _refdiv, \
> >>> + .postdiv2 =3D _postdiv2, \
> >>> + .dsmpd =3D _dsmpd, \
> >>> + .frac =3D _frac, \
> >>> +}
> >>> +
> >>>=20
> >>> struct rockchip_pll_rate_table {
> >>> =20
> >>> unsigned long rate;
> >>> unsigned int nr;
> >>> unsigned int nf;
> >>> unsigned int no;
> >>> unsigned int nb;
> >>>=20
> >>> + /* for RK3036 */
> >>> + unsigned int fbdiv;
> >>> + unsigned int postdiv1;
> >>> + unsigned int refdiv;
> >>> + unsigned int postdiv2;
> >>> + unsigned int dsmpd;
> >>> + unsigned int frac;
> >>=20
> >> same for these 2 ... should be part of the pll addition itself
> >>=20
> > };
> >=20
> > Done.
>=20
> 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 f=
or
> call "struct rk3036_pll_rate_table".
One possible solution may be to cast to void* in the general functions,=
so=20
have sturct rk3066_pll_rate_table, rk3036_pll_rate_table, have=20
rockchip_clk_register_pll and friends handle it as void* and then only =
have=20
the rockchip_rk3066_pll_* functions as well as the clk-rkxxxx.c use the=
m as=20
their actual type, as they know which they need.
Heiko
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-10-07 10:24 UTC | newest]
Thread overview: 14+ 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 3/9] clk: rockchip: add clock controller for rk3036 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
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).