1417bebc4SElaine Zhang // SPDX-License-Identifier: GPL-2.0
2417bebc4SElaine Zhang /*
3417bebc4SElaine Zhang * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
4c6f7c1a3SJoseph Chen * Author: Joseph Chen <chenjh@rock-chips.com>
5417bebc4SElaine Zhang */
6417bebc4SElaine Zhang
7417bebc4SElaine Zhang #include <common.h>
8417bebc4SElaine Zhang #include <bitfield.h>
9417bebc4SElaine Zhang #include <clk-uclass.h>
10417bebc4SElaine Zhang #include <dm.h>
11417bebc4SElaine Zhang #include <errno.h>
12417bebc4SElaine Zhang #include <syscon.h>
13417bebc4SElaine Zhang #include <asm/arch/clock.h>
14417bebc4SElaine Zhang #include <asm/arch/cru_rk3568.h>
1526663c2dSElaine Zhang #include <asm/arch/grf_rk3568.h>
16417bebc4SElaine Zhang #include <asm/arch/hardware.h>
17417bebc4SElaine Zhang #include <asm/io.h>
18417bebc4SElaine Zhang #include <dm/lists.h>
19417bebc4SElaine Zhang #include <dt-bindings/clock/rk3568-cru.h>
20417bebc4SElaine Zhang
21417bebc4SElaine Zhang DECLARE_GLOBAL_DATA_PTR;
22417bebc4SElaine Zhang
23417bebc4SElaine Zhang #define RK3568_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
24417bebc4SElaine Zhang { \
25417bebc4SElaine Zhang .rate = _rate##U, \
26417bebc4SElaine Zhang .aclk_div = _aclk_div, \
27417bebc4SElaine Zhang .pclk_div = _pclk_div, \
28417bebc4SElaine Zhang }
29417bebc4SElaine Zhang
30417bebc4SElaine Zhang #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
31417bebc4SElaine Zhang
32417bebc4SElaine Zhang static struct rockchip_cpu_rate_table rk3568_cpu_rates[] = {
33417bebc4SElaine Zhang RK3568_CPUCLK_RATE(1416000000, 1, 5),
34417bebc4SElaine Zhang RK3568_CPUCLK_RATE(1296000000, 1, 5),
35417bebc4SElaine Zhang RK3568_CPUCLK_RATE(1200000000, 1, 3),
36417bebc4SElaine Zhang RK3568_CPUCLK_RATE(1104000000, 1, 3),
37417bebc4SElaine Zhang RK3568_CPUCLK_RATE(1008000000, 1, 3),
38417bebc4SElaine Zhang RK3568_CPUCLK_RATE(912000000, 1, 3),
39417bebc4SElaine Zhang RK3568_CPUCLK_RATE(816000000, 1, 3),
40417bebc4SElaine Zhang RK3568_CPUCLK_RATE(600000000, 1, 1),
41417bebc4SElaine Zhang RK3568_CPUCLK_RATE(408000000, 1, 1),
42417bebc4SElaine Zhang { /* sentinel */ },
43417bebc4SElaine Zhang };
44417bebc4SElaine Zhang
45417bebc4SElaine Zhang static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
46417bebc4SElaine Zhang /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
47417bebc4SElaine Zhang RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
48417bebc4SElaine Zhang RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0),
49417bebc4SElaine Zhang RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0),
50417bebc4SElaine Zhang RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
51417bebc4SElaine Zhang RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
52417bebc4SElaine Zhang RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
53417bebc4SElaine Zhang RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
54417bebc4SElaine Zhang RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
55417bebc4SElaine Zhang RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
56417bebc4SElaine Zhang RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
57417bebc4SElaine Zhang RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
58417bebc4SElaine Zhang RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
59417bebc4SElaine Zhang RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
60417bebc4SElaine Zhang RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
61f6d27794Szhangqing RK3036_PLL_RATE(400000000, 1, 100, 6, 1, 1, 0),
62802c460aSElaine Zhang RK3036_PLL_RATE(200000000, 1, 100, 6, 2, 1, 0),
63417bebc4SElaine Zhang RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0),
64417bebc4SElaine Zhang { /* sentinel */ },
65417bebc4SElaine Zhang };
66417bebc4SElaine Zhang
67417bebc4SElaine Zhang static struct rockchip_pll_clock rk3568_pll_clks[] = {
68417bebc4SElaine Zhang [APLL] = PLL(pll_rk3328, PLL_APLL, RK3568_PLL_CON(0),
69417bebc4SElaine Zhang RK3568_MODE_CON, 0, 10, 0, rk3568_pll_rates),
70417bebc4SElaine Zhang [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3568_PLL_CON(8),
71417bebc4SElaine Zhang RK3568_MODE_CON, 2, 10, 0, NULL),
72392d4cefSElaine Zhang [CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3568_PLL_CON(24),
73417bebc4SElaine Zhang RK3568_MODE_CON, 4, 10, 0, rk3568_pll_rates),
74392d4cefSElaine Zhang [GPLL] = PLL(pll_rk3328, PLL_HPLL, RK3568_PLL_CON(16),
75417bebc4SElaine Zhang RK3568_MODE_CON, 6, 10, 0, rk3568_pll_rates),
76417bebc4SElaine Zhang [NPLL] = PLL(pll_rk3328, PLL_NPLL, RK3568_PLL_CON(32),
77417bebc4SElaine Zhang RK3568_MODE_CON, 10, 10, 0, rk3568_pll_rates),
78417bebc4SElaine Zhang [VPLL] = PLL(pll_rk3328, PLL_VPLL, RK3568_PLL_CON(40),
79417bebc4SElaine Zhang RK3568_MODE_CON, 12, 10, 0, rk3568_pll_rates),
80417bebc4SElaine Zhang [PPLL] = PLL(pll_rk3328, PLL_PPLL, RK3568_PMU_PLL_CON(0),
81417bebc4SElaine Zhang RK3568_PMU_MODE, 0, 10, 0, rk3568_pll_rates),
82801ca42bSElaine Zhang [HPLL] = PLL(pll_rk3328, PLL_HPLL, RK3568_PMU_PLL_CON(16),
83417bebc4SElaine Zhang RK3568_PMU_MODE, 2, 10, 0, rk3568_pll_rates),
84417bebc4SElaine Zhang };
85417bebc4SElaine Zhang
86f6d27794Szhangqing #ifndef CONFIG_SPL_BUILD
87417bebc4SElaine Zhang #define RK3568_CLK_DUMP(_id, _name, _iscru) \
88417bebc4SElaine Zhang { \
89417bebc4SElaine Zhang .id = _id, \
90417bebc4SElaine Zhang .name = _name, \
91417bebc4SElaine Zhang .is_cru = _iscru, \
92417bebc4SElaine Zhang }
93417bebc4SElaine Zhang
94417bebc4SElaine Zhang static const struct rk3568_clk_info clks_dump[] = {
95417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_APLL, "apll", true),
96417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_DPLL, "dpll", true),
97417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_GPLL, "gpll", true),
98417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_CPLL, "cpll", true),
99417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_NPLL, "npll", true),
100417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_VPLL, "vpll", true),
101417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_HPLL, "hpll", false),
102417bebc4SElaine Zhang RK3568_CLK_DUMP(PLL_PPLL, "ppll", false),
103417bebc4SElaine Zhang RK3568_CLK_DUMP(ARMCLK, "armclk", true),
104417bebc4SElaine Zhang RK3568_CLK_DUMP(ACLK_BUS, "aclk_bus", true),
105417bebc4SElaine Zhang RK3568_CLK_DUMP(PCLK_BUS, "pclk_bus", true),
106417bebc4SElaine Zhang RK3568_CLK_DUMP(ACLK_TOP_HIGH, "aclk_top_high", true),
107417bebc4SElaine Zhang RK3568_CLK_DUMP(ACLK_TOP_LOW, "aclk_top_low", true),
108417bebc4SElaine Zhang RK3568_CLK_DUMP(HCLK_TOP, "hclk_top", true),
109417bebc4SElaine Zhang RK3568_CLK_DUMP(PCLK_TOP, "pclk_top", true),
110417bebc4SElaine Zhang RK3568_CLK_DUMP(ACLK_PERIMID, "aclk_perimid", true),
111417bebc4SElaine Zhang RK3568_CLK_DUMP(HCLK_PERIMID, "hclk_perimid", true),
112417bebc4SElaine Zhang RK3568_CLK_DUMP(PCLK_PMU, "pclk_pmu", false),
113417bebc4SElaine Zhang };
114417bebc4SElaine Zhang #endif
115417bebc4SElaine Zhang
116f6d27794Szhangqing static ulong __maybe_unused
rk3568_pmu_pll_set_rate(struct rk3568_clk_priv * priv,ulong pll_id,ulong rate)117f6d27794Szhangqing rk3568_pmu_pll_set_rate(struct rk3568_clk_priv *priv,
118417bebc4SElaine Zhang ulong pll_id, ulong rate)
119417bebc4SElaine Zhang {
120417bebc4SElaine Zhang struct udevice *pmucru_dev;
121417bebc4SElaine Zhang struct rk3568_pmuclk_priv *pmu_priv;
122417bebc4SElaine Zhang int ret;
123417bebc4SElaine Zhang
124417bebc4SElaine Zhang ret = uclass_get_device_by_driver(UCLASS_CLK,
125417bebc4SElaine Zhang DM_GET_DRIVER(rockchip_rk3568_pmucru),
126417bebc4SElaine Zhang &pmucru_dev);
127417bebc4SElaine Zhang if (ret) {
128417bebc4SElaine Zhang printf("%s: could not find pmucru device\n", __func__);
129417bebc4SElaine Zhang return ret;
130417bebc4SElaine Zhang }
131417bebc4SElaine Zhang pmu_priv = dev_get_priv(pmucru_dev);
132417bebc4SElaine Zhang
133417bebc4SElaine Zhang rockchip_pll_set_rate(&rk3568_pll_clks[pll_id],
134417bebc4SElaine Zhang pmu_priv->pmucru, pll_id, rate);
135417bebc4SElaine Zhang
136417bebc4SElaine Zhang return 0;
137417bebc4SElaine Zhang }
138417bebc4SElaine Zhang
rk3568_pmu_pll_get_rate(struct rk3568_clk_priv * priv,ulong pll_id)139417bebc4SElaine Zhang static ulong rk3568_pmu_pll_get_rate(struct rk3568_clk_priv *priv,
140417bebc4SElaine Zhang ulong pll_id)
141417bebc4SElaine Zhang {
142417bebc4SElaine Zhang struct udevice *pmucru_dev;
143417bebc4SElaine Zhang struct rk3568_pmuclk_priv *pmu_priv;
144417bebc4SElaine Zhang int ret;
145417bebc4SElaine Zhang
146417bebc4SElaine Zhang ret = uclass_get_device_by_driver(UCLASS_CLK,
147417bebc4SElaine Zhang DM_GET_DRIVER(rockchip_rk3568_pmucru),
148417bebc4SElaine Zhang &pmucru_dev);
149417bebc4SElaine Zhang if (ret) {
150417bebc4SElaine Zhang printf("%s: could not find pmucru device\n", __func__);
151417bebc4SElaine Zhang return ret;
152417bebc4SElaine Zhang }
153417bebc4SElaine Zhang pmu_priv = dev_get_priv(pmucru_dev);
154417bebc4SElaine Zhang
155417bebc4SElaine Zhang return rockchip_pll_get_rate(&rk3568_pll_clks[pll_id],
156417bebc4SElaine Zhang pmu_priv->pmucru, pll_id);
157417bebc4SElaine Zhang }
158417bebc4SElaine Zhang
159417bebc4SElaine Zhang /*
160417bebc4SElaine Zhang *
161417bebc4SElaine Zhang * rational_best_approximation(31415, 10000,
162417bebc4SElaine Zhang * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
163417bebc4SElaine Zhang *
164417bebc4SElaine Zhang * you may look at given_numerator as a fixed point number,
165417bebc4SElaine Zhang * with the fractional part size described in given_denominator.
166417bebc4SElaine Zhang *
167417bebc4SElaine Zhang * for theoretical background, see:
168417bebc4SElaine Zhang * http://en.wikipedia.org/wiki/Continued_fraction
169417bebc4SElaine 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)170417bebc4SElaine Zhang static void rational_best_approximation(unsigned long given_numerator,
171417bebc4SElaine Zhang unsigned long given_denominator,
172417bebc4SElaine Zhang unsigned long max_numerator,
173417bebc4SElaine Zhang unsigned long max_denominator,
174417bebc4SElaine Zhang unsigned long *best_numerator,
175417bebc4SElaine Zhang unsigned long *best_denominator)
176417bebc4SElaine Zhang {
177417bebc4SElaine Zhang unsigned long n, d, n0, d0, n1, d1;
178417bebc4SElaine Zhang
179417bebc4SElaine Zhang n = given_numerator;
180417bebc4SElaine Zhang d = given_denominator;
181417bebc4SElaine Zhang n0 = 0;
182417bebc4SElaine Zhang d1 = 0;
183417bebc4SElaine Zhang n1 = 1;
184417bebc4SElaine Zhang d0 = 1;
185417bebc4SElaine Zhang for (;;) {
186417bebc4SElaine Zhang unsigned long t, a;
187417bebc4SElaine Zhang
188417bebc4SElaine Zhang if (n1 > max_numerator || d1 > max_denominator) {
189417bebc4SElaine Zhang n1 = n0;
190417bebc4SElaine Zhang d1 = d0;
191417bebc4SElaine Zhang break;
192417bebc4SElaine Zhang }
193417bebc4SElaine Zhang if (d == 0)
194417bebc4SElaine Zhang break;
195417bebc4SElaine Zhang t = d;
196417bebc4SElaine Zhang a = n / d;
197417bebc4SElaine Zhang d = n % d;
198417bebc4SElaine Zhang n = t;
199417bebc4SElaine Zhang t = n0 + a * n1;
200417bebc4SElaine Zhang n0 = n1;
201417bebc4SElaine Zhang n1 = t;
202417bebc4SElaine Zhang t = d0 + a * d1;
203417bebc4SElaine Zhang d0 = d1;
204417bebc4SElaine Zhang d1 = t;
205417bebc4SElaine Zhang }
206417bebc4SElaine Zhang *best_numerator = n1;
207417bebc4SElaine Zhang *best_denominator = d1;
208417bebc4SElaine Zhang }
209417bebc4SElaine Zhang
rk3568_rtc32k_get_pmuclk(struct rk3568_pmuclk_priv * priv)210417bebc4SElaine Zhang static ulong rk3568_rtc32k_get_pmuclk(struct rk3568_pmuclk_priv *priv)
211417bebc4SElaine Zhang {
212417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
213417bebc4SElaine Zhang unsigned long m, n;
214417bebc4SElaine Zhang u32 fracdiv;
215417bebc4SElaine Zhang
216417bebc4SElaine Zhang fracdiv = readl(&pmucru->pmu_clksel_con[1]);
217417bebc4SElaine Zhang m = fracdiv & RTC32K_FRAC_NUMERATOR_MASK;
218417bebc4SElaine Zhang m >>= RTC32K_FRAC_NUMERATOR_SHIFT;
219417bebc4SElaine Zhang n = fracdiv & RTC32K_FRAC_DENOMINATOR_MASK;
220417bebc4SElaine Zhang n >>= RTC32K_FRAC_DENOMINATOR_SHIFT;
221417bebc4SElaine Zhang
222417bebc4SElaine Zhang return OSC_HZ * m / n;
223417bebc4SElaine Zhang }
224417bebc4SElaine Zhang
rk3568_rtc32k_set_pmuclk(struct rk3568_pmuclk_priv * priv,ulong rate)225417bebc4SElaine Zhang static ulong rk3568_rtc32k_set_pmuclk(struct rk3568_pmuclk_priv *priv,
226417bebc4SElaine Zhang ulong rate)
227417bebc4SElaine Zhang {
228417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
229417bebc4SElaine Zhang unsigned long m, n, val;
230417bebc4SElaine Zhang
231417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
232417bebc4SElaine Zhang RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
233417bebc4SElaine Zhang
234417bebc4SElaine Zhang rational_best_approximation(rate, OSC_HZ,
235417bebc4SElaine Zhang GENMASK(16 - 1, 0),
236417bebc4SElaine Zhang GENMASK(16 - 1, 0),
237417bebc4SElaine Zhang &m, &n);
238417bebc4SElaine Zhang val = m << RTC32K_FRAC_NUMERATOR_SHIFT | n;
239417bebc4SElaine Zhang writel(val, &pmucru->pmu_clksel_con[1]);
240417bebc4SElaine Zhang
241417bebc4SElaine Zhang return rk3568_rtc32k_get_pmuclk(priv);
242417bebc4SElaine Zhang }
243417bebc4SElaine Zhang
rk3568_i2c_get_pmuclk(struct rk3568_pmuclk_priv * priv,ulong clk_id)244417bebc4SElaine Zhang static ulong rk3568_i2c_get_pmuclk(struct rk3568_pmuclk_priv *priv,
245417bebc4SElaine Zhang ulong clk_id)
246417bebc4SElaine Zhang {
247417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
248417bebc4SElaine Zhang u32 div, con;
249417bebc4SElaine Zhang
250417bebc4SElaine Zhang switch (clk_id) {
251417bebc4SElaine Zhang case CLK_I2C0:
252417bebc4SElaine Zhang con = readl(&pmucru->pmu_clksel_con[3]);
253417bebc4SElaine Zhang div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT;
254417bebc4SElaine Zhang break;
255417bebc4SElaine Zhang default:
256417bebc4SElaine Zhang return -ENOENT;
257417bebc4SElaine Zhang }
258417bebc4SElaine Zhang
259417bebc4SElaine Zhang return DIV_TO_RATE(priv->ppll_hz, div);
260417bebc4SElaine Zhang }
261417bebc4SElaine Zhang
rk3568_i2c_set_pmuclk(struct rk3568_pmuclk_priv * priv,ulong clk_id,ulong rate)262417bebc4SElaine Zhang static ulong rk3568_i2c_set_pmuclk(struct rk3568_pmuclk_priv *priv,
263417bebc4SElaine Zhang ulong clk_id, ulong rate)
264417bebc4SElaine Zhang {
265417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
266417bebc4SElaine Zhang int src_clk_div;
267417bebc4SElaine Zhang
268417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
269417bebc4SElaine Zhang assert(src_clk_div - 1 <= 127);
270417bebc4SElaine Zhang
271417bebc4SElaine Zhang switch (clk_id) {
272417bebc4SElaine Zhang case CLK_I2C0:
273417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[3], CLK_I2C0_DIV_MASK,
274417bebc4SElaine Zhang (src_clk_div - 1) << CLK_I2C0_DIV_SHIFT);
275417bebc4SElaine Zhang break;
276417bebc4SElaine Zhang default:
277417bebc4SElaine Zhang return -ENOENT;
278417bebc4SElaine Zhang }
279417bebc4SElaine Zhang
280417bebc4SElaine Zhang return rk3568_i2c_get_pmuclk(priv, clk_id);
281417bebc4SElaine Zhang }
282417bebc4SElaine Zhang
rk3568_pwm_get_pmuclk(struct rk3568_pmuclk_priv * priv,ulong clk_id)283417bebc4SElaine Zhang static ulong rk3568_pwm_get_pmuclk(struct rk3568_pmuclk_priv *priv,
284417bebc4SElaine Zhang ulong clk_id)
285417bebc4SElaine Zhang {
286417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
287417bebc4SElaine Zhang u32 div, sel, con, parent;
288417bebc4SElaine Zhang
289417bebc4SElaine Zhang switch (clk_id) {
290417bebc4SElaine Zhang case CLK_PWM0:
291417bebc4SElaine Zhang con = readl(&pmucru->pmu_clksel_con[6]);
292417bebc4SElaine Zhang sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
293417bebc4SElaine Zhang div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT;
294417bebc4SElaine Zhang if (sel == CLK_PWM0_SEL_XIN24M)
295417bebc4SElaine Zhang parent = OSC_HZ;
296417bebc4SElaine Zhang else
297417bebc4SElaine Zhang parent = priv->ppll_hz;
298417bebc4SElaine Zhang break;
299417bebc4SElaine Zhang default:
300417bebc4SElaine Zhang return -ENOENT;
301417bebc4SElaine Zhang }
302417bebc4SElaine Zhang
303417bebc4SElaine Zhang return DIV_TO_RATE(parent, div);
304417bebc4SElaine Zhang }
305417bebc4SElaine Zhang
rk3568_pwm_set_pmuclk(struct rk3568_pmuclk_priv * priv,ulong clk_id,ulong rate)306417bebc4SElaine Zhang static ulong rk3568_pwm_set_pmuclk(struct rk3568_pmuclk_priv *priv,
307417bebc4SElaine Zhang ulong clk_id, ulong rate)
308417bebc4SElaine Zhang {
309417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
310417bebc4SElaine Zhang int src_clk_div;
311417bebc4SElaine Zhang
312417bebc4SElaine Zhang switch (clk_id) {
313417bebc4SElaine Zhang case CLK_PWM0:
314417bebc4SElaine Zhang if (rate == OSC_HZ) {
315417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[6],
316417bebc4SElaine Zhang CLK_PWM0_SEL_MASK | CLK_PWM0_DIV_MASK,
317417bebc4SElaine Zhang (CLK_PWM0_SEL_XIN24M <<
318417bebc4SElaine Zhang CLK_PWM0_SEL_SHIFT) |
319417bebc4SElaine Zhang 0 << CLK_PWM0_SEL_SHIFT);
320417bebc4SElaine Zhang } else {
321417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
322417bebc4SElaine Zhang assert(src_clk_div - 1 <= 127);
323417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[6],
324417bebc4SElaine Zhang CLK_PWM0_DIV_MASK | CLK_PWM0_DIV_MASK,
325417bebc4SElaine Zhang (CLK_PWM0_SEL_PPLL << CLK_PWM0_SEL_SHIFT) |
326417bebc4SElaine Zhang (src_clk_div - 1) << CLK_PWM0_DIV_SHIFT);
327417bebc4SElaine Zhang }
328417bebc4SElaine Zhang break;
329417bebc4SElaine Zhang default:
330417bebc4SElaine Zhang return -ENOENT;
331417bebc4SElaine Zhang }
332417bebc4SElaine Zhang
333417bebc4SElaine Zhang return rk3568_pwm_get_pmuclk(priv, clk_id);
334417bebc4SElaine Zhang }
335417bebc4SElaine Zhang
rk3568_pmu_get_pmuclk(struct rk3568_pmuclk_priv * priv)336417bebc4SElaine Zhang static ulong rk3568_pmu_get_pmuclk(struct rk3568_pmuclk_priv *priv)
337417bebc4SElaine Zhang {
338417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
339417bebc4SElaine Zhang u32 div, con, sel, parent;
340417bebc4SElaine Zhang
341417bebc4SElaine Zhang con = readl(&pmucru->pmu_clksel_con[2]);
342417bebc4SElaine Zhang sel = (con & PCLK_PDPMU_SEL_MASK) >> PCLK_PDPMU_SEL_SHIFT;
343417bebc4SElaine Zhang div = (con & PCLK_PDPMU_DIV_MASK) >> PCLK_PDPMU_DIV_SHIFT;
344417bebc4SElaine Zhang if (sel)
345417bebc4SElaine Zhang parent = GPLL_HZ;
346417bebc4SElaine Zhang else
347417bebc4SElaine Zhang parent = priv->ppll_hz;
348417bebc4SElaine Zhang
349417bebc4SElaine Zhang return DIV_TO_RATE(parent, div);
350417bebc4SElaine Zhang }
351417bebc4SElaine Zhang
rk3568_pmu_set_pmuclk(struct rk3568_pmuclk_priv * priv,ulong rate)352417bebc4SElaine Zhang static ulong rk3568_pmu_set_pmuclk(struct rk3568_pmuclk_priv *priv,
353417bebc4SElaine Zhang ulong rate)
354417bebc4SElaine Zhang {
355417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
356417bebc4SElaine Zhang int src_clk_div;
357417bebc4SElaine Zhang
358417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
359417bebc4SElaine Zhang assert(src_clk_div - 1 <= 31);
360417bebc4SElaine Zhang
361417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[2],
362417bebc4SElaine Zhang PCLK_PDPMU_DIV_MASK | PCLK_PDPMU_SEL_MASK,
363417bebc4SElaine Zhang (PCLK_PDPMU_SEL_PPLL << PCLK_PDPMU_SEL_SHIFT) |
364417bebc4SElaine Zhang ((src_clk_div - 1) << PCLK_PDPMU_DIV_SHIFT));
365417bebc4SElaine Zhang
366417bebc4SElaine Zhang return rk3568_pmu_get_pmuclk(priv);
367417bebc4SElaine Zhang }
368417bebc4SElaine Zhang
rk3568_pmuclk_get_rate(struct clk * clk)369417bebc4SElaine Zhang static ulong rk3568_pmuclk_get_rate(struct clk *clk)
370417bebc4SElaine Zhang {
371417bebc4SElaine Zhang struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
372417bebc4SElaine Zhang ulong rate = 0;
373417bebc4SElaine Zhang
374417bebc4SElaine Zhang if (!priv->ppll_hz) {
375417bebc4SElaine Zhang printf("%s ppll=%lu\n", __func__, priv->ppll_hz);
376417bebc4SElaine Zhang return -ENOENT;
377417bebc4SElaine Zhang }
378417bebc4SElaine Zhang
379417bebc4SElaine Zhang debug("%s %ld\n", __func__, clk->id);
380417bebc4SElaine Zhang switch (clk->id) {
381417bebc4SElaine Zhang case PLL_PPLL:
382417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[PPLL],
383417bebc4SElaine Zhang priv->pmucru, PPLL);
384417bebc4SElaine Zhang break;
385392d4cefSElaine Zhang case PLL_HPLL:
386392d4cefSElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[HPLL],
387392d4cefSElaine Zhang priv->pmucru, HPLL);
388392d4cefSElaine Zhang break;
389417bebc4SElaine Zhang case CLK_RTC_32K:
390417bebc4SElaine Zhang case CLK_RTC32K_FRAC:
391417bebc4SElaine Zhang rate = rk3568_rtc32k_get_pmuclk(priv);
392417bebc4SElaine Zhang break;
393417bebc4SElaine Zhang case CLK_I2C0:
394417bebc4SElaine Zhang rate = rk3568_i2c_get_pmuclk(priv, clk->id);
395417bebc4SElaine Zhang break;
396417bebc4SElaine Zhang case CLK_PWM0:
397417bebc4SElaine Zhang rate = rk3568_pwm_get_pmuclk(priv, clk->id);
398417bebc4SElaine Zhang break;
399417bebc4SElaine Zhang case PCLK_PMU:
400417bebc4SElaine Zhang rate = rk3568_pmu_get_pmuclk(priv);
401417bebc4SElaine Zhang break;
402417bebc4SElaine Zhang default:
403417bebc4SElaine Zhang return -ENOENT;
404417bebc4SElaine Zhang }
405417bebc4SElaine Zhang
406417bebc4SElaine Zhang return rate;
407417bebc4SElaine Zhang }
408417bebc4SElaine Zhang
rk3568_pmuclk_set_rate(struct clk * clk,ulong rate)409417bebc4SElaine Zhang static ulong rk3568_pmuclk_set_rate(struct clk *clk, ulong rate)
410417bebc4SElaine Zhang {
411417bebc4SElaine Zhang struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
412417bebc4SElaine Zhang ulong ret = 0;
413417bebc4SElaine Zhang
414417bebc4SElaine Zhang if (!priv->ppll_hz) {
415417bebc4SElaine Zhang printf("%s ppll=%lu\n", __func__, priv->ppll_hz);
416417bebc4SElaine Zhang return -ENOENT;
417417bebc4SElaine Zhang }
418417bebc4SElaine Zhang
419417bebc4SElaine Zhang debug("%s %ld %ld\n", __func__, clk->id, rate);
420417bebc4SElaine Zhang switch (clk->id) {
421417bebc4SElaine Zhang case PLL_PPLL:
422417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[PPLL],
423417bebc4SElaine Zhang priv->pmucru, PPLL, rate);
424802c460aSElaine Zhang priv->ppll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[PPLL],
425802c460aSElaine Zhang priv->pmucru, PPLL);
426417bebc4SElaine Zhang break;
427392d4cefSElaine Zhang case PLL_HPLL:
428392d4cefSElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[HPLL],
429392d4cefSElaine Zhang priv->pmucru, HPLL, rate);
430802c460aSElaine Zhang priv->hpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[HPLL],
431802c460aSElaine Zhang priv->pmucru, HPLL);
432392d4cefSElaine Zhang break;
433417bebc4SElaine Zhang case CLK_RTC_32K:
434417bebc4SElaine Zhang case CLK_RTC32K_FRAC:
435417bebc4SElaine Zhang ret = rk3568_rtc32k_set_pmuclk(priv, rate);
436417bebc4SElaine Zhang break;
437417bebc4SElaine Zhang case CLK_I2C0:
438417bebc4SElaine Zhang ret = rk3568_i2c_set_pmuclk(priv, clk->id, rate);
439417bebc4SElaine Zhang break;
440417bebc4SElaine Zhang case CLK_PWM0:
441417bebc4SElaine Zhang ret = rk3568_pwm_set_pmuclk(priv, clk->id, rate);
442417bebc4SElaine Zhang break;
443417bebc4SElaine Zhang case PCLK_PMU:
444417bebc4SElaine Zhang ret = rk3568_pmu_set_pmuclk(priv, rate);
445417bebc4SElaine Zhang break;
446ea2fe5aaSJonas Karlman case CLK_PCIEPHY0_REF:
447ea2fe5aaSJonas Karlman case CLK_PCIEPHY1_REF:
448ea2fe5aaSJonas Karlman case CLK_PCIEPHY2_REF:
449ea2fe5aaSJonas Karlman return 0;
450417bebc4SElaine Zhang default:
451417bebc4SElaine Zhang return -ENOENT;
452417bebc4SElaine Zhang }
453417bebc4SElaine Zhang
454417bebc4SElaine Zhang return ret;
455417bebc4SElaine Zhang }
456417bebc4SElaine Zhang
rk3568_rtc32k_set_parent(struct clk * clk,struct clk * parent)457417bebc4SElaine Zhang static int rk3568_rtc32k_set_parent(struct clk *clk, struct clk *parent)
458417bebc4SElaine Zhang {
459417bebc4SElaine Zhang struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
460417bebc4SElaine Zhang struct rk3568_pmucru *pmucru = priv->pmucru;
461417bebc4SElaine Zhang
462417bebc4SElaine Zhang if (parent->id == CLK_RTC32K_FRAC)
463417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
464417bebc4SElaine Zhang RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
465417bebc4SElaine Zhang else
466417bebc4SElaine Zhang rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
467417bebc4SElaine Zhang RTC32K_SEL_OSC1_32K << RTC32K_SEL_SHIFT);
468417bebc4SElaine Zhang
469417bebc4SElaine Zhang return 0;
470417bebc4SElaine Zhang }
471417bebc4SElaine Zhang
rk3568_pmuclk_set_parent(struct clk * clk,struct clk * parent)472417bebc4SElaine Zhang static int rk3568_pmuclk_set_parent(struct clk *clk, struct clk *parent)
473417bebc4SElaine Zhang {
474417bebc4SElaine Zhang switch (clk->id) {
475417bebc4SElaine Zhang case CLK_RTC_32K:
476417bebc4SElaine Zhang return rk3568_rtc32k_set_parent(clk, parent);
477417bebc4SElaine Zhang default:
478417bebc4SElaine Zhang return -ENOENT;
479417bebc4SElaine Zhang }
480417bebc4SElaine Zhang }
481417bebc4SElaine Zhang
482417bebc4SElaine Zhang static struct clk_ops rk3568_pmuclk_ops = {
483417bebc4SElaine Zhang .get_rate = rk3568_pmuclk_get_rate,
484417bebc4SElaine Zhang .set_rate = rk3568_pmuclk_set_rate,
485417bebc4SElaine Zhang .set_parent = rk3568_pmuclk_set_parent,
486417bebc4SElaine Zhang };
487417bebc4SElaine Zhang
rk3568_pmuclk_probe(struct udevice * dev)488417bebc4SElaine Zhang static int rk3568_pmuclk_probe(struct udevice *dev)
489417bebc4SElaine Zhang {
490417bebc4SElaine Zhang struct rk3568_pmuclk_priv *priv = dev_get_priv(dev);
491417bebc4SElaine Zhang int ret = 0;
492417bebc4SElaine Zhang
493417bebc4SElaine Zhang if (priv->ppll_hz != PPLL_HZ) {
494417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[PPLL],
495417bebc4SElaine Zhang priv->pmucru,
496417bebc4SElaine Zhang PPLL, PPLL_HZ);
497417bebc4SElaine Zhang if (!ret)
498417bebc4SElaine Zhang priv->ppll_hz = PPLL_HZ;
499417bebc4SElaine Zhang }
500417bebc4SElaine Zhang
501d504dfb2SShawn Lin /* Ungate PCIe30phy refclk_m and refclk_n */
502d504dfb2SShawn Lin rk_clrsetreg(&priv->pmucru->pmu_clkgate_con[2], 0x3 << 13, 0 << 13);
503417bebc4SElaine Zhang return 0;
504417bebc4SElaine Zhang }
505417bebc4SElaine Zhang
rk3568_pmuclk_ofdata_to_platdata(struct udevice * dev)506417bebc4SElaine Zhang static int rk3568_pmuclk_ofdata_to_platdata(struct udevice *dev)
507417bebc4SElaine Zhang {
508417bebc4SElaine Zhang struct rk3568_pmuclk_priv *priv = dev_get_priv(dev);
509417bebc4SElaine Zhang
510417bebc4SElaine Zhang priv->pmucru = dev_read_addr_ptr(dev);
511417bebc4SElaine Zhang
512417bebc4SElaine Zhang return 0;
513417bebc4SElaine Zhang }
514417bebc4SElaine Zhang
rk3568_pmuclk_bind(struct udevice * dev)515417bebc4SElaine Zhang static int rk3568_pmuclk_bind(struct udevice *dev)
516417bebc4SElaine Zhang {
517417bebc4SElaine Zhang int ret = 0;
518417bebc4SElaine Zhang struct udevice *sf_child;
519417bebc4SElaine Zhang struct softreset_reg *sf_priv;
520417bebc4SElaine Zhang
521417bebc4SElaine Zhang ret = device_bind_driver_to_node(dev, "rockchip_reset",
522417bebc4SElaine Zhang "reset", dev_ofnode(dev),
523417bebc4SElaine Zhang &sf_child);
524417bebc4SElaine Zhang if (ret) {
525417bebc4SElaine Zhang debug("Warning: No rockchip reset driver: ret=%d\n", ret);
526417bebc4SElaine Zhang } else {
527417bebc4SElaine Zhang sf_priv = malloc(sizeof(struct softreset_reg));
528417bebc4SElaine Zhang sf_priv->sf_reset_offset = offsetof(struct rk3568_pmucru,
529417bebc4SElaine Zhang pmu_softrst_con[0]);
530417bebc4SElaine Zhang sf_priv->sf_reset_num = 1;
531417bebc4SElaine Zhang sf_child->priv = sf_priv;
532417bebc4SElaine Zhang }
533417bebc4SElaine Zhang
534417bebc4SElaine Zhang return 0;
535417bebc4SElaine Zhang }
536417bebc4SElaine Zhang
537417bebc4SElaine Zhang static const struct udevice_id rk3568_pmuclk_ids[] = {
538417bebc4SElaine Zhang { .compatible = "rockchip,rk3568-pmucru" },
539417bebc4SElaine Zhang { }
540417bebc4SElaine Zhang };
541417bebc4SElaine Zhang
542417bebc4SElaine Zhang U_BOOT_DRIVER(rockchip_rk3568_pmucru) = {
543417bebc4SElaine Zhang .name = "rockchip_rk3568_pmucru",
544417bebc4SElaine Zhang .id = UCLASS_CLK,
545417bebc4SElaine Zhang .of_match = rk3568_pmuclk_ids,
546417bebc4SElaine Zhang .priv_auto_alloc_size = sizeof(struct rk3568_pmuclk_priv),
547417bebc4SElaine Zhang .ofdata_to_platdata = rk3568_pmuclk_ofdata_to_platdata,
548417bebc4SElaine Zhang .ops = &rk3568_pmuclk_ops,
549417bebc4SElaine Zhang .bind = rk3568_pmuclk_bind,
550417bebc4SElaine Zhang .probe = rk3568_pmuclk_probe,
551417bebc4SElaine Zhang };
552417bebc4SElaine Zhang
rk3568_armclk_set_clk(struct rk3568_clk_priv * priv,ulong hz)553417bebc4SElaine Zhang static int rk3568_armclk_set_clk(struct rk3568_clk_priv *priv, ulong hz)
554417bebc4SElaine Zhang {
555417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
556417bebc4SElaine Zhang const struct rockchip_cpu_rate_table *rate;
557417bebc4SElaine Zhang ulong old_rate;
558417bebc4SElaine Zhang
559417bebc4SElaine Zhang rate = rockchip_get_cpu_settings(rk3568_cpu_rates, hz);
560417bebc4SElaine Zhang if (!rate) {
561417bebc4SElaine Zhang printf("%s unsupported rate\n", __func__);
562417bebc4SElaine Zhang return -EINVAL;
563417bebc4SElaine Zhang }
564417bebc4SElaine Zhang
565417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[0],
566417bebc4SElaine Zhang CLK_CORE_PRE_SEL_MASK,
567417bebc4SElaine Zhang (CLK_CORE_PRE_SEL_SRC << CLK_CORE_PRE_SEL_SHIFT));
568417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[2],
569417bebc4SElaine Zhang SCLK_CORE_PRE_SEL_MASK |
570417bebc4SElaine Zhang SCLK_CORE_SRC_SEL_MASK |
571417bebc4SElaine Zhang SCLK_CORE_SRC_DIV_MASK,
572417bebc4SElaine Zhang (SCLK_CORE_PRE_SEL_SRC <<
573417bebc4SElaine Zhang SCLK_CORE_PRE_SEL_SHIFT) |
574417bebc4SElaine Zhang (SCLK_CORE_SRC_SEL_APLL <<
575417bebc4SElaine Zhang SCLK_CORE_SRC_SEL_SHIFT) |
576417bebc4SElaine Zhang (1 << SCLK_CORE_SRC_DIV_SHIFT));
577417bebc4SElaine Zhang
578417bebc4SElaine Zhang /*
579417bebc4SElaine Zhang * set up dependent divisors for DBG and ACLK clocks.
580417bebc4SElaine Zhang */
581417bebc4SElaine Zhang old_rate = rockchip_pll_get_rate(&rk3568_pll_clks[APLL],
582417bebc4SElaine Zhang priv->cru, APLL);
583417bebc4SElaine Zhang if (old_rate > hz) {
584417bebc4SElaine Zhang if (rockchip_pll_set_rate(&rk3568_pll_clks[APLL],
585417bebc4SElaine Zhang priv->cru, APLL, hz))
586417bebc4SElaine Zhang return -EINVAL;
587417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[3],
588417bebc4SElaine Zhang GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK,
589417bebc4SElaine Zhang rate->pclk_div << GICCLK_CORE_DIV_SHIFT |
590417bebc4SElaine Zhang rate->pclk_div << ATCLK_CORE_DIV_SHIFT);
591417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[4],
592417bebc4SElaine Zhang PERIPHCLK_CORE_PRE_DIV_MASK |
593417bebc4SElaine Zhang PCLK_CORE_PRE_DIV_MASK,
594417bebc4SElaine Zhang rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT |
595417bebc4SElaine Zhang rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT);
596417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[5],
597417bebc4SElaine Zhang ACLK_CORE_NDFT_DIV_MASK,
598417bebc4SElaine Zhang rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT);
599417bebc4SElaine Zhang } else if (old_rate < hz) {
600417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[3],
601417bebc4SElaine Zhang GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK,
602417bebc4SElaine Zhang rate->pclk_div << GICCLK_CORE_DIV_SHIFT |
603417bebc4SElaine Zhang rate->pclk_div << ATCLK_CORE_DIV_SHIFT);
604417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[4],
605417bebc4SElaine Zhang PERIPHCLK_CORE_PRE_DIV_MASK |
606417bebc4SElaine Zhang PCLK_CORE_PRE_DIV_MASK,
607417bebc4SElaine Zhang rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT |
608417bebc4SElaine Zhang rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT);
609417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[5],
610417bebc4SElaine Zhang ACLK_CORE_NDFT_DIV_MASK,
611417bebc4SElaine Zhang rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT);
612417bebc4SElaine Zhang if (rockchip_pll_set_rate(&rk3568_pll_clks[APLL],
613417bebc4SElaine Zhang priv->cru, APLL, hz))
614417bebc4SElaine Zhang return -EINVAL;
615417bebc4SElaine Zhang }
616417bebc4SElaine Zhang
617417bebc4SElaine Zhang return 0;
618417bebc4SElaine Zhang }
619417bebc4SElaine Zhang
rk3568_cpll_div_get_rate(struct rk3568_clk_priv * priv,ulong clk_id)620f6d27794Szhangqing static ulong rk3568_cpll_div_get_rate(struct rk3568_clk_priv *priv,
621f6d27794Szhangqing ulong clk_id)
622f6d27794Szhangqing {
623f6d27794Szhangqing struct rk3568_cru *cru = priv->cru;
624f6d27794Szhangqing int div, mask, shift, con;
625f6d27794Szhangqing
626f6d27794Szhangqing switch (clk_id) {
627f6d27794Szhangqing case CPLL_500M:
628f6d27794Szhangqing con = 78;
629f6d27794Szhangqing mask = CPLL_500M_DIV_MASK;
630f6d27794Szhangqing shift = CPLL_500M_DIV_SHIFT;
631f6d27794Szhangqing break;
632f6d27794Szhangqing case CPLL_333M:
633f6d27794Szhangqing con = 79;
634f6d27794Szhangqing mask = CPLL_333M_DIV_MASK;
635f6d27794Szhangqing shift = CPLL_333M_DIV_SHIFT;
636f6d27794Szhangqing break;
637f6d27794Szhangqing case CPLL_250M:
638f6d27794Szhangqing con = 79;
639f6d27794Szhangqing mask = CPLL_250M_DIV_MASK;
640f6d27794Szhangqing shift = CPLL_250M_DIV_SHIFT;
641f6d27794Szhangqing break;
642f6d27794Szhangqing case CPLL_125M:
643f6d27794Szhangqing con = 80;
644f6d27794Szhangqing mask = CPLL_125M_DIV_MASK;
645f6d27794Szhangqing shift = CPLL_125M_DIV_SHIFT;
646f6d27794Szhangqing break;
647f6d27794Szhangqing case CPLL_100M:
648f6d27794Szhangqing con = 82;
649f6d27794Szhangqing mask = CPLL_100M_DIV_MASK;
650f6d27794Szhangqing shift = CPLL_100M_DIV_SHIFT;
651f6d27794Szhangqing break;
652f6d27794Szhangqing case CPLL_62P5M:
653f6d27794Szhangqing con = 80;
654f6d27794Szhangqing mask = CPLL_62P5M_DIV_MASK;
655f6d27794Szhangqing shift = CPLL_62P5M_DIV_SHIFT;
656f6d27794Szhangqing break;
657f6d27794Szhangqing case CPLL_50M:
658f6d27794Szhangqing con = 81;
659f6d27794Szhangqing mask = CPLL_50M_DIV_MASK;
660f6d27794Szhangqing shift = CPLL_50M_DIV_SHIFT;
661f6d27794Szhangqing break;
662f6d27794Szhangqing case CPLL_25M:
663f6d27794Szhangqing con = 81;
664f6d27794Szhangqing mask = CPLL_25M_DIV_MASK;
665f6d27794Szhangqing shift = CPLL_25M_DIV_SHIFT;
666f6d27794Szhangqing break;
667f6d27794Szhangqing default:
668f6d27794Szhangqing return -ENOENT;
669f6d27794Szhangqing }
670f6d27794Szhangqing
671f6d27794Szhangqing div = (readl(&cru->clksel_con[con]) & mask) >> shift;
672f6d27794Szhangqing return DIV_TO_RATE(priv->cpll_hz, div);
673f6d27794Szhangqing }
674f6d27794Szhangqing
rk3568_cpll_div_set_rate(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)675f6d27794Szhangqing static ulong rk3568_cpll_div_set_rate(struct rk3568_clk_priv *priv,
676f6d27794Szhangqing ulong clk_id, ulong rate)
677f6d27794Szhangqing {
678f6d27794Szhangqing struct rk3568_cru *cru = priv->cru;
679f6d27794Szhangqing int div, mask, shift, con;
680f6d27794Szhangqing
681f6d27794Szhangqing switch (clk_id) {
682f6d27794Szhangqing case CPLL_500M:
683f6d27794Szhangqing con = 78;
684f6d27794Szhangqing mask = CPLL_500M_DIV_MASK;
685f6d27794Szhangqing shift = CPLL_500M_DIV_SHIFT;
686f6d27794Szhangqing break;
687f6d27794Szhangqing case CPLL_333M:
688f6d27794Szhangqing con = 79;
689f6d27794Szhangqing mask = CPLL_333M_DIV_MASK;
690f6d27794Szhangqing shift = CPLL_333M_DIV_SHIFT;
691f6d27794Szhangqing break;
692f6d27794Szhangqing case CPLL_250M:
693f6d27794Szhangqing con = 79;
694f6d27794Szhangqing mask = CPLL_250M_DIV_MASK;
695f6d27794Szhangqing shift = CPLL_250M_DIV_SHIFT;
696f6d27794Szhangqing break;
697f6d27794Szhangqing case CPLL_125M:
698f6d27794Szhangqing con = 80;
699f6d27794Szhangqing mask = CPLL_125M_DIV_MASK;
700f6d27794Szhangqing shift = CPLL_125M_DIV_SHIFT;
701f6d27794Szhangqing break;
702f6d27794Szhangqing case CPLL_100M:
703f6d27794Szhangqing con = 82;
704f6d27794Szhangqing mask = CPLL_100M_DIV_MASK;
705f6d27794Szhangqing shift = CPLL_100M_DIV_SHIFT;
706f6d27794Szhangqing break;
707f6d27794Szhangqing case CPLL_62P5M:
708f6d27794Szhangqing con = 80;
709f6d27794Szhangqing mask = CPLL_62P5M_DIV_MASK;
710f6d27794Szhangqing shift = CPLL_62P5M_DIV_SHIFT;
711f6d27794Szhangqing break;
712f6d27794Szhangqing case CPLL_50M:
713f6d27794Szhangqing con = 81;
714f6d27794Szhangqing mask = CPLL_50M_DIV_MASK;
715f6d27794Szhangqing shift = CPLL_50M_DIV_SHIFT;
716f6d27794Szhangqing break;
717f6d27794Szhangqing case CPLL_25M:
718f6d27794Szhangqing con = 81;
719f6d27794Szhangqing mask = CPLL_25M_DIV_MASK;
720f6d27794Szhangqing shift = CPLL_25M_DIV_SHIFT;
721f6d27794Szhangqing break;
722f6d27794Szhangqing default:
723f6d27794Szhangqing return -ENOENT;
724f6d27794Szhangqing }
725f6d27794Szhangqing
726f6d27794Szhangqing div = DIV_ROUND_UP(priv->cpll_hz, rate);
7270de0139eSJonas Karlman if (clk_id == CPLL_25M)
7280de0139eSJonas Karlman assert(div - 1 <= 63);
7290de0139eSJonas Karlman else
730f6d27794Szhangqing assert(div - 1 <= 31);
731f6d27794Szhangqing rk_clrsetreg(&cru->clksel_con[con],
732f6d27794Szhangqing mask, (div - 1) << shift);
733f6d27794Szhangqing return rk3568_cpll_div_get_rate(priv, clk_id);
734f6d27794Szhangqing }
735f6d27794Szhangqing
rk3568_bus_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)736417bebc4SElaine Zhang static ulong rk3568_bus_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
737417bebc4SElaine Zhang {
738417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
739417bebc4SElaine Zhang u32 con, sel, rate;
740417bebc4SElaine Zhang
741417bebc4SElaine Zhang switch (clk_id) {
742417bebc4SElaine Zhang case ACLK_BUS:
743417bebc4SElaine Zhang con = readl(&cru->clksel_con[50]);
744417bebc4SElaine Zhang sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
745417bebc4SElaine Zhang if (sel == ACLK_BUS_SEL_200M)
746417bebc4SElaine Zhang rate = 200 * MHz;
747417bebc4SElaine Zhang else if (sel == ACLK_BUS_SEL_150M)
748417bebc4SElaine Zhang rate = 150 * MHz;
749417bebc4SElaine Zhang else if (sel == ACLK_BUS_SEL_100M)
750417bebc4SElaine Zhang rate = 100 * MHz;
751417bebc4SElaine Zhang else
752417bebc4SElaine Zhang rate = OSC_HZ;
753417bebc4SElaine Zhang break;
754417bebc4SElaine Zhang case PCLK_BUS:
7556c0e8ad8SElaine Zhang case PCLK_WDT_NS:
756417bebc4SElaine Zhang con = readl(&cru->clksel_con[50]);
757417bebc4SElaine Zhang sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT;
758417bebc4SElaine Zhang if (sel == PCLK_BUS_SEL_100M)
759417bebc4SElaine Zhang rate = 100 * MHz;
760417bebc4SElaine Zhang else if (sel == PCLK_BUS_SEL_75M)
761417bebc4SElaine Zhang rate = 75 * MHz;
762417bebc4SElaine Zhang else if (sel == PCLK_BUS_SEL_50M)
763417bebc4SElaine Zhang rate = 50 * MHz;
764417bebc4SElaine Zhang else
765417bebc4SElaine Zhang rate = OSC_HZ;
766417bebc4SElaine Zhang break;
767417bebc4SElaine Zhang default:
768417bebc4SElaine Zhang return -ENOENT;
769417bebc4SElaine Zhang }
770417bebc4SElaine Zhang
771417bebc4SElaine Zhang return rate;
772417bebc4SElaine Zhang }
773417bebc4SElaine Zhang
rk3568_bus_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)774417bebc4SElaine Zhang static ulong rk3568_bus_set_clk(struct rk3568_clk_priv *priv,
775417bebc4SElaine Zhang ulong clk_id, ulong rate)
776417bebc4SElaine Zhang {
777417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
778417bebc4SElaine Zhang int src_clk;
779417bebc4SElaine Zhang
780417bebc4SElaine Zhang switch (clk_id) {
781417bebc4SElaine Zhang case ACLK_BUS:
782417bebc4SElaine Zhang if (rate == 200 * MHz)
783417bebc4SElaine Zhang src_clk = ACLK_BUS_SEL_200M;
784417bebc4SElaine Zhang else if (rate == 150 * MHz)
785417bebc4SElaine Zhang src_clk = ACLK_BUS_SEL_150M;
786417bebc4SElaine Zhang else if (rate == 100 * MHz)
787417bebc4SElaine Zhang src_clk = ACLK_BUS_SEL_100M;
788417bebc4SElaine Zhang else
789417bebc4SElaine Zhang src_clk = ACLK_BUS_SEL_24M;
790417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[50],
791417bebc4SElaine Zhang ACLK_BUS_SEL_MASK,
792417bebc4SElaine Zhang src_clk << ACLK_BUS_SEL_SHIFT);
793417bebc4SElaine Zhang break;
794417bebc4SElaine Zhang case PCLK_BUS:
7956c0e8ad8SElaine Zhang case PCLK_WDT_NS:
796417bebc4SElaine Zhang if (rate == 100 * MHz)
797417bebc4SElaine Zhang src_clk = PCLK_BUS_SEL_100M;
798417bebc4SElaine Zhang else if (rate == 75 * MHz)
799417bebc4SElaine Zhang src_clk = PCLK_BUS_SEL_75M;
800417bebc4SElaine Zhang else if (rate == 50 * MHz)
801417bebc4SElaine Zhang src_clk = PCLK_BUS_SEL_50M;
802417bebc4SElaine Zhang else
803417bebc4SElaine Zhang src_clk = PCLK_BUS_SEL_24M;
804417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[50],
805417bebc4SElaine Zhang PCLK_BUS_SEL_MASK,
806417bebc4SElaine Zhang src_clk << PCLK_BUS_SEL_SHIFT);
807417bebc4SElaine Zhang break;
808417bebc4SElaine Zhang
809417bebc4SElaine Zhang default:
810417bebc4SElaine Zhang printf("do not support this bus freq\n");
811417bebc4SElaine Zhang return -EINVAL;
812417bebc4SElaine Zhang }
813417bebc4SElaine Zhang
814417bebc4SElaine Zhang return rk3568_bus_get_clk(priv, clk_id);
815417bebc4SElaine Zhang }
816417bebc4SElaine Zhang
rk3568_perimid_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)817417bebc4SElaine Zhang static ulong rk3568_perimid_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
818417bebc4SElaine Zhang {
819417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
820417bebc4SElaine Zhang u32 con, sel, rate;
821417bebc4SElaine Zhang
822417bebc4SElaine Zhang switch (clk_id) {
823417bebc4SElaine Zhang case ACLK_PERIMID:
824417bebc4SElaine Zhang con = readl(&cru->clksel_con[10]);
825417bebc4SElaine Zhang sel = (con & ACLK_PERIMID_SEL_MASK) >> ACLK_PERIMID_SEL_SHIFT;
826417bebc4SElaine Zhang if (sel == ACLK_PERIMID_SEL_300M)
827417bebc4SElaine Zhang rate = 300 * MHz;
828417bebc4SElaine Zhang else if (sel == ACLK_PERIMID_SEL_200M)
829417bebc4SElaine Zhang rate = 200 * MHz;
830417bebc4SElaine Zhang else if (sel == ACLK_PERIMID_SEL_100M)
831417bebc4SElaine Zhang rate = 100 * MHz;
832417bebc4SElaine Zhang else
833417bebc4SElaine Zhang rate = OSC_HZ;
834417bebc4SElaine Zhang break;
835417bebc4SElaine Zhang case HCLK_PERIMID:
836417bebc4SElaine Zhang con = readl(&cru->clksel_con[10]);
837417bebc4SElaine Zhang sel = (con & HCLK_PERIMID_SEL_MASK) >> HCLK_PERIMID_SEL_SHIFT;
838417bebc4SElaine Zhang if (sel == HCLK_PERIMID_SEL_150M)
839417bebc4SElaine Zhang rate = 150 * MHz;
840417bebc4SElaine Zhang else if (sel == HCLK_PERIMID_SEL_100M)
841417bebc4SElaine Zhang rate = 100 * MHz;
842417bebc4SElaine Zhang else if (sel == HCLK_PERIMID_SEL_75M)
843417bebc4SElaine Zhang rate = 75 * MHz;
844417bebc4SElaine Zhang else
845417bebc4SElaine Zhang rate = OSC_HZ;
846417bebc4SElaine Zhang break;
847417bebc4SElaine Zhang default:
848417bebc4SElaine Zhang return -ENOENT;
849417bebc4SElaine Zhang }
850417bebc4SElaine Zhang
851417bebc4SElaine Zhang return rate;
852417bebc4SElaine Zhang }
853417bebc4SElaine Zhang
rk3568_perimid_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)854417bebc4SElaine Zhang static ulong rk3568_perimid_set_clk(struct rk3568_clk_priv *priv,
855417bebc4SElaine Zhang ulong clk_id, ulong rate)
856417bebc4SElaine Zhang {
857417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
858417bebc4SElaine Zhang int src_clk;
859417bebc4SElaine Zhang
860417bebc4SElaine Zhang switch (clk_id) {
861417bebc4SElaine Zhang case ACLK_PERIMID:
862417bebc4SElaine Zhang if (rate == 300 * MHz)
863417bebc4SElaine Zhang src_clk = ACLK_PERIMID_SEL_300M;
864417bebc4SElaine Zhang else if (rate == 200 * MHz)
865417bebc4SElaine Zhang src_clk = ACLK_PERIMID_SEL_200M;
866417bebc4SElaine Zhang else if (rate == 100 * MHz)
867417bebc4SElaine Zhang src_clk = ACLK_PERIMID_SEL_100M;
868417bebc4SElaine Zhang else
869417bebc4SElaine Zhang src_clk = ACLK_PERIMID_SEL_24M;
870417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[10],
871417bebc4SElaine Zhang ACLK_PERIMID_SEL_MASK,
872417bebc4SElaine Zhang src_clk << ACLK_PERIMID_SEL_SHIFT);
873417bebc4SElaine Zhang break;
874417bebc4SElaine Zhang case HCLK_PERIMID:
875417bebc4SElaine Zhang if (rate == 150 * MHz)
876417bebc4SElaine Zhang src_clk = HCLK_PERIMID_SEL_150M;
877417bebc4SElaine Zhang else if (rate == 100 * MHz)
878417bebc4SElaine Zhang src_clk = HCLK_PERIMID_SEL_100M;
879417bebc4SElaine Zhang else if (rate == 75 * MHz)
880417bebc4SElaine Zhang src_clk = HCLK_PERIMID_SEL_75M;
881417bebc4SElaine Zhang else
882417bebc4SElaine Zhang src_clk = HCLK_PERIMID_SEL_24M;
883417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[10],
884417bebc4SElaine Zhang HCLK_PERIMID_SEL_MASK,
885417bebc4SElaine Zhang src_clk << HCLK_PERIMID_SEL_SHIFT);
886417bebc4SElaine Zhang break;
887417bebc4SElaine Zhang
888417bebc4SElaine Zhang default:
889417bebc4SElaine Zhang printf("do not support this permid freq\n");
890417bebc4SElaine Zhang return -EINVAL;
891417bebc4SElaine Zhang }
892417bebc4SElaine Zhang
893417bebc4SElaine Zhang return rk3568_perimid_get_clk(priv, clk_id);
894417bebc4SElaine Zhang }
895417bebc4SElaine Zhang
rk3568_top_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)896417bebc4SElaine Zhang static ulong rk3568_top_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
897417bebc4SElaine Zhang {
898417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
899417bebc4SElaine Zhang u32 con, sel, rate;
900417bebc4SElaine Zhang
901417bebc4SElaine Zhang switch (clk_id) {
902417bebc4SElaine Zhang case ACLK_TOP_HIGH:
903417bebc4SElaine Zhang con = readl(&cru->clksel_con[73]);
904417bebc4SElaine Zhang sel = (con & ACLK_TOP_HIGH_SEL_MASK) >> ACLK_TOP_HIGH_SEL_SHIFT;
905417bebc4SElaine Zhang if (sel == ACLK_TOP_HIGH_SEL_500M)
906417bebc4SElaine Zhang rate = 500 * MHz;
907417bebc4SElaine Zhang else if (sel == ACLK_TOP_HIGH_SEL_400M)
908417bebc4SElaine Zhang rate = 400 * MHz;
909417bebc4SElaine Zhang else if (sel == ACLK_TOP_HIGH_SEL_300M)
910417bebc4SElaine Zhang rate = 300 * MHz;
911417bebc4SElaine Zhang else
912417bebc4SElaine Zhang rate = OSC_HZ;
913417bebc4SElaine Zhang break;
914417bebc4SElaine Zhang case ACLK_TOP_LOW:
915417bebc4SElaine Zhang con = readl(&cru->clksel_con[73]);
916417bebc4SElaine Zhang sel = (con & ACLK_TOP_LOW_SEL_MASK) >> ACLK_TOP_LOW_SEL_SHIFT;
917417bebc4SElaine Zhang if (sel == ACLK_TOP_LOW_SEL_400M)
918417bebc4SElaine Zhang rate = 400 * MHz;
919417bebc4SElaine Zhang else if (sel == ACLK_TOP_LOW_SEL_300M)
920417bebc4SElaine Zhang rate = 300 * MHz;
921417bebc4SElaine Zhang else if (sel == ACLK_TOP_LOW_SEL_200M)
922417bebc4SElaine Zhang rate = 200 * MHz;
923417bebc4SElaine Zhang else
924417bebc4SElaine Zhang rate = OSC_HZ;
925417bebc4SElaine Zhang break;
926417bebc4SElaine Zhang case HCLK_TOP:
927417bebc4SElaine Zhang con = readl(&cru->clksel_con[73]);
928417bebc4SElaine Zhang sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
929417bebc4SElaine Zhang if (sel == HCLK_TOP_SEL_150M)
930417bebc4SElaine Zhang rate = 150 * MHz;
931417bebc4SElaine Zhang else if (sel == HCLK_TOP_SEL_100M)
932417bebc4SElaine Zhang rate = 100 * MHz;
933417bebc4SElaine Zhang else if (sel == HCLK_TOP_SEL_75M)
934417bebc4SElaine Zhang rate = 75 * MHz;
935417bebc4SElaine Zhang else
936417bebc4SElaine Zhang rate = OSC_HZ;
937417bebc4SElaine Zhang break;
938417bebc4SElaine Zhang case PCLK_TOP:
939417bebc4SElaine Zhang con = readl(&cru->clksel_con[73]);
940417bebc4SElaine Zhang sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
941417bebc4SElaine Zhang if (sel == PCLK_TOP_SEL_100M)
942417bebc4SElaine Zhang rate = 100 * MHz;
943417bebc4SElaine Zhang else if (sel == PCLK_TOP_SEL_75M)
944417bebc4SElaine Zhang rate = 75 * MHz;
945417bebc4SElaine Zhang else if (sel == PCLK_TOP_SEL_50M)
946417bebc4SElaine Zhang rate = 50 * MHz;
947417bebc4SElaine Zhang else
948417bebc4SElaine Zhang rate = OSC_HZ;
949417bebc4SElaine Zhang break;
950417bebc4SElaine Zhang default:
951417bebc4SElaine Zhang return -ENOENT;
952417bebc4SElaine Zhang }
953417bebc4SElaine Zhang
954417bebc4SElaine Zhang return rate;
955417bebc4SElaine Zhang }
956417bebc4SElaine Zhang
rk3568_top_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)957417bebc4SElaine Zhang static ulong rk3568_top_set_clk(struct rk3568_clk_priv *priv,
958417bebc4SElaine Zhang ulong clk_id, ulong rate)
959417bebc4SElaine Zhang {
960417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
961417bebc4SElaine Zhang int src_clk;
962417bebc4SElaine Zhang
963417bebc4SElaine Zhang switch (clk_id) {
964417bebc4SElaine Zhang case ACLK_TOP_HIGH:
965417bebc4SElaine Zhang if (rate == 500 * MHz)
966417bebc4SElaine Zhang src_clk = ACLK_TOP_HIGH_SEL_500M;
967417bebc4SElaine Zhang else if (rate == 400 * MHz)
968417bebc4SElaine Zhang src_clk = ACLK_TOP_HIGH_SEL_400M;
969417bebc4SElaine Zhang else if (rate == 300 * MHz)
970417bebc4SElaine Zhang src_clk = ACLK_TOP_HIGH_SEL_300M;
971417bebc4SElaine Zhang else
972417bebc4SElaine Zhang src_clk = ACLK_TOP_HIGH_SEL_24M;
973417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[73],
974417bebc4SElaine Zhang ACLK_TOP_HIGH_SEL_MASK,
975417bebc4SElaine Zhang src_clk << ACLK_TOP_HIGH_SEL_SHIFT);
976417bebc4SElaine Zhang break;
977417bebc4SElaine Zhang case ACLK_TOP_LOW:
978417bebc4SElaine Zhang if (rate == 400 * MHz)
979417bebc4SElaine Zhang src_clk = ACLK_TOP_LOW_SEL_400M;
980417bebc4SElaine Zhang else if (rate == 300 * MHz)
981417bebc4SElaine Zhang src_clk = ACLK_TOP_LOW_SEL_300M;
982417bebc4SElaine Zhang else if (rate == 200 * MHz)
983417bebc4SElaine Zhang src_clk = ACLK_TOP_LOW_SEL_200M;
984417bebc4SElaine Zhang else
985417bebc4SElaine Zhang src_clk = ACLK_TOP_LOW_SEL_24M;
986417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[73],
987417bebc4SElaine Zhang ACLK_TOP_LOW_SEL_MASK,
988417bebc4SElaine Zhang src_clk << ACLK_TOP_LOW_SEL_SHIFT);
989417bebc4SElaine Zhang break;
990417bebc4SElaine Zhang case HCLK_TOP:
991417bebc4SElaine Zhang if (rate == 150 * MHz)
992417bebc4SElaine Zhang src_clk = HCLK_TOP_SEL_150M;
993417bebc4SElaine Zhang else if (rate == 100 * MHz)
994417bebc4SElaine Zhang src_clk = HCLK_TOP_SEL_100M;
995417bebc4SElaine Zhang else if (rate == 75 * MHz)
996417bebc4SElaine Zhang src_clk = HCLK_TOP_SEL_75M;
997417bebc4SElaine Zhang else
998417bebc4SElaine Zhang src_clk = HCLK_TOP_SEL_24M;
999417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[73],
1000417bebc4SElaine Zhang HCLK_TOP_SEL_MASK,
1001417bebc4SElaine Zhang src_clk << HCLK_TOP_SEL_SHIFT);
1002417bebc4SElaine Zhang break;
1003417bebc4SElaine Zhang case PCLK_TOP:
1004417bebc4SElaine Zhang if (rate == 100 * MHz)
1005417bebc4SElaine Zhang src_clk = PCLK_TOP_SEL_100M;
1006417bebc4SElaine Zhang else if (rate == 75 * MHz)
1007417bebc4SElaine Zhang src_clk = PCLK_TOP_SEL_75M;
1008417bebc4SElaine Zhang else if (rate == 50 * MHz)
1009417bebc4SElaine Zhang src_clk = PCLK_TOP_SEL_50M;
1010417bebc4SElaine Zhang else
1011417bebc4SElaine Zhang src_clk = PCLK_TOP_SEL_24M;
1012417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[73],
1013417bebc4SElaine Zhang PCLK_TOP_SEL_MASK,
1014417bebc4SElaine Zhang src_clk << PCLK_TOP_SEL_SHIFT);
1015417bebc4SElaine Zhang break;
1016417bebc4SElaine Zhang
1017417bebc4SElaine Zhang default:
1018417bebc4SElaine Zhang printf("do not support this permid freq\n");
1019417bebc4SElaine Zhang return -EINVAL;
1020417bebc4SElaine Zhang }
1021417bebc4SElaine Zhang
1022417bebc4SElaine Zhang return rk3568_top_get_clk(priv, clk_id);
1023417bebc4SElaine Zhang }
1024417bebc4SElaine Zhang
rk3568_i2c_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)1025417bebc4SElaine Zhang static ulong rk3568_i2c_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1026417bebc4SElaine Zhang {
1027417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1028417bebc4SElaine Zhang u32 sel, con;
1029417bebc4SElaine Zhang ulong rate;
1030417bebc4SElaine Zhang
1031417bebc4SElaine Zhang switch (clk_id) {
1032417bebc4SElaine Zhang case CLK_I2C1:
1033417bebc4SElaine Zhang case CLK_I2C2:
1034417bebc4SElaine Zhang case CLK_I2C3:
1035417bebc4SElaine Zhang case CLK_I2C4:
1036417bebc4SElaine Zhang case CLK_I2C5:
1037417bebc4SElaine Zhang con = readl(&cru->clksel_con[71]);
1038417bebc4SElaine Zhang sel = (con & CLK_I2C_SEL_MASK) >> CLK_I2C_SEL_SHIFT;
1039417bebc4SElaine Zhang if (sel == CLK_I2C_SEL_200M)
1040417bebc4SElaine Zhang rate = 200 * MHz;
1041417bebc4SElaine Zhang else if (sel == CLK_I2C_SEL_100M)
1042417bebc4SElaine Zhang rate = 100 * MHz;
1043417bebc4SElaine Zhang else if (sel == CLK_I2C_SEL_CPLL_100M)
1044417bebc4SElaine Zhang rate = 100 * MHz;
1045417bebc4SElaine Zhang else
1046417bebc4SElaine Zhang rate = OSC_HZ;
1047417bebc4SElaine Zhang break;
1048417bebc4SElaine Zhang default:
1049417bebc4SElaine Zhang return -ENOENT;
1050417bebc4SElaine Zhang }
1051417bebc4SElaine Zhang
1052417bebc4SElaine Zhang return rate;
1053417bebc4SElaine Zhang }
1054417bebc4SElaine Zhang
rk3568_i2c_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1055417bebc4SElaine Zhang static ulong rk3568_i2c_set_clk(struct rk3568_clk_priv *priv, ulong clk_id,
1056417bebc4SElaine Zhang ulong rate)
1057417bebc4SElaine Zhang {
1058417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1059417bebc4SElaine Zhang int src_clk;
1060417bebc4SElaine Zhang
1061417bebc4SElaine Zhang if (rate == 200 * MHz)
1062417bebc4SElaine Zhang src_clk = CLK_I2C_SEL_200M;
1063417bebc4SElaine Zhang else if (rate == 100 * MHz)
1064417bebc4SElaine Zhang src_clk = CLK_I2C_SEL_100M;
1065417bebc4SElaine Zhang else
1066417bebc4SElaine Zhang src_clk = CLK_I2C_SEL_24M;
1067417bebc4SElaine Zhang
1068417bebc4SElaine Zhang switch (clk_id) {
1069417bebc4SElaine Zhang case CLK_I2C1:
1070417bebc4SElaine Zhang case CLK_I2C2:
1071417bebc4SElaine Zhang case CLK_I2C3:
1072417bebc4SElaine Zhang case CLK_I2C4:
1073417bebc4SElaine Zhang case CLK_I2C5:
1074417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[71], CLK_I2C_SEL_MASK,
1075417bebc4SElaine Zhang src_clk << CLK_I2C_SEL_SHIFT);
1076417bebc4SElaine Zhang break;
1077417bebc4SElaine Zhang default:
1078417bebc4SElaine Zhang return -ENOENT;
1079417bebc4SElaine Zhang }
1080417bebc4SElaine Zhang
1081417bebc4SElaine Zhang return rk3568_i2c_get_clk(priv, clk_id);
1082417bebc4SElaine Zhang }
1083417bebc4SElaine Zhang
rk3568_spi_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)1084417bebc4SElaine Zhang static ulong rk3568_spi_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1085417bebc4SElaine Zhang {
1086417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1087417bebc4SElaine Zhang u32 sel, con;
1088417bebc4SElaine Zhang
1089417bebc4SElaine Zhang con = readl(&cru->clksel_con[72]);
1090417bebc4SElaine Zhang
1091417bebc4SElaine Zhang switch (clk_id) {
1092417bebc4SElaine Zhang case CLK_SPI0:
1093417bebc4SElaine Zhang sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
1094417bebc4SElaine Zhang break;
1095417bebc4SElaine Zhang case CLK_SPI1:
1096417bebc4SElaine Zhang sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
1097417bebc4SElaine Zhang break;
1098417bebc4SElaine Zhang case CLK_SPI2:
1099417bebc4SElaine Zhang sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
1100417bebc4SElaine Zhang break;
1101417bebc4SElaine Zhang case CLK_SPI3:
1102417bebc4SElaine Zhang sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
1103417bebc4SElaine Zhang break;
1104417bebc4SElaine Zhang default:
1105417bebc4SElaine Zhang return -ENOENT;
1106417bebc4SElaine Zhang }
1107417bebc4SElaine Zhang
1108417bebc4SElaine Zhang switch (sel) {
1109417bebc4SElaine Zhang case CLK_SPI_SEL_200M:
1110417bebc4SElaine Zhang return 200 * MHz;
1111417bebc4SElaine Zhang case CLK_SPI_SEL_24M:
1112417bebc4SElaine Zhang return OSC_HZ;
1113417bebc4SElaine Zhang case CLK_SPI_SEL_CPLL_100M:
1114417bebc4SElaine Zhang return 100 * MHz;
1115417bebc4SElaine Zhang default:
1116417bebc4SElaine Zhang return -ENOENT;
1117417bebc4SElaine Zhang }
1118417bebc4SElaine Zhang }
1119417bebc4SElaine Zhang
rk3568_spi_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1120417bebc4SElaine Zhang static ulong rk3568_spi_set_clk(struct rk3568_clk_priv *priv,
1121417bebc4SElaine Zhang ulong clk_id, ulong rate)
1122417bebc4SElaine Zhang {
1123417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1124417bebc4SElaine Zhang int src_clk;
1125417bebc4SElaine Zhang
1126417bebc4SElaine Zhang if (rate == 200 * MHz)
1127417bebc4SElaine Zhang src_clk = CLK_SPI_SEL_200M;
1128417bebc4SElaine Zhang else if (rate == 100 * MHz)
1129417bebc4SElaine Zhang src_clk = CLK_SPI_SEL_CPLL_100M;
1130417bebc4SElaine Zhang else
1131417bebc4SElaine Zhang src_clk = CLK_SPI_SEL_24M;
1132417bebc4SElaine Zhang
1133417bebc4SElaine Zhang switch (clk_id) {
1134417bebc4SElaine Zhang case CLK_SPI0:
1135417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1136417bebc4SElaine Zhang CLK_SPI0_SEL_MASK,
1137417bebc4SElaine Zhang src_clk << CLK_SPI0_SEL_SHIFT);
1138417bebc4SElaine Zhang break;
1139417bebc4SElaine Zhang case CLK_SPI1:
1140417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1141417bebc4SElaine Zhang CLK_SPI1_SEL_MASK,
1142417bebc4SElaine Zhang src_clk << CLK_SPI1_SEL_SHIFT);
1143417bebc4SElaine Zhang break;
1144417bebc4SElaine Zhang case CLK_SPI2:
1145417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1146417bebc4SElaine Zhang CLK_SPI2_SEL_MASK,
1147417bebc4SElaine Zhang src_clk << CLK_SPI2_SEL_SHIFT);
1148417bebc4SElaine Zhang break;
1149417bebc4SElaine Zhang case CLK_SPI3:
1150417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1151417bebc4SElaine Zhang CLK_SPI3_SEL_MASK,
1152417bebc4SElaine Zhang src_clk << CLK_SPI3_SEL_SHIFT);
1153417bebc4SElaine Zhang break;
1154417bebc4SElaine Zhang default:
1155417bebc4SElaine Zhang return -ENOENT;
1156417bebc4SElaine Zhang }
1157417bebc4SElaine Zhang
1158417bebc4SElaine Zhang return rk3568_spi_get_clk(priv, clk_id);
1159417bebc4SElaine Zhang }
1160417bebc4SElaine Zhang
rk3568_pwm_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)1161417bebc4SElaine Zhang static ulong rk3568_pwm_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1162417bebc4SElaine Zhang {
1163417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1164417bebc4SElaine Zhang u32 sel, con;
1165417bebc4SElaine Zhang
1166417bebc4SElaine Zhang con = readl(&cru->clksel_con[72]);
1167417bebc4SElaine Zhang
1168417bebc4SElaine Zhang switch (clk_id) {
1169417bebc4SElaine Zhang case CLK_PWM1:
1170988eb0b8SDamon Ding sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
1171417bebc4SElaine Zhang break;
1172417bebc4SElaine Zhang case CLK_PWM2:
1173417bebc4SElaine Zhang sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
1174417bebc4SElaine Zhang break;
1175417bebc4SElaine Zhang case CLK_PWM3:
1176417bebc4SElaine Zhang sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
1177417bebc4SElaine Zhang break;
1178417bebc4SElaine Zhang default:
1179417bebc4SElaine Zhang return -ENOENT;
1180417bebc4SElaine Zhang }
1181417bebc4SElaine Zhang
1182417bebc4SElaine Zhang switch (sel) {
1183417bebc4SElaine Zhang case CLK_PWM_SEL_100M:
1184417bebc4SElaine Zhang return 100 * MHz;
1185417bebc4SElaine Zhang case CLK_PWM_SEL_24M:
1186417bebc4SElaine Zhang return OSC_HZ;
1187417bebc4SElaine Zhang case CLK_PWM_SEL_CPLL_100M:
1188417bebc4SElaine Zhang return 100 * MHz;
1189417bebc4SElaine Zhang default:
1190417bebc4SElaine Zhang return -ENOENT;
1191417bebc4SElaine Zhang }
1192417bebc4SElaine Zhang }
1193417bebc4SElaine Zhang
rk3568_pwm_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1194417bebc4SElaine Zhang static ulong rk3568_pwm_set_clk(struct rk3568_clk_priv *priv,
1195417bebc4SElaine Zhang ulong clk_id, ulong rate)
1196417bebc4SElaine Zhang {
1197417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1198417bebc4SElaine Zhang int src_clk;
1199417bebc4SElaine Zhang
1200417bebc4SElaine Zhang if (rate == 100 * MHz)
1201417bebc4SElaine Zhang src_clk = CLK_PWM_SEL_100M;
1202417bebc4SElaine Zhang else
1203417bebc4SElaine Zhang src_clk = CLK_PWM_SEL_24M;
1204417bebc4SElaine Zhang
1205417bebc4SElaine Zhang switch (clk_id) {
1206417bebc4SElaine Zhang case CLK_PWM1:
1207417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1208417bebc4SElaine Zhang CLK_PWM1_SEL_MASK,
1209417bebc4SElaine Zhang src_clk << CLK_PWM1_SEL_SHIFT);
1210417bebc4SElaine Zhang break;
1211417bebc4SElaine Zhang case CLK_PWM2:
1212417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1213417bebc4SElaine Zhang CLK_PWM2_SEL_MASK,
1214417bebc4SElaine Zhang src_clk << CLK_PWM2_SEL_SHIFT);
1215417bebc4SElaine Zhang break;
1216417bebc4SElaine Zhang case CLK_PWM3:
1217417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[72],
1218417bebc4SElaine Zhang CLK_PWM3_SEL_MASK,
1219417bebc4SElaine Zhang src_clk << CLK_PWM3_SEL_SHIFT);
1220417bebc4SElaine Zhang break;
1221417bebc4SElaine Zhang default:
1222417bebc4SElaine Zhang return -ENOENT;
1223417bebc4SElaine Zhang }
1224417bebc4SElaine Zhang
1225417bebc4SElaine Zhang return rk3568_pwm_get_clk(priv, clk_id);
1226417bebc4SElaine Zhang }
1227417bebc4SElaine Zhang
rk3568_adc_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)1228417bebc4SElaine Zhang static ulong rk3568_adc_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1229417bebc4SElaine Zhang {
1230417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1231417bebc4SElaine Zhang u32 div, sel, con, prate;
1232417bebc4SElaine Zhang
1233417bebc4SElaine Zhang switch (clk_id) {
1234417bebc4SElaine Zhang case CLK_SARADC:
1235417bebc4SElaine Zhang return OSC_HZ;
1236417bebc4SElaine Zhang case CLK_TSADC_TSEN:
1237417bebc4SElaine Zhang con = readl(&cru->clksel_con[51]);
1238417bebc4SElaine Zhang div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
1239417bebc4SElaine Zhang CLK_TSADC_TSEN_DIV_SHIFT;
1240417bebc4SElaine Zhang sel = (con & CLK_TSADC_TSEN_SEL_MASK) >>
1241417bebc4SElaine Zhang CLK_TSADC_TSEN_SEL_SHIFT;
1242417bebc4SElaine Zhang if (sel == CLK_TSADC_TSEN_SEL_24M)
1243417bebc4SElaine Zhang prate = OSC_HZ;
1244417bebc4SElaine Zhang else
1245417bebc4SElaine Zhang prate = 100 * MHz;
1246417bebc4SElaine Zhang return DIV_TO_RATE(prate, div);
1247417bebc4SElaine Zhang case CLK_TSADC:
1248417bebc4SElaine Zhang con = readl(&cru->clksel_con[51]);
1249417bebc4SElaine Zhang div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
1250417bebc4SElaine Zhang prate = rk3568_adc_get_clk(priv, CLK_TSADC_TSEN);
1251417bebc4SElaine Zhang return DIV_TO_RATE(prate, div);
1252417bebc4SElaine Zhang default:
1253417bebc4SElaine Zhang return -ENOENT;
1254417bebc4SElaine Zhang }
1255417bebc4SElaine Zhang }
1256417bebc4SElaine Zhang
rk3568_adc_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1257417bebc4SElaine Zhang static ulong rk3568_adc_set_clk(struct rk3568_clk_priv *priv,
1258417bebc4SElaine Zhang ulong clk_id, ulong rate)
1259417bebc4SElaine Zhang {
1260417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1261417bebc4SElaine Zhang int src_clk_div;
1262417bebc4SElaine Zhang ulong prate = 0;
1263417bebc4SElaine Zhang
1264417bebc4SElaine Zhang switch (clk_id) {
1265417bebc4SElaine Zhang case CLK_SARADC:
1266417bebc4SElaine Zhang return OSC_HZ;
1267417bebc4SElaine Zhang case CLK_TSADC_TSEN:
1268417bebc4SElaine Zhang if (!(OSC_HZ % rate)) {
1269417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
1270417bebc4SElaine Zhang assert(src_clk_div - 1 <= 7);
1271417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[51],
1272417bebc4SElaine Zhang CLK_TSADC_TSEN_SEL_MASK |
1273417bebc4SElaine Zhang CLK_TSADC_TSEN_DIV_MASK,
1274417bebc4SElaine Zhang (CLK_TSADC_TSEN_SEL_24M <<
1275417bebc4SElaine Zhang CLK_TSADC_TSEN_SEL_SHIFT) |
1276417bebc4SElaine Zhang (src_clk_div - 1) <<
1277417bebc4SElaine Zhang CLK_TSADC_TSEN_DIV_SHIFT);
1278417bebc4SElaine Zhang } else {
1279417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(100 * MHz, rate);
1280417bebc4SElaine Zhang assert(src_clk_div - 1 <= 7);
1281417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[51],
1282417bebc4SElaine Zhang CLK_TSADC_TSEN_SEL_MASK |
1283417bebc4SElaine Zhang CLK_TSADC_TSEN_DIV_MASK,
1284417bebc4SElaine Zhang (CLK_TSADC_TSEN_SEL_100M <<
1285417bebc4SElaine Zhang CLK_TSADC_TSEN_SEL_SHIFT) |
1286417bebc4SElaine Zhang (src_clk_div - 1) <<
1287417bebc4SElaine Zhang CLK_TSADC_TSEN_DIV_SHIFT);
1288417bebc4SElaine Zhang }
1289417bebc4SElaine Zhang break;
1290417bebc4SElaine Zhang case CLK_TSADC:
1291417bebc4SElaine Zhang prate = rk3568_adc_get_clk(priv, CLK_TSADC_TSEN);
1292417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(prate, rate);
1293417bebc4SElaine Zhang assert(src_clk_div - 1 <= 128);
1294417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[51],
1295417bebc4SElaine Zhang CLK_TSADC_DIV_MASK,
1296417bebc4SElaine Zhang (src_clk_div - 1) << CLK_TSADC_DIV_SHIFT);
1297417bebc4SElaine Zhang break;
1298417bebc4SElaine Zhang default:
1299417bebc4SElaine Zhang return -ENOENT;
1300417bebc4SElaine Zhang }
1301417bebc4SElaine Zhang return rk3568_adc_get_clk(priv, clk_id);
1302417bebc4SElaine Zhang }
1303417bebc4SElaine Zhang
rk3568_crypto_get_rate(struct rk3568_clk_priv * priv,ulong clk_id)1304417bebc4SElaine Zhang static ulong rk3568_crypto_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
1305417bebc4SElaine Zhang {
1306417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1307417bebc4SElaine Zhang u32 sel, con;
1308417bebc4SElaine Zhang
1309417bebc4SElaine Zhang switch (clk_id) {
1310417bebc4SElaine Zhang case ACLK_SECURE_FLASH:
1311417bebc4SElaine Zhang case ACLK_CRYPTO_NS:
1312417bebc4SElaine Zhang con = readl(&cru->clksel_con[27]);
1313417bebc4SElaine Zhang sel = (con & ACLK_SECURE_FLASH_SEL_MASK) >>
1314417bebc4SElaine Zhang ACLK_SECURE_FLASH_SEL_SHIFT;
1315417bebc4SElaine Zhang if (sel == ACLK_SECURE_FLASH_SEL_200M)
1316417bebc4SElaine Zhang return 200 * MHz;
1317417bebc4SElaine Zhang else if (sel == ACLK_SECURE_FLASH_SEL_150M)
1318417bebc4SElaine Zhang return 150 * MHz;
1319417bebc4SElaine Zhang else if (sel == ACLK_SECURE_FLASH_SEL_100M)
1320417bebc4SElaine Zhang return 100 * MHz;
1321417bebc4SElaine Zhang else
1322417bebc4SElaine Zhang return 24 * MHz;
1323417bebc4SElaine Zhang case HCLK_SECURE_FLASH:
1324417bebc4SElaine Zhang case HCLK_CRYPTO_NS:
1325417bebc4SElaine Zhang case CLK_CRYPTO_NS_RNG:
1326417bebc4SElaine Zhang con = readl(&cru->clksel_con[27]);
1327417bebc4SElaine Zhang sel = (con & HCLK_SECURE_FLASH_SEL_MASK) >>
1328417bebc4SElaine Zhang HCLK_SECURE_FLASH_SEL_SHIFT;
1329417bebc4SElaine Zhang if (sel == HCLK_SECURE_FLASH_SEL_150M)
1330417bebc4SElaine Zhang return 150 * MHz;
1331417bebc4SElaine Zhang else if (sel == HCLK_SECURE_FLASH_SEL_100M)
1332417bebc4SElaine Zhang return 100 * MHz;
1333417bebc4SElaine Zhang else if (sel == HCLK_SECURE_FLASH_SEL_75M)
1334417bebc4SElaine Zhang return 75 * MHz;
1335417bebc4SElaine Zhang else
1336417bebc4SElaine Zhang return 24 * MHz;
1337417bebc4SElaine Zhang case CLK_CRYPTO_NS_CORE:
1338417bebc4SElaine Zhang con = readl(&cru->clksel_con[27]);
1339417bebc4SElaine Zhang sel = (con & CLK_CRYPTO_CORE_SEL_MASK) >>
1340417bebc4SElaine Zhang CLK_CRYPTO_CORE_SEL_SHIFT;
1341417bebc4SElaine Zhang if (sel == CLK_CRYPTO_CORE_SEL_200M)
1342417bebc4SElaine Zhang return 200 * MHz;
1343417bebc4SElaine Zhang else if (sel == CLK_CRYPTO_CORE_SEL_150M)
1344417bebc4SElaine Zhang return 150 * MHz;
1345417bebc4SElaine Zhang else
1346417bebc4SElaine Zhang return 100 * MHz;
1347417bebc4SElaine Zhang case CLK_CRYPTO_NS_PKA:
1348417bebc4SElaine Zhang con = readl(&cru->clksel_con[27]);
1349417bebc4SElaine Zhang sel = (con & CLK_CRYPTO_PKA_SEL_MASK) >>
1350417bebc4SElaine Zhang CLK_CRYPTO_PKA_SEL_SHIFT;
1351417bebc4SElaine Zhang if (sel == CLK_CRYPTO_PKA_SEL_300M)
1352417bebc4SElaine Zhang return 300 * MHz;
1353417bebc4SElaine Zhang else if (sel == CLK_CRYPTO_PKA_SEL_200M)
1354417bebc4SElaine Zhang return 200 * MHz;
1355417bebc4SElaine Zhang else
1356417bebc4SElaine Zhang return 100 * MHz;
1357417bebc4SElaine Zhang default:
1358417bebc4SElaine Zhang return -ENOENT;
1359417bebc4SElaine Zhang }
1360417bebc4SElaine Zhang }
1361417bebc4SElaine Zhang
rk3568_crypto_set_rate(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1362417bebc4SElaine Zhang static ulong rk3568_crypto_set_rate(struct rk3568_clk_priv *priv,
1363417bebc4SElaine Zhang ulong clk_id, ulong rate)
1364417bebc4SElaine Zhang {
1365417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1366417bebc4SElaine Zhang u32 src_clk, mask, shift;
1367417bebc4SElaine Zhang
1368417bebc4SElaine Zhang switch (clk_id) {
1369417bebc4SElaine Zhang case ACLK_SECURE_FLASH:
1370417bebc4SElaine Zhang case ACLK_CRYPTO_NS:
1371417bebc4SElaine Zhang mask = ACLK_SECURE_FLASH_SEL_MASK;
1372417bebc4SElaine Zhang shift = ACLK_SECURE_FLASH_SEL_SHIFT;
1373417bebc4SElaine Zhang if (rate == 200 * MHz)
1374417bebc4SElaine Zhang src_clk = ACLK_SECURE_FLASH_SEL_200M;
1375417bebc4SElaine Zhang else if (rate == 150 * MHz)
1376417bebc4SElaine Zhang src_clk = ACLK_SECURE_FLASH_SEL_150M;
1377417bebc4SElaine Zhang else if (rate == 100 * MHz)
1378417bebc4SElaine Zhang src_clk = ACLK_SECURE_FLASH_SEL_100M;
1379417bebc4SElaine Zhang else
1380417bebc4SElaine Zhang src_clk = ACLK_SECURE_FLASH_SEL_24M;
1381417bebc4SElaine Zhang break;
1382417bebc4SElaine Zhang case HCLK_SECURE_FLASH:
1383417bebc4SElaine Zhang case HCLK_CRYPTO_NS:
1384417bebc4SElaine Zhang case CLK_CRYPTO_NS_RNG:
1385417bebc4SElaine Zhang mask = HCLK_SECURE_FLASH_SEL_MASK;
1386417bebc4SElaine Zhang shift = HCLK_SECURE_FLASH_SEL_SHIFT;
1387417bebc4SElaine Zhang if (rate == 150 * MHz)
1388417bebc4SElaine Zhang src_clk = HCLK_SECURE_FLASH_SEL_150M;
1389417bebc4SElaine Zhang else if (rate == 100 * MHz)
1390417bebc4SElaine Zhang src_clk = HCLK_SECURE_FLASH_SEL_100M;
1391417bebc4SElaine Zhang else if (rate == 75 * MHz)
1392417bebc4SElaine Zhang src_clk = HCLK_SECURE_FLASH_SEL_75M;
1393417bebc4SElaine Zhang else
1394417bebc4SElaine Zhang src_clk = HCLK_SECURE_FLASH_SEL_24M;
1395417bebc4SElaine Zhang break;
1396417bebc4SElaine Zhang case CLK_CRYPTO_NS_CORE:
1397417bebc4SElaine Zhang mask = CLK_CRYPTO_CORE_SEL_MASK;
1398417bebc4SElaine Zhang shift = CLK_CRYPTO_CORE_SEL_SHIFT;
1399417bebc4SElaine Zhang if (rate == 200 * MHz)
1400417bebc4SElaine Zhang src_clk = CLK_CRYPTO_CORE_SEL_200M;
1401417bebc4SElaine Zhang else if (rate == 150 * MHz)
1402417bebc4SElaine Zhang src_clk = CLK_CRYPTO_CORE_SEL_150M;
1403417bebc4SElaine Zhang else
1404417bebc4SElaine Zhang src_clk = CLK_CRYPTO_CORE_SEL_100M;
1405417bebc4SElaine Zhang break;
1406417bebc4SElaine Zhang case CLK_CRYPTO_NS_PKA:
1407417bebc4SElaine Zhang mask = CLK_CRYPTO_PKA_SEL_MASK;
1408417bebc4SElaine Zhang shift = CLK_CRYPTO_PKA_SEL_SHIFT;
1409417bebc4SElaine Zhang if (rate == 300 * MHz)
1410417bebc4SElaine Zhang src_clk = CLK_CRYPTO_PKA_SEL_300M;
1411417bebc4SElaine Zhang else if (rate == 200 * MHz)
1412417bebc4SElaine Zhang src_clk = CLK_CRYPTO_PKA_SEL_200M;
1413417bebc4SElaine Zhang else
1414417bebc4SElaine Zhang src_clk = CLK_CRYPTO_PKA_SEL_100M;
1415417bebc4SElaine Zhang break;
1416417bebc4SElaine Zhang default:
1417417bebc4SElaine Zhang return -ENOENT;
1418417bebc4SElaine Zhang }
1419417bebc4SElaine Zhang
1420417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[27], mask, src_clk << shift);
1421417bebc4SElaine Zhang
1422417bebc4SElaine Zhang return rk3568_crypto_get_rate(priv, clk_id);
1423417bebc4SElaine Zhang }
1424417bebc4SElaine Zhang
rk3568_sdmmc_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)1425417bebc4SElaine Zhang static ulong rk3568_sdmmc_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1426417bebc4SElaine Zhang {
1427417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1428417bebc4SElaine Zhang u32 sel, con;
1429417bebc4SElaine Zhang
1430417bebc4SElaine Zhang switch (clk_id) {
143177e56285SJason Zhu case HCLK_SDMMC0:
1432417bebc4SElaine Zhang case CLK_SDMMC0:
1433417bebc4SElaine Zhang con = readl(&cru->clksel_con[30]);
1434417bebc4SElaine Zhang sel = (con & CLK_SDMMC0_SEL_MASK) >> CLK_SDMMC0_SEL_SHIFT;
1435417bebc4SElaine Zhang break;
1436417bebc4SElaine Zhang case CLK_SDMMC1:
1437417bebc4SElaine Zhang con = readl(&cru->clksel_con[30]);
1438417bebc4SElaine Zhang sel = (con & CLK_SDMMC1_SEL_MASK) >> CLK_SDMMC1_SEL_SHIFT;
1439417bebc4SElaine Zhang break;
1440417bebc4SElaine Zhang case CLK_SDMMC2:
1441417bebc4SElaine Zhang con = readl(&cru->clksel_con[32]);
1442417bebc4SElaine Zhang sel = (con & CLK_SDMMC2_SEL_MASK) >> CLK_SDMMC2_SEL_SHIFT;
1443417bebc4SElaine Zhang break;
1444417bebc4SElaine Zhang default:
1445417bebc4SElaine Zhang return -ENOENT;
1446417bebc4SElaine Zhang }
1447417bebc4SElaine Zhang
1448417bebc4SElaine Zhang switch (sel) {
1449417bebc4SElaine Zhang case CLK_SDMMC_SEL_24M:
1450417bebc4SElaine Zhang return OSC_HZ;
1451417bebc4SElaine Zhang case CLK_SDMMC_SEL_400M:
1452417bebc4SElaine Zhang return 400 * MHz;
1453417bebc4SElaine Zhang case CLK_SDMMC_SEL_300M:
1454417bebc4SElaine Zhang return 300 * MHz;
1455417bebc4SElaine Zhang case CLK_SDMMC_SEL_100M:
1456417bebc4SElaine Zhang return 100 * MHz;
1457417bebc4SElaine Zhang case CLK_SDMMC_SEL_50M:
1458417bebc4SElaine Zhang return 50 * MHz;
1459417bebc4SElaine Zhang case CLK_SDMMC_SEL_750K:
1460417bebc4SElaine Zhang return 750 * KHz;
1461417bebc4SElaine Zhang default:
1462417bebc4SElaine Zhang return -ENOENT;
1463417bebc4SElaine Zhang }
1464417bebc4SElaine Zhang }
1465417bebc4SElaine Zhang
rk3568_sdmmc_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1466417bebc4SElaine Zhang static ulong rk3568_sdmmc_set_clk(struct rk3568_clk_priv *priv,
1467417bebc4SElaine Zhang ulong clk_id, ulong rate)
1468417bebc4SElaine Zhang {
1469417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1470417bebc4SElaine Zhang int src_clk;
1471417bebc4SElaine Zhang
1472417bebc4SElaine Zhang switch (rate) {
1473417bebc4SElaine Zhang case OSC_HZ:
1474fae8dbc4SJason Zhu case 26 * MHz:
1475417bebc4SElaine Zhang src_clk = CLK_SDMMC_SEL_24M;
1476417bebc4SElaine Zhang break;
1477417bebc4SElaine Zhang case 400 * MHz:
1478417bebc4SElaine Zhang src_clk = CLK_SDMMC_SEL_400M;
1479417bebc4SElaine Zhang break;
1480417bebc4SElaine Zhang case 300 * MHz:
1481417bebc4SElaine Zhang src_clk = CLK_SDMMC_SEL_300M;
1482417bebc4SElaine Zhang break;
1483417bebc4SElaine Zhang case 100 * MHz:
1484417bebc4SElaine Zhang src_clk = CLK_SDMMC_SEL_100M;
1485417bebc4SElaine Zhang break;
148677e56285SJason Zhu case 52 * MHz:
1487417bebc4SElaine Zhang case 50 * MHz:
1488417bebc4SElaine Zhang src_clk = CLK_SDMMC_SEL_50M;
1489417bebc4SElaine Zhang break;
1490417bebc4SElaine Zhang case 750 * KHz:
149177e56285SJason Zhu case 400 * KHz:
1492417bebc4SElaine Zhang src_clk = CLK_SDMMC_SEL_750K;
1493417bebc4SElaine Zhang break;
1494417bebc4SElaine Zhang default:
1495417bebc4SElaine Zhang return -ENOENT;
1496417bebc4SElaine Zhang }
1497417bebc4SElaine Zhang
1498417bebc4SElaine Zhang switch (clk_id) {
149977e56285SJason Zhu case HCLK_SDMMC0:
1500417bebc4SElaine Zhang case CLK_SDMMC0:
1501417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[30],
1502417bebc4SElaine Zhang CLK_SDMMC0_SEL_MASK,
1503417bebc4SElaine Zhang src_clk << CLK_SDMMC0_SEL_SHIFT);
1504417bebc4SElaine Zhang break;
1505417bebc4SElaine Zhang case CLK_SDMMC1:
1506417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[30],
1507417bebc4SElaine Zhang CLK_SDMMC1_SEL_MASK,
1508417bebc4SElaine Zhang src_clk << CLK_SDMMC1_SEL_SHIFT);
1509417bebc4SElaine Zhang break;
1510417bebc4SElaine Zhang case CLK_SDMMC2:
1511417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[32],
1512417bebc4SElaine Zhang CLK_SDMMC2_SEL_MASK,
1513417bebc4SElaine Zhang src_clk << CLK_SDMMC2_SEL_SHIFT);
1514417bebc4SElaine Zhang break;
1515417bebc4SElaine Zhang default:
1516417bebc4SElaine Zhang return -ENOENT;
1517417bebc4SElaine Zhang }
1518417bebc4SElaine Zhang
1519417bebc4SElaine Zhang return rk3568_sdmmc_get_clk(priv, clk_id);
1520417bebc4SElaine Zhang }
1521417bebc4SElaine Zhang
rk3568_sfc_get_clk(struct rk3568_clk_priv * priv)1522417bebc4SElaine Zhang static ulong rk3568_sfc_get_clk(struct rk3568_clk_priv *priv)
1523417bebc4SElaine Zhang {
1524417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1525417bebc4SElaine Zhang u32 sel, con;
1526417bebc4SElaine Zhang
1527417bebc4SElaine Zhang con = readl(&cru->clksel_con[28]);
1528417bebc4SElaine Zhang sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
1529417bebc4SElaine Zhang switch (sel) {
1530417bebc4SElaine Zhang case SCLK_SFC_SEL_24M:
1531417bebc4SElaine Zhang return OSC_HZ;
1532417bebc4SElaine Zhang case SCLK_SFC_SEL_50M:
1533417bebc4SElaine Zhang return 50 * MHz;
1534417bebc4SElaine Zhang case SCLK_SFC_SEL_75M:
1535417bebc4SElaine Zhang return 75 * MHz;
1536417bebc4SElaine Zhang case SCLK_SFC_SEL_100M:
1537417bebc4SElaine Zhang return 100 * MHz;
1538417bebc4SElaine Zhang case SCLK_SFC_SEL_125M:
1539417bebc4SElaine Zhang return 125 * MHz;
1540417bebc4SElaine Zhang case SCLK_SFC_SEL_150M:
15411e414535SElaine Zhang return 150 * MHz;
1542417bebc4SElaine Zhang default:
1543417bebc4SElaine Zhang return -ENOENT;
1544417bebc4SElaine Zhang }
1545417bebc4SElaine Zhang }
1546417bebc4SElaine Zhang
rk3568_sfc_set_clk(struct rk3568_clk_priv * priv,ulong rate)1547417bebc4SElaine Zhang static ulong rk3568_sfc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1548417bebc4SElaine Zhang {
1549417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1550417bebc4SElaine Zhang int src_clk;
1551417bebc4SElaine Zhang
1552417bebc4SElaine Zhang switch (rate) {
1553417bebc4SElaine Zhang case OSC_HZ:
1554417bebc4SElaine Zhang src_clk = SCLK_SFC_SEL_24M;
1555417bebc4SElaine Zhang break;
1556417bebc4SElaine Zhang case 50 * MHz:
1557417bebc4SElaine Zhang src_clk = SCLK_SFC_SEL_50M;
1558417bebc4SElaine Zhang break;
1559417bebc4SElaine Zhang case 75 * MHz:
1560417bebc4SElaine Zhang src_clk = SCLK_SFC_SEL_75M;
1561417bebc4SElaine Zhang break;
1562417bebc4SElaine Zhang case 100 * MHz:
1563417bebc4SElaine Zhang src_clk = SCLK_SFC_SEL_100M;
1564417bebc4SElaine Zhang break;
1565417bebc4SElaine Zhang case 125 * MHz:
1566417bebc4SElaine Zhang src_clk = SCLK_SFC_SEL_125M;
1567417bebc4SElaine Zhang break;
15681e414535SElaine Zhang case 150 * MHz:
1569417bebc4SElaine Zhang src_clk = SCLK_SFC_SEL_150M;
1570417bebc4SElaine Zhang break;
1571417bebc4SElaine Zhang default:
1572417bebc4SElaine Zhang return -ENOENT;
1573417bebc4SElaine Zhang }
1574417bebc4SElaine Zhang
1575417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[28],
1576417bebc4SElaine Zhang SCLK_SFC_SEL_MASK,
1577417bebc4SElaine Zhang src_clk << SCLK_SFC_SEL_SHIFT);
1578417bebc4SElaine Zhang
1579417bebc4SElaine Zhang return rk3568_sfc_get_clk(priv);
1580417bebc4SElaine Zhang }
1581417bebc4SElaine Zhang
rk3568_nand_get_clk(struct rk3568_clk_priv * priv)1582417bebc4SElaine Zhang static ulong rk3568_nand_get_clk(struct rk3568_clk_priv *priv)
1583417bebc4SElaine Zhang {
1584417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1585417bebc4SElaine Zhang u32 sel, con;
1586417bebc4SElaine Zhang
1587417bebc4SElaine Zhang con = readl(&cru->clksel_con[28]);
1588417bebc4SElaine Zhang sel = (con & NCLK_NANDC_SEL_MASK) >> NCLK_NANDC_SEL_SHIFT;
1589417bebc4SElaine Zhang switch (sel) {
1590417bebc4SElaine Zhang case NCLK_NANDC_SEL_200M:
1591417bebc4SElaine Zhang return 200 * MHz;
1592417bebc4SElaine Zhang case NCLK_NANDC_SEL_150M:
1593417bebc4SElaine Zhang return 150 * MHz;
1594417bebc4SElaine Zhang case NCLK_NANDC_SEL_100M:
1595417bebc4SElaine Zhang return 100 * MHz;
1596417bebc4SElaine Zhang case NCLK_NANDC_SEL_24M:
1597417bebc4SElaine Zhang return OSC_HZ;
1598417bebc4SElaine Zhang default:
1599417bebc4SElaine Zhang return -ENOENT;
1600417bebc4SElaine Zhang }
1601417bebc4SElaine Zhang }
1602417bebc4SElaine Zhang
rk3568_nand_set_clk(struct rk3568_clk_priv * priv,ulong rate)1603417bebc4SElaine Zhang static ulong rk3568_nand_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1604417bebc4SElaine Zhang {
1605417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1606417bebc4SElaine Zhang int src_clk;
1607417bebc4SElaine Zhang
1608417bebc4SElaine Zhang switch (rate) {
1609417bebc4SElaine Zhang case OSC_HZ:
1610417bebc4SElaine Zhang src_clk = NCLK_NANDC_SEL_24M;
1611417bebc4SElaine Zhang break;
1612417bebc4SElaine Zhang case 100 * MHz:
1613417bebc4SElaine Zhang src_clk = NCLK_NANDC_SEL_100M;
1614417bebc4SElaine Zhang break;
1615417bebc4SElaine Zhang case 150 * MHz:
1616417bebc4SElaine Zhang src_clk = NCLK_NANDC_SEL_150M;
1617417bebc4SElaine Zhang break;
1618417bebc4SElaine Zhang case 200 * MHz:
1619417bebc4SElaine Zhang src_clk = NCLK_NANDC_SEL_200M;
1620417bebc4SElaine Zhang break;
1621417bebc4SElaine Zhang default:
1622417bebc4SElaine Zhang return -ENOENT;
1623417bebc4SElaine Zhang }
1624417bebc4SElaine Zhang
1625417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[28],
1626417bebc4SElaine Zhang NCLK_NANDC_SEL_MASK,
1627417bebc4SElaine Zhang src_clk << NCLK_NANDC_SEL_SHIFT);
1628417bebc4SElaine Zhang
1629417bebc4SElaine Zhang return rk3568_nand_get_clk(priv);
1630417bebc4SElaine Zhang }
1631417bebc4SElaine Zhang
rk3568_emmc_get_clk(struct rk3568_clk_priv * priv)1632417bebc4SElaine Zhang static ulong rk3568_emmc_get_clk(struct rk3568_clk_priv *priv)
1633417bebc4SElaine Zhang {
1634417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1635417bebc4SElaine Zhang u32 sel, con;
1636417bebc4SElaine Zhang
1637417bebc4SElaine Zhang con = readl(&cru->clksel_con[28]);
1638417bebc4SElaine Zhang sel = (con & CCLK_EMMC_SEL_MASK) >> CCLK_EMMC_SEL_SHIFT;
1639417bebc4SElaine Zhang switch (sel) {
1640417bebc4SElaine Zhang case CCLK_EMMC_SEL_200M:
1641417bebc4SElaine Zhang return 200 * MHz;
1642417bebc4SElaine Zhang case CCLK_EMMC_SEL_150M:
1643417bebc4SElaine Zhang return 150 * MHz;
1644417bebc4SElaine Zhang case CCLK_EMMC_SEL_100M:
1645417bebc4SElaine Zhang return 100 * MHz;
1646417bebc4SElaine Zhang case CCLK_EMMC_SEL_50M:
1647417bebc4SElaine Zhang return 50 * MHz;
1648417bebc4SElaine Zhang case CCLK_EMMC_SEL_375K:
1649417bebc4SElaine Zhang return 375 * KHz;
1650417bebc4SElaine Zhang case CCLK_EMMC_SEL_24M:
1651417bebc4SElaine Zhang return OSC_HZ;
1652417bebc4SElaine Zhang default:
1653417bebc4SElaine Zhang return -ENOENT;
1654417bebc4SElaine Zhang }
1655417bebc4SElaine Zhang }
1656417bebc4SElaine Zhang
rk3568_emmc_set_clk(struct rk3568_clk_priv * priv,ulong rate)1657417bebc4SElaine Zhang static ulong rk3568_emmc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1658417bebc4SElaine Zhang {
1659417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1660417bebc4SElaine Zhang int src_clk;
1661417bebc4SElaine Zhang
1662417bebc4SElaine Zhang switch (rate) {
1663417bebc4SElaine Zhang case OSC_HZ:
1664417bebc4SElaine Zhang src_clk = CCLK_EMMC_SEL_24M;
1665417bebc4SElaine Zhang break;
1666d41e2874SElaine Zhang case 52 * MHz:
1667417bebc4SElaine Zhang case 50 * MHz:
1668417bebc4SElaine Zhang src_clk = CCLK_EMMC_SEL_50M;
1669417bebc4SElaine Zhang break;
1670417bebc4SElaine Zhang case 100 * MHz:
1671417bebc4SElaine Zhang src_clk = CCLK_EMMC_SEL_100M;
1672417bebc4SElaine Zhang break;
1673417bebc4SElaine Zhang case 150 * MHz:
1674417bebc4SElaine Zhang src_clk = CCLK_EMMC_SEL_150M;
1675417bebc4SElaine Zhang break;
1676417bebc4SElaine Zhang case 200 * MHz:
1677417bebc4SElaine Zhang src_clk = CCLK_EMMC_SEL_200M;
1678417bebc4SElaine Zhang break;
1679d01aebd2SElaine Zhang case 400 * KHz:
1680417bebc4SElaine Zhang case 375 * KHz:
1681417bebc4SElaine Zhang src_clk = CCLK_EMMC_SEL_375K;
1682417bebc4SElaine Zhang break;
1683417bebc4SElaine Zhang default:
1684417bebc4SElaine Zhang return -ENOENT;
1685417bebc4SElaine Zhang }
1686417bebc4SElaine Zhang
1687417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[28],
1688417bebc4SElaine Zhang CCLK_EMMC_SEL_MASK,
1689417bebc4SElaine Zhang src_clk << CCLK_EMMC_SEL_SHIFT);
1690417bebc4SElaine Zhang
1691417bebc4SElaine Zhang return rk3568_emmc_get_clk(priv);
1692417bebc4SElaine Zhang }
1693417bebc4SElaine Zhang
rk3568_emmc_get_bclk(struct rk3568_clk_priv * priv)169475c04b2aSElaine Zhang static ulong rk3568_emmc_get_bclk(struct rk3568_clk_priv *priv)
169575c04b2aSElaine Zhang {
169675c04b2aSElaine Zhang struct rk3568_cru *cru = priv->cru;
169775c04b2aSElaine Zhang u32 sel, con;
169875c04b2aSElaine Zhang
169975c04b2aSElaine Zhang con = readl(&cru->clksel_con[28]);
170075c04b2aSElaine Zhang sel = (con & BCLK_EMMC_SEL_MASK) >> BCLK_EMMC_SEL_SHIFT;
170175c04b2aSElaine Zhang switch (sel) {
170275c04b2aSElaine Zhang case BCLK_EMMC_SEL_200M:
170375c04b2aSElaine Zhang return 200 * MHz;
170475c04b2aSElaine Zhang case BCLK_EMMC_SEL_150M:
170575c04b2aSElaine Zhang return 150 * MHz;
170675c04b2aSElaine Zhang case BCLK_EMMC_SEL_125M:
170775c04b2aSElaine Zhang return 125 * MHz;
170875c04b2aSElaine Zhang default:
170975c04b2aSElaine Zhang return -ENOENT;
171075c04b2aSElaine Zhang }
171175c04b2aSElaine Zhang }
171275c04b2aSElaine Zhang
rk3568_emmc_set_bclk(struct rk3568_clk_priv * priv,ulong rate)171375c04b2aSElaine Zhang static ulong rk3568_emmc_set_bclk(struct rk3568_clk_priv *priv, ulong rate)
171475c04b2aSElaine Zhang {
171575c04b2aSElaine Zhang struct rk3568_cru *cru = priv->cru;
171675c04b2aSElaine Zhang int src_clk;
171775c04b2aSElaine Zhang
171875c04b2aSElaine Zhang switch (rate) {
171975c04b2aSElaine Zhang case 200 * MHz:
172075c04b2aSElaine Zhang src_clk = BCLK_EMMC_SEL_200M;
172175c04b2aSElaine Zhang break;
172275c04b2aSElaine Zhang case 150 * MHz:
172375c04b2aSElaine Zhang src_clk = BCLK_EMMC_SEL_150M;
172475c04b2aSElaine Zhang break;
172575c04b2aSElaine Zhang case 125 * MHz:
172675c04b2aSElaine Zhang src_clk = BCLK_EMMC_SEL_125M;
172775c04b2aSElaine Zhang break;
172875c04b2aSElaine Zhang default:
172975c04b2aSElaine Zhang return -ENOENT;
173075c04b2aSElaine Zhang }
173175c04b2aSElaine Zhang
173275c04b2aSElaine Zhang rk_clrsetreg(&cru->clksel_con[28],
173375c04b2aSElaine Zhang BCLK_EMMC_SEL_MASK,
173475c04b2aSElaine Zhang src_clk << BCLK_EMMC_SEL_SHIFT);
173575c04b2aSElaine Zhang
173675c04b2aSElaine Zhang return rk3568_emmc_get_bclk(priv);
173775c04b2aSElaine Zhang }
173875c04b2aSElaine Zhang
1739f6d27794Szhangqing #ifndef CONFIG_SPL_BUILD
rk3568_aclk_vop_get_clk(struct rk3568_clk_priv * priv)1740417bebc4SElaine Zhang static ulong rk3568_aclk_vop_get_clk(struct rk3568_clk_priv *priv)
1741417bebc4SElaine Zhang {
1742417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1743417bebc4SElaine Zhang u32 div, sel, con, parent;
1744417bebc4SElaine Zhang
1745417bebc4SElaine Zhang con = readl(&cru->clksel_con[38]);
1746417bebc4SElaine Zhang div = (con & ACLK_VOP_PRE_DIV_MASK) >> ACLK_VOP_PRE_DIV_SHIFT;
1747417bebc4SElaine Zhang sel = (con & ACLK_VOP_PRE_SEL_MASK) >> ACLK_VOP_PRE_SEL_SHIFT;
1748417bebc4SElaine Zhang if (sel == ACLK_VOP_PRE_SEL_GPLL)
1749417bebc4SElaine Zhang parent = priv->gpll_hz;
1750417bebc4SElaine Zhang else if (sel == ACLK_VOP_PRE_SEL_CPLL)
1751417bebc4SElaine Zhang parent = priv->cpll_hz;
1752417bebc4SElaine Zhang else if (sel == ACLK_VOP_PRE_SEL_VPLL)
1753417bebc4SElaine Zhang parent = priv->vpll_hz;
1754417bebc4SElaine Zhang else
1755417bebc4SElaine Zhang parent = priv->hpll_hz;
1756417bebc4SElaine Zhang
1757417bebc4SElaine Zhang return DIV_TO_RATE(parent, div);
1758417bebc4SElaine Zhang }
1759417bebc4SElaine Zhang
rk3568_aclk_vop_set_clk(struct rk3568_clk_priv * priv,ulong rate)1760417bebc4SElaine Zhang static ulong rk3568_aclk_vop_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1761417bebc4SElaine Zhang {
1762417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
17630a741659SElaine Zhang int src_clk_div, src_clk_mux;
1764417bebc4SElaine Zhang
17650a741659SElaine Zhang if ((priv->cpll_hz % rate) == 0) {
17660a741659SElaine Zhang src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
17670a741659SElaine Zhang src_clk_mux = ACLK_VOP_PRE_SEL_CPLL;
17680a741659SElaine Zhang } else {
1769417bebc4SElaine Zhang src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
17700a741659SElaine Zhang src_clk_mux = ACLK_VOP_PRE_SEL_GPLL;
17710a741659SElaine Zhang }
1772417bebc4SElaine Zhang assert(src_clk_div - 1 <= 31);
1773417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[38],
1774417bebc4SElaine Zhang ACLK_VOP_PRE_SEL_MASK | ACLK_VOP_PRE_DIV_MASK,
17750a741659SElaine Zhang src_clk_mux << ACLK_VOP_PRE_SEL_SHIFT |
1776417bebc4SElaine Zhang (src_clk_div - 1) << ACLK_VOP_PRE_DIV_SHIFT);
1777417bebc4SElaine Zhang
1778417bebc4SElaine Zhang return rk3568_aclk_vop_get_clk(priv);
1779417bebc4SElaine Zhang }
1780417bebc4SElaine Zhang
rk3568_dclk_vop_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)1781417bebc4SElaine Zhang static ulong rk3568_dclk_vop_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1782417bebc4SElaine Zhang {
1783417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1784417bebc4SElaine Zhang u32 conid, div, sel, con, parent;
1785417bebc4SElaine Zhang
1786417bebc4SElaine Zhang switch (clk_id) {
1787417bebc4SElaine Zhang case DCLK_VOP0:
1788417bebc4SElaine Zhang conid = 39;
1789417bebc4SElaine Zhang break;
1790417bebc4SElaine Zhang case DCLK_VOP1:
1791417bebc4SElaine Zhang conid = 40;
1792417bebc4SElaine Zhang break;
1793417bebc4SElaine Zhang case DCLK_VOP2:
1794417bebc4SElaine Zhang conid = 41;
1795417bebc4SElaine Zhang break;
1796417bebc4SElaine Zhang default:
1797417bebc4SElaine Zhang return -ENOENT;
1798417bebc4SElaine Zhang }
1799417bebc4SElaine Zhang
1800417bebc4SElaine Zhang con = readl(&cru->clksel_con[conid]);
1801417bebc4SElaine Zhang div = (con & DCLK0_VOP_DIV_MASK) >> DCLK0_VOP_DIV_SHIFT;
1802417bebc4SElaine Zhang sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT;
1803417bebc4SElaine Zhang if (sel == DCLK_VOP_SEL_HPLL)
1804417bebc4SElaine Zhang parent = rk3568_pmu_pll_get_rate(priv, HPLL);
1805417bebc4SElaine Zhang else if (sel == DCLK_VOP_SEL_VPLL)
1806417bebc4SElaine Zhang parent = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL],
1807417bebc4SElaine Zhang priv->cru, VPLL);
1808417bebc4SElaine Zhang else if (sel == DCLK_VOP_SEL_GPLL)
1809417bebc4SElaine Zhang parent = priv->gpll_hz;
1810417bebc4SElaine Zhang else if (sel == DCLK_VOP_SEL_CPLL)
1811417bebc4SElaine Zhang parent = priv->cpll_hz;
1812417bebc4SElaine Zhang else
1813417bebc4SElaine Zhang return -ENOENT;
1814417bebc4SElaine Zhang
1815417bebc4SElaine Zhang return DIV_TO_RATE(parent, div);
1816417bebc4SElaine Zhang }
1817417bebc4SElaine Zhang
1818*e583fa2aSElaine Zhang #define RK3568_VOP_PLL_LIMIT_FREQ 594000000
1819417bebc4SElaine Zhang
rk3568_dclk_vop_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)1820417bebc4SElaine Zhang static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv,
1821417bebc4SElaine Zhang ulong clk_id, ulong rate)
1822417bebc4SElaine Zhang {
1823417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1824417bebc4SElaine Zhang ulong pll_rate, now, best_rate = 0;
1825417bebc4SElaine Zhang u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1826417bebc4SElaine Zhang
1827417bebc4SElaine Zhang switch (clk_id) {
1828417bebc4SElaine Zhang case DCLK_VOP0:
1829417bebc4SElaine Zhang conid = 39;
1830417bebc4SElaine Zhang break;
1831417bebc4SElaine Zhang case DCLK_VOP1:
1832417bebc4SElaine Zhang conid = 40;
1833417bebc4SElaine Zhang break;
1834417bebc4SElaine Zhang case DCLK_VOP2:
1835417bebc4SElaine Zhang conid = 41;
1836417bebc4SElaine Zhang break;
1837417bebc4SElaine Zhang default:
1838417bebc4SElaine Zhang return -ENOENT;
1839417bebc4SElaine Zhang }
1840417bebc4SElaine Zhang
1841417bebc4SElaine Zhang con = readl(&cru->clksel_con[conid]);
1842417bebc4SElaine Zhang sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT;
1843417bebc4SElaine Zhang
1844417bebc4SElaine Zhang if (sel == DCLK_VOP_SEL_HPLL) {
1845801ca42bSElaine Zhang div = 1;
1846417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[conid],
1847417bebc4SElaine Zhang DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
1848417bebc4SElaine Zhang (DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT) |
1849417bebc4SElaine Zhang ((div - 1) << DCLK0_VOP_DIV_SHIFT));
1850417bebc4SElaine Zhang rk3568_pmu_pll_set_rate(priv, HPLL, div * rate);
1851417bebc4SElaine Zhang } else if (sel == DCLK_VOP_SEL_VPLL) {
1852417bebc4SElaine Zhang div = DIV_ROUND_UP(RK3568_VOP_PLL_LIMIT_FREQ, rate);
1853*e583fa2aSElaine Zhang if (div % 2)
1854*e583fa2aSElaine Zhang div = div + 1;
1855417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[conid],
1856417bebc4SElaine Zhang DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
1857417bebc4SElaine Zhang (DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT) |
1858417bebc4SElaine Zhang ((div - 1) << DCLK0_VOP_DIV_SHIFT));
1859417bebc4SElaine Zhang rockchip_pll_set_rate(&rk3568_pll_clks[VPLL],
1860417bebc4SElaine Zhang priv->cru, VPLL, div * rate);
1861417bebc4SElaine Zhang } else {
186214d9ba56SElaine Zhang for (i = sel; i <= DCLK_VOP_SEL_CPLL; i++) {
1863417bebc4SElaine Zhang switch (i) {
1864417bebc4SElaine Zhang case DCLK_VOP_SEL_GPLL:
1865417bebc4SElaine Zhang pll_rate = priv->gpll_hz;
1866417bebc4SElaine Zhang break;
1867417bebc4SElaine Zhang case DCLK_VOP_SEL_CPLL:
1868417bebc4SElaine Zhang pll_rate = priv->cpll_hz;
1869417bebc4SElaine Zhang break;
1870*e583fa2aSElaine Zhang case DCLK_VOP_SEL_HPLL:
1871*e583fa2aSElaine Zhang case DCLK_VOP_SEL_VPLL:
1872*e583fa2aSElaine Zhang continue;
1873417bebc4SElaine Zhang default:
1874417bebc4SElaine Zhang printf("do not support this vop pll sel\n");
1875417bebc4SElaine Zhang return -EINVAL;
1876417bebc4SElaine Zhang }
1877417bebc4SElaine Zhang
1878417bebc4SElaine Zhang div = DIV_ROUND_UP(pll_rate, rate);
1879417bebc4SElaine Zhang if (div > 255)
1880417bebc4SElaine Zhang continue;
1881417bebc4SElaine Zhang now = pll_rate / div;
1882417bebc4SElaine Zhang if (abs(rate - now) < abs(rate - best_rate)) {
1883417bebc4SElaine Zhang best_rate = now;
1884417bebc4SElaine Zhang best_div = div;
1885417bebc4SElaine Zhang best_sel = i;
1886417bebc4SElaine Zhang }
1887417bebc4SElaine Zhang debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1888417bebc4SElaine Zhang pll_rate, best_rate, best_div, best_sel);
1889417bebc4SElaine Zhang }
1890417bebc4SElaine Zhang
1891417bebc4SElaine Zhang if (best_rate) {
1892417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[conid],
1893417bebc4SElaine Zhang DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
1894417bebc4SElaine Zhang best_sel << DCLK0_VOP_SEL_SHIFT |
1895417bebc4SElaine Zhang (best_div - 1) << DCLK0_VOP_DIV_SHIFT);
1896417bebc4SElaine Zhang } else {
1897417bebc4SElaine Zhang printf("do not support this vop freq %lu\n", rate);
1898417bebc4SElaine Zhang return -EINVAL;
1899417bebc4SElaine Zhang }
1900417bebc4SElaine Zhang }
1901417bebc4SElaine Zhang return rk3568_dclk_vop_get_clk(priv, clk_id);
1902417bebc4SElaine Zhang }
1903417bebc4SElaine Zhang
rk3568_gmac_src_get_clk(struct rk3568_clk_priv * priv,ulong mac_id)1904417bebc4SElaine Zhang static ulong rk3568_gmac_src_get_clk(struct rk3568_clk_priv *priv,
1905417bebc4SElaine Zhang ulong mac_id)
1906417bebc4SElaine Zhang {
1907417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1908417bebc4SElaine Zhang u32 sel, con;
1909417bebc4SElaine Zhang
1910417bebc4SElaine Zhang con = readl(&cru->clksel_con[31 + mac_id * 2]);
1911417bebc4SElaine Zhang sel = (con & CLK_MAC0_2TOP_SEL_MASK) >> CLK_MAC0_2TOP_SEL_SHIFT;
1912417bebc4SElaine Zhang
1913417bebc4SElaine Zhang switch (sel) {
1914417bebc4SElaine Zhang case CLK_MAC0_2TOP_SEL_125M:
1915417bebc4SElaine Zhang return 125 * MHz;
1916417bebc4SElaine Zhang case CLK_MAC0_2TOP_SEL_50M:
1917417bebc4SElaine Zhang return 50 * MHz;
1918417bebc4SElaine Zhang case CLK_MAC0_2TOP_SEL_25M:
1919417bebc4SElaine Zhang return 25 * MHz;
1920417bebc4SElaine Zhang case CLK_MAC0_2TOP_SEL_PPLL:
1921417bebc4SElaine Zhang return rk3568_pmu_pll_get_rate(priv, HPLL);
1922417bebc4SElaine Zhang default:
1923417bebc4SElaine Zhang return -ENOENT;
1924417bebc4SElaine Zhang }
1925417bebc4SElaine Zhang }
1926417bebc4SElaine Zhang
rk3568_gmac_src_set_clk(struct rk3568_clk_priv * priv,ulong mac_id,ulong rate)1927417bebc4SElaine Zhang static ulong rk3568_gmac_src_set_clk(struct rk3568_clk_priv *priv,
1928417bebc4SElaine Zhang ulong mac_id, ulong rate)
1929417bebc4SElaine Zhang {
1930417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1931417bebc4SElaine Zhang int src_clk;
1932417bebc4SElaine Zhang
1933417bebc4SElaine Zhang switch (rate) {
1934417bebc4SElaine Zhang case 125 * MHz:
1935417bebc4SElaine Zhang src_clk = CLK_MAC0_2TOP_SEL_125M;
1936417bebc4SElaine Zhang break;
1937417bebc4SElaine Zhang case 50 * MHz:
1938417bebc4SElaine Zhang src_clk = CLK_MAC0_2TOP_SEL_50M;
1939417bebc4SElaine Zhang break;
1940417bebc4SElaine Zhang case 25 * MHz:
1941417bebc4SElaine Zhang src_clk = CLK_MAC0_2TOP_SEL_25M;
1942417bebc4SElaine Zhang break;
1943417bebc4SElaine Zhang default:
1944417bebc4SElaine Zhang return -ENOENT;
1945417bebc4SElaine Zhang }
1946417bebc4SElaine Zhang
1947417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
1948417bebc4SElaine Zhang CLK_MAC0_2TOP_SEL_MASK,
1949417bebc4SElaine Zhang src_clk << CLK_MAC0_2TOP_SEL_SHIFT);
1950417bebc4SElaine Zhang
1951417bebc4SElaine Zhang return rk3568_gmac_src_get_clk(priv, mac_id);
1952417bebc4SElaine Zhang }
1953417bebc4SElaine Zhang
rk3568_gmac_out_get_clk(struct rk3568_clk_priv * priv,ulong mac_id)1954417bebc4SElaine Zhang static ulong rk3568_gmac_out_get_clk(struct rk3568_clk_priv *priv,
1955417bebc4SElaine Zhang ulong mac_id)
1956417bebc4SElaine Zhang {
1957417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1958417bebc4SElaine Zhang u32 sel, con;
1959417bebc4SElaine Zhang
1960417bebc4SElaine Zhang con = readl(&cru->clksel_con[31 + mac_id * 2]);
1961417bebc4SElaine Zhang sel = (con & CLK_MAC0_OUT_SEL_MASK) >> CLK_MAC0_OUT_SEL_SHIFT;
1962417bebc4SElaine Zhang
1963417bebc4SElaine Zhang switch (sel) {
1964417bebc4SElaine Zhang case CLK_MAC0_OUT_SEL_125M:
1965417bebc4SElaine Zhang return 125 * MHz;
1966417bebc4SElaine Zhang case CLK_MAC0_OUT_SEL_50M:
1967417bebc4SElaine Zhang return 50 * MHz;
1968417bebc4SElaine Zhang case CLK_MAC0_OUT_SEL_25M:
1969417bebc4SElaine Zhang return 25 * MHz;
1970417bebc4SElaine Zhang case CLK_MAC0_OUT_SEL_24M:
1971417bebc4SElaine Zhang return OSC_HZ;
1972417bebc4SElaine Zhang default:
1973417bebc4SElaine Zhang return -ENOENT;
1974417bebc4SElaine Zhang }
1975417bebc4SElaine Zhang }
1976417bebc4SElaine Zhang
rk3568_gmac_out_set_clk(struct rk3568_clk_priv * priv,ulong mac_id,ulong rate)1977417bebc4SElaine Zhang static ulong rk3568_gmac_out_set_clk(struct rk3568_clk_priv *priv,
1978417bebc4SElaine Zhang ulong mac_id, ulong rate)
1979417bebc4SElaine Zhang {
1980417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
1981417bebc4SElaine Zhang int src_clk;
1982417bebc4SElaine Zhang
1983417bebc4SElaine Zhang switch (rate) {
1984417bebc4SElaine Zhang case 125 * MHz:
1985417bebc4SElaine Zhang src_clk = CLK_MAC0_OUT_SEL_125M;
1986417bebc4SElaine Zhang break;
1987417bebc4SElaine Zhang case 50 * MHz:
1988417bebc4SElaine Zhang src_clk = CLK_MAC0_OUT_SEL_50M;
1989417bebc4SElaine Zhang break;
1990417bebc4SElaine Zhang case 25 * MHz:
1991417bebc4SElaine Zhang src_clk = CLK_MAC0_OUT_SEL_25M;
1992417bebc4SElaine Zhang break;
1993417bebc4SElaine Zhang case 24 * MHz:
1994417bebc4SElaine Zhang src_clk = CLK_MAC0_OUT_SEL_24M;
1995417bebc4SElaine Zhang break;
1996417bebc4SElaine Zhang default:
1997417bebc4SElaine Zhang return -ENOENT;
1998417bebc4SElaine Zhang }
1999417bebc4SElaine Zhang
2000417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2001417bebc4SElaine Zhang CLK_MAC0_OUT_SEL_MASK,
2002417bebc4SElaine Zhang src_clk << CLK_MAC0_OUT_SEL_SHIFT);
2003417bebc4SElaine Zhang
2004417bebc4SElaine Zhang return rk3568_gmac_out_get_clk(priv, mac_id);
2005417bebc4SElaine Zhang }
2006417bebc4SElaine Zhang
rk3568_gmac_ptp_ref_get_clk(struct rk3568_clk_priv * priv,ulong mac_id)2007417bebc4SElaine Zhang static ulong rk3568_gmac_ptp_ref_get_clk(struct rk3568_clk_priv *priv,
2008417bebc4SElaine Zhang ulong mac_id)
2009417bebc4SElaine Zhang {
2010417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
2011417bebc4SElaine Zhang u32 sel, con;
2012417bebc4SElaine Zhang
2013417bebc4SElaine Zhang con = readl(&cru->clksel_con[31 + mac_id * 2]);
2014417bebc4SElaine Zhang sel = (con & CLK_GMAC0_PTP_REF_SEL_MASK) >> CLK_GMAC0_PTP_REF_SEL_SHIFT;
2015417bebc4SElaine Zhang
2016417bebc4SElaine Zhang switch (sel) {
2017417bebc4SElaine Zhang case CLK_GMAC0_PTP_REF_SEL_62_5M:
2018417bebc4SElaine Zhang return 62500 * KHz;
2019417bebc4SElaine Zhang case CLK_GMAC0_PTP_REF_SEL_100M:
2020417bebc4SElaine Zhang return 100 * MHz;
2021417bebc4SElaine Zhang case CLK_GMAC0_PTP_REF_SEL_50M:
2022417bebc4SElaine Zhang return 50 * MHz;
2023417bebc4SElaine Zhang case CLK_GMAC0_PTP_REF_SEL_24M:
2024417bebc4SElaine Zhang return OSC_HZ;
2025417bebc4SElaine Zhang default:
2026417bebc4SElaine Zhang return -ENOENT;
2027417bebc4SElaine Zhang }
2028417bebc4SElaine Zhang }
2029417bebc4SElaine Zhang
rk3568_gmac_ptp_ref_set_clk(struct rk3568_clk_priv * priv,ulong mac_id,ulong rate)2030417bebc4SElaine Zhang static ulong rk3568_gmac_ptp_ref_set_clk(struct rk3568_clk_priv *priv,
2031417bebc4SElaine Zhang ulong mac_id, ulong rate)
2032417bebc4SElaine Zhang {
2033417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
2034417bebc4SElaine Zhang int src_clk;
2035417bebc4SElaine Zhang
2036417bebc4SElaine Zhang switch (rate) {
2037417bebc4SElaine Zhang case 62500 * KHz:
2038417bebc4SElaine Zhang src_clk = CLK_GMAC0_PTP_REF_SEL_62_5M;
2039417bebc4SElaine Zhang break;
2040417bebc4SElaine Zhang case 100 * MHz:
2041417bebc4SElaine Zhang src_clk = CLK_GMAC0_PTP_REF_SEL_100M;
2042417bebc4SElaine Zhang break;
2043417bebc4SElaine Zhang case 50 * MHz:
2044417bebc4SElaine Zhang src_clk = CLK_GMAC0_PTP_REF_SEL_50M;
2045417bebc4SElaine Zhang break;
2046417bebc4SElaine Zhang case 24 * MHz:
2047417bebc4SElaine Zhang src_clk = CLK_GMAC0_PTP_REF_SEL_24M;
2048417bebc4SElaine Zhang break;
2049417bebc4SElaine Zhang default:
2050417bebc4SElaine Zhang return -ENOENT;
2051417bebc4SElaine Zhang }
2052417bebc4SElaine Zhang
2053417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2054417bebc4SElaine Zhang CLK_GMAC0_PTP_REF_SEL_MASK,
2055417bebc4SElaine Zhang src_clk << CLK_GMAC0_PTP_REF_SEL_SHIFT);
2056417bebc4SElaine Zhang
2057417bebc4SElaine Zhang return rk3568_gmac_ptp_ref_get_clk(priv, mac_id);
2058417bebc4SElaine Zhang }
2059417bebc4SElaine Zhang
rk3568_gmac_tx_rx_set_clk(struct rk3568_clk_priv * priv,ulong mac_id,ulong rate)2060417bebc4SElaine Zhang static ulong rk3568_gmac_tx_rx_set_clk(struct rk3568_clk_priv *priv,
2061417bebc4SElaine Zhang ulong mac_id, ulong rate)
2062417bebc4SElaine Zhang {
2063417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
2064417bebc4SElaine Zhang u32 con, sel, div_sel;
2065417bebc4SElaine Zhang
2066417bebc4SElaine Zhang con = readl(&cru->clksel_con[31 + mac_id * 2]);
2067417bebc4SElaine Zhang sel = (con & RMII0_MODE_MASK) >> RMII0_MODE_SHIFT;
2068417bebc4SElaine Zhang
2069417bebc4SElaine Zhang if (sel == RMII0_MODE_SEL_RGMII) {
2070417bebc4SElaine Zhang if (rate == 2500000)
2071417bebc4SElaine Zhang div_sel = RGMII0_CLK_SEL_2_5M;
2072417bebc4SElaine Zhang else if (rate == 25000000)
2073417bebc4SElaine Zhang div_sel = RGMII0_CLK_SEL_25M;
2074417bebc4SElaine Zhang else
2075417bebc4SElaine Zhang div_sel = RGMII0_CLK_SEL_125M;
2076417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2077417bebc4SElaine Zhang RGMII0_CLK_SEL_MASK,
2078417bebc4SElaine Zhang div_sel << RGMII0_CLK_SEL_SHIFT);
2079417bebc4SElaine Zhang } else if (sel == RMII0_MODE_SEL_RMII) {
2080417bebc4SElaine Zhang if (rate == 2500000)
2081417bebc4SElaine Zhang div_sel = RMII0_CLK_SEL_2_5M;
2082417bebc4SElaine Zhang else
2083417bebc4SElaine Zhang div_sel = RMII0_CLK_SEL_25M;
2084417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2085417bebc4SElaine Zhang RMII0_CLK_SEL_MASK,
2086417bebc4SElaine Zhang div_sel << RMII0_CLK_SEL_SHIFT);
2087417bebc4SElaine Zhang }
2088417bebc4SElaine Zhang
2089417bebc4SElaine Zhang return 0;
2090417bebc4SElaine Zhang }
2091417bebc4SElaine Zhang
rk3568_ebc_get_clk(struct rk3568_clk_priv * priv)2092f6d27794Szhangqing static ulong rk3568_ebc_get_clk(struct rk3568_clk_priv *priv)
2093fdd74c32SElaine Zhang {
2094fdd74c32SElaine Zhang struct rk3568_cru *cru = priv->cru;
2095fdd74c32SElaine Zhang u32 con, div, p_rate;
2096fdd74c32SElaine Zhang
2097fdd74c32SElaine Zhang con = readl(&cru->clksel_con[79]);
2098fdd74c32SElaine Zhang div = (con & CPLL_333M_DIV_MASK) >> CPLL_333M_DIV_SHIFT;
2099fdd74c32SElaine Zhang p_rate = DIV_TO_RATE(priv->cpll_hz, div);
2100fdd74c32SElaine Zhang
2101fdd74c32SElaine Zhang con = readl(&cru->clksel_con[43]);
2102fdd74c32SElaine Zhang div = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
2103fdd74c32SElaine Zhang switch (div) {
2104fdd74c32SElaine Zhang case DCLK_EBC_SEL_GPLL_400M:
2105fdd74c32SElaine Zhang return 400 * MHz;
2106fdd74c32SElaine Zhang case DCLK_EBC_SEL_CPLL_333M:
2107fdd74c32SElaine Zhang return p_rate;
2108fdd74c32SElaine Zhang case DCLK_EBC_SEL_GPLL_200M:
2109fdd74c32SElaine Zhang return 200 * MHz;
2110fdd74c32SElaine Zhang default:
2111fdd74c32SElaine Zhang return -ENOENT;
2112fdd74c32SElaine Zhang }
2113fdd74c32SElaine Zhang }
2114fdd74c32SElaine Zhang
rk3568_ebc_set_clk(struct rk3568_clk_priv * priv,ulong rate)2115f6d27794Szhangqing static ulong rk3568_ebc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
2116fdd74c32SElaine Zhang {
2117fdd74c32SElaine Zhang struct rk3568_cru *cru = priv->cru;
2118fdd74c32SElaine Zhang int src_clk_div;
2119fdd74c32SElaine Zhang
2120fdd74c32SElaine Zhang src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
2121fdd74c32SElaine Zhang assert(src_clk_div - 1 <= 31);
2122fdd74c32SElaine Zhang rk_clrsetreg(&cru->clksel_con[79],
2123fdd74c32SElaine Zhang CPLL_333M_DIV_MASK,
2124fdd74c32SElaine Zhang (src_clk_div - 1) << CPLL_333M_DIV_SHIFT);
2125fdd74c32SElaine Zhang rk_clrsetreg(&cru->clksel_con[43],
2126fdd74c32SElaine Zhang DCLK_EBC_SEL_MASK,
2127fdd74c32SElaine Zhang DCLK_EBC_SEL_CPLL_333M << DCLK_EBC_SEL_SHIFT);
2128fdd74c32SElaine Zhang
2129f6d27794Szhangqing return rk3568_ebc_get_clk(priv);
2130fdd74c32SElaine Zhang }
21310a04fb50SElaine Zhang
rk3568_rkvdec_get_clk(struct rk3568_clk_priv * priv,ulong clk_id)21320a04fb50SElaine Zhang static ulong rk3568_rkvdec_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
21330a04fb50SElaine Zhang {
21340a04fb50SElaine Zhang struct rk3568_cru *cru = priv->cru;
21350a04fb50SElaine Zhang u32 con, div, src, p_rate;
21360a04fb50SElaine Zhang
21370a04fb50SElaine Zhang switch (clk_id) {
21380a04fb50SElaine Zhang case ACLK_RKVDEC_PRE:
21390a04fb50SElaine Zhang case ACLK_RKVDEC:
21400a04fb50SElaine Zhang con = readl(&cru->clksel_con[47]);
21410a04fb50SElaine Zhang src = (con & ACLK_RKVDEC_SEL_MASK) >> ACLK_RKVDEC_SEL_SHIFT;
21420a04fb50SElaine Zhang div = (con & ACLK_RKVDEC_DIV_MASK) >> ACLK_RKVDEC_DIV_SHIFT;
21430a04fb50SElaine Zhang if (src == ACLK_RKVDEC_SEL_CPLL)
21440a04fb50SElaine Zhang p_rate = priv->cpll_hz;
21450a04fb50SElaine Zhang else
21460a04fb50SElaine Zhang p_rate = priv->gpll_hz;
21470a04fb50SElaine Zhang return DIV_TO_RATE(p_rate, div);
21480a04fb50SElaine Zhang case CLK_RKVDEC_CORE:
21490a04fb50SElaine Zhang con = readl(&cru->clksel_con[49]);
21500a04fb50SElaine Zhang src = (con & CLK_RKVDEC_CORE_SEL_MASK)
21510a04fb50SElaine Zhang >> CLK_RKVDEC_CORE_SEL_SHIFT;
21520a04fb50SElaine Zhang div = (con & CLK_RKVDEC_CORE_DIV_MASK)
21530a04fb50SElaine Zhang >> CLK_RKVDEC_CORE_DIV_SHIFT;
21540a04fb50SElaine Zhang if (src == CLK_RKVDEC_CORE_SEL_CPLL)
21550a04fb50SElaine Zhang p_rate = priv->cpll_hz;
21560a04fb50SElaine Zhang else if (src == CLK_RKVDEC_CORE_SEL_NPLL)
21570a04fb50SElaine Zhang p_rate = priv->npll_hz;
21580a04fb50SElaine Zhang else if (src == CLK_RKVDEC_CORE_SEL_VPLL)
21590a04fb50SElaine Zhang p_rate = priv->vpll_hz;
21600a04fb50SElaine Zhang else
21610a04fb50SElaine Zhang p_rate = priv->gpll_hz;
21620a04fb50SElaine Zhang return DIV_TO_RATE(p_rate, div);
21630a04fb50SElaine Zhang default:
21640a04fb50SElaine Zhang return -ENOENT;
21650a04fb50SElaine Zhang }
21660a04fb50SElaine Zhang }
21670a04fb50SElaine Zhang
rk3568_rkvdec_set_clk(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)21680a04fb50SElaine Zhang static ulong rk3568_rkvdec_set_clk(struct rk3568_clk_priv *priv,
21690a04fb50SElaine Zhang ulong clk_id, ulong rate)
21700a04fb50SElaine Zhang {
21710a04fb50SElaine Zhang struct rk3568_cru *cru = priv->cru;
21720a04fb50SElaine Zhang int src_clk_div, src, p_rate;
21730a04fb50SElaine Zhang
21740a04fb50SElaine Zhang switch (clk_id) {
21750a04fb50SElaine Zhang case ACLK_RKVDEC_PRE:
21760a04fb50SElaine Zhang case ACLK_RKVDEC:
21770a04fb50SElaine Zhang src = (readl(&cru->clksel_con[47]) & ACLK_RKVDEC_SEL_MASK)
21780a04fb50SElaine Zhang >> ACLK_RKVDEC_SEL_SHIFT;
21790a04fb50SElaine Zhang if (src == ACLK_RKVDEC_SEL_CPLL)
21800a04fb50SElaine Zhang p_rate = priv->cpll_hz;
21810a04fb50SElaine Zhang else
21820a04fb50SElaine Zhang p_rate = priv->gpll_hz;
21830a04fb50SElaine Zhang src_clk_div = DIV_ROUND_UP(p_rate, rate);
21840a04fb50SElaine Zhang assert(src_clk_div - 1 <= 31);
21850a04fb50SElaine Zhang rk_clrsetreg(&cru->clksel_con[47],
21860a04fb50SElaine Zhang ACLK_RKVDEC_SEL_MASK |
21870a04fb50SElaine Zhang ACLK_RKVDEC_DIV_MASK,
21880a04fb50SElaine Zhang (src << ACLK_RKVDEC_SEL_SHIFT) |
21890a04fb50SElaine Zhang (src_clk_div - 1) << ACLK_RKVDEC_DIV_SHIFT);
21900a04fb50SElaine Zhang break;
21910a04fb50SElaine Zhang case CLK_RKVDEC_CORE:
21920a04fb50SElaine Zhang src = (readl(&cru->clksel_con[49]) & CLK_RKVDEC_CORE_SEL_MASK)
21930a04fb50SElaine Zhang >> CLK_RKVDEC_CORE_SEL_SHIFT;
21940a04fb50SElaine Zhang if (src == CLK_RKVDEC_CORE_SEL_CPLL)
21950a04fb50SElaine Zhang p_rate = priv->cpll_hz;
21960a04fb50SElaine Zhang else if (src == CLK_RKVDEC_CORE_SEL_NPLL)
21970a04fb50SElaine Zhang p_rate = priv->npll_hz;
21980a04fb50SElaine Zhang else if (src == CLK_RKVDEC_CORE_SEL_VPLL)
21990a04fb50SElaine Zhang p_rate = priv->vpll_hz;
22000a04fb50SElaine Zhang else
22010a04fb50SElaine Zhang p_rate = priv->gpll_hz;
22020a04fb50SElaine Zhang src_clk_div = DIV_ROUND_UP(p_rate, rate);
22030a04fb50SElaine Zhang assert(src_clk_div - 1 <= 31);
22040a04fb50SElaine Zhang rk_clrsetreg(&cru->clksel_con[49],
22050a04fb50SElaine Zhang CLK_RKVDEC_CORE_SEL_MASK |
22060a04fb50SElaine Zhang CLK_RKVDEC_CORE_DIV_MASK,
22070a04fb50SElaine Zhang (src << CLK_RKVDEC_CORE_SEL_SHIFT) |
22080a04fb50SElaine Zhang (src_clk_div - 1) << CLK_RKVDEC_CORE_DIV_SHIFT);
22090a04fb50SElaine Zhang break;
22100a04fb50SElaine Zhang default:
22110a04fb50SElaine Zhang return -ENOENT;
22120a04fb50SElaine Zhang }
22130a04fb50SElaine Zhang
22140a04fb50SElaine Zhang return rk3568_rkvdec_get_clk(priv, clk_id);
22150a04fb50SElaine Zhang }
221698d806deSJonas Karlman #endif
2217563d12f2SElaine Zhang
rk3568_uart_get_rate(struct rk3568_clk_priv * priv,ulong clk_id)2218563d12f2SElaine Zhang static ulong rk3568_uart_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
2219563d12f2SElaine Zhang {
2220563d12f2SElaine Zhang struct rk3568_cru *cru = priv->cru;
2221563d12f2SElaine Zhang u32 reg, con, fracdiv, div, src, p_src, p_rate;
2222563d12f2SElaine Zhang unsigned long m, n;
2223563d12f2SElaine Zhang
2224563d12f2SElaine Zhang switch (clk_id) {
2225563d12f2SElaine Zhang case SCLK_UART1:
2226563d12f2SElaine Zhang reg = 52;
2227563d12f2SElaine Zhang break;
2228563d12f2SElaine Zhang case SCLK_UART2:
2229563d12f2SElaine Zhang reg = 54;
2230563d12f2SElaine Zhang break;
2231563d12f2SElaine Zhang case SCLK_UART3:
2232563d12f2SElaine Zhang reg = 56;
2233563d12f2SElaine Zhang break;
2234563d12f2SElaine Zhang case SCLK_UART4:
2235563d12f2SElaine Zhang reg = 58;
2236563d12f2SElaine Zhang break;
2237563d12f2SElaine Zhang case SCLK_UART5:
2238563d12f2SElaine Zhang reg = 60;
2239563d12f2SElaine Zhang break;
2240563d12f2SElaine Zhang case SCLK_UART6:
2241563d12f2SElaine Zhang reg = 62;
2242563d12f2SElaine Zhang break;
2243563d12f2SElaine Zhang case SCLK_UART7:
2244563d12f2SElaine Zhang reg = 64;
2245563d12f2SElaine Zhang break;
2246563d12f2SElaine Zhang case SCLK_UART8:
2247563d12f2SElaine Zhang reg = 66;
2248563d12f2SElaine Zhang break;
2249563d12f2SElaine Zhang case SCLK_UART9:
2250563d12f2SElaine Zhang reg = 68;
2251563d12f2SElaine Zhang break;
2252563d12f2SElaine Zhang default:
2253563d12f2SElaine Zhang return -ENOENT;
2254563d12f2SElaine Zhang }
2255563d12f2SElaine Zhang con = readl(&cru->clksel_con[reg]);
2256563d12f2SElaine Zhang src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
2257563d12f2SElaine Zhang div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
2258563d12f2SElaine Zhang p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
2259563d12f2SElaine Zhang if (p_src == CLK_UART_SRC_SEL_GPLL)
2260563d12f2SElaine Zhang p_rate = priv->gpll_hz;
2261563d12f2SElaine Zhang else if (p_src == CLK_UART_SRC_SEL_CPLL)
2262563d12f2SElaine Zhang p_rate = priv->cpll_hz;
2263563d12f2SElaine Zhang else
2264563d12f2SElaine Zhang p_rate = 480000000;
2265563d12f2SElaine Zhang if (src == CLK_UART_SEL_SRC) {
2266563d12f2SElaine Zhang return DIV_TO_RATE(p_rate, div);
2267563d12f2SElaine Zhang } else if (src == CLK_UART_SEL_FRAC) {
2268563d12f2SElaine Zhang fracdiv = readl(&cru->clksel_con[reg + 1]);
2269563d12f2SElaine Zhang n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
2270563d12f2SElaine Zhang n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
2271563d12f2SElaine Zhang m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
2272563d12f2SElaine Zhang m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
2273563d12f2SElaine Zhang return DIV_TO_RATE(p_rate, div) * n / m;
2274563d12f2SElaine Zhang } else {
2275563d12f2SElaine Zhang return OSC_HZ;
2276563d12f2SElaine Zhang }
2277563d12f2SElaine Zhang }
2278563d12f2SElaine Zhang
rk3568_uart_set_rate(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)2279563d12f2SElaine Zhang static ulong rk3568_uart_set_rate(struct rk3568_clk_priv *priv,
2280563d12f2SElaine Zhang ulong clk_id, ulong rate)
2281563d12f2SElaine Zhang {
2282563d12f2SElaine Zhang struct rk3568_cru *cru = priv->cru;
2283563d12f2SElaine Zhang u32 reg, clk_src, uart_src, div;
2284563d12f2SElaine Zhang unsigned long m = 0, n = 0, val;
2285563d12f2SElaine Zhang
2286563d12f2SElaine Zhang if (priv->gpll_hz % rate == 0) {
2287563d12f2SElaine Zhang clk_src = CLK_UART_SRC_SEL_GPLL;
2288563d12f2SElaine Zhang uart_src = CLK_UART_SEL_SRC;
2289563d12f2SElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
2290563d12f2SElaine Zhang } else if (priv->cpll_hz % rate == 0) {
2291563d12f2SElaine Zhang clk_src = CLK_UART_SRC_SEL_CPLL;
2292563d12f2SElaine Zhang uart_src = CLK_UART_SEL_SRC;
2293563d12f2SElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
2294563d12f2SElaine Zhang } else if (rate == OSC_HZ) {
2295563d12f2SElaine Zhang clk_src = CLK_UART_SRC_SEL_GPLL;
2296563d12f2SElaine Zhang uart_src = CLK_UART_SEL_XIN24M;
2297563d12f2SElaine Zhang div = 2;
2298563d12f2SElaine Zhang } else {
2299563d12f2SElaine Zhang clk_src = CLK_UART_SRC_SEL_GPLL;
2300563d12f2SElaine Zhang uart_src = CLK_UART_SEL_FRAC;
2301563d12f2SElaine Zhang div = 2;
2302563d12f2SElaine Zhang rational_best_approximation(rate, priv->gpll_hz / div,
2303563d12f2SElaine Zhang GENMASK(16 - 1, 0),
2304563d12f2SElaine Zhang GENMASK(16 - 1, 0),
2305563d12f2SElaine Zhang &m, &n);
2306563d12f2SElaine Zhang }
2307563d12f2SElaine Zhang
2308563d12f2SElaine Zhang switch (clk_id) {
2309563d12f2SElaine Zhang case SCLK_UART1:
2310563d12f2SElaine Zhang reg = 52;
2311563d12f2SElaine Zhang break;
2312563d12f2SElaine Zhang case SCLK_UART2:
2313563d12f2SElaine Zhang reg = 54;
2314563d12f2SElaine Zhang break;
2315563d12f2SElaine Zhang case SCLK_UART3:
2316563d12f2SElaine Zhang reg = 56;
2317563d12f2SElaine Zhang break;
2318563d12f2SElaine Zhang case SCLK_UART4:
2319563d12f2SElaine Zhang reg = 58;
2320563d12f2SElaine Zhang break;
2321563d12f2SElaine Zhang case SCLK_UART5:
2322563d12f2SElaine Zhang reg = 60;
2323563d12f2SElaine Zhang break;
2324563d12f2SElaine Zhang case SCLK_UART6:
2325563d12f2SElaine Zhang reg = 62;
2326563d12f2SElaine Zhang break;
2327563d12f2SElaine Zhang case SCLK_UART7:
2328563d12f2SElaine Zhang reg = 64;
2329563d12f2SElaine Zhang break;
2330563d12f2SElaine Zhang case SCLK_UART8:
2331563d12f2SElaine Zhang reg = 66;
2332563d12f2SElaine Zhang break;
2333563d12f2SElaine Zhang case SCLK_UART9:
2334563d12f2SElaine Zhang reg = 68;
2335563d12f2SElaine Zhang break;
2336563d12f2SElaine Zhang default:
2337563d12f2SElaine Zhang return -ENOENT;
2338563d12f2SElaine Zhang }
2339563d12f2SElaine Zhang rk_clrsetreg(&cru->clksel_con[reg],
2340563d12f2SElaine Zhang CLK_UART_SEL_MASK | CLK_UART_SRC_SEL_MASK |
2341563d12f2SElaine Zhang CLK_UART_SRC_DIV_MASK,
2342563d12f2SElaine Zhang (clk_src << CLK_UART_SRC_SEL_SHIFT) |
2343563d12f2SElaine Zhang (uart_src << CLK_UART_SEL_SHIFT) |
2344563d12f2SElaine Zhang ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
2345563d12f2SElaine Zhang if (m && n) {
2346563d12f2SElaine Zhang val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
2347563d12f2SElaine Zhang writel(val, &cru->clksel_con[reg + 1]);
2348563d12f2SElaine Zhang }
2349563d12f2SElaine Zhang
2350563d12f2SElaine Zhang return rk3568_uart_get_rate(priv, clk_id);
2351563d12f2SElaine Zhang }
235226663c2dSElaine Zhang
235398d806deSJonas Karlman #ifndef CONFIG_SPL_BUILD
rk3568_i2s3_get_rate(struct rk3568_clk_priv * priv,ulong clk_id)235426663c2dSElaine Zhang static ulong rk3568_i2s3_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
235526663c2dSElaine Zhang {
235626663c2dSElaine Zhang struct rk3568_cru *cru = priv->cru;
235726663c2dSElaine Zhang struct rk3568_grf *grf = priv->grf;
235826663c2dSElaine Zhang u32 con, div, src, p_rate;
235926663c2dSElaine Zhang u32 reg, fracdiv, p_src;
236026663c2dSElaine Zhang unsigned long m, n;
236126663c2dSElaine Zhang
236226663c2dSElaine Zhang switch (clk_id) {
236326663c2dSElaine Zhang case I2S3_MCLKOUT_TX:
236426663c2dSElaine Zhang con = readl(&cru->clksel_con[21]);
236526663c2dSElaine Zhang src = (con & I2S3_MCLKOUT_TX_SEL_MASK) >>
236626663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_SHIFT;
236726663c2dSElaine Zhang if (src == I2S3_MCLKOUT_TX_SEL_12M)
236826663c2dSElaine Zhang p_rate = 12000000;
236926663c2dSElaine Zhang else
237026663c2dSElaine Zhang p_rate = rk3568_i2s3_get_rate(priv, MCLK_I2S3_2CH_TX);
237126663c2dSElaine Zhang return p_rate;
237226663c2dSElaine Zhang case I2S3_MCLKOUT_RX:
237326663c2dSElaine Zhang con = readl(&cru->clksel_con[83]);
237426663c2dSElaine Zhang src = (con & I2S3_MCLKOUT_TX_SEL_MASK) >>
237526663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_SHIFT;
237626663c2dSElaine Zhang if (src == I2S3_MCLKOUT_TX_SEL_12M)
237726663c2dSElaine Zhang p_rate = 12000000;
237826663c2dSElaine Zhang else
237926663c2dSElaine Zhang p_rate = rk3568_i2s3_get_rate(priv, MCLK_I2S3_2CH_RX);
238026663c2dSElaine Zhang return p_rate;
238126663c2dSElaine Zhang case I2S3_MCLKOUT:
238226663c2dSElaine Zhang con = readl(&grf->soc_con2);
238326663c2dSElaine Zhang src = (con & I2S3_MCLKOUT_SEL_MASK)
238426663c2dSElaine Zhang >> I2S3_MCLKOUT_SEL_SHIFT;
238526663c2dSElaine Zhang if (src == I2S3_MCLKOUT_SEL_RX)
238626663c2dSElaine Zhang p_rate = rk3568_i2s3_get_rate(priv, I2S3_MCLKOUT_RX);
238726663c2dSElaine Zhang else
238826663c2dSElaine Zhang p_rate = rk3568_i2s3_get_rate(priv, I2S3_MCLKOUT_TX);
238926663c2dSElaine Zhang return p_rate;
239026663c2dSElaine Zhang case MCLK_I2S3_2CH_RX:
239126663c2dSElaine Zhang reg = 83;
239226663c2dSElaine Zhang break;
239326663c2dSElaine Zhang case MCLK_I2S3_2CH_TX:
239426663c2dSElaine Zhang reg = 21;
239526663c2dSElaine Zhang break;
239626663c2dSElaine Zhang default:
239726663c2dSElaine Zhang return -ENOENT;
239826663c2dSElaine Zhang }
239926663c2dSElaine Zhang
240026663c2dSElaine Zhang con = readl(&cru->clksel_con[reg]);
240126663c2dSElaine Zhang src = (con & CLK_I2S3_SEL_MASK) >> CLK_I2S3_SEL_SHIFT;
240226663c2dSElaine Zhang div = (con & CLK_I2S3_SRC_DIV_MASK) >> CLK_I2S3_SRC_DIV_SHIFT;
240326663c2dSElaine Zhang p_src = (con & CLK_I2S3_SRC_SEL_MASK) >> CLK_I2S3_SRC_SEL_SHIFT;
240426663c2dSElaine Zhang if (p_src == CLK_I2S3_SRC_SEL_GPLL)
240526663c2dSElaine Zhang p_rate = priv->gpll_hz;
240626663c2dSElaine Zhang else if (p_src == CLK_I2S3_SRC_SEL_CPLL)
240726663c2dSElaine Zhang p_rate = priv->cpll_hz;
240826663c2dSElaine Zhang else
240926663c2dSElaine Zhang p_rate = priv->npll_hz;
241026663c2dSElaine Zhang if (src == CLK_I2S3_SEL_SRC) {
241126663c2dSElaine Zhang return DIV_TO_RATE(p_rate, div);
241226663c2dSElaine Zhang } else if (src == CLK_I2S3_SEL_FRAC) {
241326663c2dSElaine Zhang fracdiv = readl(&cru->clksel_con[reg + 1]);
241426663c2dSElaine Zhang n = fracdiv & CLK_I2S3_FRAC_NUMERATOR_MASK;
241526663c2dSElaine Zhang n >>= CLK_I2S3_FRAC_NUMERATOR_SHIFT;
241626663c2dSElaine Zhang m = fracdiv & CLK_I2S3_FRAC_DENOMINATOR_MASK;
241726663c2dSElaine Zhang m >>= CLK_I2S3_FRAC_DENOMINATOR_SHIFT;
241826663c2dSElaine Zhang return DIV_TO_RATE(p_rate, div) * n / m;
241926663c2dSElaine Zhang } else {
242026663c2dSElaine Zhang return OSC_HZ / 2;
242126663c2dSElaine Zhang }
242226663c2dSElaine Zhang }
242326663c2dSElaine Zhang
rk3568_i2s3_set_rate(struct rk3568_clk_priv * priv,ulong clk_id,ulong rate)242426663c2dSElaine Zhang static ulong rk3568_i2s3_set_rate(struct rk3568_clk_priv *priv,
242526663c2dSElaine Zhang ulong clk_id, ulong rate)
242626663c2dSElaine Zhang {
242726663c2dSElaine Zhang struct rk3568_cru *cru = priv->cru;
242826663c2dSElaine Zhang struct rk3568_grf *grf = priv->grf;
242926663c2dSElaine Zhang u32 reg, con, clk_src, i2s_src, div;
243026663c2dSElaine Zhang unsigned long m = 0, n = 0, val;
243126663c2dSElaine Zhang
243226663c2dSElaine Zhang if (priv->gpll_hz % rate == 0) {
243326663c2dSElaine Zhang clk_src = CLK_I2S3_SRC_SEL_GPLL;
243426663c2dSElaine Zhang i2s_src = CLK_I2S3_SEL_SRC;
243526663c2dSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
243626663c2dSElaine Zhang } else if (priv->cpll_hz % rate == 0) {
243726663c2dSElaine Zhang clk_src = CLK_I2S3_SRC_SEL_CPLL;
243826663c2dSElaine Zhang i2s_src = CLK_I2S3_SEL_SRC;
243926663c2dSElaine Zhang div = DIV_ROUND_UP(priv->gpll_hz, rate);
244026663c2dSElaine Zhang } else if (rate == OSC_HZ / 2) {
244126663c2dSElaine Zhang clk_src = CLK_I2S3_SRC_SEL_GPLL;
244226663c2dSElaine Zhang i2s_src = CLK_I2S3_SEL_XIN12M;
244326663c2dSElaine Zhang div = 1;
244426663c2dSElaine Zhang } else {
244526663c2dSElaine Zhang clk_src = CLK_I2S3_SRC_SEL_GPLL;
244626663c2dSElaine Zhang i2s_src = CLK_I2S3_SEL_FRAC;
244726663c2dSElaine Zhang div = 1;
244826663c2dSElaine Zhang rational_best_approximation(rate, priv->gpll_hz / div,
244926663c2dSElaine Zhang GENMASK(16 - 1, 0),
245026663c2dSElaine Zhang GENMASK(16 - 1, 0),
245126663c2dSElaine Zhang &m, &n);
245226663c2dSElaine Zhang }
245326663c2dSElaine Zhang
245426663c2dSElaine Zhang switch (clk_id) {
245526663c2dSElaine Zhang case I2S3_MCLKOUT_TX:
245626663c2dSElaine Zhang if (rate == 12000000) {
245726663c2dSElaine Zhang rk_clrsetreg(&cru->clksel_con[21],
245826663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_MASK,
245926663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_12M <<
246026663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_SHIFT);
246126663c2dSElaine Zhang } else {
246226663c2dSElaine Zhang rk3568_i2s3_set_rate(priv, MCLK_I2S3_2CH_TX, rate),
246326663c2dSElaine Zhang rk_clrsetreg(&cru->clksel_con[21],
246426663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_MASK,
246526663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_MCLK <<
246626663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_SHIFT);
246726663c2dSElaine Zhang }
246826663c2dSElaine Zhang return rk3568_i2s3_get_rate(priv, clk_id);
246926663c2dSElaine Zhang case I2S3_MCLKOUT_RX:
247026663c2dSElaine Zhang if (rate == 12000000) {
247126663c2dSElaine Zhang rk_clrsetreg(&cru->clksel_con[83],
247226663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_MASK,
247326663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_12M <<
247426663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_SHIFT);
247526663c2dSElaine Zhang } else {
247626663c2dSElaine Zhang rk3568_i2s3_set_rate(priv, MCLK_I2S3_2CH_RX, rate),
247726663c2dSElaine Zhang rk_clrsetreg(&cru->clksel_con[21],
247826663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_MASK,
247926663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_MCLK <<
248026663c2dSElaine Zhang I2S3_MCLKOUT_TX_SEL_SHIFT);
248126663c2dSElaine Zhang }
248226663c2dSElaine Zhang return rk3568_i2s3_get_rate(priv, clk_id);
248326663c2dSElaine Zhang case I2S3_MCLKOUT:
248426663c2dSElaine Zhang con = readl(&grf->soc_con2);
248526663c2dSElaine Zhang clk_src = (con & I2S3_MCLKOUT_SEL_MASK)
248626663c2dSElaine Zhang >> I2S3_MCLKOUT_SEL_SHIFT;
248726663c2dSElaine Zhang if (clk_src == I2S3_MCLKOUT_SEL_RX)
248826663c2dSElaine Zhang rk3568_i2s3_set_rate(priv, I2S3_MCLKOUT_RX, rate);
248926663c2dSElaine Zhang else
249026663c2dSElaine Zhang rk3568_i2s3_set_rate(priv, I2S3_MCLKOUT_TX, rate);
249126663c2dSElaine Zhang return rk3568_i2s3_get_rate(priv, clk_id);
249226663c2dSElaine Zhang case MCLK_I2S3_2CH_RX:
249326663c2dSElaine Zhang reg = 83;
249426663c2dSElaine Zhang break;
249526663c2dSElaine Zhang case MCLK_I2S3_2CH_TX:
249626663c2dSElaine Zhang reg = 21;
249726663c2dSElaine Zhang break;
249826663c2dSElaine Zhang default:
249926663c2dSElaine Zhang return -ENOENT;
250026663c2dSElaine Zhang }
250126663c2dSElaine Zhang
250226663c2dSElaine Zhang rk_clrsetreg(&cru->clksel_con[reg],
250326663c2dSElaine Zhang CLK_I2S3_SEL_MASK | CLK_I2S3_SRC_SEL_MASK |
250426663c2dSElaine Zhang CLK_I2S3_SRC_DIV_MASK,
250526663c2dSElaine Zhang (clk_src << CLK_I2S3_SRC_SEL_SHIFT) |
250626663c2dSElaine Zhang (i2s_src << CLK_I2S3_SEL_SHIFT) |
250726663c2dSElaine Zhang ((div - 1) << CLK_I2S3_SRC_DIV_SHIFT));
250826663c2dSElaine Zhang if (m && n) {
250926663c2dSElaine Zhang val = m << CLK_I2S3_FRAC_NUMERATOR_SHIFT | n;
251026663c2dSElaine Zhang writel(val, &cru->clksel_con[reg + 1]);
251126663c2dSElaine Zhang }
251226663c2dSElaine Zhang return rk3568_i2s3_get_rate(priv, clk_id);
251326663c2dSElaine Zhang }
251426663c2dSElaine Zhang
2515f6d27794Szhangqing #endif
2516fdd74c32SElaine Zhang
rk3568_clk_get_rate(struct clk * clk)2517417bebc4SElaine Zhang static ulong rk3568_clk_get_rate(struct clk *clk)
2518417bebc4SElaine Zhang {
2519417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2520417bebc4SElaine Zhang ulong rate = 0;
2521417bebc4SElaine Zhang
2522417bebc4SElaine Zhang if (!priv->gpll_hz) {
2523417bebc4SElaine Zhang printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
2524417bebc4SElaine Zhang return -ENOENT;
2525417bebc4SElaine Zhang }
2526417bebc4SElaine Zhang
2527417bebc4SElaine Zhang switch (clk->id) {
2528417bebc4SElaine Zhang case PLL_APLL:
2529417bebc4SElaine Zhang case ARMCLK:
2530417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[APLL], priv->cru,
2531417bebc4SElaine Zhang APLL);
2532417bebc4SElaine Zhang break;
2533417bebc4SElaine Zhang case PLL_CPLL:
2534417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[CPLL], priv->cru,
2535417bebc4SElaine Zhang CPLL);
2536417bebc4SElaine Zhang break;
2537417bebc4SElaine Zhang case PLL_GPLL:
2538417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[GPLL], priv->cru,
2539417bebc4SElaine Zhang GPLL);
2540417bebc4SElaine Zhang break;
2541417bebc4SElaine Zhang case PLL_NPLL:
2542417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[NPLL], priv->cru,
2543417bebc4SElaine Zhang NPLL);
2544417bebc4SElaine Zhang break;
2545417bebc4SElaine Zhang case PLL_VPLL:
2546417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL], priv->cru,
2547417bebc4SElaine Zhang VPLL);
2548417bebc4SElaine Zhang break;
2549417bebc4SElaine Zhang case PLL_DPLL:
2550417bebc4SElaine Zhang rate = rockchip_pll_get_rate(&rk3568_pll_clks[DPLL], priv->cru,
2551417bebc4SElaine Zhang DPLL);
2552417bebc4SElaine Zhang break;
2553417bebc4SElaine Zhang case ACLK_BUS:
2554417bebc4SElaine Zhang case PCLK_BUS:
25556c0e8ad8SElaine Zhang case PCLK_WDT_NS:
2556417bebc4SElaine Zhang rate = rk3568_bus_get_clk(priv, clk->id);
2557417bebc4SElaine Zhang break;
2558417bebc4SElaine Zhang case ACLK_PERIMID:
2559417bebc4SElaine Zhang case HCLK_PERIMID:
2560417bebc4SElaine Zhang rate = rk3568_perimid_get_clk(priv, clk->id);
2561417bebc4SElaine Zhang break;
2562417bebc4SElaine Zhang case ACLK_TOP_HIGH:
2563417bebc4SElaine Zhang case ACLK_TOP_LOW:
2564417bebc4SElaine Zhang case HCLK_TOP:
2565417bebc4SElaine Zhang case PCLK_TOP:
2566417bebc4SElaine Zhang rate = rk3568_top_get_clk(priv, clk->id);
2567417bebc4SElaine Zhang break;
2568417bebc4SElaine Zhang case CLK_I2C1:
2569417bebc4SElaine Zhang case CLK_I2C2:
2570417bebc4SElaine Zhang case CLK_I2C3:
2571417bebc4SElaine Zhang case CLK_I2C4:
2572417bebc4SElaine Zhang case CLK_I2C5:
2573417bebc4SElaine Zhang rate = rk3568_i2c_get_clk(priv, clk->id);
2574417bebc4SElaine Zhang break;
2575417bebc4SElaine Zhang case CLK_SPI0:
2576417bebc4SElaine Zhang case CLK_SPI1:
2577417bebc4SElaine Zhang case CLK_SPI2:
2578417bebc4SElaine Zhang case CLK_SPI3:
2579417bebc4SElaine Zhang rate = rk3568_spi_get_clk(priv, clk->id);
2580417bebc4SElaine Zhang break;
2581417bebc4SElaine Zhang case CLK_PWM1:
2582417bebc4SElaine Zhang case CLK_PWM2:
2583417bebc4SElaine Zhang case CLK_PWM3:
2584417bebc4SElaine Zhang rate = rk3568_pwm_get_clk(priv, clk->id);
2585417bebc4SElaine Zhang break;
2586417bebc4SElaine Zhang case CLK_SARADC:
2587417bebc4SElaine Zhang case CLK_TSADC_TSEN:
2588417bebc4SElaine Zhang case CLK_TSADC:
2589417bebc4SElaine Zhang rate = rk3568_adc_get_clk(priv, clk->id);
2590417bebc4SElaine Zhang break;
259177e56285SJason Zhu case HCLK_SDMMC0:
2592417bebc4SElaine Zhang case CLK_SDMMC0:
2593417bebc4SElaine Zhang case CLK_SDMMC1:
2594417bebc4SElaine Zhang case CLK_SDMMC2:
2595417bebc4SElaine Zhang rate = rk3568_sdmmc_get_clk(priv, clk->id);
2596417bebc4SElaine Zhang break;
2597417bebc4SElaine Zhang case SCLK_SFC:
2598417bebc4SElaine Zhang rate = rk3568_sfc_get_clk(priv);
2599417bebc4SElaine Zhang break;
2600417bebc4SElaine Zhang case NCLK_NANDC:
2601417bebc4SElaine Zhang rate = rk3568_nand_get_clk(priv);
2602417bebc4SElaine Zhang break;
2603417bebc4SElaine Zhang case CCLK_EMMC:
2604417bebc4SElaine Zhang rate = rk3568_emmc_get_clk(priv);
2605417bebc4SElaine Zhang break;
260675c04b2aSElaine Zhang case BCLK_EMMC:
260775c04b2aSElaine Zhang rate = rk3568_emmc_get_bclk(priv);
260875c04b2aSElaine Zhang break;
260975c04b2aSElaine Zhang case TCLK_EMMC:
261075c04b2aSElaine Zhang rate = OSC_HZ;
261175c04b2aSElaine Zhang break;
2612f6d27794Szhangqing #ifndef CONFIG_SPL_BUILD
2613417bebc4SElaine Zhang case ACLK_VOP:
2614417bebc4SElaine Zhang rate = rk3568_aclk_vop_get_clk(priv);
2615417bebc4SElaine Zhang break;
2616417bebc4SElaine Zhang case DCLK_VOP0:
2617417bebc4SElaine Zhang case DCLK_VOP1:
2618417bebc4SElaine Zhang case DCLK_VOP2:
2619417bebc4SElaine Zhang rate = rk3568_dclk_vop_get_clk(priv, clk->id);
2620417bebc4SElaine Zhang break;
2621417bebc4SElaine Zhang case SCLK_GMAC0:
2622417bebc4SElaine Zhang case CLK_MAC0_2TOP:
2623417bebc4SElaine Zhang case CLK_MAC0_REFOUT:
2624417bebc4SElaine Zhang rate = rk3568_gmac_src_get_clk(priv, 0);
2625417bebc4SElaine Zhang break;
2626417bebc4SElaine Zhang case CLK_MAC0_OUT:
2627417bebc4SElaine Zhang rate = rk3568_gmac_out_get_clk(priv, 0);
2628417bebc4SElaine Zhang break;
2629417bebc4SElaine Zhang case CLK_GMAC0_PTP_REF:
2630417bebc4SElaine Zhang rate = rk3568_gmac_ptp_ref_get_clk(priv, 0);
2631417bebc4SElaine Zhang break;
2632417bebc4SElaine Zhang case SCLK_GMAC1:
2633417bebc4SElaine Zhang case CLK_MAC1_2TOP:
2634417bebc4SElaine Zhang case CLK_MAC1_REFOUT:
2635417bebc4SElaine Zhang rate = rk3568_gmac_src_get_clk(priv, 1);
2636417bebc4SElaine Zhang break;
2637417bebc4SElaine Zhang case CLK_MAC1_OUT:
2638417bebc4SElaine Zhang rate = rk3568_gmac_out_get_clk(priv, 1);
2639417bebc4SElaine Zhang break;
2640417bebc4SElaine Zhang case CLK_GMAC1_PTP_REF:
2641417bebc4SElaine Zhang rate = rk3568_gmac_ptp_ref_get_clk(priv, 1);
2642417bebc4SElaine Zhang break;
2643fdd74c32SElaine Zhang case DCLK_EBC:
2644f6d27794Szhangqing rate = rk3568_ebc_get_clk(priv);
2645fdd74c32SElaine Zhang break;
26460a04fb50SElaine Zhang case ACLK_RKVDEC_PRE:
26470a04fb50SElaine Zhang case ACLK_RKVDEC:
26480a04fb50SElaine Zhang case CLK_RKVDEC_CORE:
26490a04fb50SElaine Zhang rate = rk3568_rkvdec_get_clk(priv, clk->id);
26500a04fb50SElaine Zhang break;
26516c0e8ad8SElaine Zhang case TCLK_WDT_NS:
26526c0e8ad8SElaine Zhang rate = OSC_HZ;
26536c0e8ad8SElaine Zhang break;
265498d806deSJonas Karlman case I2S3_MCLKOUT_RX:
265598d806deSJonas Karlman case I2S3_MCLKOUT_TX:
265698d806deSJonas Karlman case MCLK_I2S3_2CH_RX:
265798d806deSJonas Karlman case MCLK_I2S3_2CH_TX:
265898d806deSJonas Karlman case I2S3_MCLKOUT:
265998d806deSJonas Karlman rate = rk3568_i2s3_get_rate(priv, clk->id);
266098d806deSJonas Karlman break;
266198d806deSJonas Karlman #endif
2662563d12f2SElaine Zhang case SCLK_UART1:
2663563d12f2SElaine Zhang case SCLK_UART2:
2664563d12f2SElaine Zhang case SCLK_UART3:
2665563d12f2SElaine Zhang case SCLK_UART4:
2666563d12f2SElaine Zhang case SCLK_UART5:
2667563d12f2SElaine Zhang case SCLK_UART6:
2668563d12f2SElaine Zhang case SCLK_UART7:
2669563d12f2SElaine Zhang case SCLK_UART8:
2670563d12f2SElaine Zhang case SCLK_UART9:
2671563d12f2SElaine Zhang rate = rk3568_uart_get_rate(priv, clk->id);
2672563d12f2SElaine Zhang break;
2673417bebc4SElaine Zhang case ACLK_SECURE_FLASH:
2674417bebc4SElaine Zhang case ACLK_CRYPTO_NS:
2675417bebc4SElaine Zhang case HCLK_SECURE_FLASH:
2676417bebc4SElaine Zhang case HCLK_CRYPTO_NS:
2677417bebc4SElaine Zhang case CLK_CRYPTO_NS_RNG:
2678417bebc4SElaine Zhang case CLK_CRYPTO_NS_CORE:
2679417bebc4SElaine Zhang case CLK_CRYPTO_NS_PKA:
2680417bebc4SElaine Zhang rate = rk3568_crypto_get_rate(priv, clk->id);
2681417bebc4SElaine Zhang break;
2682f6d27794Szhangqing case CPLL_500M:
2683f6d27794Szhangqing case CPLL_333M:
2684f6d27794Szhangqing case CPLL_250M:
2685f6d27794Szhangqing case CPLL_125M:
2686f6d27794Szhangqing case CPLL_100M:
2687f6d27794Szhangqing case CPLL_62P5M:
2688f6d27794Szhangqing case CPLL_50M:
2689f6d27794Szhangqing case CPLL_25M:
2690f6d27794Szhangqing rate = rk3568_cpll_div_get_rate(priv, clk->id);
2691f6d27794Szhangqing break;
2692417bebc4SElaine Zhang default:
2693417bebc4SElaine Zhang return -ENOENT;
2694417bebc4SElaine Zhang }
2695417bebc4SElaine Zhang
2696417bebc4SElaine Zhang return rate;
2697417bebc4SElaine Zhang };
2698417bebc4SElaine Zhang
rk3568_clk_set_rate(struct clk * clk,ulong rate)2699417bebc4SElaine Zhang static ulong rk3568_clk_set_rate(struct clk *clk, ulong rate)
2700417bebc4SElaine Zhang {
2701417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2702417bebc4SElaine Zhang ulong ret = 0;
2703417bebc4SElaine Zhang
2704417bebc4SElaine Zhang if (!priv->gpll_hz) {
2705417bebc4SElaine Zhang printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
2706417bebc4SElaine Zhang return -ENOENT;
2707417bebc4SElaine Zhang }
2708417bebc4SElaine Zhang
2709417bebc4SElaine Zhang switch (clk->id) {
2710417bebc4SElaine Zhang case PLL_APLL:
2711417bebc4SElaine Zhang case ARMCLK:
2712417bebc4SElaine Zhang if (priv->armclk_hz)
2713417bebc4SElaine Zhang rk3568_armclk_set_clk(priv, rate);
2714417bebc4SElaine Zhang priv->armclk_hz = rate;
2715417bebc4SElaine Zhang break;
2716417bebc4SElaine Zhang case PLL_CPLL:
2717417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[CPLL], priv->cru,
2718417bebc4SElaine Zhang CPLL, rate);
2719f6d27794Szhangqing priv->cpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[CPLL],
2720f6d27794Szhangqing priv->cru, CPLL);
2721417bebc4SElaine Zhang break;
2722417bebc4SElaine Zhang case PLL_GPLL:
2723417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[GPLL], priv->cru,
2724417bebc4SElaine Zhang GPLL, rate);
2725f6d27794Szhangqing priv->gpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[GPLL],
2726f6d27794Szhangqing priv->cru, GPLL);
2727417bebc4SElaine Zhang break;
2728417bebc4SElaine Zhang case PLL_NPLL:
2729417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[NPLL], priv->cru,
2730417bebc4SElaine Zhang NPLL, rate);
2731417bebc4SElaine Zhang break;
2732417bebc4SElaine Zhang case PLL_VPLL:
2733417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[VPLL], priv->cru,
2734417bebc4SElaine Zhang VPLL, rate);
2735f6d27794Szhangqing priv->vpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL],
2736f6d27794Szhangqing priv->cru,
2737f6d27794Szhangqing VPLL);
2738417bebc4SElaine Zhang break;
2739417bebc4SElaine Zhang case ACLK_BUS:
2740417bebc4SElaine Zhang case PCLK_BUS:
27416c0e8ad8SElaine Zhang case PCLK_WDT_NS:
2742aa003068SElaine Zhang ret = rk3568_bus_set_clk(priv, clk->id, rate);
2743417bebc4SElaine Zhang break;
2744417bebc4SElaine Zhang case ACLK_PERIMID:
2745417bebc4SElaine Zhang case HCLK_PERIMID:
2746aa003068SElaine Zhang ret = rk3568_perimid_set_clk(priv, clk->id, rate);
2747417bebc4SElaine Zhang break;
2748417bebc4SElaine Zhang case ACLK_TOP_HIGH:
2749417bebc4SElaine Zhang case ACLK_TOP_LOW:
2750417bebc4SElaine Zhang case HCLK_TOP:
2751417bebc4SElaine Zhang case PCLK_TOP:
2752aa003068SElaine Zhang ret = rk3568_top_set_clk(priv, clk->id, rate);
2753417bebc4SElaine Zhang break;
2754417bebc4SElaine Zhang case CLK_I2C1:
2755417bebc4SElaine Zhang case CLK_I2C2:
2756417bebc4SElaine Zhang case CLK_I2C3:
2757417bebc4SElaine Zhang case CLK_I2C4:
2758417bebc4SElaine Zhang case CLK_I2C5:
2759aa003068SElaine Zhang ret = rk3568_i2c_set_clk(priv, clk->id, rate);
2760417bebc4SElaine Zhang break;
2761417bebc4SElaine Zhang case CLK_SPI0:
2762417bebc4SElaine Zhang case CLK_SPI1:
2763417bebc4SElaine Zhang case CLK_SPI2:
2764417bebc4SElaine Zhang case CLK_SPI3:
2765aa003068SElaine Zhang ret = rk3568_spi_set_clk(priv, clk->id, rate);
2766417bebc4SElaine Zhang break;
2767417bebc4SElaine Zhang case CLK_PWM1:
2768417bebc4SElaine Zhang case CLK_PWM2:
2769417bebc4SElaine Zhang case CLK_PWM3:
2770aa003068SElaine Zhang ret = rk3568_pwm_set_clk(priv, clk->id, rate);
2771417bebc4SElaine Zhang break;
2772417bebc4SElaine Zhang case CLK_SARADC:
2773417bebc4SElaine Zhang case CLK_TSADC_TSEN:
2774417bebc4SElaine Zhang case CLK_TSADC:
2775aa003068SElaine Zhang ret = rk3568_adc_set_clk(priv, clk->id, rate);
2776417bebc4SElaine Zhang break;
277777e56285SJason Zhu case HCLK_SDMMC0:
2778417bebc4SElaine Zhang case CLK_SDMMC0:
2779417bebc4SElaine Zhang case CLK_SDMMC1:
2780417bebc4SElaine Zhang case CLK_SDMMC2:
2781aa003068SElaine Zhang ret = rk3568_sdmmc_set_clk(priv, clk->id, rate);
2782417bebc4SElaine Zhang break;
2783417bebc4SElaine Zhang case SCLK_SFC:
2784aa003068SElaine Zhang ret = rk3568_sfc_set_clk(priv, rate);
2785417bebc4SElaine Zhang break;
2786417bebc4SElaine Zhang case NCLK_NANDC:
2787aa003068SElaine Zhang ret = rk3568_nand_set_clk(priv, rate);
2788417bebc4SElaine Zhang break;
2789417bebc4SElaine Zhang case CCLK_EMMC:
2790aa003068SElaine Zhang ret = rk3568_emmc_set_clk(priv, rate);
2791417bebc4SElaine Zhang break;
279275c04b2aSElaine Zhang case BCLK_EMMC:
279375c04b2aSElaine Zhang ret = rk3568_emmc_set_bclk(priv, rate);
279475c04b2aSElaine Zhang break;
279575c04b2aSElaine Zhang case TCLK_EMMC:
279675c04b2aSElaine Zhang ret = OSC_HZ;
279775c04b2aSElaine Zhang break;
2798f6d27794Szhangqing #ifndef CONFIG_SPL_BUILD
2799417bebc4SElaine Zhang case ACLK_VOP:
2800aa003068SElaine Zhang ret = rk3568_aclk_vop_set_clk(priv, rate);
2801417bebc4SElaine Zhang break;
2802417bebc4SElaine Zhang case DCLK_VOP0:
2803417bebc4SElaine Zhang case DCLK_VOP1:
2804417bebc4SElaine Zhang case DCLK_VOP2:
2805aa003068SElaine Zhang ret = rk3568_dclk_vop_set_clk(priv, clk->id, rate);
2806417bebc4SElaine Zhang break;
2807417bebc4SElaine Zhang case SCLK_GMAC0:
2808417bebc4SElaine Zhang case CLK_MAC0_2TOP:
2809417bebc4SElaine Zhang case CLK_MAC0_REFOUT:
2810aa003068SElaine Zhang ret = rk3568_gmac_src_set_clk(priv, 0, rate);
2811417bebc4SElaine Zhang break;
2812417bebc4SElaine Zhang case CLK_MAC0_OUT:
2813aa003068SElaine Zhang ret = rk3568_gmac_out_set_clk(priv, 0, rate);
2814417bebc4SElaine Zhang break;
2815417bebc4SElaine Zhang case SCLK_GMAC0_RX_TX:
2816aa003068SElaine Zhang ret = rk3568_gmac_tx_rx_set_clk(priv, 0, rate);
2817417bebc4SElaine Zhang break;
2818417bebc4SElaine Zhang case CLK_GMAC0_PTP_REF:
2819aa003068SElaine Zhang ret = rk3568_gmac_ptp_ref_set_clk(priv, 0, rate);
2820417bebc4SElaine Zhang break;
2821417bebc4SElaine Zhang case SCLK_GMAC1:
2822417bebc4SElaine Zhang case CLK_MAC1_2TOP:
2823417bebc4SElaine Zhang case CLK_MAC1_REFOUT:
2824aa003068SElaine Zhang ret = rk3568_gmac_src_set_clk(priv, 1, rate);
2825417bebc4SElaine Zhang break;
2826417bebc4SElaine Zhang case CLK_MAC1_OUT:
2827aa003068SElaine Zhang ret = rk3568_gmac_out_set_clk(priv, 1, rate);
2828417bebc4SElaine Zhang break;
2829417bebc4SElaine Zhang case SCLK_GMAC1_RX_TX:
2830aa003068SElaine Zhang ret = rk3568_gmac_tx_rx_set_clk(priv, 1, rate);
2831417bebc4SElaine Zhang break;
2832417bebc4SElaine Zhang case CLK_GMAC1_PTP_REF:
2833aa003068SElaine Zhang ret = rk3568_gmac_ptp_ref_set_clk(priv, 1, rate);
2834417bebc4SElaine Zhang break;
2835fdd74c32SElaine Zhang case DCLK_EBC:
2836aa003068SElaine Zhang ret = rk3568_ebc_set_clk(priv, rate);
2837fdd74c32SElaine Zhang break;
28380a04fb50SElaine Zhang case ACLK_RKVDEC_PRE:
28390a04fb50SElaine Zhang case ACLK_RKVDEC:
28400a04fb50SElaine Zhang case CLK_RKVDEC_CORE:
2841aa003068SElaine Zhang ret = rk3568_rkvdec_set_clk(priv, clk->id, rate);
28420a04fb50SElaine Zhang break;
28436c0e8ad8SElaine Zhang case TCLK_WDT_NS:
28446c0e8ad8SElaine Zhang ret = OSC_HZ;
28456c0e8ad8SElaine Zhang break;
284698d806deSJonas Karlman case I2S3_MCLKOUT_RX:
284798d806deSJonas Karlman case I2S3_MCLKOUT_TX:
284898d806deSJonas Karlman case MCLK_I2S3_2CH_RX:
284998d806deSJonas Karlman case MCLK_I2S3_2CH_TX:
285098d806deSJonas Karlman case I2S3_MCLKOUT:
285198d806deSJonas Karlman ret = rk3568_i2s3_set_rate(priv, clk->id, rate);
285298d806deSJonas Karlman break;
285398d806deSJonas Karlman #endif
2854563d12f2SElaine Zhang case SCLK_UART1:
2855563d12f2SElaine Zhang case SCLK_UART2:
2856563d12f2SElaine Zhang case SCLK_UART3:
2857563d12f2SElaine Zhang case SCLK_UART4:
2858563d12f2SElaine Zhang case SCLK_UART5:
2859563d12f2SElaine Zhang case SCLK_UART6:
2860563d12f2SElaine Zhang case SCLK_UART7:
2861563d12f2SElaine Zhang case SCLK_UART8:
2862563d12f2SElaine Zhang case SCLK_UART9:
2863563d12f2SElaine Zhang ret = rk3568_uart_set_rate(priv, clk->id, rate);
2864563d12f2SElaine Zhang break;
2865417bebc4SElaine Zhang case ACLK_SECURE_FLASH:
2866417bebc4SElaine Zhang case ACLK_CRYPTO_NS:
2867417bebc4SElaine Zhang case HCLK_SECURE_FLASH:
2868417bebc4SElaine Zhang case HCLK_CRYPTO_NS:
2869417bebc4SElaine Zhang case CLK_CRYPTO_NS_RNG:
2870417bebc4SElaine Zhang case CLK_CRYPTO_NS_CORE:
2871417bebc4SElaine Zhang case CLK_CRYPTO_NS_PKA:
2872aa003068SElaine Zhang ret = rk3568_crypto_set_rate(priv, clk->id, rate);
2873417bebc4SElaine Zhang break;
2874f6d27794Szhangqing case CPLL_500M:
2875f6d27794Szhangqing case CPLL_333M:
2876f6d27794Szhangqing case CPLL_250M:
2877f6d27794Szhangqing case CPLL_125M:
2878f6d27794Szhangqing case CPLL_100M:
2879f6d27794Szhangqing case CPLL_62P5M:
2880f6d27794Szhangqing case CPLL_50M:
2881f6d27794Szhangqing case CPLL_25M:
2882aa003068SElaine Zhang ret = rk3568_cpll_div_set_rate(priv, clk->id, rate);
2883f6d27794Szhangqing break;
2884417bebc4SElaine Zhang default:
2885417bebc4SElaine Zhang return -ENOENT;
2886417bebc4SElaine Zhang }
2887417bebc4SElaine Zhang
2888417bebc4SElaine Zhang return ret;
2889417bebc4SElaine Zhang };
2890417bebc4SElaine Zhang
2891417bebc4SElaine Zhang #define ROCKCHIP_MMC_DELAY_SEL BIT(10)
2892417bebc4SElaine Zhang #define ROCKCHIP_MMC_DEGREE_MASK 0x3
2893417bebc4SElaine Zhang #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
2894417bebc4SElaine Zhang #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
2895417bebc4SElaine Zhang
2896417bebc4SElaine Zhang #define PSECS_PER_SEC 1000000000000LL
2897417bebc4SElaine Zhang /*
2898417bebc4SElaine Zhang * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
2899417bebc4SElaine Zhang * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
2900417bebc4SElaine Zhang */
2901417bebc4SElaine Zhang #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
2902417bebc4SElaine Zhang
rk3568_mmc_get_phase(struct clk * clk)2903417bebc4SElaine Zhang int rk3568_mmc_get_phase(struct clk *clk)
2904417bebc4SElaine Zhang {
2905417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2906417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
2907417bebc4SElaine Zhang u32 raw_value, delay_num;
2908417bebc4SElaine Zhang u16 degrees = 0;
2909417bebc4SElaine Zhang ulong rate;
2910417bebc4SElaine Zhang
2911417bebc4SElaine Zhang rate = rk3568_clk_get_rate(clk);
2912417bebc4SElaine Zhang if (rate < 0)
2913417bebc4SElaine Zhang return rate;
2914417bebc4SElaine Zhang
2915417bebc4SElaine Zhang if (clk->id == SCLK_EMMC_SAMPLE)
2916417bebc4SElaine Zhang raw_value = readl(&cru->emmc_con[1]);
2917417bebc4SElaine Zhang else if (clk->id == SCLK_SDMMC0_SAMPLE)
2918417bebc4SElaine Zhang raw_value = readl(&cru->sdmmc0_con[1]);
2919417bebc4SElaine Zhang else if (clk->id == SCLK_SDMMC1_SAMPLE)
2920417bebc4SElaine Zhang raw_value = readl(&cru->sdmmc1_con[1]);
2921417bebc4SElaine Zhang else
2922417bebc4SElaine Zhang raw_value = readl(&cru->sdmmc2_con[1]);
2923417bebc4SElaine Zhang
2924417bebc4SElaine Zhang raw_value >>= 1;
2925417bebc4SElaine Zhang degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
2926417bebc4SElaine Zhang
2927417bebc4SElaine Zhang if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
2928417bebc4SElaine Zhang /* degrees/delaynum * 10000 */
2929417bebc4SElaine Zhang unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
2930417bebc4SElaine Zhang 36 * (rate / 1000000);
2931417bebc4SElaine Zhang
2932417bebc4SElaine Zhang delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
2933417bebc4SElaine Zhang delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
2934417bebc4SElaine Zhang degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
2935417bebc4SElaine Zhang }
2936417bebc4SElaine Zhang
2937417bebc4SElaine Zhang return degrees % 360;
2938417bebc4SElaine Zhang }
2939417bebc4SElaine Zhang
rk3568_mmc_set_phase(struct clk * clk,u32 degrees)2940417bebc4SElaine Zhang int rk3568_mmc_set_phase(struct clk *clk, u32 degrees)
2941417bebc4SElaine Zhang {
2942417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2943417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
2944417bebc4SElaine Zhang u8 nineties, remainder, delay_num;
2945417bebc4SElaine Zhang u32 raw_value, delay;
2946417bebc4SElaine Zhang ulong rate;
2947417bebc4SElaine Zhang
2948417bebc4SElaine Zhang rate = rk3568_clk_get_rate(clk);
2949417bebc4SElaine Zhang if (rate < 0)
2950417bebc4SElaine Zhang return rate;
2951417bebc4SElaine Zhang
2952417bebc4SElaine Zhang nineties = degrees / 90;
2953417bebc4SElaine Zhang remainder = (degrees % 90);
2954417bebc4SElaine Zhang
2955417bebc4SElaine Zhang /*
2956417bebc4SElaine Zhang * Convert to delay; do a little extra work to make sure we
2957417bebc4SElaine Zhang * don't overflow 32-bit / 64-bit numbers.
2958417bebc4SElaine Zhang */
2959417bebc4SElaine Zhang delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
2960417bebc4SElaine Zhang delay *= remainder;
2961417bebc4SElaine Zhang delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
2962417bebc4SElaine Zhang (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
2963417bebc4SElaine Zhang
2964417bebc4SElaine Zhang delay_num = (u8)min_t(u32, delay, 255);
2965417bebc4SElaine Zhang
2966417bebc4SElaine Zhang raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
2967417bebc4SElaine Zhang raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
2968417bebc4SElaine Zhang raw_value |= nineties;
2969417bebc4SElaine Zhang
2970417bebc4SElaine Zhang raw_value <<= 1;
2971417bebc4SElaine Zhang if (clk->id == SCLK_EMMC_SAMPLE)
2972417bebc4SElaine Zhang writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
2973417bebc4SElaine Zhang else if (clk->id == SCLK_SDMMC0_SAMPLE)
2974417bebc4SElaine Zhang writel(raw_value | 0xffff0000, &cru->sdmmc0_con[1]);
2975417bebc4SElaine Zhang else if (clk->id == SCLK_SDMMC1_SAMPLE)
2976417bebc4SElaine Zhang writel(raw_value | 0xffff0000, &cru->sdmmc1_con[1]);
2977417bebc4SElaine Zhang else
2978417bebc4SElaine Zhang writel(raw_value | 0xffff0000, &cru->sdmmc2_con[1]);
2979417bebc4SElaine Zhang
2980417bebc4SElaine Zhang debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
2981417bebc4SElaine Zhang degrees, delay_num, raw_value, rk3568_mmc_get_phase(clk));
2982417bebc4SElaine Zhang
2983417bebc4SElaine Zhang return 0;
2984417bebc4SElaine Zhang }
2985417bebc4SElaine Zhang
rk3568_clk_get_phase(struct clk * clk)2986417bebc4SElaine Zhang static int rk3568_clk_get_phase(struct clk *clk)
2987417bebc4SElaine Zhang {
2988417bebc4SElaine Zhang int ret;
2989417bebc4SElaine Zhang
2990417bebc4SElaine Zhang debug("%s %ld\n", __func__, clk->id);
2991417bebc4SElaine Zhang switch (clk->id) {
2992417bebc4SElaine Zhang case SCLK_EMMC_SAMPLE:
2993417bebc4SElaine Zhang case SCLK_SDMMC0_SAMPLE:
2994417bebc4SElaine Zhang case SCLK_SDMMC1_SAMPLE:
2995417bebc4SElaine Zhang case SCLK_SDMMC2_SAMPLE:
2996417bebc4SElaine Zhang ret = rk3568_mmc_get_phase(clk);
2997417bebc4SElaine Zhang break;
2998417bebc4SElaine Zhang default:
2999417bebc4SElaine Zhang return -ENOENT;
3000417bebc4SElaine Zhang }
3001417bebc4SElaine Zhang
3002417bebc4SElaine Zhang return ret;
3003417bebc4SElaine Zhang }
3004417bebc4SElaine Zhang
rk3568_clk_set_phase(struct clk * clk,int degrees)3005417bebc4SElaine Zhang static int rk3568_clk_set_phase(struct clk *clk, int degrees)
3006417bebc4SElaine Zhang {
3007417bebc4SElaine Zhang int ret;
3008417bebc4SElaine Zhang
3009417bebc4SElaine Zhang debug("%s %ld\n", __func__, clk->id);
3010417bebc4SElaine Zhang switch (clk->id) {
3011417bebc4SElaine Zhang case SCLK_EMMC_SAMPLE:
3012417bebc4SElaine Zhang case SCLK_SDMMC0_SAMPLE:
3013417bebc4SElaine Zhang case SCLK_SDMMC1_SAMPLE:
3014417bebc4SElaine Zhang case SCLK_SDMMC2_SAMPLE:
3015417bebc4SElaine Zhang ret = rk3568_mmc_set_phase(clk, degrees);
3016417bebc4SElaine Zhang break;
3017417bebc4SElaine Zhang default:
3018417bebc4SElaine Zhang return -ENOENT;
3019417bebc4SElaine Zhang }
3020417bebc4SElaine Zhang
3021417bebc4SElaine Zhang return ret;
3022417bebc4SElaine Zhang }
3023417bebc4SElaine Zhang
3024417bebc4SElaine Zhang #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
rk3568_gmac0_src_set_parent(struct clk * clk,struct clk * parent)3025417bebc4SElaine Zhang static int rk3568_gmac0_src_set_parent(struct clk *clk, struct clk *parent)
3026417bebc4SElaine Zhang {
3027417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
3028417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
3029417bebc4SElaine Zhang
3030417bebc4SElaine Zhang if (parent->id == CLK_MAC0_2TOP)
3031417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31],
3032417bebc4SElaine Zhang RMII0_EXTCLK_SEL_MASK,
3033417bebc4SElaine Zhang RMII0_EXTCLK_SEL_MAC0_TOP <<
3034417bebc4SElaine Zhang RMII0_EXTCLK_SEL_SHIFT);
3035417bebc4SElaine Zhang else
3036417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31],
3037417bebc4SElaine Zhang RMII0_EXTCLK_SEL_MASK,
3038417bebc4SElaine Zhang RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT);
3039417bebc4SElaine Zhang return 0;
3040417bebc4SElaine Zhang }
3041417bebc4SElaine Zhang
rk3568_gmac1_src_set_parent(struct clk * clk,struct clk * parent)3042417bebc4SElaine Zhang static int rk3568_gmac1_src_set_parent(struct clk *clk, struct clk *parent)
3043417bebc4SElaine Zhang {
3044417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
3045417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
3046417bebc4SElaine Zhang
3047417bebc4SElaine Zhang if (parent->id == CLK_MAC1_2TOP)
3048417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[33],
3049417bebc4SElaine Zhang RMII0_EXTCLK_SEL_MASK,
3050417bebc4SElaine Zhang RMII0_EXTCLK_SEL_MAC0_TOP <<
3051417bebc4SElaine Zhang RMII0_EXTCLK_SEL_SHIFT);
3052417bebc4SElaine Zhang else
3053417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[33],
3054417bebc4SElaine Zhang RMII0_EXTCLK_SEL_MASK,
3055417bebc4SElaine Zhang RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT);
3056417bebc4SElaine Zhang return 0;
3057417bebc4SElaine Zhang }
3058417bebc4SElaine Zhang
rk3568_gmac0_tx_rx_set_parent(struct clk * clk,struct clk * parent)3059417bebc4SElaine Zhang static int rk3568_gmac0_tx_rx_set_parent(struct clk *clk, struct clk *parent)
3060417bebc4SElaine Zhang {
3061417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
3062417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
3063417bebc4SElaine Zhang
3064417bebc4SElaine Zhang if (parent->id == SCLK_GMAC0_RGMII_SPEED)
3065417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31],
3066417bebc4SElaine Zhang RMII0_MODE_MASK,
3067417bebc4SElaine Zhang RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT);
3068417bebc4SElaine Zhang else if (parent->id == SCLK_GMAC0_RMII_SPEED)
3069417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31],
3070417bebc4SElaine Zhang RMII0_MODE_MASK,
3071417bebc4SElaine Zhang RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT);
3072417bebc4SElaine Zhang else
3073417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[31],
3074417bebc4SElaine Zhang RMII0_MODE_MASK,
3075417bebc4SElaine Zhang RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT);
3076417bebc4SElaine Zhang
3077417bebc4SElaine Zhang return 0;
3078417bebc4SElaine Zhang }
3079417bebc4SElaine Zhang
rk3568_gmac1_tx_rx_set_parent(struct clk * clk,struct clk * parent)3080417bebc4SElaine Zhang static int rk3568_gmac1_tx_rx_set_parent(struct clk *clk, struct clk *parent)
3081417bebc4SElaine Zhang {
3082417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
3083417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
3084417bebc4SElaine Zhang
3085417bebc4SElaine Zhang if (parent->id == SCLK_GMAC1_RGMII_SPEED)
3086417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[33],
3087417bebc4SElaine Zhang RMII0_MODE_MASK,
3088417bebc4SElaine Zhang RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT);
3089417bebc4SElaine Zhang else if (parent->id == SCLK_GMAC1_RMII_SPEED)
3090417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[33],
3091417bebc4SElaine Zhang RMII0_MODE_MASK,
3092417bebc4SElaine Zhang RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT);
3093417bebc4SElaine Zhang else
3094417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[33],
3095417bebc4SElaine Zhang RMII0_MODE_MASK,
3096417bebc4SElaine Zhang RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT);
3097417bebc4SElaine Zhang
3098417bebc4SElaine Zhang return 0;
3099417bebc4SElaine Zhang }
3100417bebc4SElaine Zhang
rk3568_dclk_vop_set_parent(struct clk * clk,struct clk * parent)3101417bebc4SElaine Zhang static int __maybe_unused rk3568_dclk_vop_set_parent(struct clk *clk,
3102417bebc4SElaine Zhang struct clk *parent)
3103417bebc4SElaine Zhang {
3104417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
3105417bebc4SElaine Zhang struct rk3568_cru *cru = priv->cru;
3106417bebc4SElaine Zhang u32 con_id;
3107417bebc4SElaine Zhang
3108417bebc4SElaine Zhang switch (clk->id) {
3109417bebc4SElaine Zhang case DCLK_VOP0:
3110417bebc4SElaine Zhang con_id = 39;
3111417bebc4SElaine Zhang break;
3112417bebc4SElaine Zhang case DCLK_VOP1:
3113417bebc4SElaine Zhang con_id = 40;
3114417bebc4SElaine Zhang break;
3115417bebc4SElaine Zhang case DCLK_VOP2:
3116417bebc4SElaine Zhang con_id = 41;
3117417bebc4SElaine Zhang break;
3118417bebc4SElaine Zhang default:
3119417bebc4SElaine Zhang return -EINVAL;
3120417bebc4SElaine Zhang }
3121417bebc4SElaine Zhang if (parent->id == PLL_VPLL) {
3122417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
3123417bebc4SElaine Zhang DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT);
312414d9ba56SElaine Zhang } else if (parent->id == PLL_HPLL) {
3125417bebc4SElaine Zhang rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
3126417bebc4SElaine Zhang DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT);
312714d9ba56SElaine Zhang } else if (parent->id == PLL_CPLL) {
312814d9ba56SElaine Zhang rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
312914d9ba56SElaine Zhang DCLK_VOP_SEL_CPLL << DCLK0_VOP_SEL_SHIFT);
313014d9ba56SElaine Zhang } else {
313114d9ba56SElaine Zhang rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
313214d9ba56SElaine Zhang DCLK_VOP_SEL_GPLL << DCLK0_VOP_SEL_SHIFT);
3133417bebc4SElaine Zhang }
3134417bebc4SElaine Zhang
3135417bebc4SElaine Zhang return 0;
3136417bebc4SElaine Zhang }
3137417bebc4SElaine Zhang
rk3568_rkvdec_set_parent(struct clk * clk,struct clk * parent)31380a04fb50SElaine Zhang static int __maybe_unused rk3568_rkvdec_set_parent(struct clk *clk,
31390a04fb50SElaine Zhang struct clk *parent)
31400a04fb50SElaine Zhang {
31410a04fb50SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
31420a04fb50SElaine Zhang struct rk3568_cru *cru = priv->cru;
31430a04fb50SElaine Zhang u32 con_id, mask, shift;
31440a04fb50SElaine Zhang
31450a04fb50SElaine Zhang switch (clk->id) {
31460a04fb50SElaine Zhang case ACLK_RKVDEC_PRE:
31470a04fb50SElaine Zhang con_id = 47;
31480a04fb50SElaine Zhang mask = ACLK_RKVDEC_SEL_MASK;
31490a04fb50SElaine Zhang shift = ACLK_RKVDEC_SEL_SHIFT;
31500a04fb50SElaine Zhang break;
31510a04fb50SElaine Zhang case CLK_RKVDEC_CORE:
31520a04fb50SElaine Zhang con_id = 49;
31530a04fb50SElaine Zhang mask = CLK_RKVDEC_CORE_SEL_MASK;
31540a04fb50SElaine Zhang shift = CLK_RKVDEC_CORE_SEL_SHIFT;
31550a04fb50SElaine Zhang break;
31560a04fb50SElaine Zhang default:
31570a04fb50SElaine Zhang return -EINVAL;
31580a04fb50SElaine Zhang }
31590a04fb50SElaine Zhang if (parent->id == PLL_CPLL) {
31600a04fb50SElaine Zhang rk_clrsetreg(&cru->clksel_con[con_id], mask,
31610a04fb50SElaine Zhang ACLK_RKVDEC_SEL_CPLL << shift);
31620a04fb50SElaine Zhang } else {
31630a04fb50SElaine Zhang rk_clrsetreg(&cru->clksel_con[con_id], mask,
31640a04fb50SElaine Zhang ACLK_RKVDEC_SEL_GPLL << shift);
31650a04fb50SElaine Zhang }
31660a04fb50SElaine Zhang
31670a04fb50SElaine Zhang return 0;
31680a04fb50SElaine Zhang }
31690a04fb50SElaine Zhang
rk3568_i2s3_set_parent(struct clk * clk,struct clk * parent)317026663c2dSElaine Zhang static int __maybe_unused rk3568_i2s3_set_parent(struct clk *clk,
317126663c2dSElaine Zhang struct clk *parent)
317226663c2dSElaine Zhang {
317326663c2dSElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
317426663c2dSElaine Zhang struct rk3568_grf *grf = priv->grf;
317526663c2dSElaine Zhang
317626663c2dSElaine Zhang switch (clk->id) {
317726663c2dSElaine Zhang case I2S3_MCLK_IOE:
317826663c2dSElaine Zhang if (parent->id == I2S3_MCLKOUT) {
317926663c2dSElaine Zhang rk_clrsetreg(&grf->soc_con2, I2S3_MCLK_IOE_SEL_MASK,
318026663c2dSElaine Zhang I2S3_MCLK_IOE_SEL_CLKOUT <<
318126663c2dSElaine Zhang I2S3_MCLK_IOE_SEL_SHIFT);
318226663c2dSElaine Zhang } else {
318326663c2dSElaine Zhang rk_clrsetreg(&grf->soc_con2, I2S3_MCLK_IOE_SEL_MASK,
318426663c2dSElaine Zhang I2S3_MCLK_IOE_SEL_CLKIN <<
318526663c2dSElaine Zhang I2S3_MCLK_IOE_SEL_SHIFT);
318626663c2dSElaine Zhang }
318726663c2dSElaine Zhang break;
318826663c2dSElaine Zhang case I2S3_MCLKOUT:
318926663c2dSElaine Zhang if (parent->id == I2S3_MCLKOUT_RX) {
319026663c2dSElaine Zhang rk_clrsetreg(&grf->soc_con2, I2S3_MCLKOUT_SEL_MASK,
319126663c2dSElaine Zhang I2S3_MCLKOUT_SEL_RX <<
319226663c2dSElaine Zhang I2S3_MCLKOUT_SEL_SHIFT);
319326663c2dSElaine Zhang } else {
319426663c2dSElaine Zhang rk_clrsetreg(&grf->soc_con2, I2S3_MCLKOUT_SEL_MASK,
319526663c2dSElaine Zhang I2S3_MCLKOUT_SEL_TX <<
319626663c2dSElaine Zhang I2S3_MCLKOUT_SEL_SHIFT);
319726663c2dSElaine Zhang }
319826663c2dSElaine Zhang break;
319926663c2dSElaine Zhang default:
320026663c2dSElaine Zhang return -EINVAL;
320126663c2dSElaine Zhang }
320226663c2dSElaine Zhang
320326663c2dSElaine Zhang return 0;
320426663c2dSElaine Zhang }
320526663c2dSElaine Zhang
rk3568_clk_set_parent(struct clk * clk,struct clk * parent)3206417bebc4SElaine Zhang static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
3207417bebc4SElaine Zhang {
3208417bebc4SElaine Zhang switch (clk->id) {
3209417bebc4SElaine Zhang case SCLK_GMAC0:
3210417bebc4SElaine Zhang return rk3568_gmac0_src_set_parent(clk, parent);
3211417bebc4SElaine Zhang case SCLK_GMAC1:
3212417bebc4SElaine Zhang return rk3568_gmac1_src_set_parent(clk, parent);
3213417bebc4SElaine Zhang case SCLK_GMAC0_RX_TX:
3214417bebc4SElaine Zhang return rk3568_gmac0_tx_rx_set_parent(clk, parent);
3215417bebc4SElaine Zhang case SCLK_GMAC1_RX_TX:
3216417bebc4SElaine Zhang return rk3568_gmac1_tx_rx_set_parent(clk, parent);
3217417bebc4SElaine Zhang case DCLK_VOP0:
3218417bebc4SElaine Zhang case DCLK_VOP1:
3219417bebc4SElaine Zhang case DCLK_VOP2:
3220417bebc4SElaine Zhang return rk3568_dclk_vop_set_parent(clk, parent);
32210a04fb50SElaine Zhang case ACLK_RKVDEC_PRE:
32220a04fb50SElaine Zhang case CLK_RKVDEC_CORE:
32230a04fb50SElaine Zhang return rk3568_rkvdec_set_parent(clk, parent);
322426663c2dSElaine Zhang case I2S3_MCLK_IOE:
322526663c2dSElaine Zhang case I2S3_MCLKOUT:
322626663c2dSElaine Zhang return rk3568_i2s3_set_parent(clk, parent);
322719191d3bSJonas Karlman case I2S1_MCLKOUT_TX:
322819191d3bSJonas Karlman case SCLK_GMAC0_RGMII_SPEED:
322919191d3bSJonas Karlman case SCLK_GMAC0_RMII_SPEED:
323019191d3bSJonas Karlman case SCLK_GMAC1_RGMII_SPEED:
323119191d3bSJonas Karlman case SCLK_GMAC1_RMII_SPEED:
3232417bebc4SElaine Zhang default:
3233417bebc4SElaine Zhang return -ENOENT;
3234417bebc4SElaine Zhang }
3235417bebc4SElaine Zhang
3236417bebc4SElaine Zhang return 0;
3237417bebc4SElaine Zhang }
3238417bebc4SElaine Zhang #endif
3239417bebc4SElaine Zhang
3240417bebc4SElaine Zhang static struct clk_ops rk3568_clk_ops = {
3241417bebc4SElaine Zhang .get_rate = rk3568_clk_get_rate,
3242417bebc4SElaine Zhang .set_rate = rk3568_clk_set_rate,
3243417bebc4SElaine Zhang .get_phase = rk3568_clk_get_phase,
3244417bebc4SElaine Zhang .set_phase = rk3568_clk_set_phase,
3245417bebc4SElaine Zhang #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
3246417bebc4SElaine Zhang .set_parent = rk3568_clk_set_parent,
3247417bebc4SElaine Zhang #endif
3248417bebc4SElaine Zhang };
3249417bebc4SElaine Zhang
rk3568_clk_init(struct rk3568_clk_priv * priv)3250417bebc4SElaine Zhang static void rk3568_clk_init(struct rk3568_clk_priv *priv)
3251417bebc4SElaine Zhang {
3252417bebc4SElaine Zhang int ret;
3253417bebc4SElaine Zhang
3254417bebc4SElaine Zhang priv->sync_kernel = false;
3255417bebc4SElaine Zhang if (!priv->armclk_enter_hz) {
3256417bebc4SElaine Zhang priv->armclk_enter_hz =
3257417bebc4SElaine Zhang rockchip_pll_get_rate(&rk3568_pll_clks[APLL],
3258417bebc4SElaine Zhang priv->cru, APLL);
3259417bebc4SElaine Zhang priv->armclk_init_hz = priv->armclk_enter_hz;
3260417bebc4SElaine Zhang }
3261417bebc4SElaine Zhang
3262417bebc4SElaine Zhang if (priv->armclk_init_hz != APLL_HZ) {
3263417bebc4SElaine Zhang ret = rk3568_armclk_set_clk(priv, APLL_HZ);
3264417bebc4SElaine Zhang if (!ret)
3265417bebc4SElaine Zhang priv->armclk_init_hz = APLL_HZ;
3266417bebc4SElaine Zhang }
3267417bebc4SElaine Zhang if (priv->cpll_hz != CPLL_HZ) {
3268417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[CPLL], priv->cru,
3269417bebc4SElaine Zhang CPLL, CPLL_HZ);
3270417bebc4SElaine Zhang if (!ret)
3271417bebc4SElaine Zhang priv->cpll_hz = CPLL_HZ;
3272417bebc4SElaine Zhang }
3273417bebc4SElaine Zhang if (priv->gpll_hz != GPLL_HZ) {
3274417bebc4SElaine Zhang ret = rockchip_pll_set_rate(&rk3568_pll_clks[GPLL], priv->cru,
3275417bebc4SElaine Zhang GPLL, GPLL_HZ);
3276417bebc4SElaine Zhang if (!ret)
3277417bebc4SElaine Zhang priv->gpll_hz = GPLL_HZ;
3278417bebc4SElaine Zhang }
3279417bebc4SElaine Zhang
328065bd598fSJason Zhu #ifdef CONFIG_SPL_BUILD
328165bd598fSJason Zhu ret = rk3568_bus_set_clk(priv, ACLK_BUS, 150000000);
328298637248SJason Zhu if (ret < 0)
328365bd598fSJason Zhu printf("Fail to set the ACLK_BUS clock.\n");
328465bd598fSJason Zhu #endif
328565bd598fSJason Zhu
3286417bebc4SElaine Zhang priv->ppll_hz = rk3568_pmu_pll_get_rate(priv, PPLL);
3287417bebc4SElaine Zhang priv->hpll_hz = rk3568_pmu_pll_get_rate(priv, HPLL);
3288417bebc4SElaine Zhang }
3289417bebc4SElaine Zhang
rk3568_clk_probe(struct udevice * dev)3290417bebc4SElaine Zhang static int rk3568_clk_probe(struct udevice *dev)
3291417bebc4SElaine Zhang {
3292417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(dev);
3293417bebc4SElaine Zhang int ret;
3294417bebc4SElaine Zhang
3295417bebc4SElaine Zhang priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
3296417bebc4SElaine Zhang if (IS_ERR(priv->grf))
3297417bebc4SElaine Zhang return PTR_ERR(priv->grf);
3298417bebc4SElaine Zhang
3299417bebc4SElaine Zhang rk3568_clk_init(priv);
3300417bebc4SElaine Zhang
3301417bebc4SElaine Zhang /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
3302417bebc4SElaine Zhang ret = clk_set_defaults(dev);
3303417bebc4SElaine Zhang if (ret)
3304417bebc4SElaine Zhang debug("%s clk_set_defaults failed %d\n", __func__, ret);
3305417bebc4SElaine Zhang else
3306417bebc4SElaine Zhang priv->sync_kernel = true;
3307417bebc4SElaine Zhang
3308417bebc4SElaine Zhang return 0;
3309417bebc4SElaine Zhang }
3310417bebc4SElaine Zhang
rk3568_clk_ofdata_to_platdata(struct udevice * dev)3311417bebc4SElaine Zhang static int rk3568_clk_ofdata_to_platdata(struct udevice *dev)
3312417bebc4SElaine Zhang {
3313417bebc4SElaine Zhang struct rk3568_clk_priv *priv = dev_get_priv(dev);
3314417bebc4SElaine Zhang
3315417bebc4SElaine Zhang priv->cru = dev_read_addr_ptr(dev);
3316417bebc4SElaine Zhang
3317417bebc4SElaine Zhang return 0;
3318417bebc4SElaine Zhang }
3319417bebc4SElaine Zhang
rk3568_clk_bind(struct udevice * dev)3320417bebc4SElaine Zhang static int rk3568_clk_bind(struct udevice *dev)
3321417bebc4SElaine Zhang {
3322417bebc4SElaine Zhang int ret;
3323417bebc4SElaine Zhang struct udevice *sys_child, *sf_child;
3324417bebc4SElaine Zhang struct sysreset_reg *priv;
3325417bebc4SElaine Zhang struct softreset_reg *sf_priv;
3326417bebc4SElaine Zhang
3327417bebc4SElaine Zhang /* The reset driver does not have a device node, so bind it here */
3328417bebc4SElaine Zhang ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
3329417bebc4SElaine Zhang &sys_child);
3330417bebc4SElaine Zhang if (ret) {
3331417bebc4SElaine Zhang debug("Warning: No sysreset driver: ret=%d\n", ret);
3332417bebc4SElaine Zhang } else {
3333417bebc4SElaine Zhang priv = malloc(sizeof(struct sysreset_reg));
3334417bebc4SElaine Zhang priv->glb_srst_fst_value = offsetof(struct rk3568_cru,
3335417bebc4SElaine Zhang glb_srst_fst);
3336417bebc4SElaine Zhang priv->glb_srst_snd_value = offsetof(struct rk3568_cru,
3337417bebc4SElaine Zhang glb_srsr_snd);
3338417bebc4SElaine Zhang sys_child->priv = priv;
3339417bebc4SElaine Zhang }
3340417bebc4SElaine Zhang
3341417bebc4SElaine Zhang ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
3342417bebc4SElaine Zhang dev_ofnode(dev), &sf_child);
3343417bebc4SElaine Zhang if (ret) {
3344417bebc4SElaine Zhang debug("Warning: No rockchip reset driver: ret=%d\n", ret);
3345417bebc4SElaine Zhang } else {
3346417bebc4SElaine Zhang sf_priv = malloc(sizeof(struct softreset_reg));
3347417bebc4SElaine Zhang sf_priv->sf_reset_offset = offsetof(struct rk3568_cru,
3348417bebc4SElaine Zhang softrst_con[0]);
3349417bebc4SElaine Zhang sf_priv->sf_reset_num = 30;
3350417bebc4SElaine Zhang sf_child->priv = sf_priv;
3351417bebc4SElaine Zhang }
3352417bebc4SElaine Zhang
3353417bebc4SElaine Zhang return 0;
3354417bebc4SElaine Zhang }
3355417bebc4SElaine Zhang
3356417bebc4SElaine Zhang static const struct udevice_id rk3568_clk_ids[] = {
3357417bebc4SElaine Zhang { .compatible = "rockchip,rk3568-cru" },
3358417bebc4SElaine Zhang { }
3359417bebc4SElaine Zhang };
3360417bebc4SElaine Zhang
3361417bebc4SElaine Zhang U_BOOT_DRIVER(rockchip_rk3568_cru) = {
3362417bebc4SElaine Zhang .name = "rockchip_rk3568_cru",
3363417bebc4SElaine Zhang .id = UCLASS_CLK,
3364417bebc4SElaine Zhang .of_match = rk3568_clk_ids,
3365417bebc4SElaine Zhang .priv_auto_alloc_size = sizeof(struct rk3568_clk_priv),
3366417bebc4SElaine Zhang .ofdata_to_platdata = rk3568_clk_ofdata_to_platdata,
3367417bebc4SElaine Zhang .ops = &rk3568_clk_ops,
3368417bebc4SElaine Zhang .bind = rk3568_clk_bind,
3369417bebc4SElaine Zhang .probe = rk3568_clk_probe,
3370417bebc4SElaine Zhang };
3371417bebc4SElaine Zhang
3372f6d27794Szhangqing #ifndef CONFIG_SPL_BUILD
3373417bebc4SElaine Zhang /**
3374417bebc4SElaine Zhang * soc_clk_dump() - Print clock frequencies
3375417bebc4SElaine Zhang * Returns zero on success
3376417bebc4SElaine Zhang *
3377417bebc4SElaine Zhang * Implementation for the clk dump command.
3378417bebc4SElaine Zhang */
soc_clk_dump(void)3379417bebc4SElaine Zhang int soc_clk_dump(void)
3380417bebc4SElaine Zhang {
3381417bebc4SElaine Zhang struct udevice *cru_dev, *pmucru_dev;
3382417bebc4SElaine Zhang struct rk3568_clk_priv *priv;
3383417bebc4SElaine Zhang const struct rk3568_clk_info *clk_dump;
3384417bebc4SElaine Zhang struct clk clk;
3385417bebc4SElaine Zhang unsigned long clk_count = ARRAY_SIZE(clks_dump);
3386417bebc4SElaine Zhang unsigned long rate;
3387417bebc4SElaine Zhang int i, ret;
3388417bebc4SElaine Zhang
3389417bebc4SElaine Zhang ret = uclass_get_device_by_driver(UCLASS_CLK,
3390417bebc4SElaine Zhang DM_GET_DRIVER(rockchip_rk3568_cru),
3391417bebc4SElaine Zhang &cru_dev);
3392417bebc4SElaine Zhang if (ret) {
3393417bebc4SElaine Zhang printf("%s failed to get cru device\n", __func__);
3394417bebc4SElaine Zhang return ret;
3395417bebc4SElaine Zhang }
3396417bebc4SElaine Zhang
3397417bebc4SElaine Zhang ret = uclass_get_device_by_driver(UCLASS_CLK,
3398417bebc4SElaine Zhang DM_GET_DRIVER(rockchip_rk3568_pmucru),
3399417bebc4SElaine Zhang &pmucru_dev);
3400417bebc4SElaine Zhang if (ret) {
3401417bebc4SElaine Zhang printf("%s failed to get pmucru device\n", __func__);
3402417bebc4SElaine Zhang return ret;
3403417bebc4SElaine Zhang }
3404417bebc4SElaine Zhang
3405417bebc4SElaine Zhang priv = dev_get_priv(cru_dev);
3406417bebc4SElaine Zhang printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
3407417bebc4SElaine Zhang priv->sync_kernel ? "sync kernel" : "uboot",
3408417bebc4SElaine Zhang priv->armclk_enter_hz / 1000,
3409417bebc4SElaine Zhang priv->armclk_init_hz / 1000,
3410417bebc4SElaine Zhang priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
3411417bebc4SElaine Zhang priv->set_armclk_rate ? " KHz" : "N/A");
3412417bebc4SElaine Zhang for (i = 0; i < clk_count; i++) {
3413417bebc4SElaine Zhang clk_dump = &clks_dump[i];
3414417bebc4SElaine Zhang if (clk_dump->name) {
3415417bebc4SElaine Zhang clk.id = clk_dump->id;
3416417bebc4SElaine Zhang if (clk_dump->is_cru)
3417417bebc4SElaine Zhang ret = clk_request(cru_dev, &clk);
3418417bebc4SElaine Zhang else
3419417bebc4SElaine Zhang ret = clk_request(pmucru_dev, &clk);
3420417bebc4SElaine Zhang if (ret < 0)
3421417bebc4SElaine Zhang return ret;
3422417bebc4SElaine Zhang
3423417bebc4SElaine Zhang rate = clk_get_rate(&clk);
3424417bebc4SElaine Zhang clk_free(&clk);
3425417bebc4SElaine Zhang if (i == 0) {
3426417bebc4SElaine Zhang if (rate < 0)
3427417bebc4SElaine Zhang printf(" %s %s\n", clk_dump->name,
3428417bebc4SElaine Zhang "unknown");
3429417bebc4SElaine Zhang else
3430417bebc4SElaine Zhang printf(" %s %lu KHz\n", clk_dump->name,
3431417bebc4SElaine Zhang rate / 1000);
3432417bebc4SElaine Zhang } else {
3433417bebc4SElaine Zhang if (rate < 0)
3434417bebc4SElaine Zhang printf(" %s %s\n", clk_dump->name,
3435417bebc4SElaine Zhang "unknown");
3436417bebc4SElaine Zhang else
3437417bebc4SElaine Zhang printf(" %s %lu KHz\n", clk_dump->name,
3438417bebc4SElaine Zhang rate / 1000);
3439417bebc4SElaine Zhang }
3440417bebc4SElaine Zhang }
3441417bebc4SElaine Zhang }
3442417bebc4SElaine Zhang
3443417bebc4SElaine Zhang return 0;
3444417bebc4SElaine Zhang }
3445417bebc4SElaine Zhang #endif
3446