19b43a31aSFinley Xiao // SPDX-License-Identifier: GPL-2.0
29b43a31aSFinley Xiao /*
39b43a31aSFinley Xiao * Copyright (c) 2022 Rockchip Electronics Co., Ltd
49b43a31aSFinley Xiao * Author: Finley Xiao <finley.xiao@rock-chips.com>
59b43a31aSFinley Xiao */
69b43a31aSFinley Xiao
79b43a31aSFinley Xiao #include <common.h>
89b43a31aSFinley Xiao #include <clk-uclass.h>
99b43a31aSFinley Xiao #include <dm.h>
109b43a31aSFinley Xiao #include <syscon.h>
119b43a31aSFinley Xiao #include <asm/arch/clock.h>
129b43a31aSFinley Xiao #include <asm/arch/cru_rk3562.h>
139b43a31aSFinley Xiao #include <asm/arch/hardware.h>
149b43a31aSFinley Xiao #include <asm/io.h>
159b43a31aSFinley Xiao #include <dm/lists.h>
169b43a31aSFinley Xiao #include <dt-bindings/clock/rk3562-cru.h>
179b43a31aSFinley Xiao
189b43a31aSFinley Xiao DECLARE_GLOBAL_DATA_PTR;
199b43a31aSFinley Xiao
209b43a31aSFinley Xiao #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
219b43a31aSFinley Xiao
229b43a31aSFinley Xiao static struct rockchip_pll_rate_table rk3562_pll_rates[] = {
239b43a31aSFinley Xiao /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
249b43a31aSFinley Xiao RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
259b43a31aSFinley Xiao RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0),
269b43a31aSFinley Xiao RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0),
279b43a31aSFinley Xiao RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
289b43a31aSFinley Xiao RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
299b43a31aSFinley Xiao RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
309b43a31aSFinley Xiao RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
319b43a31aSFinley Xiao RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
329b43a31aSFinley Xiao RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
339b43a31aSFinley Xiao RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
34*e583fa2aSElaine Zhang RK3036_PLL_RATE(705600000, 2, 235, 4, 1, 0, 3355443),
35*e583fa2aSElaine Zhang RK3036_PLL_RATE(611520000, 4, 611, 6, 1, 0, 8724152),
369b43a31aSFinley Xiao RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
379b43a31aSFinley Xiao RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
389b43a31aSFinley Xiao RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
399b43a31aSFinley Xiao RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
409b43a31aSFinley Xiao RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
419b43a31aSFinley Xiao RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
429b43a31aSFinley Xiao RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0),
439b43a31aSFinley Xiao { /* sentinel */ },
449b43a31aSFinley Xiao };
459b43a31aSFinley Xiao
469b43a31aSFinley Xiao static struct rockchip_pll_clock rk3562_pll_clks[] = {
479b43a31aSFinley Xiao [APLL] = PLL(pll_rk3328, PLL_APLL, RK3562_PLL_CON(0),
489b43a31aSFinley Xiao RK3562_MODE_CON, 0, 10, 0, rk3562_pll_rates),
499b43a31aSFinley Xiao [GPLL] = PLL(pll_rk3328, PLL_GPLL, RK3562_PLL_CON(24),
509b43a31aSFinley Xiao RK3562_MODE_CON, 2, 10, 0, rk3562_pll_rates),
519b43a31aSFinley Xiao [VPLL] = PLL(pll_rk3328, PLL_VPLL, RK3562_PLL_CON(32),
529b43a31aSFinley Xiao RK3562_MODE_CON, 6, 10, 0, rk3562_pll_rates),
539b43a31aSFinley Xiao [HPLL] = PLL(pll_rk3328, PLL_HPLL, RK3562_PLL_CON(40),
549b43a31aSFinley Xiao RK3562_MODE_CON, 8, 10, 0, rk3562_pll_rates),
559b43a31aSFinley Xiao [CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3562_PMU1_PLL_CON(0),
569b43a31aSFinley Xiao RK3562_PMU1_MODE_CON, 0, 10, 0, rk3562_pll_rates),
579b43a31aSFinley Xiao [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3562_SUBDDR_PLL_CON(0),
589b43a31aSFinley Xiao RK3562_SUBDDR_MODE_CON, 0, 10, 0, NULL),
599b43a31aSFinley Xiao };
609b43a31aSFinley Xiao
619b43a31aSFinley Xiao #define RK3562_CPUCLK_RATE(_rate, _aclk_m_core, _pclk_dbg) \
629b43a31aSFinley Xiao { \
639b43a31aSFinley Xiao .rate = _rate##U, \
64b934ef10SFinley Xiao .aclk_div = _aclk_m_core, \
65b934ef10SFinley Xiao .pclk_div = _pclk_dbg, \
669b43a31aSFinley Xiao }
679b43a31aSFinley Xiao
689b43a31aSFinley Xiao static struct rockchip_cpu_rate_table rk3562_cpu_rates[] = {
699b43a31aSFinley Xiao RK3562_CPUCLK_RATE(1416000000, 1, 8),
709b43a31aSFinley Xiao RK3562_CPUCLK_RATE(1296000000, 1, 8),
719b43a31aSFinley Xiao RK3562_CPUCLK_RATE(1200000000, 1, 8),
729b43a31aSFinley Xiao RK3562_CPUCLK_RATE(1104000000, 1, 8),
739b43a31aSFinley Xiao RK3562_CPUCLK_RATE(1008000000, 1, 8),
749b43a31aSFinley Xiao RK3562_CPUCLK_RATE(912000000, 1, 6),
759b43a31aSFinley Xiao RK3562_CPUCLK_RATE(816000000, 1, 6),
769b43a31aSFinley Xiao RK3562_CPUCLK_RATE(600000000, 1, 6),
779b43a31aSFinley Xiao RK3562_CPUCLK_RATE(408000000, 1, 4),
789b43a31aSFinley Xiao { /* sentinel */ },
799b43a31aSFinley Xiao };
809b43a31aSFinley Xiao
819b43a31aSFinley Xiao #ifndef CONFIG_SPL_BUILD
829b43a31aSFinley Xiao #define RK3562_CLK_DUMP(_id, _name) \
839b43a31aSFinley Xiao { \
849b43a31aSFinley Xiao .id = _id, \
859b43a31aSFinley Xiao .name = _name, \
869b43a31aSFinley Xiao }
879b43a31aSFinley Xiao
889b43a31aSFinley Xiao static const struct rk3562_clk_info clks_dump[] = {
899b43a31aSFinley Xiao RK3562_CLK_DUMP(PLL_APLL, "apll"),
909b43a31aSFinley Xiao RK3562_CLK_DUMP(PLL_GPLL, "gpll"),
919b43a31aSFinley Xiao RK3562_CLK_DUMP(PLL_VPLL, "vpll"),
929b43a31aSFinley Xiao RK3562_CLK_DUMP(PLL_HPLL, "hpll"),
939b43a31aSFinley Xiao RK3562_CLK_DUMP(PLL_CPLL, "cpll"),
949b43a31aSFinley Xiao RK3562_CLK_DUMP(PLL_DPLL, "dpll"),
959b43a31aSFinley Xiao RK3562_CLK_DUMP(ACLK_BUS, "aclk_bus"),
969b43a31aSFinley Xiao RK3562_CLK_DUMP(HCLK_BUS, "hclk_bus"),
979b43a31aSFinley Xiao RK3562_CLK_DUMP(PCLK_BUS, "pclk_bus"),
989b43a31aSFinley Xiao RK3562_CLK_DUMP(ACLK_PERI, "aclk_peri"),
999b43a31aSFinley Xiao RK3562_CLK_DUMP(HCLK_PERI, "hclk_peri"),
1009b43a31aSFinley Xiao RK3562_CLK_DUMP(PCLK_PERI, "pclk_peri"),
1019b43a31aSFinley Xiao };
1029b43a31aSFinley Xiao #endif
1039b43a31aSFinley Xiao
1049b43a31aSFinley Xiao /*
1059b43a31aSFinley Xiao *
1069b43a31aSFinley Xiao * rational_best_approximation(31415, 10000,
1079b43a31aSFinley Xiao * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
1089b43a31aSFinley Xiao *
1099b43a31aSFinley Xiao * you may look at given_numerator as a fixed point number,
1109b43a31aSFinley Xiao * with the fractional part size described in given_denominator.
1119b43a31aSFinley Xiao *
1129b43a31aSFinley Xiao * for theoretical background, see:
1139b43a31aSFinley Xiao * http://en.wikipedia.org/wiki/Continued_fraction
1149b43a31aSFinley Xiao */
rational_best_approximation(unsigned long given_numerator,unsigned long given_denominator,unsigned long max_numerator,unsigned long max_denominator,unsigned long * best_numerator,unsigned long * best_denominator)1159b43a31aSFinley Xiao static void rational_best_approximation(unsigned long given_numerator,
1169b43a31aSFinley Xiao unsigned long given_denominator,
1179b43a31aSFinley Xiao unsigned long max_numerator,
1189b43a31aSFinley Xiao unsigned long max_denominator,
1199b43a31aSFinley Xiao unsigned long *best_numerator,
1209b43a31aSFinley Xiao unsigned long *best_denominator)
1219b43a31aSFinley Xiao {
1229b43a31aSFinley Xiao unsigned long n, d, n0, d0, n1, d1;
1239b43a31aSFinley Xiao
1249b43a31aSFinley Xiao n = given_numerator;
1259b43a31aSFinley Xiao d = given_denominator;
1269b43a31aSFinley Xiao n0 = 0;
1279b43a31aSFinley Xiao d1 = 0;
1289b43a31aSFinley Xiao n1 = 1;
1299b43a31aSFinley Xiao d0 = 1;
1309b43a31aSFinley Xiao for (;;) {
1319b43a31aSFinley Xiao unsigned long t, a;
1329b43a31aSFinley Xiao
1339b43a31aSFinley Xiao if (n1 > max_numerator || d1 > max_denominator) {
1349b43a31aSFinley Xiao n1 = n0;
1359b43a31aSFinley Xiao d1 = d0;
1369b43a31aSFinley Xiao break;
1379b43a31aSFinley Xiao }
1389b43a31aSFinley Xiao if (d == 0)
1399b43a31aSFinley Xiao break;
1409b43a31aSFinley Xiao t = d;
1419b43a31aSFinley Xiao a = n / d;
1429b43a31aSFinley Xiao d = n % d;
1439b43a31aSFinley Xiao n = t;
1449b43a31aSFinley Xiao t = n0 + a * n1;
1459b43a31aSFinley Xiao n0 = n1;
1469b43a31aSFinley Xiao n1 = t;
1479b43a31aSFinley Xiao t = d0 + a * d1;
1489b43a31aSFinley Xiao d0 = d1;
1499b43a31aSFinley Xiao d1 = t;
1509b43a31aSFinley Xiao }
1519b43a31aSFinley Xiao *best_numerator = n1;
1529b43a31aSFinley Xiao *best_denominator = d1;
1539b43a31aSFinley Xiao }
1549b43a31aSFinley Xiao
rk3562_armclk_set_rate(struct rk3562_clk_priv * priv,ulong new_rate)1559b43a31aSFinley Xiao static int rk3562_armclk_set_rate(struct rk3562_clk_priv *priv, ulong new_rate)
1569b43a31aSFinley Xiao {
1579b43a31aSFinley Xiao const struct rockchip_cpu_rate_table *rate;
1589b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
1599b43a31aSFinley Xiao ulong old_rate;
1609b43a31aSFinley Xiao
1619b43a31aSFinley Xiao rate = rockchip_get_cpu_settings(rk3562_cpu_rates, new_rate);
1629b43a31aSFinley Xiao if (!rate) {
1639b43a31aSFinley Xiao printf("%s unsupported rate\n", __func__);
1649b43a31aSFinley Xiao return -EINVAL;
1659b43a31aSFinley Xiao }
1669b43a31aSFinley Xiao
1679b43a31aSFinley Xiao /*
1689b43a31aSFinley Xiao * set up dependent divisors for DBG and ACLK clocks.
1699b43a31aSFinley Xiao */
1709b43a31aSFinley Xiao old_rate = rockchip_pll_get_rate(&rk3562_pll_clks[APLL], priv->cru,
1719b43a31aSFinley Xiao APLL);
1729b43a31aSFinley Xiao if (old_rate == new_rate) {
1739b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[11], ACLK_CORE_PRE_DIV_MASK,
1749b43a31aSFinley Xiao rate->aclk_div << ACLK_CORE_PRE_DIV_SHIFT);
1759b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[12], PCLK_DBG_PRE_DIV_MASK,
1769b43a31aSFinley Xiao rate->pclk_div << PCLK_DBG_PRE_DIV_SHIFT);
1779b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[10], CLK_CORE_PRE_DIV_MASK, 0);
1789b43a31aSFinley Xiao } else if (old_rate > new_rate) {
1799b43a31aSFinley Xiao if (rockchip_pll_set_rate(&rk3562_pll_clks[APLL],
1809b43a31aSFinley Xiao priv->cru, APLL, new_rate))
1819b43a31aSFinley Xiao return -EINVAL;
1829b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[11], ACLK_CORE_PRE_DIV_MASK,
1839b43a31aSFinley Xiao rate->aclk_div << ACLK_CORE_PRE_DIV_SHIFT);
1849b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[12], PCLK_DBG_PRE_DIV_MASK,
1859b43a31aSFinley Xiao rate->pclk_div << PCLK_DBG_PRE_DIV_SHIFT);
1869b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[10], CLK_CORE_PRE_DIV_MASK, 0);
1879b43a31aSFinley Xiao } else if (old_rate < new_rate) {
1889b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[11], ACLK_CORE_PRE_DIV_MASK,
1899b43a31aSFinley Xiao rate->aclk_div << ACLK_CORE_PRE_DIV_SHIFT);
1909b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[12], PCLK_DBG_PRE_DIV_MASK,
1919b43a31aSFinley Xiao rate->pclk_div << PCLK_DBG_PRE_DIV_SHIFT);
1929b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[10], CLK_CORE_PRE_DIV_MASK, 0);
1939b43a31aSFinley Xiao
1949b43a31aSFinley Xiao if (rockchip_pll_set_rate(&rk3562_pll_clks[APLL],
1959b43a31aSFinley Xiao priv->cru, APLL, new_rate))
1969b43a31aSFinley Xiao return -EINVAL;
1979b43a31aSFinley Xiao }
1989b43a31aSFinley Xiao
1999b43a31aSFinley Xiao return 0;
2009b43a31aSFinley Xiao }
2019b43a31aSFinley Xiao
rk3562_bus_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)2029b43a31aSFinley Xiao static ulong rk3562_bus_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
2039b43a31aSFinley Xiao {
2049b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
2059b43a31aSFinley Xiao u32 sel, con, div;
2069b43a31aSFinley Xiao ulong rate;
2079b43a31aSFinley Xiao
2089b43a31aSFinley Xiao switch (clk_id) {
2099b43a31aSFinley Xiao case ACLK_BUS:
2109b43a31aSFinley Xiao con = readl(&cru->clksel_con[40]);
2119b43a31aSFinley Xiao sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
2129b43a31aSFinley Xiao div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT;
2139b43a31aSFinley Xiao break;
2149b43a31aSFinley Xiao case HCLK_BUS:
2159b43a31aSFinley Xiao con = readl(&cru->clksel_con[40]);
2169b43a31aSFinley Xiao sel = (con & HCLK_BUS_SEL_MASK) >> HCLK_BUS_SEL_SHIFT;
2179b43a31aSFinley Xiao div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT;
2189b43a31aSFinley Xiao break;
2199b43a31aSFinley Xiao case PCLK_BUS:
2209b43a31aSFinley Xiao con = readl(&cru->clksel_con[41]);
2219b43a31aSFinley Xiao sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT;
2229b43a31aSFinley Xiao div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT;
2239b43a31aSFinley Xiao break;
2249b43a31aSFinley Xiao default:
2259b43a31aSFinley Xiao return -ENOENT;
2269b43a31aSFinley Xiao }
2279b43a31aSFinley Xiao
2289b43a31aSFinley Xiao if (sel == ACLK_BUS_SEL_CPLL)
2299b43a31aSFinley Xiao rate = priv->cpll_hz;
2309b43a31aSFinley Xiao else
2319b43a31aSFinley Xiao rate = priv->gpll_hz;
2329b43a31aSFinley Xiao
2339b43a31aSFinley Xiao return DIV_TO_RATE(rate, div);
2349b43a31aSFinley Xiao }
2359b43a31aSFinley Xiao
rk3562_bus_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)2369b43a31aSFinley Xiao static ulong rk3562_bus_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
2379b43a31aSFinley Xiao ulong rate)
2389b43a31aSFinley Xiao {
2399b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
2409b43a31aSFinley Xiao u32 sel, div;
2419b43a31aSFinley Xiao
2429b43a31aSFinley Xiao if (priv->cpll_hz % rate == 0) {
2439b43a31aSFinley Xiao sel = ACLK_BUS_SEL_CPLL;
2449b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
2459b43a31aSFinley Xiao } else {
2469b43a31aSFinley Xiao sel= ACLK_BUS_SEL_GPLL;
2479b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
2489b43a31aSFinley Xiao }
2499b43a31aSFinley Xiao
2509b43a31aSFinley Xiao switch (clk_id) {
2519b43a31aSFinley Xiao case ACLK_BUS:
2529b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[40],
2539b43a31aSFinley Xiao ACLK_BUS_SEL_MASK | ACLK_BUS_DIV_MASK,
2549b43a31aSFinley Xiao (sel << ACLK_BUS_SEL_SHIFT) |
2559b43a31aSFinley Xiao ((div - 1) << ACLK_BUS_DIV_SHIFT));
2569b43a31aSFinley Xiao break;
2579b43a31aSFinley Xiao case HCLK_BUS:
2589b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[40],
2599b43a31aSFinley Xiao HCLK_BUS_SEL_MASK | HCLK_BUS_DIV_MASK,
2609b43a31aSFinley Xiao (sel << HCLK_BUS_SEL_SHIFT) |
2619b43a31aSFinley Xiao ((div - 1) << HCLK_BUS_DIV_SHIFT));
2629b43a31aSFinley Xiao break;
2639b43a31aSFinley Xiao case PCLK_BUS:
2649b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[41],
2659b43a31aSFinley Xiao PCLK_BUS_SEL_MASK | PCLK_BUS_DIV_MASK,
2669b43a31aSFinley Xiao (sel << PCLK_BUS_SEL_SHIFT) |
2679b43a31aSFinley Xiao ((div - 1) << PCLK_BUS_DIV_SHIFT));
2689b43a31aSFinley Xiao break;
2699b43a31aSFinley Xiao default:
2709b43a31aSFinley Xiao return -ENOENT;
2719b43a31aSFinley Xiao }
2729b43a31aSFinley Xiao
2739b43a31aSFinley Xiao return rk3562_bus_get_rate(priv, clk_id);
2749b43a31aSFinley Xiao }
2759b43a31aSFinley Xiao
rk3562_peri_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)2769b43a31aSFinley Xiao static ulong rk3562_peri_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
2779b43a31aSFinley Xiao {
2789b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
2799b43a31aSFinley Xiao u32 sel, con, div;
2809b43a31aSFinley Xiao ulong rate;
2819b43a31aSFinley Xiao
2829b43a31aSFinley Xiao switch (clk_id) {
2839b43a31aSFinley Xiao case ACLK_PERI:
2849b43a31aSFinley Xiao con = readl(&cru->periclksel_con[0]);
2859b43a31aSFinley Xiao sel = (con & ACLK_PERI_SEL_MASK) >> ACLK_PERI_SEL_SHIFT;
2869b43a31aSFinley Xiao div = (con & ACLK_PERI_DIV_MASK) >> ACLK_PERI_DIV_SHIFT;
2879b43a31aSFinley Xiao break;
2889b43a31aSFinley Xiao case HCLK_PERI:
2899b43a31aSFinley Xiao con = readl(&cru->periclksel_con[0]);
2909b43a31aSFinley Xiao sel = (con & HCLK_PERI_SEL_MASK) >> HCLK_PERI_SEL_SHIFT;
2919b43a31aSFinley Xiao div = (con & HCLK_PERI_DIV_MASK) >> HCLK_PERI_DIV_SHIFT;
2929b43a31aSFinley Xiao break;
2939b43a31aSFinley Xiao case PCLK_PERI:
2949b43a31aSFinley Xiao con = readl(&cru->periclksel_con[1]);
2959b43a31aSFinley Xiao sel = (con & PCLK_PERI_SEL_MASK) >> PCLK_PERI_SEL_SHIFT;
2969b43a31aSFinley Xiao div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT;
2979b43a31aSFinley Xiao break;
2989b43a31aSFinley Xiao default:
2999b43a31aSFinley Xiao return -ENOENT;
3009b43a31aSFinley Xiao }
3019b43a31aSFinley Xiao
3029b43a31aSFinley Xiao if (sel == ACLK_PERI_SEL_CPLL)
3039b43a31aSFinley Xiao rate = priv->cpll_hz;
3049b43a31aSFinley Xiao else
3059b43a31aSFinley Xiao rate = priv->gpll_hz;
3069b43a31aSFinley Xiao
3079b43a31aSFinley Xiao return DIV_TO_RATE(rate, div);
3089b43a31aSFinley Xiao }
3099b43a31aSFinley Xiao
rk3562_peri_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)3109b43a31aSFinley Xiao static ulong rk3562_peri_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
3119b43a31aSFinley Xiao ulong rate)
3129b43a31aSFinley Xiao {
3139b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
3149b43a31aSFinley Xiao u32 sel, div;
3159b43a31aSFinley Xiao
3169b43a31aSFinley Xiao if (priv->cpll_hz % rate == 0) {
3179b43a31aSFinley Xiao sel = ACLK_PERI_SEL_CPLL;
3189b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
3199b43a31aSFinley Xiao } else {
3209b43a31aSFinley Xiao sel= ACLK_PERI_SEL_GPLL;
3219b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
3229b43a31aSFinley Xiao }
3239b43a31aSFinley Xiao
3249b43a31aSFinley Xiao switch (clk_id) {
3259b43a31aSFinley Xiao case ACLK_PERI:
3269b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[0],
3279b43a31aSFinley Xiao ACLK_PERI_SEL_MASK | ACLK_PERI_DIV_MASK,
3289b43a31aSFinley Xiao (sel << ACLK_PERI_SEL_SHIFT) |
3299b43a31aSFinley Xiao ((div - 1) << ACLK_PERI_DIV_SHIFT));
3309b43a31aSFinley Xiao break;
3319b43a31aSFinley Xiao case HCLK_PERI:
3329b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[0],
3339b43a31aSFinley Xiao HCLK_PERI_SEL_MASK | HCLK_PERI_DIV_MASK,
3349b43a31aSFinley Xiao (sel << HCLK_PERI_SEL_SHIFT) |
3359b43a31aSFinley Xiao ((div - 1) << HCLK_PERI_DIV_SHIFT));
3369b43a31aSFinley Xiao break;
3379b43a31aSFinley Xiao case PCLK_PERI:
3389b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[1],
3399b43a31aSFinley Xiao PCLK_PERI_SEL_MASK | PCLK_PERI_DIV_MASK,
3409b43a31aSFinley Xiao (sel << PCLK_PERI_SEL_SHIFT) |
3419b43a31aSFinley Xiao ((div - 1) << PCLK_PERI_DIV_SHIFT));
3429b43a31aSFinley Xiao break;
3439b43a31aSFinley Xiao default:
3449b43a31aSFinley Xiao return -ENOENT;
3459b43a31aSFinley Xiao }
3469b43a31aSFinley Xiao
3479b43a31aSFinley Xiao return rk3562_peri_get_rate(priv, clk_id);
3489b43a31aSFinley Xiao }
3499b43a31aSFinley Xiao
rk3562_i2c_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)3509b43a31aSFinley Xiao static ulong rk3562_i2c_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
3519b43a31aSFinley Xiao {
3529b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
3539b43a31aSFinley Xiao u32 sel, con, div;
3549b43a31aSFinley Xiao ulong rate;
3559b43a31aSFinley Xiao
3569b43a31aSFinley Xiao switch (clk_id) {
3579b43a31aSFinley Xiao case CLK_PMU0_I2C0:
3589b43a31aSFinley Xiao con = readl(&cru->pmu0clksel_con[3]);
3599b43a31aSFinley Xiao sel = (con & CLK_PMU0_I2C0_SEL_MASK) >> CLK_PMU0_I2C0_SEL_SHIFT;
3609b43a31aSFinley Xiao if (sel == CLK_PMU0_I2C0_SEL_200M)
3619b43a31aSFinley Xiao rate = 200 * MHz;
3629b43a31aSFinley Xiao else if (sel == CLK_PMU0_I2C0_SEL_24M)
3639b43a31aSFinley Xiao rate = OSC_HZ;
3649b43a31aSFinley Xiao else
3659b43a31aSFinley Xiao rate = 32768;
3669b43a31aSFinley Xiao div = (con & CLK_PMU0_I2C0_DIV_MASK) >> CLK_PMU0_I2C0_DIV_SHIFT;
3679b43a31aSFinley Xiao
3689b43a31aSFinley Xiao return DIV_TO_RATE(rate, div);
3699b43a31aSFinley Xiao case CLK_I2C:
3709b43a31aSFinley Xiao case CLK_I2C1:
3719b43a31aSFinley Xiao case CLK_I2C2:
3729b43a31aSFinley Xiao case CLK_I2C3:
3739b43a31aSFinley Xiao case CLK_I2C4:
3749b43a31aSFinley Xiao case CLK_I2C5:
3759b43a31aSFinley Xiao con = readl(&cru->clksel_con[41]);
3769b43a31aSFinley Xiao sel = (con & CLK_I2C_SEL_MASK) >> CLK_I2C_SEL_SHIFT;
3779b43a31aSFinley Xiao if (sel == CLK_I2C_SEL_200M)
3789b43a31aSFinley Xiao rate = 200 * MHz;
3799b43a31aSFinley Xiao else if (sel == CLK_I2C_SEL_100M)
3809b43a31aSFinley Xiao rate = 100 * MHz;
3819b43a31aSFinley Xiao else if (sel == CLK_I2C_SEL_50M)
3829b43a31aSFinley Xiao rate = 50 * MHz;
3839b43a31aSFinley Xiao else
3849b43a31aSFinley Xiao rate = OSC_HZ;
3859b43a31aSFinley Xiao break;
3869b43a31aSFinley Xiao default:
3879b43a31aSFinley Xiao return -ENOENT;
3889b43a31aSFinley Xiao }
3899b43a31aSFinley Xiao
3909b43a31aSFinley Xiao return rate;
3919b43a31aSFinley Xiao }
3929b43a31aSFinley Xiao
rk3562_i2c_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)3939b43a31aSFinley Xiao static ulong rk3562_i2c_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
3949b43a31aSFinley Xiao ulong rate)
3959b43a31aSFinley Xiao {
3969b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
3979b43a31aSFinley Xiao u32 sel, div;
3989b43a31aSFinley Xiao
3999b43a31aSFinley Xiao switch (clk_id) {
4009b43a31aSFinley Xiao case CLK_PMU0_I2C0:
4019b43a31aSFinley Xiao if (rate == 200 * MHz) {
4029b43a31aSFinley Xiao sel = CLK_PMU0_I2C0_SEL_200M;
4039b43a31aSFinley Xiao div = 1;
4049b43a31aSFinley Xiao } else if (rate == OSC_HZ) {
4059b43a31aSFinley Xiao sel = CLK_PMU0_I2C0_SEL_24M;
4069b43a31aSFinley Xiao div = 1;
4079b43a31aSFinley Xiao } else if (rate == 32768) {
4089b43a31aSFinley Xiao sel = CLK_PMU0_I2C0_SEL_32K;
4099b43a31aSFinley Xiao div = 1;
4109b43a31aSFinley Xiao } else {
4119b43a31aSFinley Xiao sel = CLK_PMU0_I2C0_SEL_200M;
4129b43a31aSFinley Xiao div = DIV_ROUND_UP(200 * MHz, rate);
4139b43a31aSFinley Xiao assert(div - 1 <= 31);
4149b43a31aSFinley Xiao }
4159b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu0clksel_con[3], CLK_PMU0_I2C0_DIV_MASK,
4169b43a31aSFinley Xiao (div - 1) << CLK_PMU0_I2C0_DIV_SHIFT);
4179b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu0clksel_con[3], CLK_PMU0_I2C0_SEL_MASK,
4189b43a31aSFinley Xiao sel << CLK_PMU0_I2C0_SEL_SHIFT);
4199b43a31aSFinley Xiao break;
4209b43a31aSFinley Xiao case CLK_I2C:
4219b43a31aSFinley Xiao case CLK_I2C2:
4229b43a31aSFinley Xiao case CLK_I2C3:
4239b43a31aSFinley Xiao case CLK_I2C4:
4249b43a31aSFinley Xiao case CLK_I2C5:
4259b43a31aSFinley Xiao if (rate == 200 * MHz)
4269b43a31aSFinley Xiao sel = CLK_I2C_SEL_200M;
4279b43a31aSFinley Xiao else if (rate == 100 * MHz)
4289b43a31aSFinley Xiao sel = CLK_I2C_SEL_100M;
4299b43a31aSFinley Xiao else if (rate == 50 * MHz)
4309b43a31aSFinley Xiao sel = CLK_I2C_SEL_50M;
4319b43a31aSFinley Xiao else
4329b43a31aSFinley Xiao sel = CLK_I2C_SEL_24M;
4339b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[41], CLK_I2C_SEL_MASK,
4349b43a31aSFinley Xiao sel << CLK_I2C_SEL_SHIFT);
4359b43a31aSFinley Xiao break;
4369b43a31aSFinley Xiao default:
4379b43a31aSFinley Xiao return -ENOENT;
4389b43a31aSFinley Xiao }
4399b43a31aSFinley Xiao
4409b43a31aSFinley Xiao
4419b43a31aSFinley Xiao return rk3562_i2c_get_rate(priv, clk_id);
4429b43a31aSFinley Xiao }
4439b43a31aSFinley Xiao
rk3562_uart_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)4449b43a31aSFinley Xiao static ulong rk3562_uart_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
4459b43a31aSFinley Xiao {
4469b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
4479b43a31aSFinley Xiao u32 reg, con, fracdiv, div, src, p_src, p_rate;
4489b43a31aSFinley Xiao unsigned long m, n;
4499b43a31aSFinley Xiao
4509b43a31aSFinley Xiao switch (clk_id) {
4519b43a31aSFinley Xiao case SCLK_PMU1_UART0:
4529b43a31aSFinley Xiao con = readl(&cru->pmu1clksel_con[2]);
4539b43a31aSFinley Xiao src = (con & CLK_PMU1_UART0_SEL_MASK) >>
4549b43a31aSFinley Xiao CLK_PMU1_UART0_SEL_SHIFT;
4559b43a31aSFinley Xiao div = (con & CLK_PMU1_UART0_SRC_DIV_MASK) >>
4569b43a31aSFinley Xiao CLK_PMU1_UART0_SRC_DIV_SHIFT;
4579b43a31aSFinley Xiao if (src == CLK_UART_SEL_SRC) {
4589b43a31aSFinley Xiao return DIV_TO_RATE(priv->cpll_hz, div);
4599b43a31aSFinley Xiao } else if (src == CLK_UART_SEL_FRAC) {
4609b43a31aSFinley Xiao fracdiv = readl(&cru->pmu1clksel_con[3]);
4619b43a31aSFinley Xiao n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
4629b43a31aSFinley Xiao n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
4639b43a31aSFinley Xiao m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
4649b43a31aSFinley Xiao m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
4659b43a31aSFinley Xiao return DIV_TO_RATE(priv->cpll_hz, div) * n / m;
4669b43a31aSFinley Xiao } else {
4679b43a31aSFinley Xiao return OSC_HZ;
4689b43a31aSFinley Xiao }
4699b43a31aSFinley Xiao case SCLK_UART1:
4709b43a31aSFinley Xiao reg = 21;
4719b43a31aSFinley Xiao break;
4729b43a31aSFinley Xiao case SCLK_UART2:
4739b43a31aSFinley Xiao reg = 23;
4749b43a31aSFinley Xiao break;
4759b43a31aSFinley Xiao case SCLK_UART3:
4769b43a31aSFinley Xiao reg = 25;
4779b43a31aSFinley Xiao break;
4789b43a31aSFinley Xiao case SCLK_UART4:
4799b43a31aSFinley Xiao reg = 27;
4809b43a31aSFinley Xiao break;
4819b43a31aSFinley Xiao case SCLK_UART5:
4829b43a31aSFinley Xiao reg = 29;
4839b43a31aSFinley Xiao break;
4849b43a31aSFinley Xiao case SCLK_UART6:
4859b43a31aSFinley Xiao reg = 31;
4869b43a31aSFinley Xiao break;
4879b43a31aSFinley Xiao case SCLK_UART7:
4889b43a31aSFinley Xiao reg = 33;
4899b43a31aSFinley Xiao break;
4909b43a31aSFinley Xiao case SCLK_UART8:
4919b43a31aSFinley Xiao reg = 35;
4929b43a31aSFinley Xiao break;
4939b43a31aSFinley Xiao case SCLK_UART9:
4949b43a31aSFinley Xiao reg = 37;
4959b43a31aSFinley Xiao break;
4969b43a31aSFinley Xiao default:
4979b43a31aSFinley Xiao return -ENOENT;
4989b43a31aSFinley Xiao }
4999b43a31aSFinley Xiao con = readl(&cru->periclksel_con[reg]);
5009b43a31aSFinley Xiao src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
5019b43a31aSFinley Xiao div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
5029b43a31aSFinley Xiao p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
5039b43a31aSFinley Xiao if (p_src == CLK_UART_SRC_SEL_GPLL)
5049b43a31aSFinley Xiao p_rate = priv->gpll_hz;
5059b43a31aSFinley Xiao else
5069b43a31aSFinley Xiao p_rate = priv->cpll_hz;
5079b43a31aSFinley Xiao if (src == CLK_UART_SEL_SRC) {
5089b43a31aSFinley Xiao return DIV_TO_RATE(p_rate, div);
5099b43a31aSFinley Xiao } else if (src == CLK_UART_SEL_FRAC) {
5109b43a31aSFinley Xiao fracdiv = readl(&cru->periclksel_con[reg + 1]);
5119b43a31aSFinley Xiao n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
5129b43a31aSFinley Xiao n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
5139b43a31aSFinley Xiao m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
5149b43a31aSFinley Xiao m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
5159b43a31aSFinley Xiao return DIV_TO_RATE(p_rate, div) * n / m;
5169b43a31aSFinley Xiao } else {
5179b43a31aSFinley Xiao return OSC_HZ;
5189b43a31aSFinley Xiao }
5199b43a31aSFinley Xiao }
5209b43a31aSFinley Xiao
rk3562_uart_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)5219b43a31aSFinley Xiao static ulong rk3562_uart_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
5229b43a31aSFinley Xiao ulong rate)
5239b43a31aSFinley Xiao {
5249b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
5259b43a31aSFinley Xiao u32 reg, clk_src, uart_src, div;
5269b43a31aSFinley Xiao unsigned long m = 0, n = 0, val;
5279b43a31aSFinley Xiao
5289b43a31aSFinley Xiao switch (clk_id) {
5299b43a31aSFinley Xiao case SCLK_PMU1_UART0:
5309b43a31aSFinley Xiao if (priv->cpll_hz % rate == 0) {
5319b43a31aSFinley Xiao uart_src = CLK_UART_SEL_SRC;
5329b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
5339b43a31aSFinley Xiao } else if (rate == OSC_HZ) {
5349b43a31aSFinley Xiao uart_src = CLK_UART_SEL_XIN24M;
5359b43a31aSFinley Xiao div = 2;
5369b43a31aSFinley Xiao } else {
5379b43a31aSFinley Xiao uart_src = CLK_UART_SEL_FRAC;
5389b43a31aSFinley Xiao div = 2;
5399b43a31aSFinley Xiao rational_best_approximation(rate, priv->cpll_hz / div,
5409b43a31aSFinley Xiao GENMASK(16 - 1, 0),
5419b43a31aSFinley Xiao GENMASK(16 - 1, 0),
5429b43a31aSFinley Xiao &n, &m);
5439b43a31aSFinley Xiao }
5449b43a31aSFinley Xiao
5459b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu1clksel_con[2],
5469b43a31aSFinley Xiao CLK_PMU1_UART0_SEL_MASK |
5479b43a31aSFinley Xiao CLK_PMU1_UART0_SRC_DIV_MASK,
5489b43a31aSFinley Xiao (uart_src << CLK_PMU1_UART0_SEL_SHIFT) |
5499b43a31aSFinley Xiao ((div - 1) << CLK_PMU1_UART0_SRC_DIV_SHIFT));
5509b43a31aSFinley Xiao if (m && n) {
5519b43a31aSFinley Xiao val = n << CLK_UART_FRAC_NUMERATOR_SHIFT | m;
5529b43a31aSFinley Xiao writel(val, &cru->pmu1clksel_con[3]);
5539b43a31aSFinley Xiao }
5549b43a31aSFinley Xiao
5559b43a31aSFinley Xiao return rk3562_uart_get_rate(priv, clk_id);
5569b43a31aSFinley Xiao case SCLK_UART1:
5579b43a31aSFinley Xiao reg = 21;
5589b43a31aSFinley Xiao break;
5599b43a31aSFinley Xiao case SCLK_UART2:
5609b43a31aSFinley Xiao reg = 23;
5619b43a31aSFinley Xiao break;
5629b43a31aSFinley Xiao case SCLK_UART3:
5639b43a31aSFinley Xiao reg = 25;
5649b43a31aSFinley Xiao break;
5659b43a31aSFinley Xiao case SCLK_UART4:
5669b43a31aSFinley Xiao reg = 27;
5679b43a31aSFinley Xiao break;
5689b43a31aSFinley Xiao case SCLK_UART5:
5699b43a31aSFinley Xiao reg = 29;
5709b43a31aSFinley Xiao break;
5719b43a31aSFinley Xiao case SCLK_UART6:
5729b43a31aSFinley Xiao reg = 31;
5739b43a31aSFinley Xiao break;
5749b43a31aSFinley Xiao case SCLK_UART7:
5759b43a31aSFinley Xiao reg = 33;
5769b43a31aSFinley Xiao break;
5779b43a31aSFinley Xiao case SCLK_UART8:
5789b43a31aSFinley Xiao reg = 35;
5799b43a31aSFinley Xiao break;
5809b43a31aSFinley Xiao case SCLK_UART9:
5819b43a31aSFinley Xiao reg = 37;
5829b43a31aSFinley Xiao break;
5839b43a31aSFinley Xiao default:
5849b43a31aSFinley Xiao return -ENOENT;
5859b43a31aSFinley Xiao }
5869b43a31aSFinley Xiao
5879b43a31aSFinley Xiao if (priv->gpll_hz % rate == 0) {
5889b43a31aSFinley Xiao clk_src = CLK_UART_SRC_SEL_GPLL;
5899b43a31aSFinley Xiao uart_src = CLK_UART_SEL_SRC;
5909b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
5919b43a31aSFinley Xiao } else if (priv->cpll_hz % rate == 0) {
5929b43a31aSFinley Xiao clk_src = CLK_UART_SRC_SEL_CPLL;
5939b43a31aSFinley Xiao uart_src = CLK_UART_SEL_SRC;
5949b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
5959b43a31aSFinley Xiao } else if (rate == OSC_HZ) {
5969b43a31aSFinley Xiao clk_src = CLK_UART_SRC_SEL_GPLL;
5979b43a31aSFinley Xiao uart_src = CLK_UART_SEL_XIN24M;
5989b43a31aSFinley Xiao div = 2;
5999b43a31aSFinley Xiao } else {
6009b43a31aSFinley Xiao clk_src = CLK_UART_SRC_SEL_GPLL;
6019b43a31aSFinley Xiao uart_src = CLK_UART_SEL_FRAC;
6029b43a31aSFinley Xiao div = 2;
6039b43a31aSFinley Xiao rational_best_approximation(rate, priv->gpll_hz / div,
6049b43a31aSFinley Xiao GENMASK(16 - 1, 0),
6059b43a31aSFinley Xiao GENMASK(16 - 1, 0),
6069b43a31aSFinley Xiao &n, &m);
6079b43a31aSFinley Xiao }
6089b43a31aSFinley Xiao
6099b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[reg],
6109b43a31aSFinley Xiao CLK_UART_SEL_MASK | CLK_UART_SRC_SEL_MASK |
6119b43a31aSFinley Xiao CLK_UART_SRC_DIV_MASK,
6129b43a31aSFinley Xiao (clk_src << CLK_UART_SRC_SEL_SHIFT) |
6139b43a31aSFinley Xiao (uart_src << CLK_UART_SEL_SHIFT) |
6149b43a31aSFinley Xiao ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
6159b43a31aSFinley Xiao if (m && n) {
6169b43a31aSFinley Xiao val = n << CLK_UART_FRAC_NUMERATOR_SHIFT | m;
6179b43a31aSFinley Xiao writel(val, &cru->periclksel_con[reg + 1]);
6189b43a31aSFinley Xiao }
6199b43a31aSFinley Xiao
6209b43a31aSFinley Xiao return rk3562_uart_get_rate(priv, clk_id);
6219b43a31aSFinley Xiao }
6229b43a31aSFinley Xiao
rk3562_pwm_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)6239b43a31aSFinley Xiao static ulong rk3562_pwm_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
6249b43a31aSFinley Xiao {
6259b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
6269b43a31aSFinley Xiao u32 sel, con, div, mask, shift;
6279b43a31aSFinley Xiao ulong rate;
6289b43a31aSFinley Xiao
6299b43a31aSFinley Xiao switch (clk_id) {
6309b43a31aSFinley Xiao case CLK_PMU1_PWM0:
6319b43a31aSFinley Xiao con = readl(&cru->pmu1clksel_con[4]);
6329b43a31aSFinley Xiao sel = (con & CLK_PMU1_PWM0_SEL_MASK) >> CLK_PMU1_PWM0_SEL_SHIFT;
6339b43a31aSFinley Xiao if (sel == CLK_PMU1_PWM0_SEL_200M)
6349b43a31aSFinley Xiao rate = 200 * MHz;
6359b43a31aSFinley Xiao else if (sel == CLK_PMU1_PWM0_SEL_24M)
6369b43a31aSFinley Xiao rate = OSC_HZ;
6379b43a31aSFinley Xiao else
6389b43a31aSFinley Xiao rate = 32768;
6399b43a31aSFinley Xiao div = (con & CLK_PMU1_PWM0_DIV_MASK) >> CLK_PMU1_PWM0_DIV_SHIFT;
6409b43a31aSFinley Xiao
6419b43a31aSFinley Xiao return DIV_TO_RATE(rate, div);
6429b43a31aSFinley Xiao case CLK_PWM1_PERI:
6439b43a31aSFinley Xiao mask = CLK_PWM1_PERI_SEL_MASK;
6449b43a31aSFinley Xiao shift = CLK_PWM1_PERI_SEL_SHIFT;
6459b43a31aSFinley Xiao break;
6469b43a31aSFinley Xiao case CLK_PWM2_PERI:
6479b43a31aSFinley Xiao mask = CLK_PWM2_PERI_SEL_MASK;
6489b43a31aSFinley Xiao shift = CLK_PWM2_PERI_SEL_SHIFT;
6499b43a31aSFinley Xiao break;
6509b43a31aSFinley Xiao case CLK_PWM3_PERI:
6519b43a31aSFinley Xiao mask = CLK_PWM3_PERI_SEL_MASK;
6529b43a31aSFinley Xiao shift = CLK_PWM3_PERI_SEL_SHIFT;
6539b43a31aSFinley Xiao break;
6549b43a31aSFinley Xiao default:
6559b43a31aSFinley Xiao return -ENOENT;
6569b43a31aSFinley Xiao }
6579b43a31aSFinley Xiao
6589b43a31aSFinley Xiao con = readl(&cru->periclksel_con[40]);
6599b43a31aSFinley Xiao sel = (con & mask) >> shift;
6609b43a31aSFinley Xiao if (sel == CLK_PWM_SEL_100M)
6619b43a31aSFinley Xiao rate = 100 * MHz;
6629b43a31aSFinley Xiao else if (sel == CLK_PWM_SEL_50M)
6639b43a31aSFinley Xiao rate = 50 * MHz;
6649b43a31aSFinley Xiao else
6659b43a31aSFinley Xiao rate = OSC_HZ;
6669b43a31aSFinley Xiao
6679b43a31aSFinley Xiao return rate;
6689b43a31aSFinley Xiao }
6699b43a31aSFinley Xiao
rk3562_pwm_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)6709b43a31aSFinley Xiao static ulong rk3562_pwm_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
6719b43a31aSFinley Xiao ulong rate)
6729b43a31aSFinley Xiao {
6739b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
6749b43a31aSFinley Xiao u32 sel, div, mask, shift;
6759b43a31aSFinley Xiao
6769b43a31aSFinley Xiao switch (clk_id) {
6779b43a31aSFinley Xiao case CLK_PMU1_PWM0:
6789b43a31aSFinley Xiao if (rate == 200 * MHz) {
6799b43a31aSFinley Xiao sel = CLK_PMU1_PWM0_SEL_200M;
6809b43a31aSFinley Xiao div = 1;
6819b43a31aSFinley Xiao } else if (rate == OSC_HZ) {
6829b43a31aSFinley Xiao sel = CLK_PMU1_PWM0_SEL_24M;
6839b43a31aSFinley Xiao div = 1;
6849b43a31aSFinley Xiao } else if (rate == 32768) {
6859b43a31aSFinley Xiao sel = CLK_PMU1_PWM0_SEL_32K;
6869b43a31aSFinley Xiao div = 1;
6879b43a31aSFinley Xiao } else {
6889b43a31aSFinley Xiao sel = CLK_PMU1_PWM0_SEL_200M;
6899b43a31aSFinley Xiao div = DIV_ROUND_UP(200 * MHz, rate);
6909b43a31aSFinley Xiao assert(div - 1 <= 3);
6919b43a31aSFinley Xiao }
6929b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_PWM0_DIV_MASK,
6939b43a31aSFinley Xiao (div - 1) << CLK_PMU1_PWM0_DIV_SHIFT);
6949b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_PWM0_SEL_MASK,
6959b43a31aSFinley Xiao sel << CLK_PMU1_PWM0_SEL_SHIFT);
6969b43a31aSFinley Xiao
6979b43a31aSFinley Xiao return rk3562_pwm_get_rate(priv, clk_id);
6989b43a31aSFinley Xiao case CLK_PWM1_PERI:
6999b43a31aSFinley Xiao mask = CLK_PWM1_PERI_SEL_MASK;
7009b43a31aSFinley Xiao shift = CLK_PWM1_PERI_SEL_SHIFT;
7019b43a31aSFinley Xiao break;
7029b43a31aSFinley Xiao case CLK_PWM2_PERI:
7039b43a31aSFinley Xiao mask = CLK_PWM2_PERI_SEL_MASK;
7049b43a31aSFinley Xiao shift = CLK_PWM2_PERI_SEL_SHIFT;
7059b43a31aSFinley Xiao break;
7069b43a31aSFinley Xiao case CLK_PWM3_PERI:
7079b43a31aSFinley Xiao mask = CLK_PWM3_PERI_SEL_MASK;
7089b43a31aSFinley Xiao shift = CLK_PWM3_PERI_SEL_SHIFT;
7099b43a31aSFinley Xiao break;
7109b43a31aSFinley Xiao default:
7119b43a31aSFinley Xiao return -ENOENT;
7129b43a31aSFinley Xiao }
7139b43a31aSFinley Xiao
7149b43a31aSFinley Xiao if (rate == 100 * MHz)
7159b43a31aSFinley Xiao sel = CLK_PWM_SEL_100M;
7169b43a31aSFinley Xiao else if (rate == 50 * MHz)
7179b43a31aSFinley Xiao sel = CLK_PWM_SEL_50M;
7189b43a31aSFinley Xiao else
7199b43a31aSFinley Xiao sel = CLK_PWM_SEL_24M;
7209b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[40], mask, sel << shift);
7219b43a31aSFinley Xiao
7229b43a31aSFinley Xiao return rk3562_pwm_get_rate(priv, clk_id);
7239b43a31aSFinley Xiao }
7249b43a31aSFinley Xiao
rk3562_spi_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)7259b43a31aSFinley Xiao static ulong rk3562_spi_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
7269b43a31aSFinley Xiao {
7279b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
7289b43a31aSFinley Xiao u32 sel, con, div, mask, shift;
7299b43a31aSFinley Xiao ulong rate;
7309b43a31aSFinley Xiao
7319b43a31aSFinley Xiao switch (clk_id) {
7329b43a31aSFinley Xiao case CLK_PMU1_SPI0:
7339b43a31aSFinley Xiao con = readl(&cru->pmu1clksel_con[4]);
7349b43a31aSFinley Xiao sel = (con & CLK_PMU1_SPI0_SEL_MASK) >> CLK_PMU1_SPI0_SEL_SHIFT;
7359b43a31aSFinley Xiao if (sel == CLK_PMU1_SPI0_SEL_200M)
7369b43a31aSFinley Xiao rate = 200 * MHz;
7379b43a31aSFinley Xiao else if (sel == CLK_PMU1_SPI0_SEL_24M)
7389b43a31aSFinley Xiao rate = OSC_HZ;
7399b43a31aSFinley Xiao else
7409b43a31aSFinley Xiao rate = 32768;
7419b43a31aSFinley Xiao div = (con & CLK_PMU1_SPI0_DIV_MASK) >> CLK_PMU1_SPI0_DIV_SHIFT;
7429b43a31aSFinley Xiao
7439b43a31aSFinley Xiao return DIV_TO_RATE(rate, div);
7449b43a31aSFinley Xiao case CLK_SPI1:
7459b43a31aSFinley Xiao mask = CLK_SPI1_SEL_MASK;
7469b43a31aSFinley Xiao shift = CLK_SPI1_SEL_SHIFT;
7479b43a31aSFinley Xiao break;
7489b43a31aSFinley Xiao case CLK_SPI2:
7499b43a31aSFinley Xiao mask = CLK_SPI2_SEL_MASK;
7509b43a31aSFinley Xiao shift = CLK_SPI2_SEL_SHIFT;
7519b43a31aSFinley Xiao break;
7529b43a31aSFinley Xiao default:
7539b43a31aSFinley Xiao return -ENOENT;
7549b43a31aSFinley Xiao }
7559b43a31aSFinley Xiao
7569b43a31aSFinley Xiao con = readl(&cru->periclksel_con[20]);
7579b43a31aSFinley Xiao sel = (con & mask) >> shift;
7589b43a31aSFinley Xiao if (sel == CLK_SPI_SEL_200M)
7599b43a31aSFinley Xiao rate = 200 * MHz;
7609b43a31aSFinley Xiao else if (sel == CLK_SPI_SEL_100M)
7619b43a31aSFinley Xiao rate = 100 * MHz;
7629b43a31aSFinley Xiao else if (sel == CLK_SPI_SEL_50M)
7639b43a31aSFinley Xiao rate = 50 * MHz;
7649b43a31aSFinley Xiao else
7659b43a31aSFinley Xiao rate = OSC_HZ;
7669b43a31aSFinley Xiao
7679b43a31aSFinley Xiao return rate;
7689b43a31aSFinley Xiao }
7699b43a31aSFinley Xiao
rk3562_spi_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)7709b43a31aSFinley Xiao static ulong rk3562_spi_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
7719b43a31aSFinley Xiao ulong rate)
7729b43a31aSFinley Xiao {
7739b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
7749b43a31aSFinley Xiao u32 sel, div, mask, shift;
7759b43a31aSFinley Xiao
7769b43a31aSFinley Xiao switch (clk_id) {
7779b43a31aSFinley Xiao case CLK_PMU1_SPI0:
7789b43a31aSFinley Xiao if (rate == 200 * MHz) {
7799b43a31aSFinley Xiao sel = CLK_PMU1_SPI0_SEL_200M;
7809b43a31aSFinley Xiao div = 1;
7819b43a31aSFinley Xiao } else if (rate == OSC_HZ) {
7829b43a31aSFinley Xiao sel = CLK_PMU1_SPI0_SEL_24M;
7839b43a31aSFinley Xiao div = 1;
7849b43a31aSFinley Xiao } else if (rate == 32768) {
7859b43a31aSFinley Xiao sel = CLK_PMU1_SPI0_SEL_32K;
7869b43a31aSFinley Xiao div = 1;
7879b43a31aSFinley Xiao } else {
7889b43a31aSFinley Xiao sel = CLK_PMU1_SPI0_SEL_200M;
7899b43a31aSFinley Xiao div = DIV_ROUND_UP(200 * MHz, rate);
7909b43a31aSFinley Xiao assert(div - 1 <= 3);
7919b43a31aSFinley Xiao }
7929b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_SPI0_DIV_MASK,
7939b43a31aSFinley Xiao (div - 1) << CLK_PMU1_SPI0_DIV_SHIFT);
7949b43a31aSFinley Xiao rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_SPI0_SEL_MASK,
7959b43a31aSFinley Xiao sel << CLK_PMU1_SPI0_SEL_SHIFT);
7969b43a31aSFinley Xiao
7979b43a31aSFinley Xiao return rk3562_spi_get_rate(priv, clk_id);
7989b43a31aSFinley Xiao case CLK_SPI1:
7999b43a31aSFinley Xiao mask = CLK_SPI1_SEL_MASK;
8009b43a31aSFinley Xiao shift = CLK_SPI1_SEL_SHIFT;
8019b43a31aSFinley Xiao break;
8029b43a31aSFinley Xiao case CLK_SPI2:
8039b43a31aSFinley Xiao mask = CLK_SPI2_SEL_MASK;
8049b43a31aSFinley Xiao shift = CLK_SPI2_SEL_SHIFT;
8059b43a31aSFinley Xiao break;
8069b43a31aSFinley Xiao default:
8079b43a31aSFinley Xiao return -ENOENT;
8089b43a31aSFinley Xiao }
8099b43a31aSFinley Xiao
8109b43a31aSFinley Xiao if (rate == 200 * MHz)
8119b43a31aSFinley Xiao sel = CLK_SPI_SEL_200M;
8129b43a31aSFinley Xiao else if (rate == 100 * MHz)
8139b43a31aSFinley Xiao sel = CLK_SPI_SEL_100M;
8149b43a31aSFinley Xiao else if (rate == 50 * MHz)
8159b43a31aSFinley Xiao sel = CLK_SPI_SEL_50M;
8169b43a31aSFinley Xiao else
8179b43a31aSFinley Xiao sel = CLK_SPI_SEL_24M;
8189b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[20], mask, sel << shift);
8199b43a31aSFinley Xiao
8209b43a31aSFinley Xiao return rk3562_spi_get_rate(priv, clk_id);
8219b43a31aSFinley Xiao }
8229b43a31aSFinley Xiao
rk3562_tsadc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)8239b43a31aSFinley Xiao static ulong rk3562_tsadc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
8249b43a31aSFinley Xiao {
8259b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
8269b43a31aSFinley Xiao u32 div, con;
8279b43a31aSFinley Xiao
8289b43a31aSFinley Xiao con = readl(&cru->clksel_con[43]);
8299b43a31aSFinley Xiao switch (clk_id) {
8309b43a31aSFinley Xiao case CLK_TSADC_TSEN:
8319b43a31aSFinley Xiao div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
8329b43a31aSFinley Xiao CLK_TSADC_TSEN_DIV_SHIFT;
8339b43a31aSFinley Xiao break;
8349b43a31aSFinley Xiao case CLK_TSADC:
8359b43a31aSFinley Xiao div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
8369b43a31aSFinley Xiao break;
8379b43a31aSFinley Xiao default:
8389b43a31aSFinley Xiao return -ENOENT;
8399b43a31aSFinley Xiao }
8409b43a31aSFinley Xiao
8419b43a31aSFinley Xiao return DIV_TO_RATE(OSC_HZ, div);
8429b43a31aSFinley Xiao }
8439b43a31aSFinley Xiao
rk3562_tsadc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)8449b43a31aSFinley Xiao static ulong rk3562_tsadc_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
8459b43a31aSFinley Xiao ulong rate)
8469b43a31aSFinley Xiao {
8479b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
8489b43a31aSFinley Xiao u32 div, mask, shift;
8499b43a31aSFinley Xiao
8509b43a31aSFinley Xiao switch (clk_id) {
8519b43a31aSFinley Xiao case CLK_TSADC_TSEN:
8529b43a31aSFinley Xiao mask = CLK_TSADC_TSEN_DIV_MASK;
8539b43a31aSFinley Xiao shift = CLK_TSADC_TSEN_DIV_SHIFT;
8549b43a31aSFinley Xiao break;
8559b43a31aSFinley Xiao case CLK_TSADC:
8569b43a31aSFinley Xiao mask = CLK_TSADC_DIV_MASK;
8579b43a31aSFinley Xiao shift = CLK_TSADC_DIV_SHIFT;
8589b43a31aSFinley Xiao break;
8599b43a31aSFinley Xiao default:
8609b43a31aSFinley Xiao return -ENOENT;
8619b43a31aSFinley Xiao }
8629b43a31aSFinley Xiao
8639b43a31aSFinley Xiao div = DIV_ROUND_UP(OSC_HZ, rate);
8649b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[43], mask, (div - 1) << shift);
8659b43a31aSFinley Xiao
8669b43a31aSFinley Xiao return rk3562_tsadc_get_rate(priv, clk_id);
8679b43a31aSFinley Xiao }
8689b43a31aSFinley Xiao
rk3562_saradc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)8699b43a31aSFinley Xiao static ulong rk3562_saradc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
8709b43a31aSFinley Xiao {
8719b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
8729b43a31aSFinley Xiao u32 div, con;
8739b43a31aSFinley Xiao
8749b43a31aSFinley Xiao switch (clk_id) {
8759b43a31aSFinley Xiao case CLK_SARADC_VCCIO156:
8769b43a31aSFinley Xiao con = readl(&cru->clksel_con[44]);
8779b43a31aSFinley Xiao div = (con & CLK_SARADC_VCCIO156_DIV_MASK) >>
8789b43a31aSFinley Xiao CLK_SARADC_VCCIO156_DIV_SHIFT;
8799b43a31aSFinley Xiao break;
8809b43a31aSFinley Xiao case CLK_SARADC:
8819b43a31aSFinley Xiao con = readl(&cru->periclksel_con[46]);
8829b43a31aSFinley Xiao div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
8839b43a31aSFinley Xiao break;
8849b43a31aSFinley Xiao default:
8859b43a31aSFinley Xiao return -ENOENT;
8869b43a31aSFinley Xiao }
8879b43a31aSFinley Xiao
8889b43a31aSFinley Xiao return DIV_TO_RATE(OSC_HZ, div);
8899b43a31aSFinley Xiao }
8909b43a31aSFinley Xiao
rk3562_saradc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)8919b43a31aSFinley Xiao static ulong rk3562_saradc_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
8929b43a31aSFinley Xiao ulong rate)
8939b43a31aSFinley Xiao {
8949b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
8959b43a31aSFinley Xiao u32 div;
8969b43a31aSFinley Xiao
8979b43a31aSFinley Xiao switch (clk_id) {
8989b43a31aSFinley Xiao case CLK_SARADC_VCCIO156:
8999b43a31aSFinley Xiao div = DIV_ROUND_UP(OSC_HZ, rate);
9009b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[44], CLK_SARADC_VCCIO156_DIV_MASK,
9019b43a31aSFinley Xiao (div - 1) << CLK_SARADC_VCCIO156_DIV_SHIFT);
9029b43a31aSFinley Xiao break;
9039b43a31aSFinley Xiao case CLK_SARADC:
9049b43a31aSFinley Xiao div = DIV_ROUND_UP(OSC_HZ, rate);
9059b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[46], CLK_SARADC_DIV_MASK,
9069b43a31aSFinley Xiao (div - 1) << CLK_SARADC_DIV_SHIFT);
9079b43a31aSFinley Xiao break;
9089b43a31aSFinley Xiao default:
9099b43a31aSFinley Xiao return -ENOENT;
9109b43a31aSFinley Xiao }
9119b43a31aSFinley Xiao
9129b43a31aSFinley Xiao return rk3562_saradc_get_rate(priv, clk_id);
9139b43a31aSFinley Xiao }
9149b43a31aSFinley Xiao
rk3562_sfc_get_rate(struct rk3562_clk_priv * priv)9159b43a31aSFinley Xiao static ulong rk3562_sfc_get_rate(struct rk3562_clk_priv *priv)
9169b43a31aSFinley Xiao {
9179b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
9189b43a31aSFinley Xiao u32 div, sel, con, parent;
9199b43a31aSFinley Xiao
9209b43a31aSFinley Xiao con = readl(&cru->periclksel_con[20]);
9219b43a31aSFinley Xiao div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
9229b43a31aSFinley Xiao sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
9239b43a31aSFinley Xiao if (sel == SCLK_SFC_SRC_SEL_GPLL)
9249b43a31aSFinley Xiao parent = priv->gpll_hz;
9259b43a31aSFinley Xiao else if (sel == SCLK_SFC_SRC_SEL_CPLL)
9269b43a31aSFinley Xiao parent = priv->cpll_hz;
9279b43a31aSFinley Xiao else
9289b43a31aSFinley Xiao parent = OSC_HZ;
9299b43a31aSFinley Xiao
9309b43a31aSFinley Xiao return DIV_TO_RATE(parent, div);
9319b43a31aSFinley Xiao }
9329b43a31aSFinley Xiao
rk3562_sfc_set_rate(struct rk3562_clk_priv * priv,ulong rate)9339b43a31aSFinley Xiao static ulong rk3562_sfc_set_rate(struct rk3562_clk_priv *priv, ulong rate)
9349b43a31aSFinley Xiao {
9359b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
9369b43a31aSFinley Xiao int div, sel;
9379b43a31aSFinley Xiao
9389b43a31aSFinley Xiao if (OSC_HZ % rate == 0) {
9399b43a31aSFinley Xiao div = DIV_ROUND_UP(OSC_HZ, rate);
9409b43a31aSFinley Xiao sel = SCLK_SFC_SRC_SEL_24M;
9419b43a31aSFinley Xiao } else if ((priv->cpll_hz % rate) == 0) {
9429b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
9439b43a31aSFinley Xiao sel = SCLK_SFC_SRC_SEL_CPLL;
9449b43a31aSFinley Xiao } else {
9459b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
9469b43a31aSFinley Xiao sel = SCLK_SFC_SRC_SEL_GPLL;
9479b43a31aSFinley Xiao }
9489b43a31aSFinley Xiao
9499b43a31aSFinley Xiao assert(div - 1 <= 255);
9509b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[20],
9519b43a31aSFinley Xiao SCLK_SFC_SEL_MASK | SCLK_SFC_DIV_MASK,
9529b43a31aSFinley Xiao sel << SCLK_SFC_SEL_SHIFT |
9539b43a31aSFinley Xiao (div - 1) << SCLK_SFC_DIV_SHIFT);
9549b43a31aSFinley Xiao
9559b43a31aSFinley Xiao return rk3562_sfc_get_rate(priv);
9569b43a31aSFinley Xiao }
9579b43a31aSFinley Xiao
rk3562_emmc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)9589b43a31aSFinley Xiao static ulong rk3562_emmc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
9599b43a31aSFinley Xiao {
9609b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
9619b43a31aSFinley Xiao u32 div, sel, con, parent;
9629b43a31aSFinley Xiao
9639b43a31aSFinley Xiao switch (clk_id) {
9649b43a31aSFinley Xiao case CCLK_EMMC:
9659b43a31aSFinley Xiao con = readl(&cru->periclksel_con[18]);
9669b43a31aSFinley Xiao div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
9679b43a31aSFinley Xiao sel = (con & CCLK_EMMC_SEL_MASK) >> CCLK_EMMC_SEL_SHIFT;
9689b43a31aSFinley Xiao if (sel == CCLK_EMMC_SEL_GPLL)
9699b43a31aSFinley Xiao parent = priv->gpll_hz;
9709b43a31aSFinley Xiao else if (sel == CCLK_EMMC_SEL_CPLL)
9719b43a31aSFinley Xiao parent = priv->cpll_hz;
9729b43a31aSFinley Xiao else if (sel == CCLK_EMMC_SEL_HPLL)
9739b43a31aSFinley Xiao parent = priv->hpll_hz;
9749b43a31aSFinley Xiao else
9759b43a31aSFinley Xiao parent = OSC_HZ;
9769b43a31aSFinley Xiao break;
9779b43a31aSFinley Xiao case BCLK_EMMC:
9789b43a31aSFinley Xiao con = readl(&cru->periclksel_con[19]);
9799b43a31aSFinley Xiao div = (con & BCLK_EMMC_DIV_MASK) >> BCLK_EMMC_DIV_SHIFT;
9809b43a31aSFinley Xiao sel = (con & BCLK_EMMC_SEL_MASK) >> BCLK_EMMC_SEL_SHIFT;
9819b43a31aSFinley Xiao if (sel == BCLK_EMMC_SEL_GPLL)
9829b43a31aSFinley Xiao parent = priv->gpll_hz;
9839b43a31aSFinley Xiao else
9849b43a31aSFinley Xiao parent = priv->cpll_hz;
9859b43a31aSFinley Xiao break;
9869b43a31aSFinley Xiao default:
9879b43a31aSFinley Xiao return -ENOENT;
9889b43a31aSFinley Xiao }
9899b43a31aSFinley Xiao
9909b43a31aSFinley Xiao return DIV_TO_RATE(parent, div);
9919b43a31aSFinley Xiao }
9929b43a31aSFinley Xiao
rk3562_emmc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)9939b43a31aSFinley Xiao static ulong rk3562_emmc_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
9949b43a31aSFinley Xiao ulong rate)
9959b43a31aSFinley Xiao {
9969b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
9979b43a31aSFinley Xiao int div, sel;
9989b43a31aSFinley Xiao
9999b43a31aSFinley Xiao switch (clk_id) {
10009b43a31aSFinley Xiao case CCLK_EMMC:
10019b43a31aSFinley Xiao if (OSC_HZ % rate == 0) {
10029b43a31aSFinley Xiao div = DIV_ROUND_UP(OSC_HZ, rate);
10039b43a31aSFinley Xiao sel = CCLK_EMMC_SEL_24M;
10049b43a31aSFinley Xiao } else if ((priv->cpll_hz % rate) == 0) {
10059b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
10069b43a31aSFinley Xiao sel = CCLK_EMMC_SEL_CPLL;
10079b43a31aSFinley Xiao } else if ((priv->hpll_hz % rate) == 0) {
10089b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->hpll_hz, rate);
10099b43a31aSFinley Xiao sel = CCLK_EMMC_SEL_HPLL;
10109b43a31aSFinley Xiao } else {
10119b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
10129b43a31aSFinley Xiao sel = CCLK_EMMC_SEL_GPLL;
10139b43a31aSFinley Xiao }
10149b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[18],
10159b43a31aSFinley Xiao CCLK_EMMC_SEL_MASK | CCLK_EMMC_DIV_MASK,
10169b43a31aSFinley Xiao sel << CCLK_EMMC_SEL_SHIFT |
10179b43a31aSFinley Xiao (div - 1) << CCLK_EMMC_DIV_SHIFT);
10189b43a31aSFinley Xiao break;
10199b43a31aSFinley Xiao case BCLK_EMMC:
10209b43a31aSFinley Xiao if ((priv->cpll_hz % rate) == 0) {
10219b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
10229b43a31aSFinley Xiao sel = BCLK_EMMC_SEL_CPLL;
10239b43a31aSFinley Xiao } else {
10249b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
10259b43a31aSFinley Xiao sel = BCLK_EMMC_SEL_GPLL;
10269b43a31aSFinley Xiao }
10279b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[19],
10289b43a31aSFinley Xiao BCLK_EMMC_SEL_MASK | BCLK_EMMC_DIV_MASK,
10299b43a31aSFinley Xiao sel << BCLK_EMMC_SEL_SHIFT |
10309b43a31aSFinley Xiao (div - 1) << BCLK_EMMC_DIV_SHIFT);
10319b43a31aSFinley Xiao break;
10329b43a31aSFinley Xiao default:
10339b43a31aSFinley Xiao return -ENOENT;
10349b43a31aSFinley Xiao }
10359b43a31aSFinley Xiao
10369b43a31aSFinley Xiao return rk3562_emmc_get_rate(priv, clk_id);
10379b43a31aSFinley Xiao }
10389b43a31aSFinley Xiao
rk3562_sdmmc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)10399b43a31aSFinley Xiao static ulong rk3562_sdmmc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
10409b43a31aSFinley Xiao {
10419b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
10429b43a31aSFinley Xiao u32 div, sel, con;
10439b43a31aSFinley Xiao ulong prate;
10449b43a31aSFinley Xiao
10459b43a31aSFinley Xiao switch (clk_id) {
10469b43a31aSFinley Xiao case HCLK_SDMMC0:
10479b43a31aSFinley Xiao case CCLK_SDMMC0:
10489b43a31aSFinley Xiao case SCLK_SDMMC0_SAMPLE:
10499b43a31aSFinley Xiao con = readl(&cru->periclksel_con[16]);
10509b43a31aSFinley Xiao div = (con & CCLK_SDMMC0_DIV_MASK) >> CCLK_SDMMC0_DIV_SHIFT;
10519b43a31aSFinley Xiao sel = (con & CCLK_SDMMC0_SEL_MASK) >> CCLK_SDMMC0_SEL_SHIFT;
10529b43a31aSFinley Xiao break;
10539b43a31aSFinley Xiao case HCLK_SDMMC1:
10549b43a31aSFinley Xiao case CCLK_SDMMC1:
10559b43a31aSFinley Xiao case SCLK_SDMMC1_SAMPLE:
10569b43a31aSFinley Xiao con = readl(&cru->periclksel_con[17]);
10579b43a31aSFinley Xiao div = (con & CCLK_SDMMC1_DIV_MASK) >> CCLK_SDMMC1_DIV_SHIFT;
10589b43a31aSFinley Xiao sel = (con & CCLK_SDMMC1_SEL_MASK) >> CCLK_SDMMC1_SEL_SHIFT;
10599b43a31aSFinley Xiao break;
10609b43a31aSFinley Xiao default:
10619b43a31aSFinley Xiao return -ENOENT;
10629b43a31aSFinley Xiao }
10639b43a31aSFinley Xiao
10649b43a31aSFinley Xiao if (sel == CCLK_SDMMC_SEL_GPLL)
10659b43a31aSFinley Xiao prate = priv->gpll_hz;
10669b43a31aSFinley Xiao else if (sel == CCLK_SDMMC_SEL_CPLL)
10679b43a31aSFinley Xiao prate = priv->cpll_hz;
10689b43a31aSFinley Xiao else if (sel == CCLK_SDMMC_SEL_HPLL)
10699b43a31aSFinley Xiao prate = priv->hpll_hz;
10709b43a31aSFinley Xiao else
10719b43a31aSFinley Xiao prate = OSC_HZ;
10729b43a31aSFinley Xiao
10739b43a31aSFinley Xiao return DIV_TO_RATE(prate, div);
10749b43a31aSFinley Xiao }
10759b43a31aSFinley Xiao
rk3562_sdmmc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)10769b43a31aSFinley Xiao static ulong rk3562_sdmmc_set_rate(struct rk3562_clk_priv *priv,
10779b43a31aSFinley Xiao ulong clk_id, ulong rate)
10789b43a31aSFinley Xiao {
10799b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
10809b43a31aSFinley Xiao u32 div, sel;
10819b43a31aSFinley Xiao
10829b43a31aSFinley Xiao if (OSC_HZ % rate == 0) {
10839b43a31aSFinley Xiao div = DIV_ROUND_UP(OSC_HZ, rate);
10849b43a31aSFinley Xiao sel = CCLK_SDMMC_SEL_24M;
10859b43a31aSFinley Xiao } else if ((priv->cpll_hz % rate) == 0) {
10869b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
10879b43a31aSFinley Xiao sel = CCLK_SDMMC_SEL_CPLL;
10889b43a31aSFinley Xiao } else if ((priv->hpll_hz % rate) == 0) {
10899b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->hpll_hz, rate);
10909b43a31aSFinley Xiao sel = CCLK_SDMMC_SEL_HPLL;
10919b43a31aSFinley Xiao } else {
10929b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
10939b43a31aSFinley Xiao sel = CCLK_SDMMC_SEL_CPLL;
10949b43a31aSFinley Xiao }
10959b43a31aSFinley Xiao
10969b43a31aSFinley Xiao switch (clk_id) {
10979b43a31aSFinley Xiao case HCLK_SDMMC0:
10989b43a31aSFinley Xiao case CCLK_SDMMC0:
10999b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[16],
11009b43a31aSFinley Xiao CCLK_SDMMC0_SEL_MASK | CCLK_SDMMC0_DIV_MASK,
11019b43a31aSFinley Xiao sel << CCLK_SDMMC0_SEL_SHIFT |
11029b43a31aSFinley Xiao (div - 1) << CCLK_SDMMC0_DIV_SHIFT);
11039b43a31aSFinley Xiao break;
11049b43a31aSFinley Xiao case HCLK_SDMMC1:
11059b43a31aSFinley Xiao case CCLK_SDMMC1:
11069b43a31aSFinley Xiao rk_clrsetreg(&cru->periclksel_con[17],
11079b43a31aSFinley Xiao CCLK_SDMMC1_SEL_MASK | CCLK_SDMMC1_DIV_MASK,
11089b43a31aSFinley Xiao sel << CCLK_SDMMC1_SEL_SHIFT |
11099b43a31aSFinley Xiao (div - 1) << CCLK_SDMMC1_DIV_SHIFT);
11109b43a31aSFinley Xiao break;
11119b43a31aSFinley Xiao default:
11129b43a31aSFinley Xiao return -ENOENT;
11139b43a31aSFinley Xiao }
11149b43a31aSFinley Xiao
11159b43a31aSFinley Xiao return rk3562_sdmmc_get_rate(priv, clk_id);
11169b43a31aSFinley Xiao }
11179b43a31aSFinley Xiao
rk3562_vop_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)11189b43a31aSFinley Xiao static ulong rk3562_vop_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
11199b43a31aSFinley Xiao {
11209b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
11219b43a31aSFinley Xiao u32 con, sel, div;
11229b43a31aSFinley Xiao ulong prate;
11239b43a31aSFinley Xiao
11249b43a31aSFinley Xiao switch (clk_id) {
11259b43a31aSFinley Xiao case ACLK_VOP:
11269b43a31aSFinley Xiao con = readl(&cru->clksel_con[28]);
11279b43a31aSFinley Xiao div = (con & ACLK_VOP_DIV_MASK) >> ACLK_VOP_DIV_SHIFT;
11289b43a31aSFinley Xiao sel = (con & ACLK_VOP_SEL_MASK) >> ACLK_VOP_SEL_SHIFT;
11299b43a31aSFinley Xiao if (sel == ACLK_VOP_SEL_GPLL)
11309b43a31aSFinley Xiao prate = priv->gpll_hz;
11319b43a31aSFinley Xiao else if (sel == ACLK_VOP_SEL_CPLL)
11329b43a31aSFinley Xiao prate = priv->cpll_hz;
11339b43a31aSFinley Xiao else if (sel == ACLK_VOP_SEL_HPLL)
11349b43a31aSFinley Xiao prate = priv->hpll_hz;
11359b43a31aSFinley Xiao else if (sel == ACLK_VOP_SEL_VPLL)
11369b43a31aSFinley Xiao prate = priv->vpll_hz;
11379b43a31aSFinley Xiao else
11389b43a31aSFinley Xiao return -ENOENT;
11399b43a31aSFinley Xiao
11409b43a31aSFinley Xiao return DIV_TO_RATE(prate, div);
11419b43a31aSFinley Xiao case DCLK_VOP:
11429b43a31aSFinley Xiao con = readl(&cru->clksel_con[30]);
11439b43a31aSFinley Xiao div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
11449b43a31aSFinley Xiao sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
11459b43a31aSFinley Xiao if (sel == DCLK_VOP_SEL_VPLL)
11469b43a31aSFinley Xiao priv->vpll_hz =
11479b43a31aSFinley Xiao rockchip_pll_get_rate(&rk3562_pll_clks[VPLL],
11489b43a31aSFinley Xiao priv->cru, VPLL);
11499b43a31aSFinley Xiao break;
11509b43a31aSFinley Xiao case DCLK_VOP1:
11519b43a31aSFinley Xiao con = readl(&cru->clksel_con[31]);
11529b43a31aSFinley Xiao div = (con & DCLK_VOP1_DIV_MASK) >> DCLK_VOP1_DIV_SHIFT;
11539b43a31aSFinley Xiao sel = (con & DCLK_VOP1_SEL_MASK) >> DCLK_VOP1_SEL_SHIFT;
11549b43a31aSFinley Xiao break;
11559b43a31aSFinley Xiao default:
11569b43a31aSFinley Xiao return -ENOENT;
11579b43a31aSFinley Xiao }
11589b43a31aSFinley Xiao
11599b43a31aSFinley Xiao if (sel == DCLK_VOP_SEL_GPLL)
11609b43a31aSFinley Xiao prate = priv->gpll_hz;
11619b43a31aSFinley Xiao else if (sel == DCLK_VOP_SEL_HPLL)
11629b43a31aSFinley Xiao prate = priv->hpll_hz;
11639b43a31aSFinley Xiao else if (sel == DCLK_VOP_SEL_VPLL)
11649b43a31aSFinley Xiao prate = priv->vpll_hz;
11659b43a31aSFinley Xiao else
11669b43a31aSFinley Xiao return -ENOENT;
11679b43a31aSFinley Xiao
11689b43a31aSFinley Xiao return DIV_TO_RATE(prate, div);
11699b43a31aSFinley Xiao }
11709b43a31aSFinley Xiao
1171*e583fa2aSElaine Zhang #define RK3562_VOP_PLL_LIMIT_FREQ 594000000
11729b43a31aSFinley Xiao
rk3562_vop_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)11739b43a31aSFinley Xiao static ulong rk3562_vop_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
11749b43a31aSFinley Xiao ulong rate)
11759b43a31aSFinley Xiao {
11769b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
11779b43a31aSFinley Xiao u32 i, div, sel, best_div = 0, best_sel = 0;
11789b43a31aSFinley Xiao ulong pll_rate, now, best_rate = 0;
11799b43a31aSFinley Xiao
11809b43a31aSFinley Xiao switch (clk_id) {
11819b43a31aSFinley Xiao case ACLK_VOP:
11829b43a31aSFinley Xiao if ((priv->cpll_hz % rate) == 0) {
11839b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
11849b43a31aSFinley Xiao sel = ACLK_VOP_SEL_CPLL;
11859b43a31aSFinley Xiao } else if ((priv->hpll_hz % rate) == 0) {
11869b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->hpll_hz, rate);
11879b43a31aSFinley Xiao sel = ACLK_VOP_SEL_HPLL;
11889b43a31aSFinley Xiao } else if ((priv->vpll_hz % rate) == 0) {
11899b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->vpll_hz, rate);
11909b43a31aSFinley Xiao sel = ACLK_VOP_SEL_VPLL;
11919b43a31aSFinley Xiao } else {
11929b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
11939b43a31aSFinley Xiao sel = ACLK_VOP_SEL_GPLL;
11949b43a31aSFinley Xiao }
11959b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[28],
11969b43a31aSFinley Xiao ACLK_VOP_SEL_MASK | ACLK_VOP_DIV_MASK,
11979b43a31aSFinley Xiao sel << ACLK_VOP_SEL_SHIFT |
11989b43a31aSFinley Xiao ((div - 1) << ACLK_VOP_DIV_SHIFT));
11999b43a31aSFinley Xiao
12009b43a31aSFinley Xiao return rk3562_vop_get_rate(priv, clk_id);
12019b43a31aSFinley Xiao case DCLK_VOP:
12029b43a31aSFinley Xiao div = DIV_ROUND_UP(RK3562_VOP_PLL_LIMIT_FREQ, rate);
1203*e583fa2aSElaine Zhang if (div % 2)
1204*e583fa2aSElaine Zhang div = div + 1;
12059b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[30],
12069b43a31aSFinley Xiao DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK,
12079b43a31aSFinley Xiao DCLK_VOP_SEL_VPLL << DCLK_VOP_SEL_SHIFT |
12089b43a31aSFinley Xiao ((div - 1) << DCLK_VOP_DIV_SHIFT));
12099b43a31aSFinley Xiao rockchip_pll_set_rate(&rk3562_pll_clks[VPLL], priv->cru,
12109b43a31aSFinley Xiao VPLL, div * rate);
12119b43a31aSFinley Xiao break;
12129b43a31aSFinley Xiao case DCLK_VOP1:
12139b43a31aSFinley Xiao for (i = 0; i <= DCLK_VOP_SEL_APLL; i++) {
12149b43a31aSFinley Xiao switch (i) {
12159b43a31aSFinley Xiao case DCLK_VOP_SEL_GPLL:
12169b43a31aSFinley Xiao pll_rate = priv->gpll_hz;
12179b43a31aSFinley Xiao break;
12189b43a31aSFinley Xiao case DCLK_VOP_SEL_HPLL:
12199b43a31aSFinley Xiao pll_rate = priv->hpll_hz;
12209b43a31aSFinley Xiao break;
12219b43a31aSFinley Xiao case DCLK_VOP_SEL_VPLL:
12229b43a31aSFinley Xiao case DCLK_VOP_SEL_APLL:
12239b43a31aSFinley Xiao continue;
12249b43a31aSFinley Xiao default:
12259b43a31aSFinley Xiao printf("do not support this vop pll sel\n");
12269b43a31aSFinley Xiao return -EINVAL;
12279b43a31aSFinley Xiao }
12289b43a31aSFinley Xiao
12299b43a31aSFinley Xiao div = DIV_ROUND_UP(pll_rate, rate);
12309b43a31aSFinley Xiao if (div > 255)
12319b43a31aSFinley Xiao continue;
12329b43a31aSFinley Xiao now = pll_rate / div;
12339b43a31aSFinley Xiao if (abs(rate - now) < abs(rate - best_rate)) {
12349b43a31aSFinley Xiao best_rate = now;
12359b43a31aSFinley Xiao best_div = div;
12369b43a31aSFinley Xiao best_sel = i;
12379b43a31aSFinley Xiao }
12389b43a31aSFinley Xiao debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
12399b43a31aSFinley Xiao pll_rate, best_rate, best_div, best_sel);
12409b43a31aSFinley Xiao }
12419b43a31aSFinley Xiao if (best_rate) {
12429b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[31],
12439b43a31aSFinley Xiao DCLK_VOP1_SEL_MASK | DCLK_VOP1_DIV_MASK,
12449b43a31aSFinley Xiao best_sel << DCLK_VOP1_SEL_SHIFT |
12459b43a31aSFinley Xiao (best_div - 1) << DCLK_VOP1_DIV_SHIFT);
12469b43a31aSFinley Xiao } else {
12479b43a31aSFinley Xiao printf("do not support this vop freq %lu\n", rate);
12489b43a31aSFinley Xiao return -EINVAL;
12499b43a31aSFinley Xiao }
12509b43a31aSFinley Xiao break;
12519b43a31aSFinley Xiao default:
12529b43a31aSFinley Xiao return -ENOENT;
12539b43a31aSFinley Xiao }
12549b43a31aSFinley Xiao
12559b43a31aSFinley Xiao return rk3562_vop_get_rate(priv, clk_id);
12569b43a31aSFinley Xiao }
12579b43a31aSFinley Xiao
rk3562_gmac_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)12589b43a31aSFinley Xiao static ulong rk3562_gmac_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
12599b43a31aSFinley Xiao {
12609b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
12619b43a31aSFinley Xiao u32 con, sel, div;
12629b43a31aSFinley Xiao ulong prate;
12639b43a31aSFinley Xiao
12649b43a31aSFinley Xiao switch (clk_id) {
12659b43a31aSFinley Xiao case CLK_GMAC_125M_CRU_I:
12669b43a31aSFinley Xiao con = readl(&cru->clksel_con[45]);
12679b43a31aSFinley Xiao sel = (con & CLK_GMAC_125M_SEL_MASK) >> CLK_GMAC_125M_SEL_SHIFT;
12689b43a31aSFinley Xiao if (sel == CLK_GMAC_125M)
12699b43a31aSFinley Xiao return 125000000;
12709b43a31aSFinley Xiao else
12719b43a31aSFinley Xiao return OSC_HZ;
12729b43a31aSFinley Xiao case CLK_GMAC_50M_CRU_I:
12739b43a31aSFinley Xiao con = readl(&cru->clksel_con[45]);
12749b43a31aSFinley Xiao sel = (con & CLK_GMAC_50M_SEL_MASK) >> CLK_GMAC_50M_SEL_SHIFT;
12759b43a31aSFinley Xiao if (sel == CLK_GMAC_50M)
12769b43a31aSFinley Xiao return 50000000;
12779b43a31aSFinley Xiao else
12789b43a31aSFinley Xiao return OSC_HZ;
12799b43a31aSFinley Xiao case CLK_MAC100_50M_MATRIX:
12809b43a31aSFinley Xiao con = readl(&cru->clksel_con[47]);
12819b43a31aSFinley Xiao sel = (con & CLK_GMAC_50M_SEL_MASK) >> CLK_GMAC_50M_SEL_SHIFT;
12829b43a31aSFinley Xiao if (sel == CLK_GMAC_50M)
12839b43a31aSFinley Xiao return 50000000;
12849b43a31aSFinley Xiao else
12859b43a31aSFinley Xiao return OSC_HZ;
12869b43a31aSFinley Xiao case CLK_GMAC_ETH_OUT2IO:
12879b43a31aSFinley Xiao con = readl(&cru->clksel_con[46]);
12889b43a31aSFinley Xiao sel = (con & CLK_GMAC_ETH_OUT2IO_SEL_MASK) >> CLK_GMAC_ETH_OUT2IO_SEL_SHIFT;
12899b43a31aSFinley Xiao div = (con & CLK_GMAC_ETH_OUT2IO_DIV_MASK) >> CLK_GMAC_ETH_OUT2IO_DIV_SHIFT;
12909b43a31aSFinley Xiao if (sel == CLK_GMAC_ETH_OUT2IO_GPLL)
12919b43a31aSFinley Xiao prate = priv->gpll_hz;
12929b43a31aSFinley Xiao else
12939b43a31aSFinley Xiao prate = priv->cpll_hz;
12949b43a31aSFinley Xiao break;
12959b43a31aSFinley Xiao default:
12969b43a31aSFinley Xiao return -ENOENT;
12979b43a31aSFinley Xiao }
12989b43a31aSFinley Xiao
12999b43a31aSFinley Xiao return DIV_TO_RATE(prate, div);
13009b43a31aSFinley Xiao }
13019b43a31aSFinley Xiao
rk3562_gmac_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)13029b43a31aSFinley Xiao static ulong rk3562_gmac_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
13039b43a31aSFinley Xiao ulong rate)
13049b43a31aSFinley Xiao {
13059b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
13069b43a31aSFinley Xiao u32 sel, div;
13079b43a31aSFinley Xiao
13089b43a31aSFinley Xiao switch (clk_id) {
13099b43a31aSFinley Xiao case CLK_GMAC_125M_CRU_I:
13109b43a31aSFinley Xiao if (rate == 125000000)
13119b43a31aSFinley Xiao sel = CLK_GMAC_125M;
13129b43a31aSFinley Xiao else
13139b43a31aSFinley Xiao sel = CLK_GMAC_24M;
13149b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[45], CLK_GMAC_125M_SEL_MASK,
13159b43a31aSFinley Xiao sel << CLK_GMAC_125M_SEL_SHIFT);
13169b43a31aSFinley Xiao break;
13179b43a31aSFinley Xiao case CLK_GMAC_50M_CRU_I:
13189b43a31aSFinley Xiao if (rate == 50000000)
13199b43a31aSFinley Xiao sel = CLK_GMAC_50M;
13209b43a31aSFinley Xiao else
13219b43a31aSFinley Xiao sel = CLK_GMAC_24M;
13229b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[45], CLK_GMAC_50M_SEL_MASK,
13239b43a31aSFinley Xiao sel << CLK_GMAC_50M_SEL_SHIFT);
13249b43a31aSFinley Xiao break;
13259b43a31aSFinley Xiao case CLK_MAC100_50M_MATRIX:
13269b43a31aSFinley Xiao if (rate == 50000000)
13279b43a31aSFinley Xiao sel = CLK_GMAC_50M;
13289b43a31aSFinley Xiao else
13299b43a31aSFinley Xiao sel = CLK_GMAC_24M;
13309b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[47], CLK_GMAC_50M_SEL_MASK,
13319b43a31aSFinley Xiao sel << CLK_GMAC_50M_SEL_SHIFT);
13329b43a31aSFinley Xiao break;
13339b43a31aSFinley Xiao case CLK_GMAC_ETH_OUT2IO:
13349b43a31aSFinley Xiao if ((priv->cpll_hz % rate) == 0) {
13359b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->cpll_hz, rate);
13369b43a31aSFinley Xiao sel = CLK_GMAC_ETH_OUT2IO_CPLL;
13379b43a31aSFinley Xiao } else {
13389b43a31aSFinley Xiao div = DIV_ROUND_UP(priv->gpll_hz, rate);
13399b43a31aSFinley Xiao sel = CLK_GMAC_ETH_OUT2IO_GPLL;
13409b43a31aSFinley Xiao }
13419b43a31aSFinley Xiao rk_clrsetreg(&cru->clksel_con[46],
13429b43a31aSFinley Xiao CLK_GMAC_ETH_OUT2IO_SEL_MASK | CLK_GMAC_ETH_OUT2IO_DIV_MASK,
13439b43a31aSFinley Xiao sel << CLK_GMAC_ETH_OUT2IO_SEL_SHIFT |
13449b43a31aSFinley Xiao (div - 1) << CLK_GMAC_ETH_OUT2IO_DIV_SHIFT);
13459b43a31aSFinley Xiao break;
13469b43a31aSFinley Xiao default:
13479b43a31aSFinley Xiao return -ENOENT;
13489b43a31aSFinley Xiao }
13499b43a31aSFinley Xiao
13509b43a31aSFinley Xiao return rk3562_gmac_get_rate(priv, clk_id);
13519b43a31aSFinley Xiao }
13529b43a31aSFinley Xiao
rk3562_clk_get_rate(struct clk * clk)13539b43a31aSFinley Xiao static ulong rk3562_clk_get_rate(struct clk *clk)
13549b43a31aSFinley Xiao {
13559b43a31aSFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
13569b43a31aSFinley Xiao ulong rate = 0;
13579b43a31aSFinley Xiao
13589b43a31aSFinley Xiao if (!priv->gpll_hz || !priv->cpll_hz || !priv->hpll_hz) {
13599b43a31aSFinley Xiao printf("%s: gpll=%lu, cpll=%lu, hpll=%lu\n",
13609b43a31aSFinley Xiao __func__, priv->gpll_hz, priv->cpll_hz, priv->hpll_hz);
13619b43a31aSFinley Xiao return -ENOENT;
13629b43a31aSFinley Xiao }
13639b43a31aSFinley Xiao
13649b43a31aSFinley Xiao switch (clk->id) {
13659b43a31aSFinley Xiao case PLL_APLL:
13669b43a31aSFinley Xiao case ARMCLK:
13679b43a31aSFinley Xiao rate = rockchip_pll_get_rate(&rk3562_pll_clks[APLL], priv->cru,
13689b43a31aSFinley Xiao APLL);
13699b43a31aSFinley Xiao break;
13709b43a31aSFinley Xiao case PLL_GPLL:
13719b43a31aSFinley Xiao rate = rockchip_pll_get_rate(&rk3562_pll_clks[GPLL], priv->cru,
13729b43a31aSFinley Xiao GPLL);
13739b43a31aSFinley Xiao break;
13749b43a31aSFinley Xiao
13759b43a31aSFinley Xiao case PLL_VPLL:
13769b43a31aSFinley Xiao rate = rockchip_pll_get_rate(&rk3562_pll_clks[VPLL], priv->cru,
13779b43a31aSFinley Xiao VPLL);
13789b43a31aSFinley Xiao break;
13799b43a31aSFinley Xiao case PLL_HPLL:
13809b43a31aSFinley Xiao rate = rockchip_pll_get_rate(&rk3562_pll_clks[HPLL], priv->cru,
13819b43a31aSFinley Xiao HPLL);
13829b43a31aSFinley Xiao break;
13839b43a31aSFinley Xiao case PLL_CPLL:
13849b43a31aSFinley Xiao rate = rockchip_pll_get_rate(&rk3562_pll_clks[CPLL], priv->cru,
13859b43a31aSFinley Xiao CPLL);
13869b43a31aSFinley Xiao break;
13879b43a31aSFinley Xiao case PLL_DPLL:
13889b43a31aSFinley Xiao rate = rockchip_pll_get_rate(&rk3562_pll_clks[DPLL], priv->cru,
13899b43a31aSFinley Xiao DPLL);
13909b43a31aSFinley Xiao break;
13919b43a31aSFinley Xiao case ACLK_BUS:
13929b43a31aSFinley Xiao case HCLK_BUS:
13939b43a31aSFinley Xiao case PCLK_BUS:
13949b43a31aSFinley Xiao rate = rk3562_bus_get_rate(priv, clk->id);
13959b43a31aSFinley Xiao break;
13969b43a31aSFinley Xiao case ACLK_PERI:
13979b43a31aSFinley Xiao case HCLK_PERI:
13989b43a31aSFinley Xiao case PCLK_PERI:
13999b43a31aSFinley Xiao rate = rk3562_peri_get_rate(priv, clk->id);
14009b43a31aSFinley Xiao break;
14019b43a31aSFinley Xiao case CLK_PMU0_I2C0:
14029b43a31aSFinley Xiao case CLK_I2C:
14039b43a31aSFinley Xiao case CLK_I2C1:
14049b43a31aSFinley Xiao case CLK_I2C2:
14059b43a31aSFinley Xiao case CLK_I2C3:
14069b43a31aSFinley Xiao case CLK_I2C4:
14079b43a31aSFinley Xiao case CLK_I2C5:
14089b43a31aSFinley Xiao rate = rk3562_i2c_get_rate(priv, clk->id);
14099b43a31aSFinley Xiao break;
14109b43a31aSFinley Xiao case SCLK_PMU1_UART0:
14119b43a31aSFinley Xiao case SCLK_UART1:
14129b43a31aSFinley Xiao case SCLK_UART2:
14139b43a31aSFinley Xiao case SCLK_UART3:
14149b43a31aSFinley Xiao case SCLK_UART4:
14159b43a31aSFinley Xiao case SCLK_UART5:
14169b43a31aSFinley Xiao case SCLK_UART6:
14179b43a31aSFinley Xiao case SCLK_UART7:
14189b43a31aSFinley Xiao case SCLK_UART8:
14199b43a31aSFinley Xiao case SCLK_UART9:
14209b43a31aSFinley Xiao rate = rk3562_uart_get_rate(priv, clk->id);
14219b43a31aSFinley Xiao break;
14229b43a31aSFinley Xiao case CLK_PMU1_PWM0:
14239b43a31aSFinley Xiao case CLK_PWM1_PERI:
14249b43a31aSFinley Xiao case CLK_PWM2_PERI:
14259b43a31aSFinley Xiao case CLK_PWM3_PERI:
14269b43a31aSFinley Xiao rate = rk3562_pwm_get_rate(priv, clk->id);
14279b43a31aSFinley Xiao break;
14289b43a31aSFinley Xiao case CLK_PMU1_SPI0:
14299b43a31aSFinley Xiao case CLK_SPI1:
14309b43a31aSFinley Xiao case CLK_SPI2:
14319b43a31aSFinley Xiao rate = rk3562_spi_get_rate(priv, clk->id);
14329b43a31aSFinley Xiao break;
14339b43a31aSFinley Xiao case CLK_TSADC:
14349b43a31aSFinley Xiao case CLK_TSADC_TSEN:
14359b43a31aSFinley Xiao rate = rk3562_tsadc_get_rate(priv, clk->id);
14369b43a31aSFinley Xiao break;
14379b43a31aSFinley Xiao case CLK_SARADC:
14389b43a31aSFinley Xiao case CLK_SARADC_VCCIO156:
14399b43a31aSFinley Xiao rate = rk3562_saradc_get_rate(priv, clk->id);
14409b43a31aSFinley Xiao break;
14419b43a31aSFinley Xiao case SCLK_SFC:
14429b43a31aSFinley Xiao rate = rk3562_sfc_get_rate(priv);
14439b43a31aSFinley Xiao break;
14449b43a31aSFinley Xiao case CCLK_EMMC:
14459b43a31aSFinley Xiao case BCLK_EMMC:
14469b43a31aSFinley Xiao rate = rk3562_emmc_get_rate(priv, clk->id);
14479b43a31aSFinley Xiao break;
14489b43a31aSFinley Xiao case HCLK_SDMMC0:
14499b43a31aSFinley Xiao case HCLK_SDMMC1:
14509b43a31aSFinley Xiao case CCLK_SDMMC0:
14519b43a31aSFinley Xiao case CCLK_SDMMC1:
14529b43a31aSFinley Xiao case SCLK_SDMMC0_SAMPLE:
14539b43a31aSFinley Xiao case SCLK_SDMMC1_SAMPLE:
14549b43a31aSFinley Xiao rate = rk3562_sdmmc_get_rate(priv, clk->id);
14559b43a31aSFinley Xiao break;
14569b43a31aSFinley Xiao case ACLK_VOP:
14579b43a31aSFinley Xiao case DCLK_VOP:
14589b43a31aSFinley Xiao case DCLK_VOP1:
14599b43a31aSFinley Xiao rate = rk3562_vop_get_rate(priv, clk->id);
14609b43a31aSFinley Xiao break;
14619b43a31aSFinley Xiao case CLK_GMAC_125M_CRU_I:
14629b43a31aSFinley Xiao case CLK_GMAC_50M_CRU_I:
14639b43a31aSFinley Xiao case CLK_GMAC_ETH_OUT2IO:
14649b43a31aSFinley Xiao case CLK_MAC100_50M_MATRIX:
14659b43a31aSFinley Xiao rate = rk3562_gmac_get_rate(priv, clk->id);
14669b43a31aSFinley Xiao break;
14675478db9bSFinley Xiao case CLK_WDTNS:
14685478db9bSFinley Xiao rate = OSC_HZ;
14695478db9bSFinley Xiao break;
14709b43a31aSFinley Xiao default:
14719b43a31aSFinley Xiao return -ENOENT;
14729b43a31aSFinley Xiao }
14739b43a31aSFinley Xiao
14749b43a31aSFinley Xiao return rate;
14759b43a31aSFinley Xiao };
14769b43a31aSFinley Xiao
rk3562_clk_set_rate(struct clk * clk,ulong rate)14779b43a31aSFinley Xiao static ulong rk3562_clk_set_rate(struct clk *clk, ulong rate)
14789b43a31aSFinley Xiao {
14799b43a31aSFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
14809b43a31aSFinley Xiao ulong ret = 0;
14819b43a31aSFinley Xiao
14829b43a31aSFinley Xiao if (!priv->gpll_hz || !priv->cpll_hz || !priv->hpll_hz) {
14839b43a31aSFinley Xiao printf("%s: gpll=%lu, cpll=%lu, hpll=%lu\n",
14849b43a31aSFinley Xiao __func__, priv->gpll_hz, priv->cpll_hz, priv->hpll_hz);
14859b43a31aSFinley Xiao return -ENOENT;
14869b43a31aSFinley Xiao }
14879b43a31aSFinley Xiao
14889b43a31aSFinley Xiao debug("%s: id=%ld, rate=%ld\n", __func__, clk->id, rate);
14899b43a31aSFinley Xiao
14909b43a31aSFinley Xiao switch (clk->id) {
14919b43a31aSFinley Xiao case PLL_APLL:
14929b43a31aSFinley Xiao case ARMCLK:
14939b43a31aSFinley Xiao if (priv->armclk_hz)
14949b43a31aSFinley Xiao rk3562_armclk_set_rate(priv, rate);
14959b43a31aSFinley Xiao priv->armclk_hz = rate;
14969b43a31aSFinley Xiao break;
14979b43a31aSFinley Xiao case PLL_GPLL:
14989b43a31aSFinley Xiao ret = rockchip_pll_set_rate(&rk3562_pll_clks[GPLL], priv->cru,
14999b43a31aSFinley Xiao GPLL, rate);
15009b43a31aSFinley Xiao priv->gpll_hz = rockchip_pll_get_rate(&rk3562_pll_clks[GPLL],
15019b43a31aSFinley Xiao priv->cru, GPLL);
15029b43a31aSFinley Xiao break;
15039b43a31aSFinley Xiao case PLL_VPLL:
15049b43a31aSFinley Xiao ret = rockchip_pll_set_rate(&rk3562_pll_clks[VPLL], priv->cru,
15059b43a31aSFinley Xiao VPLL, rate);
15069b43a31aSFinley Xiao priv->vpll_hz = rockchip_pll_get_rate(&rk3562_pll_clks[VPLL],
15079b43a31aSFinley Xiao priv->cru, VPLL);
15089b43a31aSFinley Xiao break;
15099b43a31aSFinley Xiao case PLL_HPLL:
15109b43a31aSFinley Xiao ret = rockchip_pll_set_rate(&rk3562_pll_clks[HPLL], priv->cru,
15119b43a31aSFinley Xiao HPLL, rate);
15129b43a31aSFinley Xiao priv->hpll_hz = rockchip_pll_get_rate(&rk3562_pll_clks[HPLL],
15139b43a31aSFinley Xiao priv->cru, HPLL);
15149b43a31aSFinley Xiao break;
15159b43a31aSFinley Xiao case ACLK_BUS:
15169b43a31aSFinley Xiao case HCLK_BUS:
15179b43a31aSFinley Xiao case PCLK_BUS:
15189b43a31aSFinley Xiao ret = rk3562_bus_set_rate(priv, clk->id, rate);
15199b43a31aSFinley Xiao break;
15209b43a31aSFinley Xiao case ACLK_PERI:
15219b43a31aSFinley Xiao case HCLK_PERI:
15229b43a31aSFinley Xiao case PCLK_PERI:
15239b43a31aSFinley Xiao ret = rk3562_peri_set_rate(priv, clk->id, rate);
15249b43a31aSFinley Xiao break;
15259b43a31aSFinley Xiao case CLK_PMU0_I2C0:
15269b43a31aSFinley Xiao case CLK_I2C:
15279b43a31aSFinley Xiao case CLK_I2C1:
15289b43a31aSFinley Xiao case CLK_I2C2:
15299b43a31aSFinley Xiao case CLK_I2C3:
15309b43a31aSFinley Xiao case CLK_I2C4:
15319b43a31aSFinley Xiao case CLK_I2C5:
15329b43a31aSFinley Xiao ret = rk3562_i2c_set_rate(priv, clk->id, rate);
15339b43a31aSFinley Xiao break;
15349b43a31aSFinley Xiao case SCLK_PMU1_UART0:
15359b43a31aSFinley Xiao case SCLK_UART1:
15369b43a31aSFinley Xiao case SCLK_UART2:
15379b43a31aSFinley Xiao case SCLK_UART3:
15389b43a31aSFinley Xiao case SCLK_UART4:
15399b43a31aSFinley Xiao case SCLK_UART5:
15409b43a31aSFinley Xiao case SCLK_UART6:
15419b43a31aSFinley Xiao case SCLK_UART7:
15429b43a31aSFinley Xiao case SCLK_UART8:
15439b43a31aSFinley Xiao case SCLK_UART9:
15449b43a31aSFinley Xiao ret = rk3562_uart_set_rate(priv, clk->id, rate);
15459b43a31aSFinley Xiao break;
15469b43a31aSFinley Xiao case CLK_PMU1_PWM0:
15479b43a31aSFinley Xiao case CLK_PWM1_PERI:
15489b43a31aSFinley Xiao case CLK_PWM2_PERI:
15499b43a31aSFinley Xiao case CLK_PWM3_PERI:
15509b43a31aSFinley Xiao ret = rk3562_pwm_set_rate(priv, clk->id, rate);
15519b43a31aSFinley Xiao break;
15529b43a31aSFinley Xiao case CLK_PMU1_SPI0:
15539b43a31aSFinley Xiao case CLK_SPI1:
15549b43a31aSFinley Xiao case CLK_SPI2:
15559b43a31aSFinley Xiao ret = rk3562_spi_set_rate(priv, clk->id, rate);
15569b43a31aSFinley Xiao break;
15579b43a31aSFinley Xiao case CLK_TSADC:
15589b43a31aSFinley Xiao case CLK_TSADC_TSEN:
15599b43a31aSFinley Xiao ret = rk3562_tsadc_set_rate(priv, clk->id, rate);
15609b43a31aSFinley Xiao break;
15619b43a31aSFinley Xiao case CLK_SARADC:
15629b43a31aSFinley Xiao case CLK_SARADC_VCCIO156:
15639b43a31aSFinley Xiao ret = rk3562_saradc_set_rate(priv, clk->id, rate);
15649b43a31aSFinley Xiao break;
15659b43a31aSFinley Xiao case SCLK_SFC:
15669b43a31aSFinley Xiao ret = rk3562_sfc_set_rate(priv, rate);
15679b43a31aSFinley Xiao break;
15689b43a31aSFinley Xiao case CCLK_EMMC:
15699b43a31aSFinley Xiao case BCLK_EMMC:
15709b43a31aSFinley Xiao ret = rk3562_emmc_set_rate(priv, clk->id, rate);
15719b43a31aSFinley Xiao break;
15729b43a31aSFinley Xiao case HCLK_SDMMC0:
15739b43a31aSFinley Xiao case HCLK_SDMMC1:
15749b43a31aSFinley Xiao case CCLK_SDMMC0:
15759b43a31aSFinley Xiao case CCLK_SDMMC1:
15769b43a31aSFinley Xiao ret = rk3562_sdmmc_set_rate(priv, clk->id, rate);
15779b43a31aSFinley Xiao break;
15789b43a31aSFinley Xiao case ACLK_VOP:
15799b43a31aSFinley Xiao case DCLK_VOP:
15809b43a31aSFinley Xiao case DCLK_VOP1:
15819b43a31aSFinley Xiao ret = rk3562_vop_set_rate(priv, clk->id, rate);
15829b43a31aSFinley Xiao break;
15839b43a31aSFinley Xiao case CLK_GMAC_125M_CRU_I:
15849b43a31aSFinley Xiao case CLK_GMAC_50M_CRU_I:
15859b43a31aSFinley Xiao case CLK_GMAC_ETH_OUT2IO:
15869b43a31aSFinley Xiao case CLK_MAC100_50M_MATRIX:
15879b43a31aSFinley Xiao ret = rk3562_gmac_set_rate(priv, clk->id, rate);
15889b43a31aSFinley Xiao break;
15899b43a31aSFinley Xiao default:
15909b43a31aSFinley Xiao return -ENOENT;
15919b43a31aSFinley Xiao }
15929b43a31aSFinley Xiao
15939b43a31aSFinley Xiao return ret;
15949b43a31aSFinley Xiao };
15959b43a31aSFinley Xiao
15969b43a31aSFinley Xiao #define ROCKCHIP_MMC_DELAY_SEL BIT(11)
15979b43a31aSFinley Xiao #define ROCKCHIP_MMC_DEGREE_SHIFT 1
15989b43a31aSFinley Xiao #define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_SHIFT)
15999b43a31aSFinley Xiao #define ROCKCHIP_MMC_DELAYNUM_SHIFT 3
16009b43a31aSFinley Xiao #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_SHIFT)
16019b43a31aSFinley Xiao #define PSECS_PER_SEC 1000000000000LL
16029b43a31aSFinley Xiao
16039b43a31aSFinley Xiao /*
16049b43a31aSFinley Xiao * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
16059b43a31aSFinley Xiao * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
16069b43a31aSFinley Xiao */
16079b43a31aSFinley Xiao #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
16089b43a31aSFinley Xiao
rk3562_mmc_get_phase(struct clk * clk)16099b43a31aSFinley Xiao int rk3562_mmc_get_phase(struct clk *clk)
16109b43a31aSFinley Xiao {
16119b43a31aSFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
16129b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
16139b43a31aSFinley Xiao u32 raw_value, delay_num;
16149b43a31aSFinley Xiao u16 degrees = 0;
16159b43a31aSFinley Xiao ulong rate;
16169b43a31aSFinley Xiao
16179b43a31aSFinley Xiao rate = rk3562_clk_get_rate(clk);
16189b43a31aSFinley Xiao if (rate < 0)
16199b43a31aSFinley Xiao return rate;
16209b43a31aSFinley Xiao
16219b43a31aSFinley Xiao if (clk->id == SCLK_SDMMC0_SAMPLE)
16229b43a31aSFinley Xiao raw_value = readl(&cru->sdmmc0_con[1]);
16239b43a31aSFinley Xiao else if (clk->id == SCLK_SDMMC0_SAMPLE)
16249b43a31aSFinley Xiao raw_value = readl(&cru->sdmmc1_con[1]);
16259b43a31aSFinley Xiao else
16269b43a31aSFinley Xiao return -ENONET;
16279b43a31aSFinley Xiao
16289b43a31aSFinley Xiao raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
16299b43a31aSFinley Xiao degrees = (raw_value >> ROCKCHIP_MMC_DEGREE_SHIFT) * 90;
16309b43a31aSFinley Xiao
16319b43a31aSFinley Xiao if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
16329b43a31aSFinley Xiao /* degrees/delaynum * 10000 */
16339b43a31aSFinley Xiao unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
16349b43a31aSFinley Xiao 36 * (rate / 1000000);
16359b43a31aSFinley Xiao
16369b43a31aSFinley Xiao delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
16379b43a31aSFinley Xiao delay_num >>= ROCKCHIP_MMC_DELAYNUM_SHIFT;
16389b43a31aSFinley Xiao degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
16399b43a31aSFinley Xiao }
16409b43a31aSFinley Xiao
16419b43a31aSFinley Xiao return degrees % 360;
16429b43a31aSFinley Xiao }
16439b43a31aSFinley Xiao
rk3562_mmc_set_phase(struct clk * clk,u32 degrees)16449b43a31aSFinley Xiao int rk3562_mmc_set_phase(struct clk *clk, u32 degrees)
16459b43a31aSFinley Xiao {
16469b43a31aSFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
16479b43a31aSFinley Xiao struct rk3562_cru *cru = priv->cru;
16489b43a31aSFinley Xiao u8 nineties, remainder, delay_num;
16499b43a31aSFinley Xiao u32 raw_value, delay;
16509b43a31aSFinley Xiao ulong rate;
16519b43a31aSFinley Xiao
16529b43a31aSFinley Xiao rate = rk3562_clk_get_rate(clk);
16539b43a31aSFinley Xiao if (rate < 0)
16549b43a31aSFinley Xiao return rate;
16559b43a31aSFinley Xiao
16569b43a31aSFinley Xiao nineties = degrees / 90;
16579b43a31aSFinley Xiao remainder = (degrees % 90);
16589b43a31aSFinley Xiao
16599b43a31aSFinley Xiao /*
16609b43a31aSFinley Xiao * Convert to delay; do a little extra work to make sure we
16619b43a31aSFinley Xiao * don't overflow 32-bit / 64-bit numbers.
16629b43a31aSFinley Xiao */
16639b43a31aSFinley Xiao delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
16649b43a31aSFinley Xiao delay *= remainder;
16659b43a31aSFinley Xiao delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
16669b43a31aSFinley Xiao (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
16679b43a31aSFinley Xiao
16689b43a31aSFinley Xiao delay_num = (u8)min_t(u32, delay, 255);
16699b43a31aSFinley Xiao
16709b43a31aSFinley Xiao raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
16719b43a31aSFinley Xiao raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_SHIFT;
16729b43a31aSFinley Xiao raw_value |= nineties << ROCKCHIP_MMC_DEGREE_SHIFT;
16739b43a31aSFinley Xiao
16749b43a31aSFinley Xiao if (clk->id == SCLK_SDMMC0_SAMPLE)
16759b43a31aSFinley Xiao writel(raw_value | 0xffff0000, &cru->sdmmc0_con[1]);
16769b43a31aSFinley Xiao else
16779b43a31aSFinley Xiao writel(raw_value | 0xffff0000, &cru->sdmmc1_con[1]);
16789b43a31aSFinley Xiao
16799b43a31aSFinley Xiao debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
16809b43a31aSFinley Xiao degrees, delay_num, raw_value, rk3562_mmc_get_phase(clk));
16819b43a31aSFinley Xiao
16829b43a31aSFinley Xiao return 0;
16839b43a31aSFinley Xiao }
16849b43a31aSFinley Xiao
rk3562_clk_get_phase(struct clk * clk)16859b43a31aSFinley Xiao static int rk3562_clk_get_phase(struct clk *clk)
16869b43a31aSFinley Xiao {
16879b43a31aSFinley Xiao int ret;
16889b43a31aSFinley Xiao
16899b43a31aSFinley Xiao switch (clk->id) {
16909b43a31aSFinley Xiao case SCLK_SDMMC0_SAMPLE:
16919b43a31aSFinley Xiao case SCLK_SDMMC1_SAMPLE:
16929b43a31aSFinley Xiao ret = rk3562_mmc_get_phase(clk);
16939b43a31aSFinley Xiao break;
16949b43a31aSFinley Xiao default:
16959b43a31aSFinley Xiao return -ENOENT;
16969b43a31aSFinley Xiao }
16979b43a31aSFinley Xiao
16989b43a31aSFinley Xiao return ret;
16999b43a31aSFinley Xiao }
17009b43a31aSFinley Xiao
rk3562_clk_set_phase(struct clk * clk,int degrees)17019b43a31aSFinley Xiao static int rk3562_clk_set_phase(struct clk *clk, int degrees)
17029b43a31aSFinley Xiao {
17039b43a31aSFinley Xiao int ret;
17049b43a31aSFinley Xiao
17059b43a31aSFinley Xiao switch (clk->id) {
17069b43a31aSFinley Xiao case SCLK_SDMMC0_SAMPLE:
17079b43a31aSFinley Xiao case SCLK_SDMMC1_SAMPLE:
17089b43a31aSFinley Xiao ret = rk3562_mmc_set_phase(clk, degrees);
17099b43a31aSFinley Xiao break;
17109b43a31aSFinley Xiao default:
17119b43a31aSFinley Xiao return -ENOENT;
17129b43a31aSFinley Xiao }
17139b43a31aSFinley Xiao
17149b43a31aSFinley Xiao return ret;
17159b43a31aSFinley Xiao }
17169b43a31aSFinley Xiao
17179b43a31aSFinley Xiao static struct clk_ops rk3562_clk_ops = {
17189b43a31aSFinley Xiao .get_rate = rk3562_clk_get_rate,
17199b43a31aSFinley Xiao .set_rate = rk3562_clk_set_rate,
17209b43a31aSFinley Xiao .get_phase = rk3562_clk_get_phase,
17219b43a31aSFinley Xiao .set_phase = rk3562_clk_set_phase,
17229b43a31aSFinley Xiao };
17239b43a31aSFinley Xiao
17249b43a31aSFinley Xiao #ifndef CONFIG_SPL_BUILD
17259b43a31aSFinley Xiao /**
17269b43a31aSFinley Xiao * soc_clk_dump() - Print clock frequencies
17279b43a31aSFinley Xiao * Returns zero on success
17289b43a31aSFinley Xiao *
17299b43a31aSFinley Xiao * Implementation for the clk dump command.
17309b43a31aSFinley Xiao */
soc_clk_dump(void)17319b43a31aSFinley Xiao int soc_clk_dump(void)
17329b43a31aSFinley Xiao {
17339b43a31aSFinley Xiao const struct rk3562_clk_info *clk_dump;
17349b43a31aSFinley Xiao struct rk3562_clk_priv *priv;
17359b43a31aSFinley Xiao struct udevice *cru_dev;
17369b43a31aSFinley Xiao struct clk clk;
17379b43a31aSFinley Xiao ulong clk_count = ARRAY_SIZE(clks_dump);
17389b43a31aSFinley Xiao ulong rate;
17399b43a31aSFinley Xiao int i, ret;
17409b43a31aSFinley Xiao
17419b43a31aSFinley Xiao ret = uclass_get_device_by_driver(UCLASS_CLK,
17429b43a31aSFinley Xiao DM_GET_DRIVER(rockchip_rk3562_cru),
17439b43a31aSFinley Xiao &cru_dev);
17449b43a31aSFinley Xiao if (ret) {
17459b43a31aSFinley Xiao printf("%s failed to get cru device\n", __func__);
17469b43a31aSFinley Xiao return ret;
17479b43a31aSFinley Xiao }
17489b43a31aSFinley Xiao
17499b43a31aSFinley Xiao priv = dev_get_priv(cru_dev);
17509b43a31aSFinley Xiao printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
17519b43a31aSFinley Xiao priv->sync_kernel ? "sync kernel" : "uboot",
17529b43a31aSFinley Xiao priv->armclk_enter_hz / 1000,
17539b43a31aSFinley Xiao priv->armclk_init_hz / 1000,
17549b43a31aSFinley Xiao priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
17559b43a31aSFinley Xiao priv->set_armclk_rate ? " KHz" : "N/A");
17569b43a31aSFinley Xiao for (i = 0; i < clk_count; i++) {
17579b43a31aSFinley Xiao clk_dump = &clks_dump[i];
17589b43a31aSFinley Xiao if (clk_dump->name) {
17599b43a31aSFinley Xiao clk.id = clk_dump->id;
17609b43a31aSFinley Xiao ret = clk_request(cru_dev, &clk);
17619b43a31aSFinley Xiao if (ret < 0)
17629b43a31aSFinley Xiao return ret;
17639b43a31aSFinley Xiao
17649b43a31aSFinley Xiao rate = clk_get_rate(&clk);
17659b43a31aSFinley Xiao clk_free(&clk);
17669b43a31aSFinley Xiao if (i == 0) {
17679b43a31aSFinley Xiao if (rate < 0)
17689b43a31aSFinley Xiao printf(" %s %s\n", clk_dump->name,
17699b43a31aSFinley Xiao "unknown");
17709b43a31aSFinley Xiao else
17719b43a31aSFinley Xiao printf(" %s %lu KHz\n", clk_dump->name,
17729b43a31aSFinley Xiao rate / 1000);
17739b43a31aSFinley Xiao } else {
17749b43a31aSFinley Xiao if (rate < 0)
17759b43a31aSFinley Xiao printf(" %s %s\n", clk_dump->name,
17769b43a31aSFinley Xiao "unknown");
17779b43a31aSFinley Xiao else
17789b43a31aSFinley Xiao printf(" %s %lu KHz\n", clk_dump->name,
17799b43a31aSFinley Xiao rate / 1000);
17809b43a31aSFinley Xiao }
17819b43a31aSFinley Xiao }
17829b43a31aSFinley Xiao }
17839b43a31aSFinley Xiao
17849b43a31aSFinley Xiao return 0;
17859b43a31aSFinley Xiao }
17869b43a31aSFinley Xiao #endif
17879b43a31aSFinley Xiao
rk3562_clk_init(struct rk3562_clk_priv * priv)17889b43a31aSFinley Xiao static void rk3562_clk_init(struct rk3562_clk_priv *priv)
17899b43a31aSFinley Xiao {
17909b43a31aSFinley Xiao int ret;
17919b43a31aSFinley Xiao
17929b43a31aSFinley Xiao priv->sync_kernel = false;
17939b43a31aSFinley Xiao if (!priv->armclk_enter_hz)
17949b43a31aSFinley Xiao priv->armclk_enter_hz =
17959b43a31aSFinley Xiao rockchip_pll_get_rate(&rk3562_pll_clks[APLL],
17969b43a31aSFinley Xiao priv->cru, APLL);
17979b43a31aSFinley Xiao
17989b43a31aSFinley Xiao if (!priv->armclk_init_hz) {
1799ffe7a059SYifeng Zhao #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_SUPPORT_USBPLUG)
18009b43a31aSFinley Xiao ret = rk3562_armclk_set_rate(priv, APLL_HZ);
18019b43a31aSFinley Xiao if (!ret)
18029b43a31aSFinley Xiao priv->armclk_init_hz = APLL_HZ;
18039b43a31aSFinley Xiao
18049b43a31aSFinley Xiao #else
18059b43a31aSFinley Xiao struct clk clk;
18069b43a31aSFinley Xiao
18079b43a31aSFinley Xiao ret = rockchip_get_scmi_clk(&clk.dev);
18089b43a31aSFinley Xiao if (ret) {
18099b43a31aSFinley Xiao printf("Failed to get scmi clk dev\n");
18109b43a31aSFinley Xiao return;
18119b43a31aSFinley Xiao }
18129b43a31aSFinley Xiao
18139b43a31aSFinley Xiao clk.id = ARMCLK;
18149b43a31aSFinley Xiao ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
18159b43a31aSFinley Xiao if (ret < 0) {
18169b43a31aSFinley Xiao printf("Failed to set scmi cpu %dhz\n", CPU_PVTPLL_HZ);
18179b43a31aSFinley Xiao return;
18189b43a31aSFinley Xiao } else {
18199b43a31aSFinley Xiao priv->armclk_init_hz = CPU_PVTPLL_HZ;
18209b43a31aSFinley Xiao }
18219b43a31aSFinley Xiao #endif
18229b43a31aSFinley Xiao }
18239b43a31aSFinley Xiao if (priv->cpll_hz != CPLL_HZ) {
18249b43a31aSFinley Xiao ret = rockchip_pll_set_rate(&rk3562_pll_clks[CPLL], priv->cru,
18259b43a31aSFinley Xiao CPLL, CPLL_HZ);
18269b43a31aSFinley Xiao if (!ret)
18279b43a31aSFinley Xiao priv->cpll_hz = CPLL_HZ;
18289b43a31aSFinley Xiao }
18299b43a31aSFinley Xiao
18309b43a31aSFinley Xiao if (priv->gpll_hz != GPLL_HZ) {
18319b43a31aSFinley Xiao ret = rockchip_pll_set_rate(&rk3562_pll_clks[GPLL], priv->cru,
18329b43a31aSFinley Xiao GPLL, GPLL_HZ);
18339b43a31aSFinley Xiao if (!ret)
18349b43a31aSFinley Xiao priv->gpll_hz = GPLL_HZ;
18359b43a31aSFinley Xiao }
18369b43a31aSFinley Xiao
18379b43a31aSFinley Xiao if (priv->hpll_hz != HPLL_HZ) {
18389b43a31aSFinley Xiao ret = rockchip_pll_set_rate(&rk3562_pll_clks[HPLL], priv->cru,
18399b43a31aSFinley Xiao HPLL, HPLL_HZ);
18409b43a31aSFinley Xiao if (!ret)
18419b43a31aSFinley Xiao priv->hpll_hz = HPLL_HZ;
18429b43a31aSFinley Xiao }
18439b43a31aSFinley Xiao }
18449b43a31aSFinley Xiao
rk3562_clk_probe(struct udevice * dev)18459b43a31aSFinley Xiao static int rk3562_clk_probe(struct udevice *dev)
18469b43a31aSFinley Xiao {
18479b43a31aSFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(dev);
18489b43a31aSFinley Xiao int ret;
18499b43a31aSFinley Xiao
18509b43a31aSFinley Xiao rk3562_clk_init(priv);
18519b43a31aSFinley Xiao
18529b43a31aSFinley Xiao /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
18539b43a31aSFinley Xiao ret = clk_set_defaults(dev);
18549b43a31aSFinley Xiao if (ret)
18559b43a31aSFinley Xiao debug("%s clk_set_defaults failed %d\n", __func__, ret);
18569b43a31aSFinley Xiao else
18579b43a31aSFinley Xiao priv->sync_kernel = true;
18589b43a31aSFinley Xiao
18599b43a31aSFinley Xiao return 0;
18609b43a31aSFinley Xiao }
18619b43a31aSFinley Xiao
rk3562_clk_ofdata_to_platdata(struct udevice * dev)18629b43a31aSFinley Xiao static int rk3562_clk_ofdata_to_platdata(struct udevice *dev)
18639b43a31aSFinley Xiao {
18649b43a31aSFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(dev);
18659b43a31aSFinley Xiao
18669b43a31aSFinley Xiao priv->cru = dev_read_addr_ptr(dev);
18679b43a31aSFinley Xiao
18689b43a31aSFinley Xiao return 0;
18699b43a31aSFinley Xiao }
18709b43a31aSFinley Xiao
rk3562_clk_bind(struct udevice * dev)18719b43a31aSFinley Xiao static int rk3562_clk_bind(struct udevice *dev)
18729b43a31aSFinley Xiao {
18739b43a31aSFinley Xiao struct udevice *sys_child, *sf_child;
18749b43a31aSFinley Xiao struct softreset_reg *sf_priv;
18759b43a31aSFinley Xiao struct sysreset_reg *priv;
18769b43a31aSFinley Xiao int ret;
18779b43a31aSFinley Xiao
18789b43a31aSFinley Xiao /* The reset driver does not have a device node, so bind it here */
18799b43a31aSFinley Xiao ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
18809b43a31aSFinley Xiao &sys_child);
18819b43a31aSFinley Xiao if (ret) {
18829b43a31aSFinley Xiao debug("Warning: No sysreset driver: ret=%d\n", ret);
18839b43a31aSFinley Xiao } else {
18849b43a31aSFinley Xiao priv = malloc(sizeof(struct sysreset_reg));
18859b43a31aSFinley Xiao priv->glb_srst_fst_value = offsetof(struct rk3562_cru,
18869b43a31aSFinley Xiao glb_srst_fst);
18879b43a31aSFinley Xiao priv->glb_srst_snd_value = offsetof(struct rk3562_cru,
18889b43a31aSFinley Xiao glb_srst_snd);
18899b43a31aSFinley Xiao sys_child->priv = priv;
18909b43a31aSFinley Xiao }
18919b43a31aSFinley Xiao
18929b43a31aSFinley Xiao ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
18939b43a31aSFinley Xiao dev_ofnode(dev), &sf_child);
18949b43a31aSFinley Xiao if (ret) {
18959b43a31aSFinley Xiao debug("Warning: No rockchip reset driver: ret=%d\n", ret);
18969b43a31aSFinley Xiao } else {
18979b43a31aSFinley Xiao sf_priv = malloc(sizeof(struct softreset_reg));
18989b43a31aSFinley Xiao sf_priv->sf_reset_offset = offsetof(struct rk3562_cru,
18999b43a31aSFinley Xiao softrst_con[0]);
19009b43a31aSFinley Xiao /* (0x30444 - 0x400) / 4 + 1 = 49170 */
19019b43a31aSFinley Xiao sf_priv->sf_reset_num = 49170;
19029b43a31aSFinley Xiao sf_child->priv = sf_priv;
19039b43a31aSFinley Xiao }
19049b43a31aSFinley Xiao
19059b43a31aSFinley Xiao return 0;
19069b43a31aSFinley Xiao }
19079b43a31aSFinley Xiao
19089b43a31aSFinley Xiao static const struct udevice_id rk3562_clk_ids[] = {
19099b43a31aSFinley Xiao { .compatible = "rockchip,rk3562-cru" },
19109b43a31aSFinley Xiao { }
19119b43a31aSFinley Xiao };
19129b43a31aSFinley Xiao
19139b43a31aSFinley Xiao U_BOOT_DRIVER(rockchip_rk3562_cru) = {
19149b43a31aSFinley Xiao .name = "rockchip_rk3562_cru",
19159b43a31aSFinley Xiao .id = UCLASS_CLK,
19169b43a31aSFinley Xiao .of_match = rk3562_clk_ids,
19179b43a31aSFinley Xiao .priv_auto_alloc_size = sizeof(struct rk3562_clk_priv),
19189b43a31aSFinley Xiao .ofdata_to_platdata = rk3562_clk_ofdata_to_platdata,
19199b43a31aSFinley Xiao .ops = &rk3562_clk_ops,
19209b43a31aSFinley Xiao .bind = rk3562_clk_bind,
19219b43a31aSFinley Xiao .probe = rk3562_clk_probe,
19229b43a31aSFinley Xiao };
1923bcf6e1a4SFinley Xiao
1924bcf6e1a4SFinley Xiao /* spl scmi clk */
1925bcf6e1a4SFinley Xiao #ifdef CONFIG_SPL_BUILD
1926bcf6e1a4SFinley Xiao
rk3562_crypto_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)1927bcf6e1a4SFinley Xiao static ulong rk3562_crypto_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
1928bcf6e1a4SFinley Xiao {
1929bcf6e1a4SFinley Xiao struct rk3562_cru *cru = priv->cru;
1930bcf6e1a4SFinley Xiao u32 sel, con;
1931bcf6e1a4SFinley Xiao ulong rate;
1932bcf6e1a4SFinley Xiao
1933bcf6e1a4SFinley Xiao con = readl(&cru->periclksel_con[43]);
1934bcf6e1a4SFinley Xiao switch (clk_id) {
1935bcf6e1a4SFinley Xiao case CLK_CORE_CRYPTO:
1936bcf6e1a4SFinley Xiao sel = (con & CLK_CORE_CRYPTO_SEL_MASK) >>
1937bcf6e1a4SFinley Xiao CLK_CORE_CRYPTO_SEL_SHIFT;
1938bcf6e1a4SFinley Xiao if (sel == CLK_CORE_CRYPTO_SEL_200M)
1939bcf6e1a4SFinley Xiao rate = 200 * MHz;
1940bcf6e1a4SFinley Xiao else if (sel == CLK_CORE_CRYPTO_SEL_100M)
1941bcf6e1a4SFinley Xiao rate = 100 * MHz;
1942bcf6e1a4SFinley Xiao else
1943bcf6e1a4SFinley Xiao rate = OSC_HZ;
1944bcf6e1a4SFinley Xiao break;
1945bcf6e1a4SFinley Xiao case CLK_PKA_CRYPTO:
1946bcf6e1a4SFinley Xiao sel = (con & CLK_PKA_CRYPTO_SEL_MASK) >>
1947bcf6e1a4SFinley Xiao CLK_PKA_CRYPTO_SEL_SHIFT;
1948bcf6e1a4SFinley Xiao if (sel == CLK_PKA_CRYPTO_SEL_300M)
1949bcf6e1a4SFinley Xiao rate = 300 * MHz;
1950bcf6e1a4SFinley Xiao else if (sel == CLK_PKA_CRYPTO_SEL_200M)
1951bcf6e1a4SFinley Xiao rate = 200 * MHz;
1952bcf6e1a4SFinley Xiao else if (sel == CLK_PKA_CRYPTO_SEL_100M)
1953bcf6e1a4SFinley Xiao rate = 100 * MHz;
1954bcf6e1a4SFinley Xiao else
1955bcf6e1a4SFinley Xiao rate = OSC_HZ;
1956bcf6e1a4SFinley Xiao break;
1957bcf6e1a4SFinley Xiao default:
1958bcf6e1a4SFinley Xiao return -ENOENT;
1959bcf6e1a4SFinley Xiao }
1960bcf6e1a4SFinley Xiao
1961bcf6e1a4SFinley Xiao return rate;
1962bcf6e1a4SFinley Xiao }
1963bcf6e1a4SFinley Xiao
rk3562_crypto_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)1964bcf6e1a4SFinley Xiao static ulong rk3562_crypto_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
1965bcf6e1a4SFinley Xiao ulong rate)
1966bcf6e1a4SFinley Xiao {
1967bcf6e1a4SFinley Xiao struct rk3562_cru *cru = priv->cru;
1968bcf6e1a4SFinley Xiao u32 mask, shift, sel;
1969bcf6e1a4SFinley Xiao
1970bcf6e1a4SFinley Xiao switch (clk_id) {
1971bcf6e1a4SFinley Xiao case CLK_CORE_CRYPTO:
1972bcf6e1a4SFinley Xiao mask = CLK_CORE_CRYPTO_SEL_MASK;
1973bcf6e1a4SFinley Xiao shift = CLK_CORE_CRYPTO_SEL_SHIFT;
1974bcf6e1a4SFinley Xiao if (rate == 200 * MHz)
1975bcf6e1a4SFinley Xiao sel = CLK_CORE_CRYPTO_SEL_200M;
1976bcf6e1a4SFinley Xiao else if (rate == 100 * MHz)
1977bcf6e1a4SFinley Xiao sel = CLK_CORE_CRYPTO_SEL_100M;
1978bcf6e1a4SFinley Xiao else
1979bcf6e1a4SFinley Xiao sel = CLK_CORE_CRYPTO_SEL_24M;
1980bcf6e1a4SFinley Xiao break;
1981bcf6e1a4SFinley Xiao case CLK_PKA_CRYPTO:
1982bcf6e1a4SFinley Xiao mask = CLK_PKA_CRYPTO_SEL_MASK;
1983bcf6e1a4SFinley Xiao shift = CLK_PKA_CRYPTO_SEL_SHIFT;
1984bcf6e1a4SFinley Xiao if (rate == 300 * MHz)
1985bcf6e1a4SFinley Xiao sel = CLK_PKA_CRYPTO_SEL_300M;
1986bcf6e1a4SFinley Xiao else if (rate == 200 * MHz)
1987bcf6e1a4SFinley Xiao sel = CLK_PKA_CRYPTO_SEL_200M;
1988bcf6e1a4SFinley Xiao else if (rate == 100 * MHz)
1989bcf6e1a4SFinley Xiao sel = CLK_PKA_CRYPTO_SEL_100M;
1990bcf6e1a4SFinley Xiao else
1991bcf6e1a4SFinley Xiao sel = CLK_PKA_CRYPTO_SEL_24M;
1992bcf6e1a4SFinley Xiao break;
1993bcf6e1a4SFinley Xiao default:
1994bcf6e1a4SFinley Xiao return -ENOENT;
1995bcf6e1a4SFinley Xiao }
1996bcf6e1a4SFinley Xiao rk_clrsetreg(&cru->periclksel_con[43], mask, sel << shift);
1997bcf6e1a4SFinley Xiao
1998bcf6e1a4SFinley Xiao return rk3562_crypto_get_rate(priv, clk_id);
1999bcf6e1a4SFinley Xiao }
2000bcf6e1a4SFinley Xiao
rk3562_clk_scmi_get_rate(struct clk * clk)2001bcf6e1a4SFinley Xiao static ulong rk3562_clk_scmi_get_rate(struct clk *clk)
2002bcf6e1a4SFinley Xiao {
2003bcf6e1a4SFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
2004bcf6e1a4SFinley Xiao
2005bcf6e1a4SFinley Xiao switch (clk->id) {
2006bcf6e1a4SFinley Xiao case CLK_CORE_CRYPTO:
2007bcf6e1a4SFinley Xiao case CLK_PKA_CRYPTO:
2008bcf6e1a4SFinley Xiao return rk3562_crypto_get_rate(priv, clk->id);
2009bcf6e1a4SFinley Xiao default:
2010bcf6e1a4SFinley Xiao return -ENOENT;
2011bcf6e1a4SFinley Xiao }
2012bcf6e1a4SFinley Xiao };
2013bcf6e1a4SFinley Xiao
rk3562_clk_scmi_set_rate(struct clk * clk,ulong rate)2014bcf6e1a4SFinley Xiao static ulong rk3562_clk_scmi_set_rate(struct clk *clk, ulong rate)
2015bcf6e1a4SFinley Xiao {
2016bcf6e1a4SFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
2017bcf6e1a4SFinley Xiao
2018bcf6e1a4SFinley Xiao switch (clk->id) {
2019bcf6e1a4SFinley Xiao case CLK_CORE_CRYPTO:
2020bcf6e1a4SFinley Xiao case CLK_PKA_CRYPTO:
2021bcf6e1a4SFinley Xiao return rk3562_crypto_set_rate(priv, clk->id, rate);
2022bcf6e1a4SFinley Xiao default:
2023bcf6e1a4SFinley Xiao return -ENOENT;
2024bcf6e1a4SFinley Xiao }
2025bcf6e1a4SFinley Xiao return 0;
2026bcf6e1a4SFinley Xiao };
2027bcf6e1a4SFinley Xiao
rk3562_scmi_clk_ofdata_to_platdata(struct udevice * dev)2028bcf6e1a4SFinley Xiao static int rk3562_scmi_clk_ofdata_to_platdata(struct udevice *dev)
2029bcf6e1a4SFinley Xiao {
2030bcf6e1a4SFinley Xiao struct rk3562_clk_priv *priv = dev_get_priv(dev);
2031bcf6e1a4SFinley Xiao
2032bcf6e1a4SFinley Xiao priv->cru = (struct rk3562_cru *)0xff100000;
2033bcf6e1a4SFinley Xiao
2034bcf6e1a4SFinley Xiao return 0;
2035bcf6e1a4SFinley Xiao }
2036bcf6e1a4SFinley Xiao
2037bcf6e1a4SFinley Xiao /* A fake scmi driver for SPL/TPL where smccc agent is not available. */
2038bcf6e1a4SFinley Xiao static const struct clk_ops scmi_clk_ops = {
2039bcf6e1a4SFinley Xiao .get_rate = rk3562_clk_scmi_get_rate,
2040bcf6e1a4SFinley Xiao .set_rate = rk3562_clk_scmi_set_rate,
2041bcf6e1a4SFinley Xiao };
2042bcf6e1a4SFinley Xiao
2043bcf6e1a4SFinley Xiao U_BOOT_DRIVER(scmi_clock) = {
2044bcf6e1a4SFinley Xiao .name = "scmi_clk",
2045bcf6e1a4SFinley Xiao .id = UCLASS_CLK,
2046bcf6e1a4SFinley Xiao .ops = &scmi_clk_ops,
2047bcf6e1a4SFinley Xiao .priv_auto_alloc_size = sizeof(struct rk3562_clk_priv),
2048bcf6e1a4SFinley Xiao .ofdata_to_platdata = rk3562_scmi_clk_ofdata_to_platdata,
2049bcf6e1a4SFinley Xiao };
2050bcf6e1a4SFinley Xiao #endif
2051