10265e00cSElaine Zhang // SPDX-License-Identifier: GPL-2.0
20265e00cSElaine Zhang /*
30265e00cSElaine Zhang * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
40265e00cSElaine Zhang * Author: Elaine Zhang <zhangqing@rock-chips.com>
50265e00cSElaine Zhang */
60265e00cSElaine Zhang
70265e00cSElaine Zhang #include <common.h>
80265e00cSElaine Zhang #include <bitfield.h>
90265e00cSElaine Zhang #include <clk-uclass.h>
100265e00cSElaine Zhang #include <dm.h>
110265e00cSElaine Zhang #include <errno.h>
120265e00cSElaine Zhang #include <syscon.h>
130265e00cSElaine Zhang #include <asm/arch/clock.h>
140265e00cSElaine Zhang #include <asm/arch/cru_rk3576.h>
150265e00cSElaine Zhang #include <asm/arch/hardware.h>
160265e00cSElaine Zhang #include <asm/io.h>
170265e00cSElaine Zhang #include <dm/lists.h>
180265e00cSElaine Zhang #include <dt-bindings/clock/rockchip,rk3576-cru.h>
190265e00cSElaine Zhang
200265e00cSElaine Zhang DECLARE_GLOBAL_DATA_PTR;
210265e00cSElaine Zhang
220265e00cSElaine Zhang #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
230265e00cSElaine Zhang
240265e00cSElaine Zhang #if 1
250265e00cSElaine Zhang static struct rockchip_pll_rate_table rk3576_24m_pll_rates[] = {
260265e00cSElaine Zhang /* _mhz, _p, _m, _s, _k */
270265e00cSElaine Zhang RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
280265e00cSElaine Zhang RK3588_PLL_RATE(1200000000, 1, 100, 1, 0),
290265e00cSElaine Zhang RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
309e41c644SElaine Zhang RK3588_PLL_RATE(1150000000, 3, 575, 2, 0),
310265e00cSElaine Zhang RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
320265e00cSElaine Zhang RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
330265e00cSElaine Zhang RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
340265e00cSElaine Zhang RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
350265e00cSElaine Zhang RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
360265e00cSElaine Zhang RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
370265e00cSElaine Zhang RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
380265e00cSElaine Zhang RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
390265e00cSElaine Zhang RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
400265e00cSElaine Zhang RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
41d2c37103SDamon Ding RK3588_PLL_RATE(610400000, 3, 305, 2, 13107),
420265e00cSElaine Zhang RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
430265e00cSElaine Zhang RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
440265e00cSElaine Zhang RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
450265e00cSElaine Zhang RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
460265e00cSElaine Zhang { /* sentinel */ },
470265e00cSElaine Zhang };
480265e00cSElaine Zhang #else
490265e00cSElaine Zhang static struct rockchip_pll_rate_table rk3576_26m_pll_rates[] = {
500265e00cSElaine Zhang /* _mhz, _p, _m, _s, _k */
510265e00cSElaine Zhang RK3588_PLL_RATE(1188000000, 2, 183, 1, 50412),
520265e00cSElaine Zhang RK3588_PLL_RATE(1100000000, 2, 338, 2, 30247),
530265e00cSElaine Zhang RK3588_PLL_RATE(1014000000, 1, 156, 2, 0),
540265e00cSElaine Zhang RK3588_PLL_RATE(1000000000, 2, 308, 2, 45371),
550265e00cSElaine Zhang RK3588_PLL_RATE(858000000, 1, 132, 2, 0),
560265e00cSElaine Zhang RK3588_PLL_RATE(806000000, 1, 124, 2, 0),
570265e00cSElaine Zhang RK3588_PLL_RATE(786432000, 2, 242, 2, 64165),
580265e00cSElaine Zhang RK3588_PLL_RATE(594000000, 2, 183, 2, 50412),
590265e00cSElaine Zhang RK3588_PLL_RATE(297000000, 2, 183, 3, 50412),
600265e00cSElaine Zhang RK3588_PLL_RATE(148500000, 2, 183, 4, 50412),
610265e00cSElaine Zhang { /* sentinel */ },
620265e00cSElaine Zhang };
630265e00cSElaine Zhang #endif
640265e00cSElaine Zhang
650265e00cSElaine Zhang static struct rockchip_pll_clock rk3576_pll_clks[] = {
660265e00cSElaine Zhang [BPLL] = PLL(pll_rk3588, PLL_BPLL, RK3576_PLL_CON(0),
670265e00cSElaine Zhang RK3576_BPLL_MODE_CON0, 0, 15, 0,
680265e00cSElaine Zhang rk3576_24m_pll_rates),
690265e00cSElaine Zhang [LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3576_LPLL_CON(16),
700265e00cSElaine Zhang RK3576_LPLL_MODE_CON0, 0, 15, 0, rk3576_24m_pll_rates),
710265e00cSElaine Zhang [VPLL] = PLL(pll_rk3588, PLL_VPLL, RK3576_PLL_CON(88),
720265e00cSElaine Zhang RK3576_LPLL_MODE_CON0, 4, 15, 0, rk3576_24m_pll_rates),
730265e00cSElaine Zhang [AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3576_PLL_CON(96),
740265e00cSElaine Zhang RK3576_MODE_CON0, 6, 15, 0, rk3576_24m_pll_rates),
750265e00cSElaine Zhang [CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3576_PLL_CON(104),
760265e00cSElaine Zhang RK3576_MODE_CON0, 8, 15, 0, rk3576_24m_pll_rates),
770265e00cSElaine Zhang [GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3576_PLL_CON(112),
780265e00cSElaine Zhang RK3576_MODE_CON0, 2, 15, 0, rk3576_24m_pll_rates),
790265e00cSElaine Zhang [PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3576_PMU_PLL_CON(128),
800265e00cSElaine Zhang RK3576_MODE_CON0, 10, 15, 0, rk3576_24m_pll_rates),
810265e00cSElaine Zhang };
820265e00cSElaine Zhang
830265e00cSElaine Zhang #ifndef CONFIG_SPL_BUILD
840265e00cSElaine Zhang #define RK3576_CLK_DUMP(_id, _name, _iscru) \
850265e00cSElaine Zhang { \
860265e00cSElaine Zhang .id = _id, \
870265e00cSElaine Zhang .name = _name, \
880265e00cSElaine Zhang .is_cru = _iscru, \
890265e00cSElaine Zhang }
900265e00cSElaine Zhang
910265e00cSElaine Zhang static const struct rk3576_clk_info clks_dump[] = {
920265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_BPLL, "bpll", true),
930265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_LPLL, "lpll", true),
940265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_VPLL, "vpll", true),
950265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_AUPLL, "aupll", true),
960265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_CPLL, "cpll", true),
970265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_GPLL, "gpll", true),
980265e00cSElaine Zhang RK3576_CLK_DUMP(PLL_PPLL, "ppll", true),
990265e00cSElaine Zhang RK3576_CLK_DUMP(ACLK_BUS_ROOT, "aclk_bus_root", true),
1000265e00cSElaine Zhang RK3576_CLK_DUMP(PCLK_BUS_ROOT, "pclk_bus_root", true),
1010265e00cSElaine Zhang RK3576_CLK_DUMP(HCLK_BUS_ROOT, "hclk_bus_root", true),
1020265e00cSElaine Zhang RK3576_CLK_DUMP(ACLK_TOP, "aclk_top", true),
1030265e00cSElaine Zhang RK3576_CLK_DUMP(ACLK_TOP_MID, "aclk_top_mid", true),
1040265e00cSElaine Zhang RK3576_CLK_DUMP(PCLK_TOP_ROOT, "pclk_top", true),
1050265e00cSElaine Zhang RK3576_CLK_DUMP(HCLK_TOP, "hclk_top", true),
1060265e00cSElaine Zhang };
1070265e00cSElaine Zhang #endif
1080265e00cSElaine Zhang
1090265e00cSElaine Zhang #ifdef CONFIG_SPL_BUILD
1100265e00cSElaine Zhang #ifndef BITS_WITH_WMASK
1110265e00cSElaine Zhang #define BITS_WITH_WMASK(bits, msk, shift) \
1120265e00cSElaine Zhang ((bits) << (shift)) | ((msk) << ((shift) + 16))
1130265e00cSElaine Zhang #endif
1140265e00cSElaine Zhang #endif
1150265e00cSElaine Zhang
1160265e00cSElaine Zhang #ifndef CONFIG_SPL_BUILD
1170265e00cSElaine Zhang /*
1180265e00cSElaine Zhang *
1190265e00cSElaine Zhang * rational_best_approximation(31415, 10000,
1200265e00cSElaine Zhang * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
1210265e00cSElaine Zhang *
1220265e00cSElaine Zhang * you may look at given_numerator as a fixed point number,
1230265e00cSElaine Zhang * with the fractional part size described in given_denominator.
1240265e00cSElaine Zhang *
1250265e00cSElaine Zhang * for theoretical background, see:
1260265e00cSElaine Zhang * http://en.wikipedia.org/wiki/Continued_fraction
1270265e00cSElaine Zhang */
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)1280265e00cSElaine Zhang static void rational_best_approximation(unsigned long given_numerator,
1290265e00cSElaine Zhang unsigned long given_denominator,
1300265e00cSElaine Zhang unsigned long max_numerator,
1310265e00cSElaine Zhang unsigned long max_denominator,
1320265e00cSElaine Zhang unsigned long *best_numerator,
1330265e00cSElaine Zhang unsigned long *best_denominator)
1340265e00cSElaine Zhang {
1350265e00cSElaine Zhang unsigned long n, d, n0, d0, n1, d1;
1360265e00cSElaine Zhang
1370265e00cSElaine Zhang n = given_numerator;
1380265e00cSElaine Zhang d = given_denominator;
1390265e00cSElaine Zhang n0 = 0;
1400265e00cSElaine Zhang d1 = 0;
1410265e00cSElaine Zhang n1 = 1;
1420265e00cSElaine Zhang d0 = 1;
1430265e00cSElaine Zhang for (;;) {
1440265e00cSElaine Zhang unsigned long t, a;
1450265e00cSElaine Zhang
1460265e00cSElaine Zhang if (n1 > max_numerator || d1 > max_denominator) {
1470265e00cSElaine Zhang n1 = n0;
1480265e00cSElaine Zhang d1 = d0;
1490265e00cSElaine Zhang break;
1500265e00cSElaine Zhang }
1510265e00cSElaine Zhang if (d == 0)
1520265e00cSElaine Zhang break;
1530265e00cSElaine Zhang t = d;
1540265e00cSElaine Zhang a = n / d;
1550265e00cSElaine Zhang d = n % d;
1560265e00cSElaine Zhang n = t;
1570265e00cSElaine Zhang t = n0 + a * n1;
1580265e00cSElaine Zhang n0 = n1;
1590265e00cSElaine Zhang n1 = t;
1600265e00cSElaine Zhang t = d0 + a * d1;
1610265e00cSElaine Zhang d0 = d1;
1620265e00cSElaine Zhang d1 = t;
1630265e00cSElaine Zhang }
1640265e00cSElaine Zhang *best_numerator = n1;
1650265e00cSElaine Zhang *best_denominator = d1;
1660265e00cSElaine Zhang }
1670265e00cSElaine Zhang #endif
1680265e00cSElaine Zhang
rk3576_bus_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)1690265e00cSElaine Zhang static ulong rk3576_bus_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1700265e00cSElaine Zhang {
1710265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
1720265e00cSElaine Zhang u32 con, sel, div, rate;
1730265e00cSElaine Zhang
1740265e00cSElaine Zhang switch (clk_id) {
1750265e00cSElaine Zhang case ACLK_BUS_ROOT:
1760265e00cSElaine Zhang con = readl(&cru->clksel_con[55]);
1770265e00cSElaine Zhang sel = (con & ACLK_BUS_ROOT_SEL_MASK) >>
1780265e00cSElaine Zhang ACLK_BUS_ROOT_SEL_SHIFT;
1790265e00cSElaine Zhang div = (con & ACLK_BUS_ROOT_DIV_MASK) >>
1800265e00cSElaine Zhang ACLK_BUS_ROOT_DIV_SHIFT;
1810265e00cSElaine Zhang if (sel == ACLK_BUS_ROOT_SEL_CPLL)
1820265e00cSElaine Zhang rate = DIV_TO_RATE(priv->cpll_hz , div);
1830265e00cSElaine Zhang else
1840265e00cSElaine Zhang rate = DIV_TO_RATE(priv->gpll_hz, div);
1850265e00cSElaine Zhang break;
1860265e00cSElaine Zhang case HCLK_BUS_ROOT:
1870265e00cSElaine Zhang con = readl(&cru->clksel_con[55]);
1880265e00cSElaine Zhang sel = (con & HCLK_BUS_ROOT_SEL_MASK) >>
1890265e00cSElaine Zhang HCLK_BUS_ROOT_SEL_SHIFT;
1900265e00cSElaine Zhang if (sel == HCLK_BUS_ROOT_SEL_200M)
1910265e00cSElaine Zhang rate = 198 * MHz;
1920265e00cSElaine Zhang else if (sel == HCLK_BUS_ROOT_SEL_100M)
1930265e00cSElaine Zhang rate = 100 * MHz;
1940265e00cSElaine Zhang else if (sel == HCLK_BUS_ROOT_SEL_50M)
1950265e00cSElaine Zhang rate = 50 * MHz;
1960265e00cSElaine Zhang else
1970265e00cSElaine Zhang rate = OSC_HZ;
1980265e00cSElaine Zhang break;
1990265e00cSElaine Zhang case PCLK_BUS_ROOT:
2000265e00cSElaine Zhang con = readl(&cru->clksel_con[55]);
2010265e00cSElaine Zhang sel = (con & PCLK_BUS_ROOT_SEL_MASK) >>
2020265e00cSElaine Zhang PCLK_BUS_ROOT_SEL_SHIFT;
2030265e00cSElaine Zhang if (sel == PCLK_BUS_ROOT_SEL_100M)
2040265e00cSElaine Zhang rate = 100 * MHz;
2050265e00cSElaine Zhang else if (sel == PCLK_BUS_ROOT_SEL_50M)
2060265e00cSElaine Zhang rate = 50 * MHz;
2070265e00cSElaine Zhang else
2080265e00cSElaine Zhang rate = OSC_HZ;
2090265e00cSElaine Zhang break;
2100265e00cSElaine Zhang default:
2110265e00cSElaine Zhang return -ENOENT;
2120265e00cSElaine Zhang }
2130265e00cSElaine Zhang
2140265e00cSElaine Zhang return rate;
2150265e00cSElaine Zhang }
2160265e00cSElaine Zhang
rk3576_bus_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)2170265e00cSElaine Zhang static ulong rk3576_bus_set_clk(struct rk3576_clk_priv *priv,
2180265e00cSElaine Zhang ulong clk_id, ulong rate)
2190265e00cSElaine Zhang {
2200265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
2210265e00cSElaine Zhang int src_clk, src_clk_div;
2220265e00cSElaine Zhang
2230265e00cSElaine Zhang switch (clk_id) {
2240265e00cSElaine Zhang case ACLK_BUS_ROOT:
2250265e00cSElaine Zhang if (!(priv->cpll_hz % rate)) {
2260265e00cSElaine Zhang src_clk = ACLK_BUS_ROOT_SEL_CPLL;
2270265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
2280265e00cSElaine Zhang } else {
2290265e00cSElaine Zhang src_clk = ACLK_BUS_ROOT_SEL_GPLL;
2300265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
2310265e00cSElaine Zhang }
2320265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[55],
2330265e00cSElaine Zhang ACLK_BUS_ROOT_SEL_MASK,
2340265e00cSElaine Zhang src_clk << ACLK_BUS_ROOT_SEL_SHIFT);
2350265e00cSElaine Zhang assert(src_clk_div - 1 <= 31);
2360265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[55],
2370265e00cSElaine Zhang ACLK_BUS_ROOT_DIV_MASK |
2380265e00cSElaine Zhang ACLK_BUS_ROOT_SEL_MASK,
2390265e00cSElaine Zhang (src_clk <<
2400265e00cSElaine Zhang ACLK_BUS_ROOT_SEL_SHIFT) |
2410265e00cSElaine Zhang (src_clk_div - 1) << ACLK_BUS_ROOT_DIV_SHIFT);
2420265e00cSElaine Zhang break;
2430265e00cSElaine Zhang case HCLK_BUS_ROOT:
2440265e00cSElaine Zhang if (rate >= 198 * MHz)
2450265e00cSElaine Zhang src_clk = HCLK_BUS_ROOT_SEL_200M;
2460265e00cSElaine Zhang else if (rate >= 99 * MHz)
2470265e00cSElaine Zhang src_clk = HCLK_BUS_ROOT_SEL_100M;
2480265e00cSElaine Zhang else if (rate >= 50 * MHz)
2490265e00cSElaine Zhang src_clk = HCLK_BUS_ROOT_SEL_50M;
2500265e00cSElaine Zhang else
2510265e00cSElaine Zhang src_clk = HCLK_BUS_ROOT_SEL_OSC;
2520265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[55],
2530265e00cSElaine Zhang HCLK_BUS_ROOT_SEL_MASK,
2540265e00cSElaine Zhang src_clk << HCLK_BUS_ROOT_SEL_SHIFT);
2550265e00cSElaine Zhang break;
2560265e00cSElaine Zhang case PCLK_BUS_ROOT:
2570265e00cSElaine Zhang if (rate >= 99 * MHz)
2580265e00cSElaine Zhang src_clk = PCLK_BUS_ROOT_SEL_100M;
2590265e00cSElaine Zhang else if (rate >= 50 * MHz)
2600265e00cSElaine Zhang src_clk = PCLK_BUS_ROOT_SEL_50M;
2610265e00cSElaine Zhang else
2620265e00cSElaine Zhang src_clk = PCLK_BUS_ROOT_SEL_OSC;
2630265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[55],
2640265e00cSElaine Zhang PCLK_BUS_ROOT_SEL_MASK,
2650265e00cSElaine Zhang src_clk << PCLK_BUS_ROOT_SEL_SHIFT);
2660265e00cSElaine Zhang break;
2670265e00cSElaine Zhang default:
2680265e00cSElaine Zhang printf("do not support this center freq\n");
2690265e00cSElaine Zhang return -EINVAL;
2700265e00cSElaine Zhang }
2710265e00cSElaine Zhang
2720265e00cSElaine Zhang return rk3576_bus_get_clk(priv, clk_id);
2730265e00cSElaine Zhang }
2740265e00cSElaine Zhang
rk3576_top_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)2750265e00cSElaine Zhang static ulong rk3576_top_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
2760265e00cSElaine Zhang {
2770265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
2780265e00cSElaine Zhang u32 con, sel, div, rate, prate;
2790265e00cSElaine Zhang
2800265e00cSElaine Zhang switch (clk_id) {
2810265e00cSElaine Zhang case ACLK_TOP:
2820265e00cSElaine Zhang con = readl(&cru->clksel_con[9]);
2830265e00cSElaine Zhang div = (con & ACLK_TOP_DIV_MASK) >>
2840265e00cSElaine Zhang ACLK_TOP_DIV_SHIFT;
2850265e00cSElaine Zhang sel = (con & ACLK_TOP_SEL_MASK) >>
2860265e00cSElaine Zhang ACLK_TOP_SEL_SHIFT;
2870265e00cSElaine Zhang if (sel == ACLK_TOP_SEL_CPLL)
2880265e00cSElaine Zhang prate = priv->cpll_hz;
2890265e00cSElaine Zhang else if (sel == ACLK_TOP_SEL_AUPLL)
2900265e00cSElaine Zhang prate = priv->aupll_hz;
2910265e00cSElaine Zhang else
2920265e00cSElaine Zhang prate = priv->gpll_hz;
2930265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
2940265e00cSElaine Zhang case ACLK_TOP_MID:
2950265e00cSElaine Zhang con = readl(&cru->clksel_con[10]);
2960265e00cSElaine Zhang div = (con & ACLK_TOP_MID_DIV_MASK) >>
2970265e00cSElaine Zhang ACLK_TOP_MID_DIV_SHIFT;
2980265e00cSElaine Zhang sel = (con & ACLK_TOP_MID_SEL_MASK) >>
2990265e00cSElaine Zhang ACLK_TOP_MID_SEL_SHIFT;
3000265e00cSElaine Zhang if (sel == ACLK_TOP_MID_SEL_CPLL)
3010265e00cSElaine Zhang prate = priv->cpll_hz;
3020265e00cSElaine Zhang else
3030265e00cSElaine Zhang prate = priv->gpll_hz;
3040265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
3050265e00cSElaine Zhang case PCLK_TOP_ROOT:
3060265e00cSElaine Zhang con = readl(&cru->clksel_con[8]);
3070265e00cSElaine Zhang sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
3080265e00cSElaine Zhang if (sel == PCLK_TOP_SEL_100M)
3090265e00cSElaine Zhang rate = 100 * MHz;
3100265e00cSElaine Zhang else if (sel == PCLK_TOP_SEL_50M)
3110265e00cSElaine Zhang rate = 50 * MHz;
3120265e00cSElaine Zhang else
3130265e00cSElaine Zhang rate = OSC_HZ;
3140265e00cSElaine Zhang break;
3150265e00cSElaine Zhang case HCLK_TOP:
3160265e00cSElaine Zhang con = readl(&cru->clksel_con[19]);
3170265e00cSElaine Zhang sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
3180265e00cSElaine Zhang if (sel == HCLK_TOP_SEL_200M)
3190265e00cSElaine Zhang rate = 200 * MHz;
3200265e00cSElaine Zhang else if (sel == HCLK_TOP_SEL_100M)
3210265e00cSElaine Zhang rate = 100 * MHz;
3220265e00cSElaine Zhang else if (sel == HCLK_TOP_SEL_50M)
3230265e00cSElaine Zhang rate = 50 * MHz;
3240265e00cSElaine Zhang else
3250265e00cSElaine Zhang rate = OSC_HZ;
3260265e00cSElaine Zhang break;
3270265e00cSElaine Zhang default:
3280265e00cSElaine Zhang return -ENOENT;
3290265e00cSElaine Zhang }
3300265e00cSElaine Zhang
3310265e00cSElaine Zhang return rate;
3320265e00cSElaine Zhang }
3330265e00cSElaine Zhang
rk3576_top_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)3340265e00cSElaine Zhang static ulong rk3576_top_set_clk(struct rk3576_clk_priv *priv,
3350265e00cSElaine Zhang ulong clk_id, ulong rate)
3360265e00cSElaine Zhang {
3370265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
3380265e00cSElaine Zhang int src_clk, src_clk_div;
3390265e00cSElaine Zhang
3400265e00cSElaine Zhang switch (clk_id) {
3410265e00cSElaine Zhang case ACLK_TOP:
3420265e00cSElaine Zhang if (!(priv->cpll_hz % rate)) {
3430265e00cSElaine Zhang src_clk = ACLK_TOP_SEL_CPLL;
3440265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
3450265e00cSElaine Zhang } else {
3460265e00cSElaine Zhang src_clk = ACLK_TOP_SEL_GPLL;
3470265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
3480265e00cSElaine Zhang }
3490265e00cSElaine Zhang assert(src_clk_div - 1 <= 31);
3500265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[9],
3510265e00cSElaine Zhang ACLK_TOP_DIV_MASK |
3520265e00cSElaine Zhang ACLK_TOP_SEL_MASK,
3530265e00cSElaine Zhang (src_clk <<
3540265e00cSElaine Zhang ACLK_TOP_SEL_SHIFT) |
3550265e00cSElaine Zhang (src_clk_div - 1) << ACLK_TOP_SEL_SHIFT);
3560265e00cSElaine Zhang break;
3570265e00cSElaine Zhang case ACLK_TOP_MID:
3580265e00cSElaine Zhang if (!(priv->cpll_hz % rate)) {
3590265e00cSElaine Zhang src_clk = ACLK_TOP_MID_SEL_CPLL;
3600265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
3610265e00cSElaine Zhang } else {
3620265e00cSElaine Zhang src_clk = ACLK_TOP_MID_SEL_GPLL;
3630265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
3640265e00cSElaine Zhang }
3650265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[10],
3660265e00cSElaine Zhang ACLK_TOP_MID_DIV_MASK |
3670265e00cSElaine Zhang ACLK_TOP_MID_SEL_MASK,
3680265e00cSElaine Zhang (ACLK_TOP_MID_SEL_GPLL <<
3690265e00cSElaine Zhang ACLK_TOP_MID_SEL_SHIFT) |
3700265e00cSElaine Zhang (src_clk_div - 1) << ACLK_TOP_MID_DIV_SHIFT);
3710265e00cSElaine Zhang break;
3720265e00cSElaine Zhang case PCLK_TOP_ROOT:
3730265e00cSElaine Zhang if (rate >= 99 * MHz)
3740265e00cSElaine Zhang src_clk = PCLK_TOP_SEL_100M;
3750265e00cSElaine Zhang else if (rate >= 50 * MHz)
3760265e00cSElaine Zhang src_clk = PCLK_TOP_SEL_50M;
3770265e00cSElaine Zhang else
3780265e00cSElaine Zhang src_clk = PCLK_TOP_SEL_OSC;
3790265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[8],
3800265e00cSElaine Zhang PCLK_TOP_SEL_MASK,
3810265e00cSElaine Zhang src_clk << PCLK_TOP_SEL_SHIFT);
3820265e00cSElaine Zhang break;
3830265e00cSElaine Zhang case HCLK_TOP:
3840265e00cSElaine Zhang if (rate >= 198 * MHz)
3850265e00cSElaine Zhang src_clk = HCLK_TOP_SEL_200M;
3860265e00cSElaine Zhang else if (rate >= 99 * MHz)
3870265e00cSElaine Zhang src_clk = HCLK_TOP_SEL_100M;
3880265e00cSElaine Zhang else if (rate >= 50 * MHz)
3890265e00cSElaine Zhang src_clk = HCLK_TOP_SEL_50M;
3900265e00cSElaine Zhang else
3910265e00cSElaine Zhang src_clk = HCLK_TOP_SEL_OSC;
3920265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[19],
3930265e00cSElaine Zhang HCLK_TOP_SEL_MASK,
3940265e00cSElaine Zhang src_clk << HCLK_TOP_SEL_SHIFT);
3950265e00cSElaine Zhang break;
3960265e00cSElaine Zhang default:
3970265e00cSElaine Zhang printf("do not support this top freq\n");
3980265e00cSElaine Zhang return -EINVAL;
3990265e00cSElaine Zhang }
4000265e00cSElaine Zhang
4010265e00cSElaine Zhang return rk3576_top_get_clk(priv, clk_id);
4020265e00cSElaine Zhang }
4030265e00cSElaine Zhang
rk3576_i2c_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)4040265e00cSElaine Zhang static ulong rk3576_i2c_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
4050265e00cSElaine Zhang {
4060265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
4070265e00cSElaine Zhang u32 sel, con;
4080265e00cSElaine Zhang ulong rate;
4090265e00cSElaine Zhang
4100265e00cSElaine Zhang switch (clk_id) {
4110265e00cSElaine Zhang case CLK_I2C0:
4120265e00cSElaine Zhang con = readl(&cru->pmuclksel_con[6]);
4130265e00cSElaine Zhang sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
4140265e00cSElaine Zhang break;
4150265e00cSElaine Zhang case CLK_I2C1:
4160265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4170265e00cSElaine Zhang sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
4180265e00cSElaine Zhang break;
4190265e00cSElaine Zhang case CLK_I2C2:
4200265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4210265e00cSElaine Zhang sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
4220265e00cSElaine Zhang break;
4230265e00cSElaine Zhang case CLK_I2C3:
4240265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4250265e00cSElaine Zhang sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
4260265e00cSElaine Zhang break;
4270265e00cSElaine Zhang case CLK_I2C4:
4280265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4290265e00cSElaine Zhang sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
4300265e00cSElaine Zhang break;
4310265e00cSElaine Zhang case CLK_I2C5:
4320265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4330265e00cSElaine Zhang sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
4340265e00cSElaine Zhang break;
4350265e00cSElaine Zhang case CLK_I2C6:
4360265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4370265e00cSElaine Zhang sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
4380265e00cSElaine Zhang break;
4390265e00cSElaine Zhang case CLK_I2C7:
4400265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4410265e00cSElaine Zhang sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
4420265e00cSElaine Zhang break;
4430265e00cSElaine Zhang case CLK_I2C8:
4440265e00cSElaine Zhang con = readl(&cru->clksel_con[57]);
4450265e00cSElaine Zhang sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
4460265e00cSElaine Zhang break;
4470265e00cSElaine Zhang case CLK_I2C9:
4480265e00cSElaine Zhang con = readl(&cru->clksel_con[58]);
4490265e00cSElaine Zhang sel = (con & CLK_I2C9_SEL_MASK) >> CLK_I2C9_SEL_SHIFT;
4500265e00cSElaine Zhang break;
4510265e00cSElaine Zhang
4520265e00cSElaine Zhang default:
4530265e00cSElaine Zhang return -ENOENT;
4540265e00cSElaine Zhang }
4550265e00cSElaine Zhang if (sel == CLK_I2C_SEL_200M)
4560265e00cSElaine Zhang rate = 200 * MHz;
4570265e00cSElaine Zhang else if (sel == CLK_I2C_SEL_100M)
4580265e00cSElaine Zhang rate = 100 * MHz;
4590265e00cSElaine Zhang else if (sel == CLK_I2C_SEL_50M)
4600265e00cSElaine Zhang rate = 50 * MHz;
4610265e00cSElaine Zhang else
4620265e00cSElaine Zhang rate = OSC_HZ;
4630265e00cSElaine Zhang
4640265e00cSElaine Zhang return rate;
4650265e00cSElaine Zhang }
4660265e00cSElaine Zhang
rk3576_i2c_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)4670265e00cSElaine Zhang static ulong rk3576_i2c_set_clk(struct rk3576_clk_priv *priv, ulong clk_id,
4680265e00cSElaine Zhang ulong rate)
4690265e00cSElaine Zhang {
4700265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
4710265e00cSElaine Zhang int src_clk;
4720265e00cSElaine Zhang
4730265e00cSElaine Zhang if (rate >= 198 * MHz)
4740265e00cSElaine Zhang src_clk = CLK_I2C_SEL_200M;
4750265e00cSElaine Zhang else if (rate >= 99 * MHz)
4760265e00cSElaine Zhang src_clk = CLK_I2C_SEL_100M;
4770265e00cSElaine Zhang if (rate >= 50 * MHz)
4780265e00cSElaine Zhang src_clk = CLK_I2C_SEL_50M;
4790265e00cSElaine Zhang else
4800265e00cSElaine Zhang src_clk = CLK_I2C_SEL_OSC;
4810265e00cSElaine Zhang
4820265e00cSElaine Zhang switch (clk_id) {
4830265e00cSElaine Zhang case CLK_I2C0:
4840265e00cSElaine Zhang rk_clrsetreg(&cru->pmuclksel_con[6], CLK_I2C0_SEL_MASK,
4850265e00cSElaine Zhang src_clk << CLK_I2C0_SEL_SHIFT);
4860265e00cSElaine Zhang break;
4870265e00cSElaine Zhang case CLK_I2C1:
4880265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C1_SEL_MASK,
4890265e00cSElaine Zhang src_clk << CLK_I2C1_SEL_SHIFT);
4900265e00cSElaine Zhang break;
4910265e00cSElaine Zhang case CLK_I2C2:
4920265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C2_SEL_MASK,
4930265e00cSElaine Zhang src_clk << CLK_I2C2_SEL_SHIFT);
4940265e00cSElaine Zhang break;
4950265e00cSElaine Zhang case CLK_I2C3:
4960265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C3_SEL_MASK,
4970265e00cSElaine Zhang src_clk << CLK_I2C3_SEL_SHIFT);
4980265e00cSElaine Zhang break;
4990265e00cSElaine Zhang case CLK_I2C4:
5000265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C4_SEL_MASK,
5010265e00cSElaine Zhang src_clk << CLK_I2C4_SEL_SHIFT);
5020265e00cSElaine Zhang break;
5030265e00cSElaine Zhang case CLK_I2C5:
5040265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C5_SEL_MASK,
5050265e00cSElaine Zhang src_clk << CLK_I2C5_SEL_SHIFT);
5060265e00cSElaine Zhang break;
5070265e00cSElaine Zhang case CLK_I2C6:
5080265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C6_SEL_MASK,
5090265e00cSElaine Zhang src_clk << CLK_I2C6_SEL_SHIFT);
5100265e00cSElaine Zhang break;
5110265e00cSElaine Zhang case CLK_I2C7:
5120265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C7_SEL_MASK,
5130265e00cSElaine Zhang src_clk << CLK_I2C7_SEL_SHIFT);
5140265e00cSElaine Zhang break;
5150265e00cSElaine Zhang case CLK_I2C8:
5160265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[57], CLK_I2C8_SEL_MASK,
5170265e00cSElaine Zhang src_clk << CLK_I2C8_SEL_SHIFT);
5180265e00cSElaine Zhang case CLK_I2C9:
5190265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[58], CLK_I2C9_SEL_MASK,
5200265e00cSElaine Zhang src_clk << CLK_I2C9_SEL_SHIFT);
5210265e00cSElaine Zhang break;
5220265e00cSElaine Zhang default:
5230265e00cSElaine Zhang return -ENOENT;
5240265e00cSElaine Zhang }
5250265e00cSElaine Zhang
5260265e00cSElaine Zhang return rk3576_i2c_get_clk(priv, clk_id);
5270265e00cSElaine Zhang }
5280265e00cSElaine Zhang
rk3576_spi_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)5290265e00cSElaine Zhang static ulong rk3576_spi_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
5300265e00cSElaine Zhang {
5310265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
5320265e00cSElaine Zhang u32 sel, con;
5330265e00cSElaine Zhang
5340265e00cSElaine Zhang switch (clk_id) {
5350265e00cSElaine Zhang case CLK_SPI0:
5360265e00cSElaine Zhang con = readl(&cru->clksel_con[70]);
5370265e00cSElaine Zhang sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
5380265e00cSElaine Zhang break;
5390265e00cSElaine Zhang case CLK_SPI1:
5400265e00cSElaine Zhang con = readl(&cru->clksel_con[71]);
5410265e00cSElaine Zhang sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
5420265e00cSElaine Zhang break;
5430265e00cSElaine Zhang case CLK_SPI2:
5440265e00cSElaine Zhang con = readl(&cru->clksel_con[71]);
5450265e00cSElaine Zhang sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
5460265e00cSElaine Zhang break;
5470265e00cSElaine Zhang case CLK_SPI3:
5480265e00cSElaine Zhang con = readl(&cru->clksel_con[71]);
5490265e00cSElaine Zhang sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
5500265e00cSElaine Zhang break;
5510265e00cSElaine Zhang case CLK_SPI4:
5520265e00cSElaine Zhang con = readl(&cru->clksel_con[71]);
5530265e00cSElaine Zhang sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
5540265e00cSElaine Zhang break;
5550265e00cSElaine Zhang default:
5560265e00cSElaine Zhang return -ENOENT;
5570265e00cSElaine Zhang }
5580265e00cSElaine Zhang
5590265e00cSElaine Zhang switch (sel) {
5600265e00cSElaine Zhang case CLK_SPI_SEL_200M:
5610265e00cSElaine Zhang return 200 * MHz;
5620265e00cSElaine Zhang case CLK_SPI_SEL_100M:
5630265e00cSElaine Zhang return 100 * MHz;
5640265e00cSElaine Zhang case CLK_SPI_SEL_50M:
5650265e00cSElaine Zhang return 50 * MHz;
5660265e00cSElaine Zhang case CLK_SPI_SEL_OSC:
5670265e00cSElaine Zhang return OSC_HZ;
5680265e00cSElaine Zhang default:
5690265e00cSElaine Zhang return -ENOENT;
5700265e00cSElaine Zhang }
5710265e00cSElaine Zhang }
5720265e00cSElaine Zhang
rk3576_spi_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)5730265e00cSElaine Zhang static ulong rk3576_spi_set_clk(struct rk3576_clk_priv *priv,
5740265e00cSElaine Zhang ulong clk_id, ulong rate)
5750265e00cSElaine Zhang {
5760265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
5770265e00cSElaine Zhang int src_clk;
5780265e00cSElaine Zhang
5790265e00cSElaine Zhang if (rate >= 198 * MHz)
5800265e00cSElaine Zhang src_clk = CLK_SPI_SEL_200M;
5810265e00cSElaine Zhang else if (rate >= 99 * MHz)
5820265e00cSElaine Zhang src_clk = CLK_SPI_SEL_100M;
5830265e00cSElaine Zhang else if (rate >= 50 * MHz)
5840265e00cSElaine Zhang src_clk = CLK_SPI_SEL_50M;
5850265e00cSElaine Zhang else
5860265e00cSElaine Zhang src_clk = CLK_SPI_SEL_OSC;
5870265e00cSElaine Zhang
5880265e00cSElaine Zhang switch (clk_id) {
5890265e00cSElaine Zhang case CLK_SPI0:
5900265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[70],
5910265e00cSElaine Zhang CLK_SPI0_SEL_MASK,
5920265e00cSElaine Zhang src_clk << CLK_SPI0_SEL_SHIFT);
5930265e00cSElaine Zhang break;
5940265e00cSElaine Zhang case CLK_SPI1:
5950265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[71],
5960265e00cSElaine Zhang CLK_SPI1_SEL_MASK,
5970265e00cSElaine Zhang src_clk << CLK_SPI1_SEL_SHIFT);
5980265e00cSElaine Zhang break;
5990265e00cSElaine Zhang case CLK_SPI2:
6000265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[71],
6010265e00cSElaine Zhang CLK_SPI2_SEL_MASK,
6020265e00cSElaine Zhang src_clk << CLK_SPI2_SEL_SHIFT);
6030265e00cSElaine Zhang break;
6040265e00cSElaine Zhang case CLK_SPI3:
6050265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[71],
6060265e00cSElaine Zhang CLK_SPI3_SEL_MASK,
6070265e00cSElaine Zhang src_clk << CLK_SPI3_SEL_SHIFT);
6080265e00cSElaine Zhang break;
6090265e00cSElaine Zhang case CLK_SPI4:
6100265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[71],
6110265e00cSElaine Zhang CLK_SPI4_SEL_MASK,
6120265e00cSElaine Zhang src_clk << CLK_SPI4_SEL_SHIFT);
6130265e00cSElaine Zhang break;
6140265e00cSElaine Zhang default:
6150265e00cSElaine Zhang return -ENOENT;
6160265e00cSElaine Zhang }
6170265e00cSElaine Zhang
6180265e00cSElaine Zhang return rk3576_spi_get_clk(priv, clk_id);
6190265e00cSElaine Zhang }
6200265e00cSElaine Zhang
rk3576_pwm_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)6210265e00cSElaine Zhang static ulong rk3576_pwm_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
6220265e00cSElaine Zhang {
6230265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
6240265e00cSElaine Zhang u32 sel, con;
6250265e00cSElaine Zhang
6260265e00cSElaine Zhang switch (clk_id) {
6270265e00cSElaine Zhang case CLK_PWM1:
6280265e00cSElaine Zhang con = readl(&cru->clksel_con[71]);
6290265e00cSElaine Zhang sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
6300265e00cSElaine Zhang break;
6310265e00cSElaine Zhang case CLK_PWM2:
6320265e00cSElaine Zhang con = readl(&cru->clksel_con[74]);
6330265e00cSElaine Zhang sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
6340265e00cSElaine Zhang break;
6350265e00cSElaine Zhang case CLK_PMU1PWM:
6360265e00cSElaine Zhang con = readl(&cru->pmuclksel_con[5]);
6370265e00cSElaine Zhang sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
6380265e00cSElaine Zhang break;
6390265e00cSElaine Zhang default:
6400265e00cSElaine Zhang return -ENOENT;
6410265e00cSElaine Zhang }
6420265e00cSElaine Zhang
6430265e00cSElaine Zhang switch (sel) {
6440265e00cSElaine Zhang case CLK_PWM_SEL_100M:
6450265e00cSElaine Zhang return 100 * MHz;
6460265e00cSElaine Zhang case CLK_PWM_SEL_50M:
6470265e00cSElaine Zhang return 50 * MHz;
6480265e00cSElaine Zhang case CLK_PWM_SEL_OSC:
6490265e00cSElaine Zhang return OSC_HZ;
6500265e00cSElaine Zhang default:
6510265e00cSElaine Zhang return -ENOENT;
6520265e00cSElaine Zhang }
6530265e00cSElaine Zhang }
6540265e00cSElaine Zhang
rk3576_pwm_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)6550265e00cSElaine Zhang static ulong rk3576_pwm_set_clk(struct rk3576_clk_priv *priv,
6560265e00cSElaine Zhang ulong clk_id, ulong rate)
6570265e00cSElaine Zhang {
6580265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
6590265e00cSElaine Zhang int src_clk;
6600265e00cSElaine Zhang
6610265e00cSElaine Zhang if (rate >= 99 * MHz)
6620265e00cSElaine Zhang src_clk = CLK_PWM_SEL_100M;
6630265e00cSElaine Zhang else if (rate >= 50 * MHz)
6640265e00cSElaine Zhang src_clk = CLK_PWM_SEL_50M;
6650265e00cSElaine Zhang else
6660265e00cSElaine Zhang src_clk = CLK_PWM_SEL_OSC;
6670265e00cSElaine Zhang
6680265e00cSElaine Zhang switch (clk_id) {
6690265e00cSElaine Zhang case CLK_PWM1:
6700265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[71],
6710265e00cSElaine Zhang CLK_PWM1_SEL_MASK,
6720265e00cSElaine Zhang src_clk << CLK_PWM1_SEL_SHIFT);
6730265e00cSElaine Zhang break;
6740265e00cSElaine Zhang case CLK_PWM2:
6750265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[74],
6760265e00cSElaine Zhang CLK_PWM2_SEL_MASK,
6770265e00cSElaine Zhang src_clk << CLK_PWM2_SEL_SHIFT);
6780265e00cSElaine Zhang break;
6790265e00cSElaine Zhang case CLK_PMU1PWM:
6800265e00cSElaine Zhang rk_clrsetreg(&cru->pmuclksel_con[5],
6810265e00cSElaine Zhang CLK_PMU1PWM_SEL_MASK,
6820265e00cSElaine Zhang src_clk << CLK_PMU1PWM_SEL_SHIFT);
6830265e00cSElaine Zhang break;
6840265e00cSElaine Zhang default:
6850265e00cSElaine Zhang return -ENOENT;
6860265e00cSElaine Zhang }
6870265e00cSElaine Zhang
6880265e00cSElaine Zhang return rk3576_pwm_get_clk(priv, clk_id);
6890265e00cSElaine Zhang }
6900265e00cSElaine Zhang
rk3576_adc_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)6910265e00cSElaine Zhang static ulong rk3576_adc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
6920265e00cSElaine Zhang {
6930265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
6940265e00cSElaine Zhang u32 div, sel, con, prate;
6950265e00cSElaine Zhang
6960265e00cSElaine Zhang switch (clk_id) {
6970265e00cSElaine Zhang case CLK_SARADC:
6980265e00cSElaine Zhang con = readl(&cru->clksel_con[58]);
6990265e00cSElaine Zhang div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
7000265e00cSElaine Zhang sel = (con & CLK_SARADC_SEL_MASK) >>
7010265e00cSElaine Zhang CLK_SARADC_SEL_SHIFT;
7020265e00cSElaine Zhang if (sel == CLK_SARADC_SEL_OSC)
7030265e00cSElaine Zhang prate = OSC_HZ;
7040265e00cSElaine Zhang else
7050265e00cSElaine Zhang prate = priv->gpll_hz;
7060265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
7070265e00cSElaine Zhang case CLK_TSADC:
7080265e00cSElaine Zhang con = readl(&cru->clksel_con[59]);
7090265e00cSElaine Zhang div = (con & CLK_TSADC_DIV_MASK) >>
7100265e00cSElaine Zhang CLK_TSADC_DIV_SHIFT;
7110265e00cSElaine Zhang prate = OSC_HZ;
7120265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
7130265e00cSElaine Zhang default:
7140265e00cSElaine Zhang return -ENOENT;
7150265e00cSElaine Zhang }
7160265e00cSElaine Zhang }
7170265e00cSElaine Zhang
rk3576_adc_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)7180265e00cSElaine Zhang static ulong rk3576_adc_set_clk(struct rk3576_clk_priv *priv,
7190265e00cSElaine Zhang ulong clk_id, ulong rate)
7200265e00cSElaine Zhang {
7210265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
7220265e00cSElaine Zhang int src_clk_div;
7230265e00cSElaine Zhang
7240265e00cSElaine Zhang switch (clk_id) {
7250265e00cSElaine Zhang case CLK_SARADC:
7260265e00cSElaine Zhang if (!(OSC_HZ % rate)) {
7270265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
7280265e00cSElaine Zhang assert(src_clk_div - 1 <= 255);
7290265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[58],
7300265e00cSElaine Zhang CLK_SARADC_SEL_MASK |
7310265e00cSElaine Zhang CLK_SARADC_DIV_MASK,
7320265e00cSElaine Zhang (CLK_SARADC_SEL_OSC <<
7330265e00cSElaine Zhang CLK_SARADC_SEL_SHIFT) |
7340265e00cSElaine Zhang (src_clk_div - 1) <<
7350265e00cSElaine Zhang CLK_SARADC_DIV_SHIFT);
7360265e00cSElaine Zhang } else {
7370265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
7380265e00cSElaine Zhang assert(src_clk_div - 1 <= 255);
7390265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[59],
7400265e00cSElaine Zhang CLK_SARADC_SEL_MASK |
7410265e00cSElaine Zhang CLK_SARADC_DIV_MASK,
7420265e00cSElaine Zhang (CLK_SARADC_SEL_GPLL <<
7430265e00cSElaine Zhang CLK_SARADC_SEL_SHIFT) |
7440265e00cSElaine Zhang (src_clk_div - 1) <<
7450265e00cSElaine Zhang CLK_SARADC_DIV_SHIFT);
7460265e00cSElaine Zhang }
7470265e00cSElaine Zhang break;
7480265e00cSElaine Zhang case CLK_TSADC:
7490265e00cSElaine Zhang src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
7500265e00cSElaine Zhang assert(src_clk_div - 1 <= 255);
7510265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[58],
7520265e00cSElaine Zhang CLK_TSADC_DIV_MASK,
7530265e00cSElaine Zhang (src_clk_div - 1) <<
7540265e00cSElaine Zhang CLK_TSADC_DIV_SHIFT);
7550265e00cSElaine Zhang break;
7560265e00cSElaine Zhang default:
7570265e00cSElaine Zhang return -ENOENT;
7580265e00cSElaine Zhang }
7590265e00cSElaine Zhang return rk3576_adc_get_clk(priv, clk_id);
7600265e00cSElaine Zhang }
7610265e00cSElaine Zhang
rk3576_mmc_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)7620265e00cSElaine Zhang static ulong rk3576_mmc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
7630265e00cSElaine Zhang {
7640265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
7650265e00cSElaine Zhang u32 sel, con, prate, div = 0;
7660265e00cSElaine Zhang
7670265e00cSElaine Zhang switch (clk_id) {
7680265e00cSElaine Zhang case CCLK_SRC_SDIO:
7694a69562cSElaine Zhang case HCLK_SDIO:
7700265e00cSElaine Zhang con = readl(&cru->clksel_con[104]);
7710265e00cSElaine Zhang div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
7720265e00cSElaine Zhang sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
7730265e00cSElaine Zhang CCLK_SDIO_SRC_SEL_SHIFT;
7740265e00cSElaine Zhang if (sel == CCLK_SDIO_SRC_SEL_GPLL)
7750265e00cSElaine Zhang prate = priv->gpll_hz;
7760265e00cSElaine Zhang else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
7770265e00cSElaine Zhang prate = priv->cpll_hz;
7780265e00cSElaine Zhang else
7790265e00cSElaine Zhang prate = OSC_HZ;
7800265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
7810265e00cSElaine Zhang case CCLK_SRC_SDMMC0:
7824a69562cSElaine Zhang case HCLK_SDMMC0:
7830265e00cSElaine Zhang con = readl(&cru->clksel_con[105]);
7840265e00cSElaine Zhang div = (con & CCLK_SDMMC0_SRC_DIV_MASK) >> CCLK_SDMMC0_SRC_DIV_SHIFT;
7850265e00cSElaine Zhang sel = (con & CCLK_SDMMC0_SRC_SEL_MASK) >>
7860265e00cSElaine Zhang CCLK_SDMMC0_SRC_SEL_SHIFT;
7870265e00cSElaine Zhang if (sel == CCLK_SDMMC0_SRC_SEL_GPLL)
7880265e00cSElaine Zhang prate = priv->gpll_hz;
7890265e00cSElaine Zhang else if (sel == CCLK_SDMMC0_SRC_SEL_CPLL)
7900265e00cSElaine Zhang prate = priv->cpll_hz;
7910265e00cSElaine Zhang else
7920265e00cSElaine Zhang prate = OSC_HZ;
7930265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
7940265e00cSElaine Zhang case CCLK_SRC_EMMC:
7954a69562cSElaine Zhang case HCLK_EMMC:
7960265e00cSElaine Zhang con = readl(&cru->clksel_con[89]);
7970265e00cSElaine Zhang div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
7980265e00cSElaine Zhang sel = (con & CCLK_EMMC_SEL_MASK) >>
7990265e00cSElaine Zhang CCLK_EMMC_SEL_SHIFT;
8000265e00cSElaine Zhang if (sel == CCLK_EMMC_SEL_GPLL)
8010265e00cSElaine Zhang prate = priv->gpll_hz;
8020265e00cSElaine Zhang else if (sel == CCLK_EMMC_SEL_CPLL)
8030265e00cSElaine Zhang prate = priv->cpll_hz;
8040265e00cSElaine Zhang else
8050265e00cSElaine Zhang prate = OSC_HZ;
8060265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
8070265e00cSElaine Zhang case BCLK_EMMC:
8080265e00cSElaine Zhang con = readl(&cru->clksel_con[90]);
8090265e00cSElaine Zhang sel = (con & BCLK_EMMC_SEL_MASK) >>
8100265e00cSElaine Zhang BCLK_EMMC_SEL_SHIFT;
8110265e00cSElaine Zhang if (sel == BCLK_EMMC_SEL_200M)
8120265e00cSElaine Zhang prate = 200 * MHz;
8130265e00cSElaine Zhang else if (sel == BCLK_EMMC_SEL_100M)
8140265e00cSElaine Zhang prate = 100 * MHz;
8150265e00cSElaine Zhang else if (sel == BCLK_EMMC_SEL_50M)
8160265e00cSElaine Zhang prate = 50 * MHz;
8170265e00cSElaine Zhang else
8180265e00cSElaine Zhang prate = OSC_HZ;
8190265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
8200265e00cSElaine Zhang case SCLK_FSPI_X2:
8210265e00cSElaine Zhang con = readl(&cru->clksel_con[89]);
8220265e00cSElaine Zhang div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
8230265e00cSElaine Zhang sel = (con & SCLK_FSPI_SEL_MASK) >>
8240265e00cSElaine Zhang SCLK_FSPI_SEL_SHIFT;
8250265e00cSElaine Zhang if (sel == SCLK_FSPI_SEL_GPLL)
8260265e00cSElaine Zhang prate = priv->gpll_hz;
8270265e00cSElaine Zhang else if (sel == SCLK_FSPI_SEL_CPLL)
8280265e00cSElaine Zhang prate = priv->cpll_hz;
8290265e00cSElaine Zhang else
8300265e00cSElaine Zhang prate = OSC_HZ;
8310265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
8320265e00cSElaine Zhang case SCLK_FSPI1_X2:
8330265e00cSElaine Zhang con = readl(&cru->clksel_con[106]);
8340265e00cSElaine Zhang div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
8350265e00cSElaine Zhang sel = (con & SCLK_FSPI_SEL_MASK) >>
8360265e00cSElaine Zhang SCLK_FSPI_SEL_SHIFT;
8370265e00cSElaine Zhang if (sel == SCLK_FSPI_SEL_GPLL)
8380265e00cSElaine Zhang prate = priv->gpll_hz;
8390265e00cSElaine Zhang else if (sel == SCLK_FSPI_SEL_CPLL)
8400265e00cSElaine Zhang prate = priv->cpll_hz;
8410265e00cSElaine Zhang else
8420265e00cSElaine Zhang prate = OSC_HZ;
8430265e00cSElaine Zhang return DIV_TO_RATE(prate, div);
844431b7b81SElaine Zhang case DCLK_DECOM:
845431b7b81SElaine Zhang con = readl(&cru->clksel_con[72]);
846431b7b81SElaine Zhang div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
847431b7b81SElaine Zhang sel = (con & DCLK_DECOM_SEL_MASK) >> DCLK_DECOM_SEL_SHIFT;
848431b7b81SElaine Zhang if (sel == DCLK_DECOM_SEL_SPLL)
849431b7b81SElaine Zhang prate = priv->spll_hz;
850431b7b81SElaine Zhang else
851431b7b81SElaine Zhang prate = priv->gpll_hz;
852431b7b81SElaine Zhang return DIV_TO_RATE(prate, div);
853431b7b81SElaine Zhang
8540265e00cSElaine Zhang default:
8550265e00cSElaine Zhang return -ENOENT;
8560265e00cSElaine Zhang }
8570265e00cSElaine Zhang }
8580265e00cSElaine Zhang
rk3576_mmc_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)8590265e00cSElaine Zhang static ulong rk3576_mmc_set_clk(struct rk3576_clk_priv *priv,
8600265e00cSElaine Zhang ulong clk_id, ulong rate)
8610265e00cSElaine Zhang {
8620265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
8630265e00cSElaine Zhang int src_clk, div = 0;
8640265e00cSElaine Zhang
8650265e00cSElaine Zhang switch (clk_id) {
8660265e00cSElaine Zhang case CCLK_SRC_SDIO:
8670265e00cSElaine Zhang case CCLK_SRC_SDMMC0:
8680265e00cSElaine Zhang case CCLK_SRC_EMMC:
8690265e00cSElaine Zhang case SCLK_FSPI_X2:
8700265e00cSElaine Zhang case SCLK_FSPI1_X2:
8714a69562cSElaine Zhang case HCLK_SDMMC0:
8724a69562cSElaine Zhang case HCLK_EMMC:
8734a69562cSElaine Zhang case HCLK_SDIO:
8740265e00cSElaine Zhang if (!(OSC_HZ % rate)) {
8750265e00cSElaine Zhang src_clk = SCLK_FSPI_SEL_OSC;
8760265e00cSElaine Zhang div = DIV_ROUND_UP(OSC_HZ, rate);
8770265e00cSElaine Zhang } else if (!(priv->cpll_hz % rate)) {
8780265e00cSElaine Zhang src_clk = SCLK_FSPI_SEL_CPLL;
8790265e00cSElaine Zhang div = DIV_ROUND_UP(priv->cpll_hz, rate);
8800265e00cSElaine Zhang } else {
8810265e00cSElaine Zhang src_clk = SCLK_FSPI_SEL_GPLL;
8820265e00cSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
8830265e00cSElaine Zhang }
8840265e00cSElaine Zhang break;
8850265e00cSElaine Zhang case BCLK_EMMC:
8860265e00cSElaine Zhang if (rate >= 198 * MHz)
8870265e00cSElaine Zhang src_clk = BCLK_EMMC_SEL_200M;
8880265e00cSElaine Zhang else if (rate >= 99 * MHz)
8890265e00cSElaine Zhang src_clk = BCLK_EMMC_SEL_100M;
8900265e00cSElaine Zhang else if (rate >= 50 * MHz)
8910265e00cSElaine Zhang src_clk = BCLK_EMMC_SEL_50M;
8920265e00cSElaine Zhang else
8930265e00cSElaine Zhang src_clk = BCLK_EMMC_SEL_OSC;
8940265e00cSElaine Zhang break;
895431b7b81SElaine Zhang case DCLK_DECOM:
896431b7b81SElaine Zhang if (!(priv->spll_hz % rate)) {
897431b7b81SElaine Zhang src_clk = DCLK_DECOM_SEL_SPLL;
898431b7b81SElaine Zhang div = DIV_ROUND_UP(priv->spll_hz, rate);
899431b7b81SElaine Zhang } else {
900431b7b81SElaine Zhang src_clk = DCLK_DECOM_SEL_GPLL;
901431b7b81SElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
902431b7b81SElaine Zhang }
903431b7b81SElaine Zhang break;
9040265e00cSElaine Zhang default:
9050265e00cSElaine Zhang return -ENOENT;
9060265e00cSElaine Zhang }
9070265e00cSElaine Zhang
9080265e00cSElaine Zhang switch (clk_id) {
9090265e00cSElaine Zhang case CCLK_SRC_SDIO:
9104a69562cSElaine Zhang case HCLK_SDIO:
9110265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[104],
9120265e00cSElaine Zhang CCLK_SDIO_SRC_SEL_MASK |
9130265e00cSElaine Zhang CCLK_SDIO_SRC_DIV_MASK,
9140265e00cSElaine Zhang (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
9150265e00cSElaine Zhang (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
9160265e00cSElaine Zhang break;
9170265e00cSElaine Zhang case CCLK_SRC_SDMMC0:
9184a69562cSElaine Zhang case HCLK_SDMMC0:
9190265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[105],
9204a69562cSElaine Zhang CCLK_SDMMC0_SRC_SEL_MASK |
9214a69562cSElaine Zhang CCLK_SDMMC0_SRC_DIV_MASK,
9224a69562cSElaine Zhang (src_clk << CCLK_SDMMC0_SRC_SEL_SHIFT) |
9234a69562cSElaine Zhang (div - 1) << CCLK_SDMMC0_SRC_DIV_SHIFT);
9240265e00cSElaine Zhang break;
9250265e00cSElaine Zhang case CCLK_SRC_EMMC:
9264a69562cSElaine Zhang case HCLK_EMMC:
9270265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[89],
9280265e00cSElaine Zhang CCLK_EMMC_DIV_MASK |
9290265e00cSElaine Zhang CCLK_EMMC_SEL_MASK,
9300265e00cSElaine Zhang (src_clk << CCLK_EMMC_SEL_SHIFT) |
9310265e00cSElaine Zhang (div - 1) << CCLK_EMMC_DIV_SHIFT);
9320265e00cSElaine Zhang break;
9330265e00cSElaine Zhang case SCLK_FSPI_X2:
9340265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[89],
9350265e00cSElaine Zhang SCLK_FSPI_DIV_MASK |
9360265e00cSElaine Zhang SCLK_FSPI_SEL_MASK,
9370265e00cSElaine Zhang (src_clk << SCLK_FSPI_SEL_SHIFT) |
9380265e00cSElaine Zhang (div - 1) << SCLK_FSPI_DIV_SHIFT);
9390265e00cSElaine Zhang break;
9400265e00cSElaine Zhang case SCLK_FSPI1_X2:
9410265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[106],
9420265e00cSElaine Zhang SCLK_FSPI_DIV_MASK |
9430265e00cSElaine Zhang SCLK_FSPI_SEL_MASK,
9440265e00cSElaine Zhang (src_clk << SCLK_FSPI_SEL_SHIFT) |
9450265e00cSElaine Zhang (div - 1) << SCLK_FSPI_DIV_SHIFT);
9460265e00cSElaine Zhang break;
9470265e00cSElaine Zhang case BCLK_EMMC:
9480265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[90],
9490265e00cSElaine Zhang BCLK_EMMC_SEL_MASK,
9500265e00cSElaine Zhang src_clk << BCLK_EMMC_SEL_SHIFT);
9510265e00cSElaine Zhang break;
952431b7b81SElaine Zhang case DCLK_DECOM:
953431b7b81SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
954431b7b81SElaine Zhang DCLK_DECOM_DIV_MASK |
955431b7b81SElaine Zhang DCLK_DECOM_SEL_MASK,
956431b7b81SElaine Zhang (src_clk << DCLK_DECOM_SEL_SHIFT) |
957431b7b81SElaine Zhang (div - 1) << DCLK_DECOM_DIV_SHIFT);
958431b7b81SElaine Zhang break;
959431b7b81SElaine Zhang
9600265e00cSElaine Zhang default:
9610265e00cSElaine Zhang return -ENOENT;
9620265e00cSElaine Zhang }
9630265e00cSElaine Zhang
9640265e00cSElaine Zhang return rk3576_mmc_get_clk(priv, clk_id);
9650265e00cSElaine Zhang }
9660265e00cSElaine Zhang
9670265e00cSElaine Zhang #ifndef CONFIG_SPL_BUILD
9680265e00cSElaine Zhang
rk3576_aclk_vop_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)9690265e00cSElaine Zhang static ulong rk3576_aclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
9700265e00cSElaine Zhang {
9710265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
9720265e00cSElaine Zhang u32 div, sel, con, parent = 0;
9730265e00cSElaine Zhang
9740265e00cSElaine Zhang switch (clk_id) {
9750265e00cSElaine Zhang case ACLK_VOP_ROOT:
9760265e00cSElaine Zhang case ACLK_VOP:
9770265e00cSElaine Zhang con = readl(&cru->clksel_con[144]);
9780265e00cSElaine Zhang div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
9790265e00cSElaine Zhang sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
9800265e00cSElaine Zhang if (sel == ACLK_VOP_ROOT_SEL_GPLL)
9810265e00cSElaine Zhang parent = priv->gpll_hz;
9820265e00cSElaine Zhang else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
9830265e00cSElaine Zhang parent = priv->cpll_hz;
9840265e00cSElaine Zhang else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
9850265e00cSElaine Zhang parent = priv->aupll_hz;
9860265e00cSElaine Zhang else if (sel == ACLK_VOP_ROOT_SEL_SPLL)
9870265e00cSElaine Zhang parent = priv->spll_hz;
9880265e00cSElaine Zhang else if (sel == ACLK_VOP_ROOT_SEL_LPLL)
9890265e00cSElaine Zhang parent = priv->lpll_hz / 2;
9900265e00cSElaine Zhang return DIV_TO_RATE(parent, div);
9910265e00cSElaine Zhang case ACLK_VO0_ROOT:
9920265e00cSElaine Zhang con = readl(&cru->clksel_con[149]);
9930265e00cSElaine Zhang div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
9940265e00cSElaine Zhang sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
9950265e00cSElaine Zhang if (sel == ACLK_VO0_ROOT_SEL_GPLL)
9960265e00cSElaine Zhang parent = priv->gpll_hz;
9970265e00cSElaine Zhang else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
9980265e00cSElaine Zhang parent = priv->cpll_hz;
9990265e00cSElaine Zhang else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
10000265e00cSElaine Zhang parent = priv->lpll_hz / 2;
10010265e00cSElaine Zhang else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
10020265e00cSElaine Zhang parent = priv->bpll_hz / 4;
10030265e00cSElaine Zhang return DIV_TO_RATE(parent, div);
10040265e00cSElaine Zhang case ACLK_VO1_ROOT:
10050265e00cSElaine Zhang con = readl(&cru->clksel_con[158]);
10060265e00cSElaine Zhang div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
10070265e00cSElaine Zhang sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
10080265e00cSElaine Zhang if (sel == ACLK_VO0_ROOT_SEL_GPLL)
10090265e00cSElaine Zhang parent = priv->gpll_hz;
10100265e00cSElaine Zhang else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
10110265e00cSElaine Zhang parent = priv->cpll_hz;
10120265e00cSElaine Zhang else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
10130265e00cSElaine Zhang parent = priv->lpll_hz / 2;
10140265e00cSElaine Zhang else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
10150265e00cSElaine Zhang parent = priv->bpll_hz / 4;
10160265e00cSElaine Zhang return DIV_TO_RATE(parent, div);
10170265e00cSElaine Zhang case HCLK_VOP_ROOT:
10180265e00cSElaine Zhang con = readl(&cru->clksel_con[144]);
10190265e00cSElaine Zhang sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
10200265e00cSElaine Zhang if (sel == HCLK_VOP_ROOT_SEL_200M)
10210265e00cSElaine Zhang return 200 * MHz;
10220265e00cSElaine Zhang else if (sel == HCLK_VOP_ROOT_SEL_100M)
10230265e00cSElaine Zhang return 100 * MHz;
10240265e00cSElaine Zhang else if (sel == HCLK_VOP_ROOT_SEL_50M)
10250265e00cSElaine Zhang return 50 * MHz;
10260265e00cSElaine Zhang else
10270265e00cSElaine Zhang return OSC_HZ;
10280265e00cSElaine Zhang case PCLK_VOP_ROOT:
10290265e00cSElaine Zhang con = readl(&cru->clksel_con[144]);
10300265e00cSElaine Zhang sel = (con & PCLK_VOP_ROOT_SEL_MASK) >> PCLK_VOP_ROOT_SEL_SHIFT;
10310265e00cSElaine Zhang if (sel == PCLK_VOP_ROOT_SEL_100M)
10320265e00cSElaine Zhang return 100 * MHz;
10330265e00cSElaine Zhang else if (sel == PCLK_VOP_ROOT_SEL_50M)
10340265e00cSElaine Zhang return 50 * MHz;
10350265e00cSElaine Zhang else
10360265e00cSElaine Zhang return OSC_HZ;
10370265e00cSElaine Zhang
10380265e00cSElaine Zhang default:
10390265e00cSElaine Zhang return -ENOENT;
10400265e00cSElaine Zhang }
10410265e00cSElaine Zhang }
10420265e00cSElaine Zhang
rk3576_aclk_vop_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)10430265e00cSElaine Zhang static ulong rk3576_aclk_vop_set_clk(struct rk3576_clk_priv *priv,
10440265e00cSElaine Zhang ulong clk_id, ulong rate)
10450265e00cSElaine Zhang {
10460265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
10470265e00cSElaine Zhang int src_clk, div;
10480265e00cSElaine Zhang
10490265e00cSElaine Zhang switch (clk_id) {
10500265e00cSElaine Zhang case ACLK_VOP_ROOT:
10510265e00cSElaine Zhang case ACLK_VOP:
10520265e00cSElaine Zhang if (rate == 700 * MHz) {
10530265e00cSElaine Zhang src_clk = ACLK_VOP_ROOT_SEL_SPLL;
10540265e00cSElaine Zhang div = 1;
10550265e00cSElaine Zhang } else if (!(priv->cpll_hz % rate)) {
10560265e00cSElaine Zhang src_clk = ACLK_VOP_ROOT_SEL_CPLL;
10570265e00cSElaine Zhang div = DIV_ROUND_UP(priv->cpll_hz, rate);
10580265e00cSElaine Zhang } else {
10590265e00cSElaine Zhang src_clk = ACLK_VOP_ROOT_SEL_GPLL;
10600265e00cSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
10610265e00cSElaine Zhang }
10620265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[144],
10630265e00cSElaine Zhang ACLK_VOP_ROOT_DIV_MASK |
10640265e00cSElaine Zhang ACLK_VOP_ROOT_SEL_MASK,
10650265e00cSElaine Zhang (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
10660265e00cSElaine Zhang (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
10670265e00cSElaine Zhang break;
10680265e00cSElaine Zhang case ACLK_VO0_ROOT:
10690265e00cSElaine Zhang if (!(priv->cpll_hz % rate)) {
10700265e00cSElaine Zhang src_clk = ACLK_VO0_ROOT_SEL_CPLL;
10710265e00cSElaine Zhang div = DIV_ROUND_UP(priv->cpll_hz, rate);
10720265e00cSElaine Zhang } else {
10730265e00cSElaine Zhang src_clk = ACLK_VO0_ROOT_SEL_GPLL;
10740265e00cSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
10750265e00cSElaine Zhang }
10760265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[149],
10770265e00cSElaine Zhang ACLK_VO0_ROOT_DIV_MASK |
10780265e00cSElaine Zhang ACLK_VO0_ROOT_SEL_MASK,
10790265e00cSElaine Zhang (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
10800265e00cSElaine Zhang (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
10810265e00cSElaine Zhang break;
10820265e00cSElaine Zhang case ACLK_VO1_ROOT:
10830265e00cSElaine Zhang if (!(priv->cpll_hz % rate)) {
10840265e00cSElaine Zhang src_clk = ACLK_VO0_ROOT_SEL_CPLL;
10850265e00cSElaine Zhang div = DIV_ROUND_UP(priv->cpll_hz, rate);
10860265e00cSElaine Zhang } else {
10870265e00cSElaine Zhang src_clk = ACLK_VO0_ROOT_SEL_GPLL;
10880265e00cSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
10890265e00cSElaine Zhang }
10900265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[158],
10910265e00cSElaine Zhang ACLK_VO0_ROOT_DIV_MASK |
10920265e00cSElaine Zhang ACLK_VO0_ROOT_SEL_MASK,
10930265e00cSElaine Zhang (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
10940265e00cSElaine Zhang (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
10950265e00cSElaine Zhang break;
10960265e00cSElaine Zhang case HCLK_VOP_ROOT:
10970265e00cSElaine Zhang if (rate == 200 * MHz)
10980265e00cSElaine Zhang src_clk = HCLK_VOP_ROOT_SEL_200M;
10990265e00cSElaine Zhang else if (rate == 100 * MHz)
11000265e00cSElaine Zhang src_clk = HCLK_VOP_ROOT_SEL_100M;
11010265e00cSElaine Zhang else if (rate == 50 * MHz)
11020265e00cSElaine Zhang src_clk = HCLK_VOP_ROOT_SEL_50M;
11030265e00cSElaine Zhang else
11040265e00cSElaine Zhang src_clk = HCLK_VOP_ROOT_SEL_OSC;
11050265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[144],
11060265e00cSElaine Zhang HCLK_VOP_ROOT_SEL_MASK,
11070265e00cSElaine Zhang src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
11080265e00cSElaine Zhang break;
11090265e00cSElaine Zhang case PCLK_VOP_ROOT:
11100265e00cSElaine Zhang if (rate == 100 * MHz)
11110265e00cSElaine Zhang src_clk = PCLK_VOP_ROOT_SEL_100M;
11120265e00cSElaine Zhang else if (rate == 50 * MHz)
11130265e00cSElaine Zhang src_clk = PCLK_VOP_ROOT_SEL_50M;
11140265e00cSElaine Zhang else
11150265e00cSElaine Zhang src_clk = PCLK_VOP_ROOT_SEL_OSC;
11160265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[144],
11170265e00cSElaine Zhang PCLK_VOP_ROOT_SEL_MASK,
11180265e00cSElaine Zhang src_clk << PCLK_VOP_ROOT_SEL_SHIFT);
11190265e00cSElaine Zhang break;
11200265e00cSElaine Zhang
11210265e00cSElaine Zhang default:
11220265e00cSElaine Zhang return -ENOENT;
11230265e00cSElaine Zhang }
11240265e00cSElaine Zhang
11250265e00cSElaine Zhang return rk3576_aclk_vop_get_clk(priv, clk_id);
11260265e00cSElaine Zhang }
11270265e00cSElaine Zhang
rk3576_dclk_vop_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)11280265e00cSElaine Zhang static ulong rk3576_dclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
11290265e00cSElaine Zhang {
11300265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
11310265e00cSElaine Zhang u32 div, sel, con, parent;
11320265e00cSElaine Zhang
11330265e00cSElaine Zhang switch (clk_id) {
11340265e00cSElaine Zhang case DCLK_VP0:
11350265e00cSElaine Zhang case DCLK_VP0_SRC:
11360265e00cSElaine Zhang con = readl(&cru->clksel_con[145]);
11370265e00cSElaine Zhang div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
11380265e00cSElaine Zhang sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
11390265e00cSElaine Zhang break;
11400265e00cSElaine Zhang case DCLK_VP1:
11410265e00cSElaine Zhang case DCLK_VP1_SRC:
11420265e00cSElaine Zhang con = readl(&cru->clksel_con[146]);
11430265e00cSElaine Zhang div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
11440265e00cSElaine Zhang sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
11450265e00cSElaine Zhang break;
11460265e00cSElaine Zhang case DCLK_VP2:
11470265e00cSElaine Zhang case DCLK_VP2_SRC:
11480265e00cSElaine Zhang con = readl(&cru->clksel_con[147]);
11490265e00cSElaine Zhang div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
11500265e00cSElaine Zhang sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
11510265e00cSElaine Zhang break;
11520265e00cSElaine Zhang default:
11530265e00cSElaine Zhang return -ENOENT;
11540265e00cSElaine Zhang }
11550265e00cSElaine Zhang
11560265e00cSElaine Zhang if (sel == DCLK_VOP_SRC_SEL_VPLL)
11570265e00cSElaine Zhang parent = priv->vpll_hz;
11580265e00cSElaine Zhang else if (sel == DCLK_VOP_SRC_SEL_BPLL)
11590265e00cSElaine Zhang parent = priv->bpll_hz / 4;
11600265e00cSElaine Zhang else if (sel == DCLK_VOP_SRC_SEL_LPLL)
11610265e00cSElaine Zhang parent = priv->lpll_hz / 2;
11620265e00cSElaine Zhang else if (sel == DCLK_VOP_SRC_SEL_GPLL)
11630265e00cSElaine Zhang parent = priv->gpll_hz;
11640265e00cSElaine Zhang else
11650265e00cSElaine Zhang parent = priv->cpll_hz;
11660265e00cSElaine Zhang
11670265e00cSElaine Zhang return DIV_TO_RATE(parent, div);
11680265e00cSElaine Zhang }
11690265e00cSElaine Zhang
117026b67b4bSDamon Ding #define RK3576_VOP_PLL_LIMIT_FREQ 594000000
11710265e00cSElaine Zhang
rk3576_dclk_vop_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)11720265e00cSElaine Zhang static ulong rk3576_dclk_vop_set_clk(struct rk3576_clk_priv *priv,
11730265e00cSElaine Zhang ulong clk_id, ulong rate)
11740265e00cSElaine Zhang {
11750265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
11760265e00cSElaine Zhang ulong pll_rate, now, best_rate = 0;
11770265e00cSElaine Zhang u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
11780265e00cSElaine Zhang u32 mask, div_shift, sel_shift;
11790265e00cSElaine Zhang
11800265e00cSElaine Zhang switch (clk_id) {
11810265e00cSElaine Zhang case DCLK_VP0:
11820265e00cSElaine Zhang case DCLK_VP0_SRC:
11830265e00cSElaine Zhang conid = 145;
11840265e00cSElaine Zhang con = readl(&cru->clksel_con[conid]);
11850265e00cSElaine Zhang sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
11860265e00cSElaine Zhang mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
11870265e00cSElaine Zhang div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
11880265e00cSElaine Zhang sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
11890265e00cSElaine Zhang break;
11900265e00cSElaine Zhang case DCLK_VP1:
11910265e00cSElaine Zhang case DCLK_VP1_SRC:
11920265e00cSElaine Zhang conid = 146;
11930265e00cSElaine Zhang con = readl(&cru->clksel_con[conid]);
11940265e00cSElaine Zhang sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
11950265e00cSElaine Zhang mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
11960265e00cSElaine Zhang div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
11970265e00cSElaine Zhang sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
11980265e00cSElaine Zhang break;
11990265e00cSElaine Zhang case DCLK_VP2:
12000265e00cSElaine Zhang case DCLK_VP2_SRC:
12010265e00cSElaine Zhang conid = 147;
12020265e00cSElaine Zhang con = readl(&cru->clksel_con[conid]);
12030265e00cSElaine Zhang sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
12040265e00cSElaine Zhang mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
12050265e00cSElaine Zhang div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
12060265e00cSElaine Zhang sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
12070265e00cSElaine Zhang break;
12080265e00cSElaine Zhang default:
12090265e00cSElaine Zhang return -ENOENT;
12100265e00cSElaine Zhang }
12110265e00cSElaine Zhang
12120265e00cSElaine Zhang if (sel == DCLK_VOP_SRC_SEL_VPLL) {
12130265e00cSElaine Zhang pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
12140265e00cSElaine Zhang priv->cru, VPLL);
12150265e00cSElaine Zhang if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
12160265e00cSElaine Zhang div = DIV_ROUND_UP(pll_rate, rate);
12170265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[conid],
12180265e00cSElaine Zhang mask,
12190265e00cSElaine Zhang DCLK_VOP_SRC_SEL_VPLL << sel_shift |
12200265e00cSElaine Zhang ((div - 1) << div_shift));
12210265e00cSElaine Zhang } else {
12220265e00cSElaine Zhang div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ, rate);
12230265e00cSElaine Zhang if (div % 2)
12240265e00cSElaine Zhang div = div + 1;
12250265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[conid],
12260265e00cSElaine Zhang mask,
12270265e00cSElaine Zhang DCLK_VOP_SRC_SEL_VPLL << sel_shift |
12280265e00cSElaine Zhang ((div - 1) << div_shift));
12290265e00cSElaine Zhang rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
12300265e00cSElaine Zhang priv->cru, VPLL, div * rate);
12310265e00cSElaine Zhang priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
12320265e00cSElaine Zhang priv->cru, VPLL);
12330265e00cSElaine Zhang }
12340265e00cSElaine Zhang } else {
12350265e00cSElaine Zhang for (i = 0; i <= DCLK_VOP_SRC_SEL_LPLL; i++) {
12360265e00cSElaine Zhang switch (i) {
12370265e00cSElaine Zhang case DCLK_VOP_SRC_SEL_GPLL:
12380265e00cSElaine Zhang pll_rate = priv->gpll_hz;
12390265e00cSElaine Zhang break;
12400265e00cSElaine Zhang case DCLK_VOP_SRC_SEL_CPLL:
12410265e00cSElaine Zhang pll_rate = priv->cpll_hz;
12420265e00cSElaine Zhang break;
12430265e00cSElaine Zhang case DCLK_VOP_SRC_SEL_BPLL:
12440265e00cSElaine Zhang pll_rate = 0;
12450265e00cSElaine Zhang break;
12460265e00cSElaine Zhang case DCLK_VOP_SRC_SEL_LPLL:
12470265e00cSElaine Zhang pll_rate = 0;
12480265e00cSElaine Zhang break;
12490265e00cSElaine Zhang case DCLK_VOP_SRC_SEL_VPLL:
12500265e00cSElaine Zhang pll_rate = 0;
12510265e00cSElaine Zhang break;
12520265e00cSElaine Zhang default:
12530265e00cSElaine Zhang printf("do not support this vop pll sel\n");
12540265e00cSElaine Zhang return -EINVAL;
12550265e00cSElaine Zhang }
12560265e00cSElaine Zhang
12570265e00cSElaine Zhang div = DIV_ROUND_UP(pll_rate, rate);
12580265e00cSElaine Zhang if (div > 255)
12590265e00cSElaine Zhang continue;
12600265e00cSElaine Zhang now = pll_rate / div;
12610265e00cSElaine Zhang if (abs(rate - now) < abs(rate - best_rate)) {
12620265e00cSElaine Zhang best_rate = now;
12630265e00cSElaine Zhang best_div = div;
12640265e00cSElaine Zhang best_sel = i;
12650265e00cSElaine Zhang }
12660265e00cSElaine Zhang debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
12670265e00cSElaine Zhang pll_rate, best_rate, best_div, best_sel);
12680265e00cSElaine Zhang }
12690265e00cSElaine Zhang
12700265e00cSElaine Zhang if (best_rate) {
12710265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[conid],
12720265e00cSElaine Zhang mask,
12730265e00cSElaine Zhang best_sel << sel_shift |
12740265e00cSElaine Zhang (best_div - 1) << div_shift);
12750265e00cSElaine Zhang } else {
12760265e00cSElaine Zhang printf("do not support this vop freq %lu\n", rate);
12770265e00cSElaine Zhang return -EINVAL;
12780265e00cSElaine Zhang }
12790265e00cSElaine Zhang }
12800265e00cSElaine Zhang return rk3576_dclk_vop_get_clk(priv, clk_id);
12810265e00cSElaine Zhang }
12820265e00cSElaine Zhang
rk3576_clk_csihost_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)12830265e00cSElaine Zhang static ulong rk3576_clk_csihost_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
12840265e00cSElaine Zhang {
12850265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
12860265e00cSElaine Zhang u32 div, sel, con, parent;
12870265e00cSElaine Zhang
12880265e00cSElaine Zhang switch (clk_id) {
12890265e00cSElaine Zhang case CLK_DSIHOST0:
12900265e00cSElaine Zhang con = readl(&cru->clksel_con[151]);
12910265e00cSElaine Zhang div = (con & CLK_DSIHOST0_DIV_MASK) >> CLK_DSIHOST0_DIV_SHIFT;
12920265e00cSElaine Zhang sel = (con & CLK_DSIHOST0_SEL_MASK) >> CLK_DSIHOST0_SEL_SHIFT;
12930265e00cSElaine Zhang break;
12940265e00cSElaine Zhang default:
12950265e00cSElaine Zhang return -ENOENT;
12960265e00cSElaine Zhang }
12970265e00cSElaine Zhang
12980265e00cSElaine Zhang if (sel == CLK_DSIHOST0_SEL_VPLL)
12990265e00cSElaine Zhang parent = priv->vpll_hz;
13000265e00cSElaine Zhang else if (sel == CLK_DSIHOST0_SEL_BPLL)
13010265e00cSElaine Zhang parent = priv->bpll_hz / 4;
13020265e00cSElaine Zhang else if (sel == CLK_DSIHOST0_SEL_LPLL)
13030265e00cSElaine Zhang parent = priv->lpll_hz / 2;
13040265e00cSElaine Zhang else if (sel == CLK_DSIHOST0_SEL_GPLL)
13050265e00cSElaine Zhang parent = priv->gpll_hz;
13060265e00cSElaine Zhang else if (sel == CLK_DSIHOST0_SEL_SPLL)
13070265e00cSElaine Zhang parent = priv->spll_hz;
13080265e00cSElaine Zhang else
13090265e00cSElaine Zhang parent = priv->cpll_hz;
13100265e00cSElaine Zhang
13110265e00cSElaine Zhang return DIV_TO_RATE(parent, div);
13120265e00cSElaine Zhang }
13130265e00cSElaine Zhang
rk3576_clk_csihost_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)13140265e00cSElaine Zhang static ulong rk3576_clk_csihost_set_clk(struct rk3576_clk_priv *priv,
13150265e00cSElaine Zhang ulong clk_id, ulong rate)
13160265e00cSElaine Zhang {
13170265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
13180265e00cSElaine Zhang ulong pll_rate, now, best_rate = 0;
13190265e00cSElaine Zhang u32 i, con, div, best_div = 0, best_sel = 0;
13200265e00cSElaine Zhang u32 mask, div_shift, sel_shift;
13210265e00cSElaine Zhang
13220265e00cSElaine Zhang switch (clk_id) {
13230265e00cSElaine Zhang case CLK_DSIHOST0:
13240265e00cSElaine Zhang con = 151;
13250265e00cSElaine Zhang mask = CLK_DSIHOST0_SEL_MASK | CLK_DSIHOST0_DIV_MASK;
13260265e00cSElaine Zhang div_shift = CLK_DSIHOST0_DIV_SHIFT;
13270265e00cSElaine Zhang sel_shift = CLK_DSIHOST0_SEL_SHIFT;
13280265e00cSElaine Zhang break;
13290265e00cSElaine Zhang default:
13300265e00cSElaine Zhang return -ENOENT;
13310265e00cSElaine Zhang }
13320265e00cSElaine Zhang for (i = 0; i <= CLK_DSIHOST0_SEL_LPLL; i++) {
13330265e00cSElaine Zhang switch (i) {
13340265e00cSElaine Zhang case CLK_DSIHOST0_SEL_GPLL:
13350265e00cSElaine Zhang pll_rate = priv->gpll_hz;
13360265e00cSElaine Zhang break;
13370265e00cSElaine Zhang case CLK_DSIHOST0_SEL_CPLL:
13380265e00cSElaine Zhang pll_rate = priv->cpll_hz;
13390265e00cSElaine Zhang break;
13400265e00cSElaine Zhang case CLK_DSIHOST0_SEL_BPLL:
13410265e00cSElaine Zhang pll_rate = 0;
13420265e00cSElaine Zhang break;
13430265e00cSElaine Zhang case CLK_DSIHOST0_SEL_LPLL:
13440265e00cSElaine Zhang pll_rate = 0;
13450265e00cSElaine Zhang break;
13460265e00cSElaine Zhang case CLK_DSIHOST0_SEL_VPLL:
13470265e00cSElaine Zhang pll_rate = 0;
13480265e00cSElaine Zhang break;
13490265e00cSElaine Zhang case CLK_DSIHOST0_SEL_SPLL:
13500265e00cSElaine Zhang pll_rate = priv->spll_hz;
13510265e00cSElaine Zhang break;
13520265e00cSElaine Zhang default:
13530265e00cSElaine Zhang printf("do not support this vop pll sel\n");
13540265e00cSElaine Zhang return -EINVAL;
13550265e00cSElaine Zhang }
13560265e00cSElaine Zhang
13570265e00cSElaine Zhang div = DIV_ROUND_UP(pll_rate, rate);
13580265e00cSElaine Zhang if (div > 255)
13590265e00cSElaine Zhang continue;
13600265e00cSElaine Zhang now = pll_rate / div;
13610265e00cSElaine Zhang if (abs(rate - now) < abs(rate - best_rate)) {
13620265e00cSElaine Zhang best_rate = now;
13630265e00cSElaine Zhang best_div = div;
13640265e00cSElaine Zhang best_sel = i;
13650265e00cSElaine Zhang }
13660265e00cSElaine Zhang debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
13670265e00cSElaine Zhang pll_rate, best_rate, best_div, best_sel);
13680265e00cSElaine Zhang }
13690265e00cSElaine Zhang if (best_rate) {
13700265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[con],
13710265e00cSElaine Zhang mask,
13720265e00cSElaine Zhang best_sel << sel_shift |
13730265e00cSElaine Zhang (best_div - 1) << div_shift);
13740265e00cSElaine Zhang } else {
13750265e00cSElaine Zhang printf("do not support this vop freq %lu\n", rate);
13760265e00cSElaine Zhang return -EINVAL;
13770265e00cSElaine Zhang }
13780265e00cSElaine Zhang return rk3576_clk_csihost_get_clk(priv, clk_id);
13790265e00cSElaine Zhang }
13800265e00cSElaine Zhang
rk3576_dclk_ebc_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)13810265e00cSElaine Zhang static ulong rk3576_dclk_ebc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
13820265e00cSElaine Zhang {
13830265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
13840265e00cSElaine Zhang u32 div, sel, con, parent;
13850265e00cSElaine Zhang unsigned long m = 0, n = 0;
13860265e00cSElaine Zhang
13870265e00cSElaine Zhang switch (clk_id) {
13880265e00cSElaine Zhang case DCLK_EBC:
13890265e00cSElaine Zhang con = readl(&cru->clksel_con[123]);
13900265e00cSElaine Zhang div = (con & DCLK_EBC_DIV_MASK) >> DCLK_EBC_DIV_SHIFT;
13910265e00cSElaine Zhang sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
13920265e00cSElaine Zhang if (sel == DCLK_EBC_SEL_CPLL)
13930265e00cSElaine Zhang parent = priv->cpll_hz;
13940265e00cSElaine Zhang else if (sel == DCLK_EBC_SEL_VPLL)
13950265e00cSElaine Zhang parent = priv->vpll_hz;
13960265e00cSElaine Zhang else if (sel == DCLK_EBC_SEL_AUPLL)
13970265e00cSElaine Zhang parent = priv->aupll_hz;
13980265e00cSElaine Zhang else if (sel == DCLK_EBC_SEL_LPLL)
13990265e00cSElaine Zhang parent = priv->lpll_hz / 2;
14000265e00cSElaine Zhang else if (sel == DCLK_EBC_SEL_GPLL)
14010265e00cSElaine Zhang parent = priv->gpll_hz;
14020265e00cSElaine Zhang else if (sel == DCLK_EBC_SEL_FRAC_SRC)
14030265e00cSElaine Zhang parent = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC);
14040265e00cSElaine Zhang else
14050265e00cSElaine Zhang parent = OSC_HZ;
14060265e00cSElaine Zhang return DIV_TO_RATE(parent, div);
14070265e00cSElaine Zhang case DCLK_EBC_FRAC_SRC:
14080265e00cSElaine Zhang con = readl(&cru->clksel_con[123]);
14090265e00cSElaine Zhang div = readl(&cru->clksel_con[122]);
14100265e00cSElaine Zhang sel = (con & DCLK_EBC_FRAC_SRC_SEL_MASK) >> DCLK_EBC_FRAC_SRC_SEL_SHIFT;
14110265e00cSElaine Zhang if (sel == DCLK_EBC_FRAC_SRC_SEL_GPLL)
14120265e00cSElaine Zhang parent = priv->gpll_hz;
14130265e00cSElaine Zhang else if (sel == DCLK_EBC_FRAC_SRC_SEL_CPLL)
14140265e00cSElaine Zhang parent = priv->cpll_hz;
14150265e00cSElaine Zhang else if (sel == DCLK_EBC_FRAC_SRC_SEL_VPLL)
14160265e00cSElaine Zhang parent = priv->vpll_hz;
14170265e00cSElaine Zhang else if (sel == DCLK_EBC_FRAC_SRC_SEL_AUPLL)
14180265e00cSElaine Zhang parent = priv->aupll_hz;
14190265e00cSElaine Zhang else
14200265e00cSElaine Zhang parent = OSC_HZ;
14210265e00cSElaine Zhang
14220265e00cSElaine Zhang n = div & CLK_UART_FRAC_NUMERATOR_MASK;
14230265e00cSElaine Zhang n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
14240265e00cSElaine Zhang m = div & CLK_UART_FRAC_DENOMINATOR_MASK;
14250265e00cSElaine Zhang m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
14260265e00cSElaine Zhang return parent * n / m;
14270265e00cSElaine Zhang default:
14280265e00cSElaine Zhang return -ENOENT;
14290265e00cSElaine Zhang }
14300265e00cSElaine Zhang }
14310265e00cSElaine Zhang
rk3576_dclk_ebc_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)14320265e00cSElaine Zhang static ulong rk3576_dclk_ebc_set_clk(struct rk3576_clk_priv *priv,
14330265e00cSElaine Zhang ulong clk_id, ulong rate)
14340265e00cSElaine Zhang {
14350265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
1436f215d626SElaine Zhang ulong pll_rate, now, best_rate = 0;
1437f215d626SElaine Zhang u32 i, con, sel, div, best_div = 0, best_sel = 0;
14380265e00cSElaine Zhang unsigned long m = 0, n = 0, val;
14390265e00cSElaine Zhang
14400265e00cSElaine Zhang switch (clk_id) {
14410265e00cSElaine Zhang case DCLK_EBC:
1442f215d626SElaine Zhang con = readl(&cru->clksel_con[123]);
1443f215d626SElaine Zhang sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
1444f215d626SElaine Zhang if (sel == DCLK_EBC_SEL_VPLL) {
1445f215d626SElaine Zhang pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1446f215d626SElaine Zhang priv->cru, VPLL);
1447f215d626SElaine Zhang if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ &&
1448f215d626SElaine Zhang pll_rate % rate == 0) {
1449f215d626SElaine Zhang div = DIV_ROUND_UP(pll_rate, rate);
1450f215d626SElaine Zhang rk_clrsetreg(&cru->clksel_con[123],
1451f215d626SElaine Zhang DCLK_EBC_DIV_MASK,
1452f215d626SElaine Zhang (div - 1) << DCLK_EBC_DIV_SHIFT);
14530265e00cSElaine Zhang } else {
1454f215d626SElaine Zhang div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ,
1455f215d626SElaine Zhang rate);
1456f215d626SElaine Zhang if (div % 2)
1457f215d626SElaine Zhang div = div + 1;
1458f215d626SElaine Zhang rk_clrsetreg(&cru->clksel_con[123],
1459f215d626SElaine Zhang DCLK_EBC_DIV_MASK,
1460f215d626SElaine Zhang (div - 1) << DCLK_EBC_DIV_SHIFT);
1461f215d626SElaine Zhang rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
1462f215d626SElaine Zhang priv->cru,
1463f215d626SElaine Zhang VPLL, div * rate);
1464f215d626SElaine Zhang priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1465f215d626SElaine Zhang priv->cru,
1466f215d626SElaine Zhang VPLL);
1467f215d626SElaine Zhang }
1468f215d626SElaine Zhang } else if (sel == DCLK_EBC_SEL_FRAC_SRC) {
14690265e00cSElaine Zhang rk3576_dclk_ebc_set_clk(priv, DCLK_EBC_FRAC_SRC, rate);
14700265e00cSElaine Zhang div = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC) / rate;
14710265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[123],
1472f215d626SElaine Zhang DCLK_EBC_DIV_MASK,
14730265e00cSElaine Zhang (div - 1) << DCLK_EBC_DIV_SHIFT);
1474f215d626SElaine Zhang } else {
1475f215d626SElaine Zhang for (i = 0; i <= DCLK_EBC_SEL_LPLL; i++) {
1476f215d626SElaine Zhang switch (i) {
1477f215d626SElaine Zhang case DCLK_EBC_SEL_GPLL:
1478f215d626SElaine Zhang pll_rate = priv->gpll_hz;
1479f215d626SElaine Zhang break;
1480f215d626SElaine Zhang case DCLK_EBC_SEL_CPLL:
1481f215d626SElaine Zhang pll_rate = priv->cpll_hz;
1482f215d626SElaine Zhang break;
1483f215d626SElaine Zhang case DCLK_EBC_SEL_VPLL:
1484f215d626SElaine Zhang pll_rate = 0;
1485f215d626SElaine Zhang break;
1486f215d626SElaine Zhang case DCLK_EBC_SEL_AUPLL:
1487f215d626SElaine Zhang pll_rate = priv->aupll_hz;
1488f215d626SElaine Zhang break;
1489f215d626SElaine Zhang case DCLK_EBC_SEL_LPLL:
1490f215d626SElaine Zhang pll_rate = 0;
1491f215d626SElaine Zhang break;
1492f215d626SElaine Zhang default:
1493f215d626SElaine Zhang printf("not support ebc pll sel\n");
1494f215d626SElaine Zhang return -EINVAL;
1495f215d626SElaine Zhang }
1496f215d626SElaine Zhang
1497f215d626SElaine Zhang div = DIV_ROUND_UP(pll_rate, rate);
1498f215d626SElaine Zhang if (div > 255)
1499f215d626SElaine Zhang continue;
1500f215d626SElaine Zhang now = pll_rate / div;
1501f215d626SElaine Zhang if (abs(rate - now) < abs(rate - best_rate)) {
1502f215d626SElaine Zhang best_rate = now;
1503f215d626SElaine Zhang best_div = div;
1504f215d626SElaine Zhang best_sel = i;
1505f215d626SElaine Zhang }
1506f215d626SElaine Zhang }
1507f215d626SElaine Zhang
1508f215d626SElaine Zhang if (best_rate) {
1509f215d626SElaine Zhang rk_clrsetreg(&cru->clksel_con[123],
1510f215d626SElaine Zhang DCLK_EBC_DIV_MASK |
1511f215d626SElaine Zhang DCLK_EBC_SEL_MASK,
1512f215d626SElaine Zhang best_sel <<
1513f215d626SElaine Zhang DCLK_EBC_SEL_SHIFT |
1514f215d626SElaine Zhang (best_div - 1) <<
1515f215d626SElaine Zhang DCLK_EBC_DIV_SHIFT);
1516f215d626SElaine Zhang } else {
1517f215d626SElaine Zhang printf("do not support this vop freq %lu\n",
1518f215d626SElaine Zhang rate);
1519f215d626SElaine Zhang return -EINVAL;
1520f215d626SElaine Zhang }
1521f215d626SElaine Zhang }
15220265e00cSElaine Zhang break;
15230265e00cSElaine Zhang case DCLK_EBC_FRAC_SRC:
15240265e00cSElaine Zhang sel = DCLK_EBC_FRAC_SRC_SEL_GPLL;
15250265e00cSElaine Zhang div = 1;
15260265e00cSElaine Zhang rational_best_approximation(rate, priv->gpll_hz,
15270265e00cSElaine Zhang GENMASK(16 - 1, 0),
15280265e00cSElaine Zhang GENMASK(16 - 1, 0),
15290265e00cSElaine Zhang &m, &n);
15300265e00cSElaine Zhang
15310265e00cSElaine Zhang if (m < 4 && m != 0) {
15320265e00cSElaine Zhang if (n % 2 == 0)
15330265e00cSElaine Zhang val = 1;
15340265e00cSElaine Zhang else
15350265e00cSElaine Zhang val = DIV_ROUND_UP(4, m);
15360265e00cSElaine Zhang
15370265e00cSElaine Zhang n *= val;
15380265e00cSElaine Zhang m *= val;
15390265e00cSElaine Zhang if (n > 0xffff) {
15400265e00cSElaine Zhang n = 0xffff;
15410265e00cSElaine Zhang }
15420265e00cSElaine Zhang }
15430265e00cSElaine Zhang
15440265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[123],
15450265e00cSElaine Zhang DCLK_EBC_FRAC_SRC_SEL_MASK,
15460265e00cSElaine Zhang (sel << DCLK_EBC_FRAC_SRC_SEL_SHIFT));
15470265e00cSElaine Zhang if (m && n) {
15480265e00cSElaine Zhang val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
15490265e00cSElaine Zhang writel(val, &cru->clksel_con[122]);
15500265e00cSElaine Zhang }
15510265e00cSElaine Zhang break;
15520265e00cSElaine Zhang default:
15530265e00cSElaine Zhang return -ENOENT;
15540265e00cSElaine Zhang }
15550265e00cSElaine Zhang return rk3576_dclk_ebc_get_clk(priv, clk_id);
15560265e00cSElaine Zhang }
15570265e00cSElaine Zhang
rk3576_gmac_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)15580265e00cSElaine Zhang static ulong rk3576_gmac_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
15590265e00cSElaine Zhang {
15600265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
15610265e00cSElaine Zhang u32 con, div, src, p_rate;
15620265e00cSElaine Zhang
15630265e00cSElaine Zhang switch (clk_id) {
15640265e00cSElaine Zhang case CLK_GMAC0_PTP_REF_SRC:
15650265e00cSElaine Zhang case CLK_GMAC0_PTP_REF:
15660265e00cSElaine Zhang con = readl(&cru->clksel_con[105]);
15670265e00cSElaine Zhang div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
15680265e00cSElaine Zhang src = (con & CLK_GMAC0_PTP_SEL_MASK) >> CLK_GMAC0_PTP_SEL_SHIFT;
15690265e00cSElaine Zhang if (src == CLK_GMAC0_PTP_SEL_GPLL)
15700265e00cSElaine Zhang p_rate = priv->gpll_hz;
15710265e00cSElaine Zhang else if (src == CLK_GMAC0_PTP_SEL_CPLL)
15720265e00cSElaine Zhang p_rate = priv->cpll_hz;
15730265e00cSElaine Zhang else
15740265e00cSElaine Zhang p_rate = GMAC0_PTP_REFCLK_IN;
15750265e00cSElaine Zhang return DIV_TO_RATE(p_rate, div);
15760265e00cSElaine Zhang case CLK_GMAC1_PTP_REF_SRC:
15770265e00cSElaine Zhang case CLK_GMAC1_PTP_REF:
15780265e00cSElaine Zhang con = readl(&cru->clksel_con[104]);
15790265e00cSElaine Zhang div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
15800265e00cSElaine Zhang src = (con & CLK_GMAC1_PTP_SEL_MASK) >> CLK_GMAC1_PTP_SEL_SHIFT;
15810265e00cSElaine Zhang if (src == CLK_GMAC1_PTP_SEL_GPLL)
15820265e00cSElaine Zhang p_rate = priv->gpll_hz;
15830265e00cSElaine Zhang else if (src == CLK_GMAC1_PTP_SEL_CPLL)
15840265e00cSElaine Zhang p_rate = priv->cpll_hz;
15850265e00cSElaine Zhang else
15860265e00cSElaine Zhang p_rate = GMAC1_PTP_REFCLK_IN;
15870265e00cSElaine Zhang return DIV_TO_RATE(p_rate, div);
15880265e00cSElaine Zhang case CLK_GMAC0_125M_SRC:
15890265e00cSElaine Zhang con = readl(&cru->clksel_con[30]);
15900265e00cSElaine Zhang div = (con & CLK_GMAC0_125M_DIV_MASK) >> CLK_GMAC0_125M_DIV_SHIFT;
15910265e00cSElaine Zhang return DIV_TO_RATE(priv->cpll_hz, div);
15920265e00cSElaine Zhang case CLK_GMAC1_125M_SRC:
15930265e00cSElaine Zhang con = readl(&cru->clksel_con[31]);
15940265e00cSElaine Zhang div = (con & CLK_GMAC1_125M_DIV_MASK) >> CLK_GMAC1_125M_DIV_SHIFT;
15950265e00cSElaine Zhang return DIV_TO_RATE(priv->cpll_hz, div);
15960265e00cSElaine Zhang default:
15970265e00cSElaine Zhang return -ENOENT;
15980265e00cSElaine Zhang }
15990265e00cSElaine Zhang }
16000265e00cSElaine Zhang
rk3576_gmac_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)16010265e00cSElaine Zhang static ulong rk3576_gmac_set_clk(struct rk3576_clk_priv *priv,
16020265e00cSElaine Zhang ulong clk_id, ulong rate)
16030265e00cSElaine Zhang {
16040265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
16050265e00cSElaine Zhang int div, src;
16060265e00cSElaine Zhang
16070265e00cSElaine Zhang div = DIV_ROUND_UP(priv->cpll_hz, rate);
16080265e00cSElaine Zhang
16090265e00cSElaine Zhang switch (clk_id) {
16100265e00cSElaine Zhang case CLK_GMAC0_PTP_REF_SRC:
16110265e00cSElaine Zhang case CLK_GMAC0_PTP_REF:
16120265e00cSElaine Zhang if (rate == GMAC0_PTP_REFCLK_IN) {
16130265e00cSElaine Zhang src = CLK_GMAC0_PTP_SEL_REFIN;
16140265e00cSElaine Zhang div = 1;
16150265e00cSElaine Zhang } else if (!(priv->gpll_hz % rate)) {
16160265e00cSElaine Zhang src = CLK_GMAC0_PTP_SEL_GPLL;
16170265e00cSElaine Zhang div = priv->gpll_hz / rate;
16180265e00cSElaine Zhang } else {
16190265e00cSElaine Zhang src = CLK_GMAC0_PTP_SEL_CPLL;
16200265e00cSElaine Zhang div = priv->cpll_hz / rate;
16210265e00cSElaine Zhang }
16220265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[105],
16230265e00cSElaine Zhang CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
16240265e00cSElaine Zhang src << CLK_GMAC0_PTP_SEL_SHIFT |
16250265e00cSElaine Zhang (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
16260265e00cSElaine Zhang break;
16270265e00cSElaine Zhang case CLK_GMAC1_PTP_REF_SRC:
16280265e00cSElaine Zhang case CLK_GMAC1_PTP_REF:
16290265e00cSElaine Zhang if (rate == GMAC1_PTP_REFCLK_IN) {
16300265e00cSElaine Zhang src = CLK_GMAC1_PTP_SEL_REFIN;
16310265e00cSElaine Zhang div = 1;
16320265e00cSElaine Zhang } else if (!(priv->gpll_hz % rate)) {
16330265e00cSElaine Zhang src = CLK_GMAC1_PTP_SEL_GPLL;
16340265e00cSElaine Zhang div = priv->gpll_hz / rate;
16350265e00cSElaine Zhang } else {
16360265e00cSElaine Zhang src = CLK_GMAC1_PTP_SEL_CPLL;
16370265e00cSElaine Zhang div = priv->cpll_hz / rate;
16380265e00cSElaine Zhang }
16390265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[104],
16400265e00cSElaine Zhang CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
16410265e00cSElaine Zhang src << CLK_GMAC1_PTP_SEL_SHIFT |
16420265e00cSElaine Zhang (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
16430265e00cSElaine Zhang break;
16440265e00cSElaine Zhang
16450265e00cSElaine Zhang case CLK_GMAC0_125M_SRC:
16460265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[30],
16470265e00cSElaine Zhang CLK_GMAC0_125M_DIV_MASK,
16480265e00cSElaine Zhang (div - 1) << CLK_GMAC0_125M_DIV_SHIFT);
16490265e00cSElaine Zhang break;
16500265e00cSElaine Zhang case CLK_GMAC1_125M_SRC:
16510265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[31],
16520265e00cSElaine Zhang CLK_GMAC1_125M_DIV_MASK,
16530265e00cSElaine Zhang (div - 1) << CLK_GMAC1_125M_DIV_SHIFT);
16540265e00cSElaine Zhang break;
16550265e00cSElaine Zhang default:
16560265e00cSElaine Zhang return -ENOENT;
16570265e00cSElaine Zhang }
16580265e00cSElaine Zhang
16590265e00cSElaine Zhang return rk3576_gmac_get_clk(priv, clk_id);
16600265e00cSElaine Zhang }
16610265e00cSElaine Zhang
rk3576_uart_frac_get_rate(struct rk3576_clk_priv * priv,ulong clk_id)16620265e00cSElaine Zhang static ulong rk3576_uart_frac_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
16630265e00cSElaine Zhang {
16640265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
16650265e00cSElaine Zhang u32 reg, con, fracdiv, p_src, p_rate;
16660265e00cSElaine Zhang unsigned long m, n;
16670265e00cSElaine Zhang
16680265e00cSElaine Zhang switch (clk_id) {
16690265e00cSElaine Zhang case CLK_UART_FRAC_0:
16700265e00cSElaine Zhang reg = 21;
16710265e00cSElaine Zhang break;
16720265e00cSElaine Zhang case CLK_UART_FRAC_1:
16730265e00cSElaine Zhang reg = 23;
16740265e00cSElaine Zhang break;
16750265e00cSElaine Zhang case CLK_UART_FRAC_2:
16760265e00cSElaine Zhang reg = 25;
16770265e00cSElaine Zhang break;
16780265e00cSElaine Zhang default:
16790265e00cSElaine Zhang return -ENOENT;
16800265e00cSElaine Zhang }
16810265e00cSElaine Zhang con = readl(&cru->clksel_con[reg + 1]);
16820265e00cSElaine Zhang p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
16830265e00cSElaine Zhang if (p_src == CLK_UART_SRC_SEL_GPLL)
16840265e00cSElaine Zhang p_rate = priv->gpll_hz;
16850265e00cSElaine Zhang else if (p_src == CLK_UART_SRC_SEL_CPLL)
16860265e00cSElaine Zhang p_rate = priv->cpll_hz;
16870265e00cSElaine Zhang else if (p_src == CLK_UART_SRC_SEL_AUPLL)
16880265e00cSElaine Zhang p_rate = priv->aupll_hz;
16890265e00cSElaine Zhang else
16900265e00cSElaine Zhang p_rate = OSC_HZ;
16910265e00cSElaine Zhang
16920265e00cSElaine Zhang fracdiv = readl(&cru->clksel_con[reg]);
16930265e00cSElaine Zhang n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
16940265e00cSElaine Zhang n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
16950265e00cSElaine Zhang m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
16960265e00cSElaine Zhang m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
16970265e00cSElaine Zhang return p_rate * n / m;
16980265e00cSElaine Zhang }
16990265e00cSElaine Zhang
rk3576_uart_frac_set_rate(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)17000265e00cSElaine Zhang static ulong rk3576_uart_frac_set_rate(struct rk3576_clk_priv *priv,
17010265e00cSElaine Zhang ulong clk_id, ulong rate)
17020265e00cSElaine Zhang {
17030265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
17040265e00cSElaine Zhang u32 reg, clk_src, p_rate;
17050265e00cSElaine Zhang unsigned long m = 0, n = 0, val;
17060265e00cSElaine Zhang
17070265e00cSElaine Zhang if (priv->cpll_hz % rate == 0) {
17080265e00cSElaine Zhang clk_src = CLK_UART_SRC_SEL_CPLL;
17090265e00cSElaine Zhang p_rate = priv->cpll_hz;
17100265e00cSElaine Zhang } else if (rate == OSC_HZ) {
17110265e00cSElaine Zhang clk_src = CLK_UART_SRC_SEL_OSC;
17120265e00cSElaine Zhang p_rate = OSC_HZ;
17130265e00cSElaine Zhang } else {
17140265e00cSElaine Zhang clk_src = CLK_UART_SRC_SEL_GPLL;
17150265e00cSElaine Zhang p_rate = priv->cpll_hz;
17160265e00cSElaine Zhang }
17170265e00cSElaine Zhang rational_best_approximation(rate, p_rate,
17180265e00cSElaine Zhang GENMASK(16 - 1, 0),
17190265e00cSElaine Zhang GENMASK(16 - 1, 0),
17200265e00cSElaine Zhang &m, &n);
17210265e00cSElaine Zhang
17220265e00cSElaine Zhang if (m < 4 && m != 0) {
17230265e00cSElaine Zhang if (n % 2 == 0)
17240265e00cSElaine Zhang val = 1;
17250265e00cSElaine Zhang else
17260265e00cSElaine Zhang val = DIV_ROUND_UP(4, m);
17270265e00cSElaine Zhang
17280265e00cSElaine Zhang n *= val;
17290265e00cSElaine Zhang m *= val;
17300265e00cSElaine Zhang if (n > 0xffff) {
17310265e00cSElaine Zhang n = 0xffff;
17320265e00cSElaine Zhang }
17330265e00cSElaine Zhang }
17340265e00cSElaine Zhang
17350265e00cSElaine Zhang
17360265e00cSElaine Zhang switch (clk_id) {
17370265e00cSElaine Zhang case CLK_UART_FRAC_0:
17380265e00cSElaine Zhang reg = 21;
17390265e00cSElaine Zhang break;
17400265e00cSElaine Zhang case CLK_UART_FRAC_1:
17410265e00cSElaine Zhang reg = 23;
17420265e00cSElaine Zhang break;
17430265e00cSElaine Zhang case CLK_UART_FRAC_2:
17440265e00cSElaine Zhang reg = 25;
17450265e00cSElaine Zhang break;
17460265e00cSElaine Zhang default:
17470265e00cSElaine Zhang return -ENOENT;
17480265e00cSElaine Zhang }
17490265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[reg +1],
17500265e00cSElaine Zhang CLK_UART_SRC_SEL_MASK,
17510265e00cSElaine Zhang (clk_src << CLK_UART_SRC_SEL_SHIFT));
17520265e00cSElaine Zhang if (m && n) {
17530265e00cSElaine Zhang val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
17540265e00cSElaine Zhang writel(val, &cru->clksel_con[reg]);
17550265e00cSElaine Zhang }
17560265e00cSElaine Zhang
17570265e00cSElaine Zhang return rk3576_uart_frac_get_rate(priv, clk_id);
17580265e00cSElaine Zhang }
17590265e00cSElaine Zhang
17600265e00cSElaine Zhang
rk3576_uart_get_rate(struct rk3576_clk_priv * priv,ulong clk_id)17610265e00cSElaine Zhang static ulong rk3576_uart_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
17620265e00cSElaine Zhang {
17630265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
17640265e00cSElaine Zhang u32 con, div, src, p_rate;
17650265e00cSElaine Zhang
17660265e00cSElaine Zhang switch (clk_id) {
17670265e00cSElaine Zhang case SCLK_UART0:
17680265e00cSElaine Zhang con = readl(&cru->clksel_con[60]);
17690265e00cSElaine Zhang break;
17700265e00cSElaine Zhang case SCLK_UART1:
17710265e00cSElaine Zhang con = readl(&cru->pmuclksel_con[8]);
17720265e00cSElaine Zhang src = (con & CLK_UART1_SEL_MASK) >> CLK_UART1_SEL_SHIFT;
17730265e00cSElaine Zhang if (src == CLK_UART1_SEL_OSC)
17740265e00cSElaine Zhang return OSC_HZ;
17750265e00cSElaine Zhang con = readl(&cru->clksel_con[27]);
17760265e00cSElaine Zhang break;
17770265e00cSElaine Zhang case SCLK_UART2:
17780265e00cSElaine Zhang con = readl(&cru->clksel_con[61]);
17790265e00cSElaine Zhang break;
17800265e00cSElaine Zhang case SCLK_UART3:
17810265e00cSElaine Zhang con = readl(&cru->clksel_con[62]);
17820265e00cSElaine Zhang break;
17830265e00cSElaine Zhang case SCLK_UART4:
17840265e00cSElaine Zhang con = readl(&cru->clksel_con[63]);
17850265e00cSElaine Zhang break;
17860265e00cSElaine Zhang case SCLK_UART5:
17870265e00cSElaine Zhang con = readl(&cru->clksel_con[64]);
17880265e00cSElaine Zhang break;
17890265e00cSElaine Zhang case SCLK_UART6:
17900265e00cSElaine Zhang con = readl(&cru->clksel_con[65]);
17910265e00cSElaine Zhang break;
17920265e00cSElaine Zhang case SCLK_UART7:
17930265e00cSElaine Zhang con = readl(&cru->clksel_con[66]);
17940265e00cSElaine Zhang break;
17950265e00cSElaine Zhang case SCLK_UART8:
17960265e00cSElaine Zhang con = readl(&cru->clksel_con[67]);
17970265e00cSElaine Zhang break;
17980265e00cSElaine Zhang case SCLK_UART9:
17990265e00cSElaine Zhang con = readl(&cru->clksel_con[68]);
18000265e00cSElaine Zhang break;
18010265e00cSElaine Zhang case SCLK_UART10:
18020265e00cSElaine Zhang con = readl(&cru->clksel_con[69]);
18030265e00cSElaine Zhang break;
18040265e00cSElaine Zhang case SCLK_UART11:
18050265e00cSElaine Zhang con = readl(&cru->clksel_con[70]);
18060265e00cSElaine Zhang break;
18070265e00cSElaine Zhang default:
18080265e00cSElaine Zhang return -ENOENT;
18090265e00cSElaine Zhang }
18100265e00cSElaine Zhang if (clk_id == SCLK_UART1) {
18110265e00cSElaine Zhang src = (con & CLK_UART1_SRC_SEL_SHIFT) >> CLK_UART1_SRC_SEL_SHIFT;
18120265e00cSElaine Zhang div = (con & CLK_UART1_SRC_DIV_MASK) >> CLK_UART1_SRC_DIV_SHIFT;
18130265e00cSElaine Zhang } else {
18140265e00cSElaine Zhang src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
18150265e00cSElaine Zhang div = (con & CLK_UART_DIV_MASK) >> CLK_UART_DIV_SHIFT;
18160265e00cSElaine Zhang }
18170265e00cSElaine Zhang if (src == CLK_UART_SEL_GPLL)
18180265e00cSElaine Zhang p_rate = priv->gpll_hz;
18190265e00cSElaine Zhang else if (src == CLK_UART_SEL_CPLL)
18200265e00cSElaine Zhang p_rate = priv->cpll_hz;
18210265e00cSElaine Zhang else if (src == CLK_UART_SEL_AUPLL)
18220265e00cSElaine Zhang p_rate = priv->aupll_hz;
18230265e00cSElaine Zhang else if (src == CLK_UART_SEL_FRAC0)
18240265e00cSElaine Zhang p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0);
18250265e00cSElaine Zhang else if (src == CLK_UART_SEL_FRAC1)
18260265e00cSElaine Zhang p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1);
18270265e00cSElaine Zhang else if (src == CLK_UART_SEL_FRAC2)
18280265e00cSElaine Zhang p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2);
18290265e00cSElaine Zhang else
18300265e00cSElaine Zhang p_rate = OSC_HZ;
18310265e00cSElaine Zhang
18320265e00cSElaine Zhang return DIV_TO_RATE(p_rate, div);
18330265e00cSElaine Zhang }
18340265e00cSElaine Zhang
rk3576_uart_set_rate(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)18350265e00cSElaine Zhang static ulong rk3576_uart_set_rate(struct rk3576_clk_priv *priv,
18360265e00cSElaine Zhang ulong clk_id, ulong rate)
18370265e00cSElaine Zhang {
18380265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
18390265e00cSElaine Zhang u32 reg, clk_src = 0, div = 0;
18400265e00cSElaine Zhang
18410265e00cSElaine Zhang if (!(priv->gpll_hz % rate)) {
18420265e00cSElaine Zhang clk_src = CLK_UART_SEL_GPLL;
18430265e00cSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
18440265e00cSElaine Zhang } else if (!(priv->cpll_hz % rate)) {
18450265e00cSElaine Zhang clk_src = CLK_UART_SEL_CPLL;
18460265e00cSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
18470265e00cSElaine Zhang } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0) % rate)) {
18480265e00cSElaine Zhang clk_src = CLK_UART_SEL_FRAC0;
18490265e00cSElaine Zhang div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0), rate);
18500265e00cSElaine Zhang } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1) % rate)) {
18510265e00cSElaine Zhang clk_src = CLK_UART_SEL_FRAC1;
18520265e00cSElaine Zhang div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1), rate);
18530265e00cSElaine Zhang } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2) % rate)) {
18540265e00cSElaine Zhang clk_src = CLK_UART_SEL_FRAC2;
18550265e00cSElaine Zhang div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2), rate);
18560265e00cSElaine Zhang } else if (!(OSC_HZ % rate)) {
18570265e00cSElaine Zhang clk_src = CLK_UART_SEL_OSC;
18580265e00cSElaine Zhang div = DIV_ROUND_UP(OSC_HZ, rate);
18590265e00cSElaine Zhang }
18600265e00cSElaine Zhang
18610265e00cSElaine Zhang switch (clk_id) {
18620265e00cSElaine Zhang case SCLK_UART0:
18630265e00cSElaine Zhang reg = 60;
18640265e00cSElaine Zhang break;
18650265e00cSElaine Zhang case SCLK_UART1:
18660265e00cSElaine Zhang if (rate == OSC_HZ) {
18670265e00cSElaine Zhang rk_clrsetreg(&cru->pmuclksel_con[8],
18680265e00cSElaine Zhang CLK_UART1_SEL_MASK,
18690265e00cSElaine Zhang (CLK_UART1_SEL_OSC << CLK_UART1_SEL_SHIFT));
18700265e00cSElaine Zhang return 0;
18710265e00cSElaine Zhang } else {
18720265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[27],
18730265e00cSElaine Zhang CLK_UART1_SRC_SEL_MASK |
18740265e00cSElaine Zhang CLK_UART1_SRC_DIV_MASK,
18750265e00cSElaine Zhang (clk_src << CLK_UART1_SRC_SEL_SHIFT) |
18760265e00cSElaine Zhang ((div - 1) << CLK_UART1_SRC_DIV_SHIFT));
18770265e00cSElaine Zhang rk_clrsetreg(&cru->pmuclksel_con[8],
18780265e00cSElaine Zhang CLK_UART1_SEL_MASK,
18790265e00cSElaine Zhang (CLK_UART1_SEL_TOP << CLK_UART1_SEL_SHIFT));
18800265e00cSElaine Zhang return 0;
18810265e00cSElaine Zhang }
18820265e00cSElaine Zhang break;
18830265e00cSElaine Zhang case SCLK_UART2:
18840265e00cSElaine Zhang reg = 61;
18850265e00cSElaine Zhang break;
18860265e00cSElaine Zhang case SCLK_UART3:
18870265e00cSElaine Zhang reg = 62;
18880265e00cSElaine Zhang break;
18890265e00cSElaine Zhang case SCLK_UART4:
18900265e00cSElaine Zhang reg = 63;
18910265e00cSElaine Zhang break;
18920265e00cSElaine Zhang case SCLK_UART5:
18930265e00cSElaine Zhang reg = 64;
18940265e00cSElaine Zhang break;
18950265e00cSElaine Zhang case SCLK_UART6:
18960265e00cSElaine Zhang reg = 65;
18970265e00cSElaine Zhang break;
18980265e00cSElaine Zhang case SCLK_UART7:
18990265e00cSElaine Zhang reg = 66;
19000265e00cSElaine Zhang break;
19010265e00cSElaine Zhang case SCLK_UART8:
19020265e00cSElaine Zhang reg = 67;
19030265e00cSElaine Zhang break;
19040265e00cSElaine Zhang case SCLK_UART9:
19050265e00cSElaine Zhang reg = 68;
19060265e00cSElaine Zhang break;
19070265e00cSElaine Zhang case SCLK_UART10:
19080265e00cSElaine Zhang reg = 69;
19090265e00cSElaine Zhang break;
19100265e00cSElaine Zhang case SCLK_UART11:
19110265e00cSElaine Zhang reg = 70;
19120265e00cSElaine Zhang break;
19130265e00cSElaine Zhang default:
19140265e00cSElaine Zhang return -ENOENT;
19150265e00cSElaine Zhang }
19160265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[reg],
19170265e00cSElaine Zhang CLK_UART_SEL_MASK |
19180265e00cSElaine Zhang CLK_UART_DIV_MASK,
19190265e00cSElaine Zhang (clk_src << CLK_UART_SEL_SHIFT) |
19200265e00cSElaine Zhang ((div - 1) << CLK_UART_DIV_SHIFT));
19210265e00cSElaine Zhang
19220265e00cSElaine Zhang return rk3576_uart_get_rate(priv, clk_id);
19230265e00cSElaine Zhang }
1924cdb92760SElaine Zhang
rk3576_ref_clkout_get_clk(struct rk3576_clk_priv * priv,ulong clk_id)1925cdb92760SElaine Zhang static ulong rk3576_ref_clkout_get_clk(struct rk3576_clk_priv *priv,
1926cdb92760SElaine Zhang ulong clk_id)
1927cdb92760SElaine Zhang {
1928cdb92760SElaine Zhang struct rk3576_cru *cru = priv->cru;
1929cdb92760SElaine Zhang u32 reg, con, div, src, p_rate;
1930cdb92760SElaine Zhang
1931cdb92760SElaine Zhang switch (clk_id) {
1932cdb92760SElaine Zhang case REF_CLK0_OUT_PLL:
1933cdb92760SElaine Zhang reg = 33;
1934cdb92760SElaine Zhang break;
1935cdb92760SElaine Zhang case REF_CLK1_OUT_PLL:
1936cdb92760SElaine Zhang reg = 34;
1937cdb92760SElaine Zhang break;
1938cdb92760SElaine Zhang case REF_CLK2_OUT_PLL:
1939cdb92760SElaine Zhang reg = 35;
1940cdb92760SElaine Zhang break;
1941cdb92760SElaine Zhang default:
1942cdb92760SElaine Zhang return -ENOENT;
1943cdb92760SElaine Zhang }
1944cdb92760SElaine Zhang con = readl(&cru->clksel_con[reg]);
1945cdb92760SElaine Zhang div = (con & REF_CLK0_OUT_PLL_DIV_MASK) >> REF_CLK0_OUT_PLL_DIV_SHIFT;
1946cdb92760SElaine Zhang src = (con & REF_CLK0_OUT_PLL_SEL_MASK) >> REF_CLK0_OUT_PLL_SEL_SHIFT;
1947cdb92760SElaine Zhang if (src == REF_CLK0_OUT_PLL_SEL_GPLL)
1948cdb92760SElaine Zhang p_rate = priv->gpll_hz;
1949cdb92760SElaine Zhang else if (src == REF_CLK0_OUT_PLL_SEL_CPLL)
1950cdb92760SElaine Zhang p_rate = priv->cpll_hz;
1951cdb92760SElaine Zhang else if (src == REF_CLK0_OUT_PLL_SEL_SPLL)
1952cdb92760SElaine Zhang p_rate = priv->spll_hz;
1953cdb92760SElaine Zhang else if (src == REF_CLK0_OUT_PLL_SEL_AUPLL)
1954cdb92760SElaine Zhang p_rate = priv->aupll_hz;
1955cdb92760SElaine Zhang else if (src == REF_CLK0_OUT_PLL_SEL_LPLL)
1956cdb92760SElaine Zhang p_rate = priv->lpll_hz / 2;
1957cdb92760SElaine Zhang else
1958cdb92760SElaine Zhang p_rate = OSC_HZ;
1959cdb92760SElaine Zhang return DIV_TO_RATE(p_rate, div);
1960cdb92760SElaine Zhang }
1961cdb92760SElaine Zhang
rk3576_ref_clkout_set_clk(struct rk3576_clk_priv * priv,ulong clk_id,ulong rate)1962cdb92760SElaine Zhang static ulong rk3576_ref_clkout_set_clk(struct rk3576_clk_priv *priv,
1963cdb92760SElaine Zhang ulong clk_id, ulong rate)
1964cdb92760SElaine Zhang {
1965cdb92760SElaine Zhang struct rk3576_cru *cru = priv->cru;
1966cdb92760SElaine Zhang ulong p_rate, now, best_rate = 0;
1967cdb92760SElaine Zhang u32 i, con, div, best_div = 0, best_sel = 0;
1968cdb92760SElaine Zhang
1969cdb92760SElaine Zhang switch (clk_id) {
1970cdb92760SElaine Zhang case REF_CLK0_OUT_PLL:
1971cdb92760SElaine Zhang con = 33;
1972cdb92760SElaine Zhang break;
1973cdb92760SElaine Zhang case REF_CLK1_OUT_PLL:
1974cdb92760SElaine Zhang con = 34;
1975cdb92760SElaine Zhang break;
1976cdb92760SElaine Zhang case REF_CLK2_OUT_PLL:
1977cdb92760SElaine Zhang con = 35;
1978cdb92760SElaine Zhang break;
1979cdb92760SElaine Zhang default:
1980cdb92760SElaine Zhang return -ENOENT;
1981cdb92760SElaine Zhang }
1982cdb92760SElaine Zhang
1983cdb92760SElaine Zhang for (i = 0; i <= REF_CLK0_OUT_PLL_SEL_OSC; i++) {
1984cdb92760SElaine Zhang switch (i) {
1985cdb92760SElaine Zhang case REF_CLK0_OUT_PLL_SEL_GPLL:
1986cdb92760SElaine Zhang p_rate = priv->gpll_hz;
1987cdb92760SElaine Zhang break;
1988cdb92760SElaine Zhang case REF_CLK0_OUT_PLL_SEL_CPLL:
1989cdb92760SElaine Zhang p_rate = priv->cpll_hz;
1990cdb92760SElaine Zhang break;
1991cdb92760SElaine Zhang case REF_CLK0_OUT_PLL_SEL_SPLL:
1992cdb92760SElaine Zhang p_rate = priv->spll_hz;
1993cdb92760SElaine Zhang break;
1994cdb92760SElaine Zhang case REF_CLK0_OUT_PLL_SEL_AUPLL:
1995cdb92760SElaine Zhang p_rate = priv->aupll_hz;
1996cdb92760SElaine Zhang break;
1997cdb92760SElaine Zhang case REF_CLK0_OUT_PLL_SEL_LPLL:
1998cdb92760SElaine Zhang p_rate = 0;
1999cdb92760SElaine Zhang break;
2000cdb92760SElaine Zhang case REF_CLK0_OUT_PLL_SEL_OSC:
2001cdb92760SElaine Zhang p_rate = OSC_HZ;
2002cdb92760SElaine Zhang break;
2003cdb92760SElaine Zhang default:
2004cdb92760SElaine Zhang printf("do not support this vop pll sel\n");
2005cdb92760SElaine Zhang return -EINVAL;
2006cdb92760SElaine Zhang }
2007cdb92760SElaine Zhang
2008cdb92760SElaine Zhang div = DIV_ROUND_UP(p_rate, rate);
2009cdb92760SElaine Zhang if (div > 255)
2010cdb92760SElaine Zhang continue;
2011cdb92760SElaine Zhang now = p_rate / div;
2012cdb92760SElaine Zhang if (abs(rate - now) < abs(rate - best_rate)) {
2013cdb92760SElaine Zhang best_rate = now;
2014cdb92760SElaine Zhang best_div = div;
2015cdb92760SElaine Zhang best_sel = i;
2016cdb92760SElaine Zhang }
2017cdb92760SElaine Zhang debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
2018cdb92760SElaine Zhang p_rate, best_rate, best_div, best_sel);
2019cdb92760SElaine Zhang }
2020cdb92760SElaine Zhang if (best_rate) {
2021cdb92760SElaine Zhang rk_clrsetreg(&cru->clksel_con[con],
2022cdb92760SElaine Zhang REF_CLK0_OUT_PLL_DIV_MASK |
2023cdb92760SElaine Zhang REF_CLK0_OUT_PLL_SEL_MASK,
2024cdb92760SElaine Zhang best_sel << REF_CLK0_OUT_PLL_SEL_SHIFT |
2025cdb92760SElaine Zhang (best_div - 1) << REF_CLK0_OUT_PLL_DIV_SHIFT);
2026cdb92760SElaine Zhang } else {
2027cdb92760SElaine Zhang printf("do not support this vop freq %lu\n", rate);
2028cdb92760SElaine Zhang return -EINVAL;
2029cdb92760SElaine Zhang }
2030cdb92760SElaine Zhang
2031cdb92760SElaine Zhang return rk3576_ref_clkout_get_clk(priv, clk_id);
2032cdb92760SElaine Zhang }
2033cdb92760SElaine Zhang
20340265e00cSElaine Zhang #endif
20350265e00cSElaine Zhang
rk3576_ufs_ref_get_rate(struct rk3576_clk_priv * priv,ulong clk_id)20360265e00cSElaine Zhang static ulong rk3576_ufs_ref_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
20370265e00cSElaine Zhang {
20380265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
20390265e00cSElaine Zhang u32 src, div;
20400265e00cSElaine Zhang
20410265e00cSElaine Zhang src = readl(&cru->pmuclksel_con[3]) & 0x3;
20420265e00cSElaine Zhang div= readl(&cru->pmuclksel_con[1]) & 0xff;
20430265e00cSElaine Zhang if (src == 0)
20440265e00cSElaine Zhang return OSC_HZ;
20450265e00cSElaine Zhang else if (src == 2)
20460265e00cSElaine Zhang return priv->ppll_hz / (div + 1);
20470265e00cSElaine Zhang else
20480265e00cSElaine Zhang return 26000000;
20490265e00cSElaine Zhang
20500265e00cSElaine Zhang }
20510265e00cSElaine Zhang
rk3576_clk_get_rate(struct clk * clk)20520265e00cSElaine Zhang static ulong rk3576_clk_get_rate(struct clk *clk)
20530265e00cSElaine Zhang {
20540265e00cSElaine Zhang struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
20550265e00cSElaine Zhang ulong rate = 0;
20560265e00cSElaine Zhang
20570265e00cSElaine Zhang if (!priv->gpll_hz) {
20580265e00cSElaine Zhang printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
20590265e00cSElaine Zhang return -ENOENT;
20600265e00cSElaine Zhang }
20610265e00cSElaine Zhang
20620265e00cSElaine Zhang if (!priv->ppll_hz) {
20630265e00cSElaine Zhang priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
20640265e00cSElaine Zhang priv->cru, PPLL);
20650265e00cSElaine Zhang }
20660265e00cSElaine Zhang
20670265e00cSElaine Zhang switch (clk->id) {
20680265e00cSElaine Zhang case PLL_LPLL:
20690265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[LPLL], priv->cru,
20700265e00cSElaine Zhang LPLL);
20710265e00cSElaine Zhang priv->lpll_hz = rate;
20720265e00cSElaine Zhang break;
20730265e00cSElaine Zhang case PLL_BPLL:
20740265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[BPLL], priv->cru,
20750265e00cSElaine Zhang BPLL);
20760265e00cSElaine Zhang priv->bpll_hz = rate;
20770265e00cSElaine Zhang break;
20780265e00cSElaine Zhang case PLL_GPLL:
20790265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL], priv->cru,
20800265e00cSElaine Zhang GPLL);
20810265e00cSElaine Zhang break;
20820265e00cSElaine Zhang case PLL_CPLL:
20830265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL], priv->cru,
20840265e00cSElaine Zhang CPLL);
20850265e00cSElaine Zhang break;
20860265e00cSElaine Zhang case PLL_VPLL:
20870265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL], priv->cru,
20880265e00cSElaine Zhang VPLL);
20890265e00cSElaine Zhang break;
20900265e00cSElaine Zhang case PLL_AUPLL:
20910265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL], priv->cru,
20920265e00cSElaine Zhang AUPLL);
20930265e00cSElaine Zhang break;
20940265e00cSElaine Zhang case PLL_PPLL:
20950265e00cSElaine Zhang rate = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL], priv->cru,
20960265e00cSElaine Zhang PPLL) * 2;
20970265e00cSElaine Zhang break;
20980265e00cSElaine Zhang case ACLK_BUS_ROOT:
20990265e00cSElaine Zhang case HCLK_BUS_ROOT:
21000265e00cSElaine Zhang case PCLK_BUS_ROOT:
21010265e00cSElaine Zhang rate = rk3576_bus_get_clk(priv, clk->id);
21020265e00cSElaine Zhang break;
21030265e00cSElaine Zhang case ACLK_TOP:
21040265e00cSElaine Zhang case HCLK_TOP:
21050265e00cSElaine Zhang case PCLK_TOP_ROOT:
21060265e00cSElaine Zhang case ACLK_TOP_MID:
21070265e00cSElaine Zhang rate = rk3576_top_get_clk(priv, clk->id);
21080265e00cSElaine Zhang break;
21090265e00cSElaine Zhang case CLK_I2C0:
21100265e00cSElaine Zhang case CLK_I2C1:
21110265e00cSElaine Zhang case CLK_I2C2:
21120265e00cSElaine Zhang case CLK_I2C3:
21130265e00cSElaine Zhang case CLK_I2C4:
21140265e00cSElaine Zhang case CLK_I2C5:
21150265e00cSElaine Zhang case CLK_I2C6:
21160265e00cSElaine Zhang case CLK_I2C7:
21170265e00cSElaine Zhang case CLK_I2C8:
21180265e00cSElaine Zhang case CLK_I2C9:
21190265e00cSElaine Zhang rate = rk3576_i2c_get_clk(priv, clk->id);
21200265e00cSElaine Zhang break;
21210265e00cSElaine Zhang case CLK_SPI0:
21220265e00cSElaine Zhang case CLK_SPI1:
21230265e00cSElaine Zhang case CLK_SPI2:
21240265e00cSElaine Zhang case CLK_SPI3:
21250265e00cSElaine Zhang case CLK_SPI4:
21260265e00cSElaine Zhang rate = rk3576_spi_get_clk(priv, clk->id);
21270265e00cSElaine Zhang break;
21280265e00cSElaine Zhang case CLK_PWM1:
21290265e00cSElaine Zhang case CLK_PWM2:
21300265e00cSElaine Zhang case CLK_PMU1PWM:
21310265e00cSElaine Zhang rate = rk3576_pwm_get_clk(priv, clk->id);
21320265e00cSElaine Zhang break;
21330265e00cSElaine Zhang case CLK_SARADC:
21340265e00cSElaine Zhang case CLK_TSADC:
21350265e00cSElaine Zhang rate = rk3576_adc_get_clk(priv, clk->id);
21360265e00cSElaine Zhang break;
21370265e00cSElaine Zhang case CCLK_SRC_SDIO:
21380265e00cSElaine Zhang case CCLK_SRC_SDMMC0:
21390265e00cSElaine Zhang case CCLK_SRC_EMMC:
21400265e00cSElaine Zhang case BCLK_EMMC:
21410265e00cSElaine Zhang case SCLK_FSPI_X2:
21420265e00cSElaine Zhang case SCLK_FSPI1_X2:
2143431b7b81SElaine Zhang case DCLK_DECOM:
21444a69562cSElaine Zhang case HCLK_SDMMC0:
21454a69562cSElaine Zhang case HCLK_EMMC:
21464a69562cSElaine Zhang case HCLK_SDIO:
21470265e00cSElaine Zhang rate = rk3576_mmc_get_clk(priv, clk->id);
21480265e00cSElaine Zhang break;
21490265e00cSElaine Zhang case TCLK_WDT0:
21500265e00cSElaine Zhang rate = OSC_HZ;
21510265e00cSElaine Zhang break;
21520265e00cSElaine Zhang #ifndef CONFIG_SPL_BUILD
21530265e00cSElaine Zhang case ACLK_VOP_ROOT:
21540265e00cSElaine Zhang case ACLK_VOP:
21550265e00cSElaine Zhang case ACLK_VO0_ROOT:
21560265e00cSElaine Zhang case ACLK_VO1_ROOT:
21570265e00cSElaine Zhang case HCLK_VOP_ROOT:
21580265e00cSElaine Zhang case PCLK_VOP_ROOT:
21590265e00cSElaine Zhang rate = rk3576_aclk_vop_get_clk(priv, clk->id);
21600265e00cSElaine Zhang break;
21610265e00cSElaine Zhang case DCLK_VP0:
21620265e00cSElaine Zhang case DCLK_VP0_SRC:
21630265e00cSElaine Zhang case DCLK_VP1:
21640265e00cSElaine Zhang case DCLK_VP1_SRC:
21650265e00cSElaine Zhang case DCLK_VP2:
21660265e00cSElaine Zhang case DCLK_VP2_SRC:
21670265e00cSElaine Zhang rate = rk3576_dclk_vop_get_clk(priv, clk->id);
21680265e00cSElaine Zhang break;
21690265e00cSElaine Zhang case CLK_GMAC0_PTP_REF_SRC:
21700265e00cSElaine Zhang case CLK_GMAC1_PTP_REF_SRC:
21710265e00cSElaine Zhang case CLK_GMAC0_PTP_REF:
21720265e00cSElaine Zhang case CLK_GMAC1_PTP_REF:
21730265e00cSElaine Zhang case CLK_GMAC0_125M_SRC:
21740265e00cSElaine Zhang case CLK_GMAC1_125M_SRC:
21750265e00cSElaine Zhang rate = rk3576_gmac_get_clk(priv, clk->id);
21760265e00cSElaine Zhang break;
21770265e00cSElaine Zhang case CLK_UART_FRAC_0:
21780265e00cSElaine Zhang case CLK_UART_FRAC_1:
21790265e00cSElaine Zhang case CLK_UART_FRAC_2:
21800265e00cSElaine Zhang rate = rk3576_uart_frac_get_rate(priv, clk->id);
21810265e00cSElaine Zhang break;
21820265e00cSElaine Zhang case SCLK_UART0:
21830265e00cSElaine Zhang case SCLK_UART1:
21840265e00cSElaine Zhang case SCLK_UART2:
21850265e00cSElaine Zhang case SCLK_UART3:
21860265e00cSElaine Zhang case SCLK_UART4:
21870265e00cSElaine Zhang case SCLK_UART5:
21880265e00cSElaine Zhang case SCLK_UART6:
21890265e00cSElaine Zhang case SCLK_UART7:
21900265e00cSElaine Zhang case SCLK_UART8:
21910265e00cSElaine Zhang case SCLK_UART9:
21920265e00cSElaine Zhang case SCLK_UART10:
21930265e00cSElaine Zhang case SCLK_UART11:
21940265e00cSElaine Zhang rate = rk3576_uart_get_rate(priv, clk->id);
21950265e00cSElaine Zhang break;
21960265e00cSElaine Zhang case CLK_DSIHOST0:
21970265e00cSElaine Zhang rate = rk3576_clk_csihost_get_clk(priv, clk->id);
21980265e00cSElaine Zhang break;
21990265e00cSElaine Zhang case DCLK_EBC:
22000265e00cSElaine Zhang case DCLK_EBC_FRAC_SRC:
22010265e00cSElaine Zhang rate = rk3576_dclk_ebc_get_clk(priv, clk->id);
22020265e00cSElaine Zhang break;
2203cdb92760SElaine Zhang case REF_CLK0_OUT_PLL:
2204cdb92760SElaine Zhang case REF_CLK1_OUT_PLL:
2205cdb92760SElaine Zhang case REF_CLK2_OUT_PLL:
2206cdb92760SElaine Zhang rate = rk3576_ref_clkout_get_clk(priv, clk->id);
2207cdb92760SElaine Zhang break;
22080265e00cSElaine Zhang #endif
22090265e00cSElaine Zhang case CLK_REF_UFS_CLKOUT:
22100265e00cSElaine Zhang case CLK_REF_OSC_MPHY:
22110265e00cSElaine Zhang rate = rk3576_ufs_ref_get_rate(priv, clk->id);
22120265e00cSElaine Zhang break;
22130265e00cSElaine Zhang
22140265e00cSElaine Zhang default:
22150265e00cSElaine Zhang return -ENOENT;
22160265e00cSElaine Zhang }
22170265e00cSElaine Zhang
22180265e00cSElaine Zhang return rate;
22190265e00cSElaine Zhang };
22200265e00cSElaine Zhang
rk3576_clk_set_rate(struct clk * clk,ulong rate)22210265e00cSElaine Zhang static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate)
22220265e00cSElaine Zhang {
22230265e00cSElaine Zhang struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
22240265e00cSElaine Zhang ulong ret = 0;
22250265e00cSElaine Zhang
22260265e00cSElaine Zhang if (!priv->ppll_hz) {
22270265e00cSElaine Zhang priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
22280265e00cSElaine Zhang priv->cru, PPLL);
22290265e00cSElaine Zhang }
22300265e00cSElaine Zhang if (!priv->aupll_hz) {
22310265e00cSElaine Zhang priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
22320265e00cSElaine Zhang priv->cru, AUPLL);
22330265e00cSElaine Zhang }
22340265e00cSElaine Zhang
22350265e00cSElaine Zhang switch (clk->id) {
22360265e00cSElaine Zhang case PLL_CPLL:
22370265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
22380265e00cSElaine Zhang CPLL, rate);
22390265e00cSElaine Zhang priv->cpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL],
22400265e00cSElaine Zhang priv->cru, CPLL);
22410265e00cSElaine Zhang break;
22420265e00cSElaine Zhang case PLL_GPLL:
22430265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
22440265e00cSElaine Zhang GPLL, rate);
22450265e00cSElaine Zhang priv->gpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL],
22460265e00cSElaine Zhang priv->cru, GPLL);
22470265e00cSElaine Zhang break;
22480265e00cSElaine Zhang case PLL_VPLL:
22490265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[VPLL], priv->cru,
22500265e00cSElaine Zhang VPLL, rate);
22510265e00cSElaine Zhang priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
22520265e00cSElaine Zhang priv->cru, VPLL);
22530265e00cSElaine Zhang break;
22540265e00cSElaine Zhang case PLL_AUPLL:
22550265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[AUPLL], priv->cru,
22560265e00cSElaine Zhang AUPLL, rate);
22570265e00cSElaine Zhang priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
22580265e00cSElaine Zhang priv->cru, AUPLL);
22590265e00cSElaine Zhang break;
22600265e00cSElaine Zhang case PLL_PPLL:
22610265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[PPLL], priv->cru,
22620265e00cSElaine Zhang PPLL, rate);
22630265e00cSElaine Zhang priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
22640265e00cSElaine Zhang priv->cru, PPLL) * 2;
22650265e00cSElaine Zhang break;
22660265e00cSElaine Zhang case ACLK_BUS_ROOT:
22670265e00cSElaine Zhang case HCLK_BUS_ROOT:
22680265e00cSElaine Zhang case PCLK_BUS_ROOT:
22690265e00cSElaine Zhang ret = rk3576_bus_set_clk(priv, clk->id, rate);
22700265e00cSElaine Zhang break;
22710265e00cSElaine Zhang case ACLK_TOP:
22720265e00cSElaine Zhang case HCLK_TOP:
22730265e00cSElaine Zhang case PCLK_TOP_ROOT:
22740265e00cSElaine Zhang case ACLK_TOP_MID:
22750265e00cSElaine Zhang ret = rk3576_top_set_clk(priv, clk->id, rate);
22760265e00cSElaine Zhang break;
22770265e00cSElaine Zhang case CLK_I2C0:
22780265e00cSElaine Zhang case CLK_I2C1:
22790265e00cSElaine Zhang case CLK_I2C2:
22800265e00cSElaine Zhang case CLK_I2C3:
22810265e00cSElaine Zhang case CLK_I2C4:
22820265e00cSElaine Zhang case CLK_I2C5:
22830265e00cSElaine Zhang case CLK_I2C6:
22840265e00cSElaine Zhang case CLK_I2C7:
22850265e00cSElaine Zhang case CLK_I2C8:
22860265e00cSElaine Zhang case CLK_I2C9:
22870265e00cSElaine Zhang ret = rk3576_i2c_set_clk(priv, clk->id, rate);
22880265e00cSElaine Zhang break;
22890265e00cSElaine Zhang case CLK_SPI0:
22900265e00cSElaine Zhang case CLK_SPI1:
22910265e00cSElaine Zhang case CLK_SPI2:
22920265e00cSElaine Zhang case CLK_SPI3:
22930265e00cSElaine Zhang case CLK_SPI4:
22940265e00cSElaine Zhang ret = rk3576_spi_set_clk(priv, clk->id, rate);
22950265e00cSElaine Zhang break;
22960265e00cSElaine Zhang case CLK_PWM1:
22970265e00cSElaine Zhang case CLK_PWM2:
22980265e00cSElaine Zhang case CLK_PMU1PWM:
22990265e00cSElaine Zhang ret = rk3576_pwm_set_clk(priv, clk->id, rate);
23000265e00cSElaine Zhang break;
23010265e00cSElaine Zhang case CLK_SARADC:
23020265e00cSElaine Zhang case CLK_TSADC:
23030265e00cSElaine Zhang ret = rk3576_adc_set_clk(priv, clk->id, rate);
23040265e00cSElaine Zhang break;
23050265e00cSElaine Zhang case CCLK_SRC_SDIO:
23060265e00cSElaine Zhang case CCLK_SRC_SDMMC0:
23070265e00cSElaine Zhang case CCLK_SRC_EMMC:
23080265e00cSElaine Zhang case BCLK_EMMC:
23090265e00cSElaine Zhang case SCLK_FSPI_X2:
23100265e00cSElaine Zhang case SCLK_FSPI1_X2:
2311431b7b81SElaine Zhang case DCLK_DECOM:
23124a69562cSElaine Zhang case HCLK_SDMMC0:
23134a69562cSElaine Zhang case HCLK_EMMC:
23144a69562cSElaine Zhang case HCLK_SDIO:
23150265e00cSElaine Zhang ret = rk3576_mmc_set_clk(priv, clk->id, rate);
23160265e00cSElaine Zhang break;
23170265e00cSElaine Zhang case TCLK_WDT0:
23180265e00cSElaine Zhang ret = OSC_HZ;
23190265e00cSElaine Zhang break;
23200265e00cSElaine Zhang #ifndef CONFIG_SPL_BUILD
23210265e00cSElaine Zhang case ACLK_VOP_ROOT:
23220265e00cSElaine Zhang case ACLK_VOP:
23230265e00cSElaine Zhang case ACLK_VO0_ROOT:
23240265e00cSElaine Zhang case ACLK_VO1_ROOT:
23250265e00cSElaine Zhang case HCLK_VOP_ROOT:
23260265e00cSElaine Zhang case PCLK_VOP_ROOT:
23270265e00cSElaine Zhang ret = rk3576_aclk_vop_set_clk(priv, clk->id, rate);
23280265e00cSElaine Zhang break;
23290265e00cSElaine Zhang case DCLK_VP0:
23300265e00cSElaine Zhang case DCLK_VP0_SRC:
23310265e00cSElaine Zhang case DCLK_VP1:
23320265e00cSElaine Zhang case DCLK_VP1_SRC:
23330265e00cSElaine Zhang case DCLK_VP2:
23340265e00cSElaine Zhang case DCLK_VP2_SRC:
23350265e00cSElaine Zhang ret = rk3576_dclk_vop_set_clk(priv, clk->id, rate);
23360265e00cSElaine Zhang break;
23370265e00cSElaine Zhang case CLK_GMAC0_PTP_REF_SRC:
23380265e00cSElaine Zhang case CLK_GMAC1_PTP_REF_SRC:
23390265e00cSElaine Zhang case CLK_GMAC0_PTP_REF:
23400265e00cSElaine Zhang case CLK_GMAC1_PTP_REF:
23410265e00cSElaine Zhang case CLK_GMAC0_125M_SRC:
23420265e00cSElaine Zhang case CLK_GMAC1_125M_SRC:
23430265e00cSElaine Zhang ret = rk3576_gmac_set_clk(priv, clk->id, rate);
23440265e00cSElaine Zhang break;
23450265e00cSElaine Zhang case CLK_UART_FRAC_0:
23460265e00cSElaine Zhang case CLK_UART_FRAC_1:
23470265e00cSElaine Zhang case CLK_UART_FRAC_2:
23480265e00cSElaine Zhang ret = rk3576_uart_frac_set_rate(priv, clk->id, rate);
23490265e00cSElaine Zhang break;
23500265e00cSElaine Zhang case SCLK_UART0:
23510265e00cSElaine Zhang case SCLK_UART1:
23520265e00cSElaine Zhang case SCLK_UART2:
23530265e00cSElaine Zhang case SCLK_UART3:
23540265e00cSElaine Zhang case SCLK_UART4:
23550265e00cSElaine Zhang case SCLK_UART5:
23560265e00cSElaine Zhang case SCLK_UART6:
23570265e00cSElaine Zhang case SCLK_UART7:
23580265e00cSElaine Zhang case SCLK_UART8:
23590265e00cSElaine Zhang case SCLK_UART9:
23600265e00cSElaine Zhang case SCLK_UART10:
23610265e00cSElaine Zhang case SCLK_UART11:
23620265e00cSElaine Zhang ret = rk3576_uart_set_rate(priv, clk->id, rate);
23630265e00cSElaine Zhang break;
23640265e00cSElaine Zhang case CLK_DSIHOST0:
23650265e00cSElaine Zhang ret = rk3576_clk_csihost_set_clk(priv, clk->id, rate);
23660265e00cSElaine Zhang break;
23670265e00cSElaine Zhang case DCLK_EBC:
23680265e00cSElaine Zhang case DCLK_EBC_FRAC_SRC:
23690265e00cSElaine Zhang ret = rk3576_dclk_ebc_set_clk(priv, clk->id, rate);
23700265e00cSElaine Zhang break;
2371cdb92760SElaine Zhang case REF_CLK0_OUT_PLL:
2372cdb92760SElaine Zhang case REF_CLK1_OUT_PLL:
2373cdb92760SElaine Zhang case REF_CLK2_OUT_PLL:
2374cdb92760SElaine Zhang ret = rk3576_ref_clkout_set_clk(priv, clk->id, rate);
2375cdb92760SElaine Zhang break;
23760265e00cSElaine Zhang #endif
23770265e00cSElaine Zhang default:
23780265e00cSElaine Zhang return -ENOENT;
23790265e00cSElaine Zhang }
23800265e00cSElaine Zhang
23810265e00cSElaine Zhang return ret;
23820265e00cSElaine Zhang };
23830265e00cSElaine Zhang
23840265e00cSElaine Zhang #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
rk3576_dclk_vop_set_parent(struct clk * clk,struct clk * parent)23850265e00cSElaine Zhang static int __maybe_unused rk3576_dclk_vop_set_parent(struct clk *clk,
23860265e00cSElaine Zhang struct clk *parent)
23870265e00cSElaine Zhang {
23880265e00cSElaine Zhang struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
23890265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
23900265e00cSElaine Zhang u32 sel;
23910265e00cSElaine Zhang const char *clock_dev_name = parent->dev->name;
23920265e00cSElaine Zhang
23930265e00cSElaine Zhang if (parent->id == PLL_VPLL)
23940265e00cSElaine Zhang sel = 2;
23950265e00cSElaine Zhang else if (parent->id == PLL_GPLL)
23960265e00cSElaine Zhang sel = 0;
23970265e00cSElaine Zhang else if (parent->id == PLL_CPLL)
23980265e00cSElaine Zhang sel = 1;
23990265e00cSElaine Zhang else if (parent->id == PLL_BPLL)
24000265e00cSElaine Zhang sel = 3;
24010265e00cSElaine Zhang else
24020265e00cSElaine Zhang sel = 4;
24030265e00cSElaine Zhang
24040265e00cSElaine Zhang switch (clk->id) {
24050265e00cSElaine Zhang case DCLK_VP0_SRC:
24060265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[145], DCLK0_VOP_SRC_SEL_MASK,
24070265e00cSElaine Zhang sel << DCLK0_VOP_SRC_SEL_SHIFT);
24080265e00cSElaine Zhang break;
24090265e00cSElaine Zhang case DCLK_VP1_SRC:
24100265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[146], DCLK0_VOP_SRC_SEL_MASK,
24110265e00cSElaine Zhang sel << DCLK0_VOP_SRC_SEL_SHIFT);
24120265e00cSElaine Zhang break;
24130265e00cSElaine Zhang case DCLK_VP2_SRC:
24140265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SRC_SEL_MASK,
24150265e00cSElaine Zhang sel << DCLK0_VOP_SRC_SEL_SHIFT);
24160265e00cSElaine Zhang break;
24170265e00cSElaine Zhang case DCLK_VP0:
24180265e00cSElaine Zhang if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
24190265e00cSElaine Zhang sel = 1;
24200265e00cSElaine Zhang else
24210265e00cSElaine Zhang sel = 0;
24220265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SEL_MASK,
24230265e00cSElaine Zhang sel << DCLK0_VOP_SEL_SHIFT);
24240265e00cSElaine Zhang break;
24250265e00cSElaine Zhang case DCLK_VP1:
24260265e00cSElaine Zhang if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
24270265e00cSElaine Zhang sel = 1;
24280265e00cSElaine Zhang else
24290265e00cSElaine Zhang sel = 0;
24300265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[147], DCLK1_VOP_SEL_MASK,
24310265e00cSElaine Zhang sel << DCLK1_VOP_SEL_SHIFT);
24320265e00cSElaine Zhang break;
24330265e00cSElaine Zhang case DCLK_VP2:
24340265e00cSElaine Zhang if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
24350265e00cSElaine Zhang sel = 1;
24360265e00cSElaine Zhang else
24370265e00cSElaine Zhang sel = 0;
24380265e00cSElaine Zhang rk_clrsetreg(&cru->clksel_con[147], DCLK2_VOP_SEL_MASK,
24390265e00cSElaine Zhang sel << DCLK2_VOP_SEL_SHIFT);
24400265e00cSElaine Zhang break;
2441f215d626SElaine Zhang case DCLK_EBC:
2442f215d626SElaine Zhang if (parent->id == PLL_GPLL)
2443f215d626SElaine Zhang sel = 0;
2444f215d626SElaine Zhang else if (parent->id == PLL_CPLL)
2445f215d626SElaine Zhang sel = 1;
2446f215d626SElaine Zhang else if (parent->id == PLL_VPLL)
2447f215d626SElaine Zhang sel = 2;
2448f215d626SElaine Zhang else if (parent->id == PLL_AUPLL)
2449f215d626SElaine Zhang sel = 3;
2450f215d626SElaine Zhang else if (parent->id == PLL_LPLL)
2451f215d626SElaine Zhang sel = 4;
2452f215d626SElaine Zhang else if (parent->id == DCLK_EBC_FRAC_SRC)
2453f215d626SElaine Zhang sel = 5;
2454f215d626SElaine Zhang else
2455f215d626SElaine Zhang sel = 6;
2456f215d626SElaine Zhang rk_clrsetreg(&cru->clksel_con[123], DCLK_EBC_SEL_MASK,
2457f215d626SElaine Zhang sel << DCLK_EBC_SEL_SHIFT);
2458f215d626SElaine Zhang break;
24590265e00cSElaine Zhang default:
24600265e00cSElaine Zhang return -EINVAL;
24610265e00cSElaine Zhang }
24620265e00cSElaine Zhang return 0;
24630265e00cSElaine Zhang }
24640265e00cSElaine Zhang
rk3576_ufs_ref_set_parent(struct clk * clk,struct clk * parent)24650265e00cSElaine Zhang static int __maybe_unused rk3576_ufs_ref_set_parent(struct clk *clk,
24660265e00cSElaine Zhang struct clk *parent)
24670265e00cSElaine Zhang {
24680265e00cSElaine Zhang struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
24690265e00cSElaine Zhang struct rk3576_cru *cru = priv->cru;
24700265e00cSElaine Zhang u32 sel;
24710265e00cSElaine Zhang const char *clock_dev_name = parent->dev->name;
24720265e00cSElaine Zhang
24730265e00cSElaine Zhang if (parent->id == CLK_REF_MPHY_26M)
24740265e00cSElaine Zhang sel = 2;
24750265e00cSElaine Zhang else if (!strcmp(clock_dev_name, "xin24m"))
24760265e00cSElaine Zhang sel = 0;
24770265e00cSElaine Zhang else
24780265e00cSElaine Zhang sel = 1;
24790265e00cSElaine Zhang
24800265e00cSElaine Zhang rk_clrsetreg(&cru->pmuclksel_con[3], 0x3, sel << 0);
24810265e00cSElaine Zhang return 0;
24820265e00cSElaine Zhang }
24830265e00cSElaine Zhang
rk3576_clk_set_parent(struct clk * clk,struct clk * parent)24840265e00cSElaine Zhang static int rk3576_clk_set_parent(struct clk *clk, struct clk *parent)
24850265e00cSElaine Zhang {
24860265e00cSElaine Zhang switch (clk->id) {
24870265e00cSElaine Zhang case DCLK_VP0_SRC:
24880265e00cSElaine Zhang case DCLK_VP1_SRC:
24890265e00cSElaine Zhang case DCLK_VP2_SRC:
24900265e00cSElaine Zhang case DCLK_VP0:
24910265e00cSElaine Zhang case DCLK_VP1:
24920265e00cSElaine Zhang case DCLK_VP2:
2493f215d626SElaine Zhang case DCLK_EBC:
24940265e00cSElaine Zhang return rk3576_dclk_vop_set_parent(clk, parent);
24950265e00cSElaine Zhang case CLK_REF_OSC_MPHY:
24960265e00cSElaine Zhang return rk3576_ufs_ref_set_parent(clk, parent);
24970265e00cSElaine Zhang
24980265e00cSElaine Zhang default:
24990265e00cSElaine Zhang return -ENOENT;
25000265e00cSElaine Zhang }
25010265e00cSElaine Zhang
25020265e00cSElaine Zhang return 0;
25030265e00cSElaine Zhang }
25040265e00cSElaine Zhang #endif
25050265e00cSElaine Zhang
25060265e00cSElaine Zhang static struct clk_ops rk3576_clk_ops = {
25070265e00cSElaine Zhang .get_rate = rk3576_clk_get_rate,
25080265e00cSElaine Zhang .set_rate = rk3576_clk_set_rate,
25090265e00cSElaine Zhang #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
25100265e00cSElaine Zhang .set_parent = rk3576_clk_set_parent,
25110265e00cSElaine Zhang #endif
25120265e00cSElaine Zhang };
25130265e00cSElaine Zhang
rk3576_clk_init(struct rk3576_clk_priv * priv)25140265e00cSElaine Zhang static void rk3576_clk_init(struct rk3576_clk_priv *priv)
25150265e00cSElaine Zhang {
25160265e00cSElaine Zhang int ret;
25170265e00cSElaine Zhang
25180265e00cSElaine Zhang priv->spll_hz = 702000000;
25190265e00cSElaine Zhang
25200265e00cSElaine Zhang if (priv->cpll_hz != CPLL_HZ) {
25210265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
25220265e00cSElaine Zhang CPLL, CPLL_HZ);
25230265e00cSElaine Zhang if (!ret)
25240265e00cSElaine Zhang priv->cpll_hz = CPLL_HZ;
25250265e00cSElaine Zhang }
25260265e00cSElaine Zhang if (priv->gpll_hz != GPLL_HZ) {
25270265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
25280265e00cSElaine Zhang GPLL, GPLL_HZ);
25290265e00cSElaine Zhang if (!ret)
25300265e00cSElaine Zhang priv->gpll_hz = GPLL_HZ;
25310265e00cSElaine Zhang }
2532f215d626SElaine Zhang rk_clrsetreg(&priv->cru->clksel_con[123],
2533f215d626SElaine Zhang DCLK_EBC_FRAC_SRC_SEL_MASK,
2534f215d626SElaine Zhang (DCLK_EBC_FRAC_SRC_SEL_GPLL <<
2535f215d626SElaine Zhang DCLK_EBC_FRAC_SRC_SEL_SHIFT));
25360265e00cSElaine Zhang }
25370265e00cSElaine Zhang
rk3576_clk_probe(struct udevice * dev)25380265e00cSElaine Zhang static int rk3576_clk_probe(struct udevice *dev)
25390265e00cSElaine Zhang {
25400265e00cSElaine Zhang struct rk3576_clk_priv *priv = dev_get_priv(dev);
25410265e00cSElaine Zhang int ret;
25427f4710efSFinley Xiao #if CONFIG_IS_ENABLED(CLK_SCMI)
25437f4710efSFinley Xiao struct clk clk;
25447f4710efSFinley Xiao #endif
25450265e00cSElaine Zhang
25460265e00cSElaine Zhang priv->sync_kernel = false;
25470265e00cSElaine Zhang
25480265e00cSElaine Zhang #ifdef CONFIG_SPL_BUILD
25490265e00cSElaine Zhang /* relase presetn_bigcore_biu/cru/grf */
25500265e00cSElaine Zhang writel(0x1c001c00, 0x26010010);
25510265e00cSElaine Zhang /* set spll to normal mode */
25520265e00cSElaine Zhang writel(BITS_WITH_WMASK(2, 0x7U, 6),
25530265e00cSElaine Zhang RK3576_SCRU_BASE + RK3576_PLL_CON(137));
25540265e00cSElaine Zhang writel(BITS_WITH_WMASK(1, 0x3U, 0),
25550265e00cSElaine Zhang RK3576_SCRU_BASE + RK3576_MODE_CON0);
25560265e00cSElaine Zhang /* fix ppll\aupll\cpll */
25570265e00cSElaine Zhang writel(BITS_WITH_WMASK(2, 0x7U, 6),
25580265e00cSElaine Zhang RK3576_CRU_BASE + RK3576_PMU_PLL_CON(129));
25590265e00cSElaine Zhang writel(BITS_WITH_WMASK(2, 0x7U, 6),
25600265e00cSElaine Zhang RK3576_CRU_BASE + RK3576_PLL_CON(97));
25610265e00cSElaine Zhang writel(BITS_WITH_WMASK(2, 0x7U, 6),
25620265e00cSElaine Zhang RK3576_CRU_BASE + RK3576_PLL_CON(105));
25630265e00cSElaine Zhang writel(BITS_WITH_WMASK(1, 0x3U, 6),
25640265e00cSElaine Zhang RK3576_CRU_BASE + RK3576_MODE_CON0);
25650265e00cSElaine Zhang writel(BITS_WITH_WMASK(1, 0x3U, 8),
25660265e00cSElaine Zhang RK3576_CRU_BASE + RK3576_MODE_CON0);
2567*5c6e0812SElaine Zhang if (!(readl(RK3576_CRU_BASE + RK3576_LITCORE_CLKSEL_CON(0)) & CLK_LITCORE_SEL_MASK)) {
25680265e00cSElaine Zhang /* init cci */
25690265e00cSElaine Zhang writel(0xffff0000, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
25700265e00cSElaine Zhang if (!priv->armclk_enter_hz) {
25710265e00cSElaine Zhang ret = rockchip_pll_set_rate(&rk3576_pll_clks[LPLL], priv->cru,
25720265e00cSElaine Zhang LPLL, LPLL_HZ);
25730265e00cSElaine Zhang priv->armclk_enter_hz =
25740265e00cSElaine Zhang rockchip_pll_get_rate(&rk3576_pll_clks[LPLL],
25750265e00cSElaine Zhang priv->cru, LPLL);
25760265e00cSElaine Zhang priv->armclk_init_hz = priv->armclk_enter_hz;
25770265e00cSElaine Zhang rk_clrsetreg(&priv->cru->litclksel_con[0], CLK_LITCORE_DIV_MASK,
25780265e00cSElaine Zhang 0 << CLK_LITCORE_DIV_SHIFT);
25790265e00cSElaine Zhang }
25807f4710efSFinley Xiao /* init cci */
25817f4710efSFinley Xiao writel(0xffff20cb, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2582d38d4a65SFinley Xiao
2583*5c6e0812SElaine Zhang }
2584*5c6e0812SElaine Zhang if (!(readl(RK3576_CRU_BASE + RK3576_BIGCORE_CLKSEL_CON(0)) & CLK_BIGCORE_SEL_MASK)) {
2585*5c6e0812SElaine Zhang rockchip_pll_set_rate(&rk3576_pll_clks[BPLL], priv->cru,
2586*5c6e0812SElaine Zhang BPLL, LPLL_HZ);
2587d38d4a65SFinley Xiao /* Change bigcore rm from 4 to 3 */
2588d38d4a65SFinley Xiao writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x3c);
2589d38d4a65SFinley Xiao writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x44);
2590d38d4a65SFinley Xiao writel(0x00020002, RK3576_BIGCORE_GRF_BASE + 0x38);
2591d38d4a65SFinley Xiao udelay(1);
2592d38d4a65SFinley Xiao writel(0x00020000, RK3576_BIGCORE_GRF_BASE + 0x38);
2593*5c6e0812SElaine Zhang }
25940265e00cSElaine Zhang #endif
25950265e00cSElaine Zhang
25960265e00cSElaine Zhang priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
25970265e00cSElaine Zhang if (IS_ERR(priv->grf))
25980265e00cSElaine Zhang return PTR_ERR(priv->grf);
25990265e00cSElaine Zhang
26000265e00cSElaine Zhang rk3576_clk_init(priv);
26017f4710efSFinley Xiao
26027f4710efSFinley Xiao #if CONFIG_IS_ENABLED(CLK_SCMI)
26037f4710efSFinley Xiao #ifndef CONFIG_SPL_BUILD
26047f4710efSFinley Xiao ret = rockchip_get_scmi_clk(&clk.dev);
26057f4710efSFinley Xiao if (ret) {
26067f4710efSFinley Xiao printf("Failed to get scmi clk dev, ret=%d\n", ret);
26077f4710efSFinley Xiao return ret;
26087f4710efSFinley Xiao }
26097f4710efSFinley Xiao if (!priv->armclk_enter_hz) {
26107f4710efSFinley Xiao clk.id = ARMCLK_L;
26117f4710efSFinley Xiao ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
26127f4710efSFinley Xiao if (ret < 0) {
26137f4710efSFinley Xiao printf("Failed to set cpubl, ret=%d\n", ret);
26147f4710efSFinley Xiao } else {
26157f4710efSFinley Xiao priv->armclk_enter_hz = CPU_PVTPLL_HZ;
26167f4710efSFinley Xiao priv->armclk_init_hz = CPU_PVTPLL_HZ;
26177f4710efSFinley Xiao }
26187f4710efSFinley Xiao }
26197f4710efSFinley Xiao clk.id = ARMCLK_B;
26207f4710efSFinley Xiao ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
26217f4710efSFinley Xiao if (ret < 0)
26227f4710efSFinley Xiao printf("Failed to set cpub, ret=%d\n", ret);
26237f4710efSFinley Xiao #endif
26247f4710efSFinley Xiao #endif
26250265e00cSElaine Zhang
26260265e00cSElaine Zhang /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
26270265e00cSElaine Zhang ret = clk_set_defaults(dev);
26280265e00cSElaine Zhang if (ret)
26290265e00cSElaine Zhang debug("%s clk_set_defaults failed %d\n", __func__, ret);
26300265e00cSElaine Zhang else
26310265e00cSElaine Zhang priv->sync_kernel = true;
26320265e00cSElaine Zhang
26330265e00cSElaine Zhang return 0;
26340265e00cSElaine Zhang }
26350265e00cSElaine Zhang
rk3576_clk_ofdata_to_platdata(struct udevice * dev)26360265e00cSElaine Zhang static int rk3576_clk_ofdata_to_platdata(struct udevice *dev)
26370265e00cSElaine Zhang {
26380265e00cSElaine Zhang struct rk3576_clk_priv *priv = dev_get_priv(dev);
26390265e00cSElaine Zhang
26400265e00cSElaine Zhang priv->cru = dev_read_addr_ptr(dev);
26410265e00cSElaine Zhang
26420265e00cSElaine Zhang return 0;
26430265e00cSElaine Zhang }
26440265e00cSElaine Zhang
rk3576_clk_bind(struct udevice * dev)26450265e00cSElaine Zhang static int rk3576_clk_bind(struct udevice *dev)
26460265e00cSElaine Zhang {
26470265e00cSElaine Zhang int ret;
26480265e00cSElaine Zhang struct udevice *sys_child, *sf_child;
26490265e00cSElaine Zhang struct sysreset_reg *priv;
26500265e00cSElaine Zhang struct softreset_reg *sf_priv;
26510265e00cSElaine Zhang
26520265e00cSElaine Zhang /* The reset driver does not have a device node, so bind it here */
26530265e00cSElaine Zhang ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
26540265e00cSElaine Zhang &sys_child);
26550265e00cSElaine Zhang if (ret) {
26560265e00cSElaine Zhang debug("Warning: No sysreset driver: ret=%d\n", ret);
26570265e00cSElaine Zhang } else {
26580265e00cSElaine Zhang priv = malloc(sizeof(struct sysreset_reg));
26590265e00cSElaine Zhang priv->glb_srst_fst_value = offsetof(struct rk3576_cru,
26600265e00cSElaine Zhang glb_srst_fst);
26610265e00cSElaine Zhang priv->glb_srst_snd_value = offsetof(struct rk3576_cru,
26620265e00cSElaine Zhang glb_srsr_snd);
26630265e00cSElaine Zhang sys_child->priv = priv;
26640265e00cSElaine Zhang }
26650265e00cSElaine Zhang
26660265e00cSElaine Zhang ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
26670265e00cSElaine Zhang dev_ofnode(dev), &sf_child);
26680265e00cSElaine Zhang if (ret) {
26690265e00cSElaine Zhang debug("Warning: No rockchip reset driver: ret=%d\n", ret);
26700265e00cSElaine Zhang } else {
26710265e00cSElaine Zhang sf_priv = malloc(sizeof(struct softreset_reg));
26720265e00cSElaine Zhang sf_priv->sf_reset_offset = offsetof(struct rk3576_cru,
26730265e00cSElaine Zhang softrst_con[0]);
26740265e00cSElaine Zhang sf_priv->sf_reset_num = 524454;
26750265e00cSElaine Zhang sf_child->priv = sf_priv;
26760265e00cSElaine Zhang }
26770265e00cSElaine Zhang
26780265e00cSElaine Zhang return 0;
26790265e00cSElaine Zhang }
26800265e00cSElaine Zhang
26810265e00cSElaine Zhang static const struct udevice_id rk3576_clk_ids[] = {
26820265e00cSElaine Zhang { .compatible = "rockchip,rk3576-cru" },
26830265e00cSElaine Zhang { }
26840265e00cSElaine Zhang };
26850265e00cSElaine Zhang
26860265e00cSElaine Zhang U_BOOT_DRIVER(rockchip_rk3576_cru) = {
26870265e00cSElaine Zhang .name = "rockchip_rk3576_cru",
26880265e00cSElaine Zhang .id = UCLASS_CLK,
26890265e00cSElaine Zhang .of_match = rk3576_clk_ids,
26900265e00cSElaine Zhang .priv_auto_alloc_size = sizeof(struct rk3576_clk_priv),
26910265e00cSElaine Zhang .ofdata_to_platdata = rk3576_clk_ofdata_to_platdata,
26920265e00cSElaine Zhang .ops = &rk3576_clk_ops,
26930265e00cSElaine Zhang .bind = rk3576_clk_bind,
26940265e00cSElaine Zhang .probe = rk3576_clk_probe,
26950265e00cSElaine Zhang };
26960265e00cSElaine Zhang
26970265e00cSElaine Zhang #ifndef CONFIG_SPL_BUILD
26980265e00cSElaine Zhang /**
26990265e00cSElaine Zhang * soc_clk_dump() - Print clock frequencies
27000265e00cSElaine Zhang * Returns zero on success
27010265e00cSElaine Zhang *
27020265e00cSElaine Zhang * Implementation for the clk dump command.
27030265e00cSElaine Zhang */
soc_clk_dump(void)27040265e00cSElaine Zhang int soc_clk_dump(void)
27050265e00cSElaine Zhang {
27060265e00cSElaine Zhang struct udevice *cru_dev;
27070265e00cSElaine Zhang struct rk3576_clk_priv *priv;
27080265e00cSElaine Zhang const struct rk3576_clk_info *clk_dump;
27090265e00cSElaine Zhang struct clk clk;
27100265e00cSElaine Zhang unsigned long clk_count = ARRAY_SIZE(clks_dump);
27110265e00cSElaine Zhang unsigned long rate;
27120265e00cSElaine Zhang int i, ret;
27130265e00cSElaine Zhang
27140265e00cSElaine Zhang ret = uclass_get_device_by_driver(UCLASS_CLK,
27150265e00cSElaine Zhang DM_GET_DRIVER(rockchip_rk3576_cru),
27160265e00cSElaine Zhang &cru_dev);
27170265e00cSElaine Zhang if (ret) {
27180265e00cSElaine Zhang printf("%s failed to get cru device\n", __func__);
27190265e00cSElaine Zhang return ret;
27200265e00cSElaine Zhang }
27210265e00cSElaine Zhang
27220265e00cSElaine Zhang priv = dev_get_priv(cru_dev);
27230265e00cSElaine Zhang printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
27240265e00cSElaine Zhang priv->sync_kernel ? "sync kernel" : "uboot",
27250265e00cSElaine Zhang priv->armclk_enter_hz / 1000,
27260265e00cSElaine Zhang priv->armclk_init_hz / 1000,
27270265e00cSElaine Zhang priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
27280265e00cSElaine Zhang priv->set_armclk_rate ? " KHz" : "N/A");
27290265e00cSElaine Zhang for (i = 0; i < clk_count; i++) {
27300265e00cSElaine Zhang clk_dump = &clks_dump[i];
27310265e00cSElaine Zhang if (clk_dump->name) {
27320265e00cSElaine Zhang memset(&clk, 0, sizeof(struct clk));
27330265e00cSElaine Zhang clk.id = clk_dump->id;
27340265e00cSElaine Zhang if (clk_dump->is_cru)
27350265e00cSElaine Zhang ret = clk_request(cru_dev, &clk);
27360265e00cSElaine Zhang if (ret < 0)
27370265e00cSElaine Zhang return ret;
27380265e00cSElaine Zhang
27390265e00cSElaine Zhang rate = clk_get_rate(&clk);
27400265e00cSElaine Zhang clk_free(&clk);
27410265e00cSElaine Zhang if (rate < 0)
27420265e00cSElaine Zhang printf(" %s %s\n", clk_dump->name,
27430265e00cSElaine Zhang "unknown");
27440265e00cSElaine Zhang else
27450265e00cSElaine Zhang printf(" %s %lu KHz\n", clk_dump->name,
27460265e00cSElaine Zhang rate / 1000);
27470265e00cSElaine Zhang }
27480265e00cSElaine Zhang }
27490265e00cSElaine Zhang
27500265e00cSElaine Zhang return 0;
27510265e00cSElaine Zhang }
27520265e00cSElaine Zhang #endif
2753