From a554bb5fb01804a38fde3782831c9567d997939e Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 8 Nov 2016 17:10:14 +0800 Subject: clk: rockchip: validity should be checked prior to cpu clock rate change If validity is not checked prior to clock rate change, clk_set_rate( cpu_clk, unsupported_rate) will return success, but the real clock rate change operation is prohibited in post clock change event. Alough post clock change event will report error due to unsupported clock rate is set, but this error message is ignored by clock framework. Signed-off-by: Elaine Zhang Tested-by: Rocky Hao Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-cpu.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/clk/rockchip') diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 05b3d73bfefa..0e09684d43a5 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -124,9 +124,18 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, struct clk_notifier_data *ndata) { const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; + const struct rockchip_cpuclk_rate_table *rate; unsigned long alt_prate, alt_div; unsigned long flags; + /* check validity of the new rate */ + rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for cpuclk\n", + __func__, ndata->new_rate); + return -EINVAL; + } + alt_prate = clk_get_rate(cpuclk->alt_parent); spin_lock_irqsave(cpuclk->lock, flags); -- cgit v1.2.3 From 9c496033b3b4a7d8c832018b471e20c1fc988504 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 16 Nov 2016 08:19:41 +0800 Subject: clk: rockchip: fix copy-paste error in rk3399 testclk Fix RK3368_* to RK3399_* for rk3399 clk_test clock. Signed-off-by: Jianqun Xu Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk/rockchip') diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 828005556376..3490887b0579 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -1383,8 +1383,8 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { /* clk_test */ /* clk_test_pre is controlled by CRU_MISC_CON[3] */ COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED, - RK3368_CLKSEL_CON(58), 0, 5, DFLAGS, - RK3368_CLKGATE_CON(13), 11, GFLAGS), + RK3399_CLKSEL_CON(58), 0, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 11, GFLAGS), /* ddrc */ GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3), -- cgit v1.2.3 From e44dde27949254b7da7259ab90864c211c14ade3 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Wed, 16 Nov 2016 16:49:23 +0800 Subject: clk: rockchip: add clock controller for rk1108 Add the clock tree definition and driver for rk1108 SoC. Signed-off-by: Shawn Lin Tested-by: Jacob Chen Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk-rk1108.c | 531 ++++++++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 15 ++ 3 files changed, 547 insertions(+) create mode 100644 drivers/clk/rockchip/clk-rk1108.c (limited to 'drivers/clk/rockchip') diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index b5f2c8ed12e1..16e098c36f90 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -11,6 +11,7 @@ obj-y += clk-mmc-phase.o obj-y += clk-ddr.o obj-$(CONFIG_RESET_CONTROLLER) += softrst.o +obj-y += clk-rk1108.o obj-y += clk-rk3036.o obj-y += clk-rk3188.o obj-y += clk-rk3228.o diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c new file mode 100644 index 000000000000..92750d798e5d --- /dev/null +++ b/drivers/clk/rockchip/clk-rk1108.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Shawn Lin + * Andy Yan + * + * 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 +#include +#include +#include +#include +#include "clk.h" + +#define RK1108_GRF_SOC_STATUS0 0x480 + +enum rk1108_plls { + apll, dpll, gpll, +}; + +static struct rockchip_pll_rate_table rk1108_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), + { /* sentinel */ }, +}; + +#define RK1108_DIV_CORE_MASK 0xf +#define RK1108_DIV_CORE_SHIFT 4 + +#define RK1108_CLKSEL0(_core_peri_div) \ + { \ + .reg = RK1108_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\ + RK1108_DIV_CORE_SHIFT) \ + } + +#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \ + { \ + .prate = _prate, \ + .divs = { \ + RK1108_CLKSEL0(_core_peri_div), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = { + RK1108_CPUCLK_RATE(816000000, 4), + RK1108_CPUCLK_RATE(600000000, 4), + RK1108_CPUCLK_RATE(312000000, 4), +}; + +static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = { + .core_reg = RK1108_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, + .mux_core_shift = 8, + .mux_core_mask = 0x1, +}; + +PNAME(mux_pll_p) = { "xin24m", "xin24m"}; +PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" }; +PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; +PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" }; +PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" }; +PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" }; +PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" }; +PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" }; +PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" }; +PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" }; +PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" }; +PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" }; +PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" }; +PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; +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_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" }; +PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; +PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; +PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" }; +PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; + +static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0), + RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates), + [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8), + RK1108_PLL_CON(11), 8, 31, 0, NULL), + [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16), + RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_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) +#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK + +static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata = + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(13), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata = + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(14), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata = + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(15), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata = + MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(5), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata = + MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(6), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata = + MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(7), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { + MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, + RK1108_MISC_CON, 13, 2, MFLAGS), + MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, + RK1108_MISC_CON, 15, 2, MFLAGS), + /* + * Clock-Architecture Diagram 2 + */ + + /* PD_CORE */ + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 1, GFLAGS), + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 0, GFLAGS), + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 2, GFLAGS), + COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK1108_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK1108_CLKGATE_CON(0), 4, GFLAGS), + GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(11), 0, GFLAGS), + GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(11), 1, GFLAGS), + + /* PD_RKVENC */ + + /* PD_RKVDEC */ + + /* PD_PMU_wrapper */ + COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(38), 0, 5, DFLAGS, + RK1108_CLKGATE_CON(8), 12, GFLAGS), + GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 0, GFLAGS), + GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 1, GFLAGS), + GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 2, GFLAGS), + GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 3, GFLAGS), + GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 4, GFLAGS), + GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 5, GFLAGS), + GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(10), 6, GFLAGS), + COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(8), 15, GFLAGS), + COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(8), 14, GFLAGS), + GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(8), 13, GFLAGS), + + /* + * Clock-Architecture Diagram 4 + */ + COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK1108_CLKGATE_CON(6), 0, GFLAGS), + GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(17), 0, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, + RK1108_CLKSEL_CON(29), 0, 5, DFLAGS, + RK1108_CLKGATE_CON(7), 2, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, + RK1108_CLKSEL_CON(29), 8, 5, DFLAGS, + RK1108_CLKGATE_CON(7), 3, GFLAGS), + + INVERTER(0, "pclk_vip", "ext_vip", + RK1108_CLKSEL_CON(31), 8, IFLAGS), + GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(7), 6, GFLAGS), + GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(18), 10, GFLAGS), + GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(6), 5, GFLAGS), + GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(6), 4, GFLAGS), + COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0, + RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), + + /* + * Clock-Architecture Diagram 5 + */ + + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + + COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, + RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(2), 0, GFLAGS), + COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(8), 0, + RK1108_CLKGATE_CON(2), 1, GFLAGS, + &rk1108_i2s0_fracmux), + GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT, + RK1108_CLKGATE_CON(2), 2, GFLAGS), + COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0, + RK1108_CLKSEL_CON(5), 15, 1, MFLAGS, + RK1108_CLKGATE_CON(2), 3, GFLAGS), + + COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, + RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(2), 4, GFLAGS), + COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(9), 0, + RK2928_CLKGATE_CON(2), 5, GFLAGS, + &rk1108_i2s1_fracmux), + GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, + RK1108_CLKGATE_CON(2), 6, GFLAGS), + + COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, + RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 8, GFLAGS), + COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(10), 0, + RK1108_CLKGATE_CON(2), 9, GFLAGS, + &rk1108_i2s2_fracmux), + GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT, + RK1108_CLKGATE_CON(2), 10, GFLAGS), + + /* PD_BUS */ + GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 0, GFLAGS), + GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 1, GFLAGS), + GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 2, GFLAGS), + COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, + RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0, + RK1108_CLKSEL_CON(3), 0, 5, DFLAGS, + RK1108_CLKGATE_CON(1), 4, GFLAGS), + COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0, + RK1108_CLKSEL_CON(3), 8, 5, DFLAGS, + RK1108_CLKGATE_CON(1), 5, GFLAGS), + GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 6, GFLAGS), + GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 7, GFLAGS), + GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 8, GFLAGS), + GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 9, GFLAGS), + GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(1), 10, GFLAGS), + GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 4, GFLAGS), + + COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 1, GFLAGS), + COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 3, GFLAGS), + COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 5, GFLAGS), + + COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(16), 0, + RK1108_CLKGATE_CON(3), 2, GFLAGS, + &rk1108_uart0_fracmux), + COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(17), 0, + RK1108_CLKGATE_CON(3), 4, GFLAGS, + &rk1108_uart1_fracmux), + COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(18), 0, + RK1108_CLKGATE_CON(3), 6, GFLAGS, + &rk1108_uart2_fracmux), + GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 10, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 11, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 12, GFLAGS), + + COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 7, GFLAGS), + COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 8, GFLAGS), + COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 9, GFLAGS), + GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 0, GFLAGS), + GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 1, GFLAGS), + GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 2, GFLAGS), + COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, + RK1108_CLKGATE_CON(3), 10, GFLAGS), + GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 6, GFLAGS), + GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 3, GFLAGS), + GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 7, GFLAGS), + GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 8, GFLAGS), + GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(13), 9, GFLAGS), + + GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(14), 0, GFLAGS), + + GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, + RK1108_CLKGATE_CON(12), 2, GFLAGS), + GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(12), 3, GFLAGS), + GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(12), 1, GFLAGS), + + /* PD_DDR */ + GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 8, GFLAGS), + GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 9, GFLAGS), + GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 10, GFLAGS), + COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, + DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK1108_CLKGATE_CON(10), 9, GFLAGS), + GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(12), 4, GFLAGS), + GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(12), 5, GFLAGS), + GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(12), 6, GFLAGS), + GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(0), 11, GFLAGS), + + /* + * Clock-Architecture Diagram 6 + */ + + /* PD_PERI */ + COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, + RK1108_CLKSEL_CON(23), 10, 5, DFLAGS, + RK1108_CLKGATE_CON(4), 5, GFLAGS), + GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(15), 13, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, + RK1108_CLKSEL_CON(23), 5, 5, DFLAGS, + RK1108_CLKGATE_CON(4), 4, GFLAGS), + GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(15), 12, GFLAGS), + + GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(4), 1, GFLAGS), + GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, + RK1108_CLKGATE_CON(4), 2, GFLAGS), + COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED, + RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, + RK1108_CLKGATE_CON(15), 11, GFLAGS), + + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, + RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, + RK1108_CLKGATE_CON(5), 0, GFLAGS), + + COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, + RK1108_CLKSEL_CON(25), 10, 2, MFLAGS, + RK1108_CLKGATE_CON(5), 2, GFLAGS), + DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, + RK1108_CLKSEL_CON(26), 0, 8, DFLAGS), + + COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0, + RK1108_CLKSEL_CON(25), 12, 2, MFLAGS, + RK1108_CLKGATE_CON(5), 1, GFLAGS), + DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0, + RK2928_CLKSEL_CON(26), 8, 8, DFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS), + + COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, + RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK1108_CLKGATE_CON(5), 3, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS), + + COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, + RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, + RK1108_CLKGATE_CON(5), 4, GFLAGS), + GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS), + + COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, + RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, + RK1108_CLKGATE_CON(4), 10, GFLAGS), + MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, + RK1108_CLKSEL_CON(24), 8, 2, MFLAGS), + GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS), + GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS), + GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS), + + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1), +}; + +static const char *const rk1108_critical_clocks[] __initconst = { + "aclk_core", + "aclk_bus_src_gpll", + "aclk_periph", + "hclk_periph", + "pclk_periph", +}; + +static void __init rk1108_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); + return; + } + + rockchip_clk_register_plls(ctx, rk1108_pll_clks, + ARRAY_SIZE(rk1108_pll_clks), + RK1108_GRF_SOC_STATUS0); + rockchip_clk_register_branches(ctx, rk1108_clk_branches, + ARRAY_SIZE(rk1108_clk_branches)); + rockchip_clk_protect_critical(rk1108_critical_clocks, + ARRAY_SIZE(rk1108_critical_clocks)); + + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk1108_cpuclk_data, rk1108_cpuclk_rates, + ARRAY_SIZE(rk1108_cpuclk_rates)); + + rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); +} +CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 1653edd792a5..d67eecc4ade9 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -34,6 +34,21 @@ struct clk; #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) +/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */ +#define RK1108_PLL_CON(x) ((x) * 0x4) +#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60) +#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120) +#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180) +#define RK1108_GLB_SRST_FST 0x1c0 +#define RK1108_GLB_SRST_SND 0x1c4 +#define RK1108_MISC_CON 0x1cc +#define RK1108_SDMMC_CON0 0x1d8 +#define RK1108_SDMMC_CON1 0x1dc +#define RK1108_SDIO_CON0 0x1e0 +#define RK1108_SDIO_CON1 0x1e4 +#define RK1108_EMMC_CON0 0x1e8 +#define RK1108_EMMC_CON1 0x1ec + #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) -- cgit v1.2.3