diff options
Diffstat (limited to 'drivers/clk/rockchip/clk-rk3399.c')
| -rw-r--r-- | drivers/clk/rockchip/clk-rk3399.c | 117 |
1 files changed, 80 insertions, 37 deletions
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 5a628148f3f0..c2b243d7a5e2 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -1,22 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2016 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/module.h> +#include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/regmap.h> #include <dt-bindings/clock/rk3399-cru.h> #include "clk.h" @@ -297,9 +291,10 @@ static struct rockchip_clk_branch rk3399_pmuclk_wifi_fracmux __initdata = RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS); static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = { - .core_reg = RK3399_CLKSEL_CON(0), - .div_core_shift = 0, - .div_core_mask = 0x1f, + .core_reg[0] = RK3399_CLKSEL_CON(0), + .div_core_shift[0] = 0, + .div_core_mask[0] = 0x1f, + .num_cores = 1, .mux_core_alt = 3, .mux_core_main = 0, .mux_core_shift = 6, @@ -307,9 +302,10 @@ static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = { }; static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = { - .core_reg = RK3399_CLKSEL_CON(2), - .div_core_shift = 0, - .div_core_mask = 0x1f, + .core_reg[0] = RK3399_CLKSEL_CON(2), + .div_core_shift[0] = 0, + .div_core_mask[0] = 0x1f, + .num_cores = 1, .mux_core_alt = 3, .mux_core_main = 1, .mux_core_shift = 6, @@ -485,7 +481,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "atclk_core_l", "armclkl", CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3399_CLKGATE_CON(0), 5, GFLAGS), - COMPOSITE_NOMUX(0, "pclk_dbg_core_l", "armclkl", CLK_IGNORE_UNUSED, + COMPOSITE_NOMUX(PCLK_COREDBG_L, "pclk_dbg_core_l", "armclkl", CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3399_CLKGATE_CON(0), 6, GFLAGS), @@ -535,7 +531,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_core_adb400_core_b_2_gic", "armclkb", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(14), 4, GFLAGS), - DIV(0, "pclken_dbg_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, + DIV(PCLK_COREDBG_B, "pclken_dbg_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(3), 13, 2, DFLAGS | CLK_DIVIDER_READ_ONLY), GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, @@ -601,7 +597,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(28), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 3, GFLAGS), - COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", 0, + COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(96), 0, RK3399_CLKGATE_CON(8), 4, GFLAGS, &rk3399_i2s0_fracmux), @@ -611,7 +607,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(29), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 6, GFLAGS), - COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", 0, + COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(97), 0, RK3399_CLKGATE_CON(8), 7, GFLAGS, &rk3399_i2s1_fracmux), @@ -621,7 +617,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(30), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 9, GFLAGS), - COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", 0, + COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(98), 0, RK3399_CLKGATE_CON(8), 10, GFLAGS, &rk3399_i2s2_fracmux), @@ -1267,7 +1263,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKSEL_CON(56), 6, 2, MFLAGS, RK3399_CLKGATE_CON(10), 7, GFLAGS), - COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, 0, + COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(56), 5, 1, MFLAGS, 0, 5, DFLAGS), /* gic */ @@ -1303,6 +1299,9 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS), GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS), + /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */ + SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_alive"), + GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS), GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS), @@ -1515,7 +1514,10 @@ static const char *const rk3399_cru_critical_clocks[] __initconst = { "aclk_vio_noc", /* ddrc */ - "sclk_ddrc" + "sclk_ddrc", + + "armclkl", + "armclkb", }; static const char *const rk3399_pmucru_critical_clocks[] __initconst = { @@ -1529,8 +1531,8 @@ static const char *const rk3399_pmucru_critical_clocks[] __initconst = { static void __init rk3399_clk_init(struct device_node *np) { struct rockchip_clk_provider *ctx; + unsigned long clk_nr_clks; void __iomem *reg_base; - struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -1538,30 +1540,21 @@ static void __init rk3399_clk_init(struct device_node *np) return; } - ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + clk_nr_clks = rockchip_clk_find_max_clk_id(rk3399_clk_branches, + ARRAY_SIZE(rk3399_clk_branches)) + 1; + 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; } - /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */ - clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_alive", 0, 1, 1); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock pclk_wdt: %ld\n", - __func__, PTR_ERR(clk)); - else - rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); - rockchip_clk_register_plls(ctx, rk3399_pll_clks, ARRAY_SIZE(rk3399_pll_clks), -1); rockchip_clk_register_branches(ctx, rk3399_clk_branches, ARRAY_SIZE(rk3399_clk_branches)); - rockchip_clk_protect_critical(rk3399_cru_critical_clocks, - ARRAY_SIZE(rk3399_cru_critical_clocks)); - rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl", mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), &rk3399_cpuclkl_data, rk3399_cpuclkl_rates, @@ -1572,6 +1565,9 @@ static void __init rk3399_clk_init(struct device_node *np) &rk3399_cpuclkb_data, rk3399_cpuclkb_rates, ARRAY_SIZE(rk3399_cpuclkb_rates)); + rockchip_clk_protect_critical(rk3399_cru_critical_clocks, + ARRAY_SIZE(rk3399_cru_critical_clocks)); + rockchip_register_softrst(np, 21, reg_base + RK3399_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); @@ -1584,6 +1580,7 @@ CLK_OF_DECLARE(rk3399_cru, "rockchip,rk3399-cru", rk3399_clk_init); static void __init rk3399_pmu_clk_init(struct device_node *np) { struct rockchip_clk_provider *ctx; + unsigned long clkpmu_nr_clks; void __iomem *reg_base; reg_base = of_iomap(np, 0); @@ -1592,7 +1589,9 @@ static void __init rk3399_pmu_clk_init(struct device_node *np) return; } - ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS); + clkpmu_nr_clks = rockchip_clk_find_max_clk_id(rk3399_clk_pmu_branches, + ARRAY_SIZE(rk3399_clk_pmu_branches)) + 1; + ctx = rockchip_clk_init(np, reg_base, clkpmu_nr_clks); if (IS_ERR(ctx)) { pr_err("%s: rockchip pmu clk init failed\n", __func__); iounmap(reg_base); @@ -1614,3 +1613,47 @@ static void __init rk3399_pmu_clk_init(struct device_node *np) rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3399_cru_pmu, "rockchip,rk3399-pmucru", rk3399_pmu_clk_init); + +struct clk_rk3399_inits { + void (*inits)(struct device_node *np); +}; + +static const struct clk_rk3399_inits clk_rk3399_pmucru_init = { + .inits = rk3399_pmu_clk_init, +}; + +static const struct clk_rk3399_inits clk_rk3399_cru_init = { + .inits = rk3399_clk_init, +}; + +static const struct of_device_id clk_rk3399_match_table[] = { + { + .compatible = "rockchip,rk3399-cru", + .data = &clk_rk3399_cru_init, + }, { + .compatible = "rockchip,rk3399-pmucru", + .data = &clk_rk3399_pmucru_init, + }, + { } +}; + +static int __init clk_rk3399_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct clk_rk3399_inits *init_data; + + init_data = device_get_match_data(&pdev->dev); + if (init_data->inits) + init_data->inits(np); + + return 0; +} + +static struct platform_driver clk_rk3399_driver = { + .driver = { + .name = "clk-rk3399", + .of_match_table = clk_rk3399_match_table, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver_probe(clk_rk3399_driver, clk_rk3399_probe); |
