1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2021 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun * Author: Elaine Zhang <zhangqing@rock-chips.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <bitfield.h>
9*4882a593Smuzhiyun #include <clk-uclass.h>
10*4882a593Smuzhiyun #include <dm.h>
11*4882a593Smuzhiyun #include <errno.h>
12*4882a593Smuzhiyun #include <syscon.h>
13*4882a593Smuzhiyun #include <asm/arch/clock.h>
14*4882a593Smuzhiyun #include <asm/arch/cru_rv1106.h>
15*4882a593Smuzhiyun #include <asm/arch/grf_rv1106.h>
16*4882a593Smuzhiyun #include <asm/arch/hardware.h>
17*4882a593Smuzhiyun #include <asm/io.h>
18*4882a593Smuzhiyun #include <dm/lists.h>
19*4882a593Smuzhiyun #include <dt-bindings/clock/rv1106-cru.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
26*4882a593Smuzhiyun static struct rockchip_pll_rate_table rv1106_pll_rates[] = {
27*4882a593Smuzhiyun /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
28*4882a593Smuzhiyun RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
29*4882a593Smuzhiyun RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
30*4882a593Smuzhiyun RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
31*4882a593Smuzhiyun RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
32*4882a593Smuzhiyun RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
33*4882a593Smuzhiyun RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
34*4882a593Smuzhiyun RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
35*4882a593Smuzhiyun { /* sentinel */ },
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun static struct rockchip_pll_clock rv1106_pll_clks[] = {
39*4882a593Smuzhiyun [APLL] = PLL(pll_rk3328, PLL_APLL, RV1106_PLL_CON(0),
40*4882a593Smuzhiyun RV1106_MODE_CON, 0, 10, 0, rv1106_pll_rates),
41*4882a593Smuzhiyun [DPLL] = PLL(pll_rk3328, PLL_DPLL, RV1106_PLL_CON(16),
42*4882a593Smuzhiyun RV1106_SUBDDRMODE_CON, 0, 10, 0, NULL),
43*4882a593Smuzhiyun [CPLL] = PLL(pll_rk3328, PLL_CPLL, RV1106_PLL_CON(8),
44*4882a593Smuzhiyun RV1106_MODE_CON, 2, 10, 0, rv1106_pll_rates),
45*4882a593Smuzhiyun [GPLL] = PLL(pll_rk3328, PLL_GPLL, RV1106_PLL_CON(24),
46*4882a593Smuzhiyun RV1106_MODE_CON, 4, 10, 0, rv1106_pll_rates),
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
51*4882a593Smuzhiyun #define RV1106_CLK_DUMP(_id, _name, _iscru) \
52*4882a593Smuzhiyun { \
53*4882a593Smuzhiyun .id = _id, \
54*4882a593Smuzhiyun .name = _name, \
55*4882a593Smuzhiyun .is_cru = _iscru, \
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun static const struct rv1106_clk_info clks_dump[] = {
59*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
60*4882a593Smuzhiyun RV1106_CLK_DUMP(PLL_APLL, "apll", true),
61*4882a593Smuzhiyun RV1106_CLK_DUMP(PLL_DPLL, "dpll", true),
62*4882a593Smuzhiyun RV1106_CLK_DUMP(PLL_GPLL, "gpll", true),
63*4882a593Smuzhiyun RV1106_CLK_DUMP(PLL_CPLL, "cpll", true),
64*4882a593Smuzhiyun RV1106_CLK_DUMP(ACLK_PERI_ROOT, "aclk_peri_root", true),
65*4882a593Smuzhiyun RV1106_CLK_DUMP(HCLK_PERI_ROOT, "hclK_peri_root", true),
66*4882a593Smuzhiyun RV1106_CLK_DUMP(PCLK_PERI_ROOT, "pclk_peri_root", true),
67*4882a593Smuzhiyun RV1106_CLK_DUMP(ACLK_BUS_ROOT, "aclk_bus_root", true),
68*4882a593Smuzhiyun RV1106_CLK_DUMP(PCLK_TOP_ROOT, "pclk_top_root", true),
69*4882a593Smuzhiyun RV1106_CLK_DUMP(PCLK_PMU_ROOT, "pclk_pmu_root", true),
70*4882a593Smuzhiyun RV1106_CLK_DUMP(HCLK_PMU_ROOT, "hclk_pmu_root", true),
71*4882a593Smuzhiyun #endif
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun #endif
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
rv1106_peri_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)76*4882a593Smuzhiyun static ulong rv1106_peri_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
79*4882a593Smuzhiyun u32 con, sel, rate;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun switch (clk_id) {
82*4882a593Smuzhiyun case ACLK_PERI_ROOT:
83*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[1]);
84*4882a593Smuzhiyun sel = (con & ACLK_PERI_SEL_MASK) >> ACLK_PERI_SEL_SHIFT;
85*4882a593Smuzhiyun if (sel == ACLK_PERI_SEL_400M)
86*4882a593Smuzhiyun rate = 400 * MHz;
87*4882a593Smuzhiyun else if (sel == ACLK_PERI_SEL_200M)
88*4882a593Smuzhiyun rate = 200 * MHz;
89*4882a593Smuzhiyun else if (sel == ACLK_PERI_SEL_100M)
90*4882a593Smuzhiyun rate = 100 * MHz;
91*4882a593Smuzhiyun else
92*4882a593Smuzhiyun rate = OSC_HZ;
93*4882a593Smuzhiyun break;
94*4882a593Smuzhiyun case HCLK_PERI_ROOT:
95*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[1]);
96*4882a593Smuzhiyun sel = (con & HCLK_PERI_SEL_MASK) >> HCLK_PERI_SEL_SHIFT;
97*4882a593Smuzhiyun if (sel == HCLK_PERI_SEL_200M)
98*4882a593Smuzhiyun rate = 200 * MHz;
99*4882a593Smuzhiyun else if (sel == HCLK_PERI_SEL_100M)
100*4882a593Smuzhiyun rate = 100 * MHz;
101*4882a593Smuzhiyun else if (sel == HCLK_PERI_SEL_50M)
102*4882a593Smuzhiyun rate = 50 * MHz;
103*4882a593Smuzhiyun else
104*4882a593Smuzhiyun rate = OSC_HZ;
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun case PCLK_PERI_ROOT:
107*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[1]);
108*4882a593Smuzhiyun sel = (con & PCLK_PERI_SEL_MASK) >> PCLK_PERI_SEL_SHIFT;
109*4882a593Smuzhiyun if (sel == PCLK_PERI_SEL_100M)
110*4882a593Smuzhiyun rate = 100 * MHz;
111*4882a593Smuzhiyun else if (sel == PCLK_PERI_SEL_50M)
112*4882a593Smuzhiyun rate = 50 * MHz;
113*4882a593Smuzhiyun else
114*4882a593Smuzhiyun rate = OSC_HZ;
115*4882a593Smuzhiyun break;
116*4882a593Smuzhiyun case ACLK_BUS_ROOT:
117*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[9]);
118*4882a593Smuzhiyun sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
119*4882a593Smuzhiyun if (sel == ACLK_BUS_SEL_300M)
120*4882a593Smuzhiyun rate = 300 * MHz;
121*4882a593Smuzhiyun else if (sel == ACLK_BUS_SEL_200M)
122*4882a593Smuzhiyun rate = 200 * MHz;
123*4882a593Smuzhiyun else if (sel == ACLK_BUS_SEL_100M)
124*4882a593Smuzhiyun rate = 100 * MHz;
125*4882a593Smuzhiyun else
126*4882a593Smuzhiyun rate = OSC_HZ;
127*4882a593Smuzhiyun break;
128*4882a593Smuzhiyun case PCLK_TOP_ROOT:
129*4882a593Smuzhiyun con = readl(&cru->clksel_con[24]);
130*4882a593Smuzhiyun sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
131*4882a593Smuzhiyun if (sel == PCLK_TOP_SEL_100M)
132*4882a593Smuzhiyun rate = 100 * MHz;
133*4882a593Smuzhiyun else if (sel == PCLK_TOP_SEL_50M)
134*4882a593Smuzhiyun rate = 50 * MHz;
135*4882a593Smuzhiyun else
136*4882a593Smuzhiyun rate = OSC_HZ;
137*4882a593Smuzhiyun break;
138*4882a593Smuzhiyun case PCLK_PMU_ROOT:
139*4882a593Smuzhiyun con = readl(&cru->pmu_clksel_con[0]);
140*4882a593Smuzhiyun sel = (con & PCLK_PMU_SEL_MASK) >> PCLK_PMU_SEL_SHIFT;
141*4882a593Smuzhiyun if (sel == PCLK_PMU_SEL_100M)
142*4882a593Smuzhiyun rate = 100 * MHz;
143*4882a593Smuzhiyun else
144*4882a593Smuzhiyun rate = OSC_HZ;
145*4882a593Smuzhiyun break;
146*4882a593Smuzhiyun case HCLK_PMU_ROOT:
147*4882a593Smuzhiyun con = readl(&cru->pmu_clksel_con[0]);
148*4882a593Smuzhiyun sel = (con & HCLK_PMU_SEL_MASK) >> HCLK_PMU_SEL_SHIFT;
149*4882a593Smuzhiyun if (sel == HCLK_PMU_SEL_200M)
150*4882a593Smuzhiyun rate = 200 * MHz;
151*4882a593Smuzhiyun else if (sel == HCLK_PMU_SEL_100M)
152*4882a593Smuzhiyun rate = 100 * MHz;
153*4882a593Smuzhiyun else
154*4882a593Smuzhiyun rate = OSC_HZ;
155*4882a593Smuzhiyun break;
156*4882a593Smuzhiyun default:
157*4882a593Smuzhiyun return -ENOENT;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun return rate;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
rv1106_peri_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)163*4882a593Smuzhiyun static ulong rv1106_peri_set_clk(struct rv1106_clk_priv *priv,
164*4882a593Smuzhiyun ulong clk_id, ulong rate)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
167*4882a593Smuzhiyun int src_clk;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun switch (clk_id) {
170*4882a593Smuzhiyun case ACLK_PERI_ROOT:
171*4882a593Smuzhiyun if (rate >= 396 * MHz)
172*4882a593Smuzhiyun src_clk = ACLK_PERI_SEL_400M;
173*4882a593Smuzhiyun else if (rate >= 198 * MHz)
174*4882a593Smuzhiyun src_clk = ACLK_PERI_SEL_200M;
175*4882a593Smuzhiyun else if (rate >= 99 * MHz)
176*4882a593Smuzhiyun src_clk = ACLK_PERI_SEL_100M;
177*4882a593Smuzhiyun else
178*4882a593Smuzhiyun src_clk = ACLK_PERI_SEL_24M;
179*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[1],
180*4882a593Smuzhiyun ACLK_PERI_SEL_MASK,
181*4882a593Smuzhiyun src_clk << ACLK_PERI_SEL_SHIFT);
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun case HCLK_PERI_ROOT:
184*4882a593Smuzhiyun if (rate >= 198 * MHz)
185*4882a593Smuzhiyun src_clk = HCLK_PERI_SEL_200M;
186*4882a593Smuzhiyun else if (rate >= 99 * MHz)
187*4882a593Smuzhiyun src_clk = HCLK_PERI_SEL_100M;
188*4882a593Smuzhiyun else if (rate >= 48 * MHz)
189*4882a593Smuzhiyun src_clk = HCLK_PERI_SEL_50M;
190*4882a593Smuzhiyun else
191*4882a593Smuzhiyun src_clk = HCLK_PERI_SEL_24M;
192*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[1],
193*4882a593Smuzhiyun HCLK_PERI_SEL_MASK,
194*4882a593Smuzhiyun src_clk << HCLK_PERI_SEL_SHIFT);
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun case PCLK_PERI_ROOT:
197*4882a593Smuzhiyun if (rate >= 99 * MHz)
198*4882a593Smuzhiyun src_clk = PCLK_PERI_SEL_100M;
199*4882a593Smuzhiyun else if (rate >= 48 * MHz)
200*4882a593Smuzhiyun src_clk = PCLK_PERI_SEL_50M;
201*4882a593Smuzhiyun else
202*4882a593Smuzhiyun src_clk = PCLK_PERI_SEL_24M;
203*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[1],
204*4882a593Smuzhiyun PCLK_PERI_SEL_MASK,
205*4882a593Smuzhiyun src_clk << PCLK_PERI_SEL_SHIFT);
206*4882a593Smuzhiyun break;
207*4882a593Smuzhiyun case ACLK_BUS_ROOT:
208*4882a593Smuzhiyun if (rate >= 297 * MHz)
209*4882a593Smuzhiyun src_clk = ACLK_BUS_SEL_300M;
210*4882a593Smuzhiyun else if (rate >= 198 * MHz)
211*4882a593Smuzhiyun src_clk = ACLK_BUS_SEL_200M;
212*4882a593Smuzhiyun else if (rate >= 99 * MHz)
213*4882a593Smuzhiyun src_clk = ACLK_BUS_SEL_100M;
214*4882a593Smuzhiyun else
215*4882a593Smuzhiyun src_clk = ACLK_BUS_SEL_24M;
216*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[9],
217*4882a593Smuzhiyun ACLK_BUS_SEL_MASK,
218*4882a593Smuzhiyun src_clk << ACLK_BUS_SEL_SHIFT);
219*4882a593Smuzhiyun break;
220*4882a593Smuzhiyun case PCLK_TOP_ROOT:
221*4882a593Smuzhiyun if (rate >= 99 * MHz)
222*4882a593Smuzhiyun src_clk = PCLK_TOP_SEL_100M;
223*4882a593Smuzhiyun else if (rate >= 48 * MHz)
224*4882a593Smuzhiyun src_clk = PCLK_TOP_SEL_50M;
225*4882a593Smuzhiyun else
226*4882a593Smuzhiyun src_clk = PCLK_TOP_SEL_24M;
227*4882a593Smuzhiyun rk_clrsetreg(&cru->clksel_con[24],
228*4882a593Smuzhiyun PCLK_TOP_SEL_MASK,
229*4882a593Smuzhiyun src_clk << PCLK_TOP_SEL_SHIFT);
230*4882a593Smuzhiyun break;
231*4882a593Smuzhiyun case PCLK_PMU_ROOT:
232*4882a593Smuzhiyun if (rate >= 99 * MHz)
233*4882a593Smuzhiyun src_clk = PCLK_PMU_SEL_100M;
234*4882a593Smuzhiyun else
235*4882a593Smuzhiyun src_clk = PCLK_PMU_SEL_24M;
236*4882a593Smuzhiyun rk_clrsetreg(&cru->pmu_clksel_con[0],
237*4882a593Smuzhiyun PCLK_PMU_SEL_MASK,
238*4882a593Smuzhiyun src_clk << PCLK_PMU_SEL_SHIFT);
239*4882a593Smuzhiyun break;
240*4882a593Smuzhiyun case HCLK_PMU_ROOT:
241*4882a593Smuzhiyun if (rate >= 198 * MHz)
242*4882a593Smuzhiyun src_clk = HCLK_PMU_SEL_200M;
243*4882a593Smuzhiyun else if (rate >= 99 * MHz)
244*4882a593Smuzhiyun src_clk = HCLK_PMU_SEL_100M;
245*4882a593Smuzhiyun else
246*4882a593Smuzhiyun src_clk = HCLK_PMU_SEL_24M;
247*4882a593Smuzhiyun rk_clrsetreg(&cru->pmu_clksel_con[0],
248*4882a593Smuzhiyun HCLK_PMU_SEL_MASK,
249*4882a593Smuzhiyun src_clk << HCLK_PMU_SEL_SHIFT);
250*4882a593Smuzhiyun break;
251*4882a593Smuzhiyun default:
252*4882a593Smuzhiyun printf("do not support this permid freq\n");
253*4882a593Smuzhiyun return -EINVAL;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun return rv1106_peri_get_clk(priv, clk_id);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
rv1106_i2c_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)259*4882a593Smuzhiyun static ulong rv1106_i2c_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
262*4882a593Smuzhiyun u32 sel, con;
263*4882a593Smuzhiyun ulong rate;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun switch (clk_id) {
266*4882a593Smuzhiyun case CLK_I2C1:
267*4882a593Smuzhiyun con = readl(&cru->pmu_clksel_con[0]);
268*4882a593Smuzhiyun sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
269*4882a593Smuzhiyun if (sel == CLK_I2C1_SEL_200M)
270*4882a593Smuzhiyun rate = 200 * MHz;
271*4882a593Smuzhiyun else if (sel == CLK_I2C1_SEL_100M)
272*4882a593Smuzhiyun rate = 100 * MHz;
273*4882a593Smuzhiyun else if (sel == CLK_I2C1_SEL_24M)
274*4882a593Smuzhiyun rate = OSC_HZ;
275*4882a593Smuzhiyun else
276*4882a593Smuzhiyun rate = 32768;
277*4882a593Smuzhiyun return rate;
278*4882a593Smuzhiyun case CLK_I2C0:
279*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[1]);
280*4882a593Smuzhiyun sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
281*4882a593Smuzhiyun break;
282*4882a593Smuzhiyun case CLK_I2C2:
283*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[1]);
284*4882a593Smuzhiyun sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
285*4882a593Smuzhiyun break;
286*4882a593Smuzhiyun case CLK_I2C3:
287*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[1]);
288*4882a593Smuzhiyun sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
289*4882a593Smuzhiyun break;
290*4882a593Smuzhiyun case CLK_I2C4:
291*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[2]);
292*4882a593Smuzhiyun sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
293*4882a593Smuzhiyun break;
294*4882a593Smuzhiyun default:
295*4882a593Smuzhiyun return -ENOENT;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (sel == CLK_I2C0_SEL_200M)
299*4882a593Smuzhiyun rate = 200 * MHz;
300*4882a593Smuzhiyun else if (sel == CLK_I2C0_SEL_100M)
301*4882a593Smuzhiyun rate = 100 * MHz;
302*4882a593Smuzhiyun else if (sel == CLK_I2C0_SEL_50M)
303*4882a593Smuzhiyun rate = 50 * MHz;
304*4882a593Smuzhiyun else
305*4882a593Smuzhiyun rate = OSC_HZ;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun return rate;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun #endif
310*4882a593Smuzhiyun
rv1106_crypto_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)311*4882a593Smuzhiyun static ulong rv1106_crypto_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
314*4882a593Smuzhiyun u32 sel, con;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun switch (clk_id) {
317*4882a593Smuzhiyun case CLK_CORE_CRYPTO:
318*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[6]);
319*4882a593Smuzhiyun sel = (con & CLK_CORE_CRYPTO_SEL_MASK) >>
320*4882a593Smuzhiyun CLK_CORE_CRYPTO_SEL_SHIFT;
321*4882a593Smuzhiyun break;
322*4882a593Smuzhiyun case CLK_PKA_CRYPTO:
323*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[6]);
324*4882a593Smuzhiyun sel = (con & CLK_PKA_CRYPTO_SEL_MASK) >>
325*4882a593Smuzhiyun CLK_PKA_CRYPTO_SEL_SHIFT;
326*4882a593Smuzhiyun break;
327*4882a593Smuzhiyun default:
328*4882a593Smuzhiyun return -ENOENT;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun switch (sel) {
331*4882a593Smuzhiyun case CLK_CRYPTO_SEL_300M:
332*4882a593Smuzhiyun return 300 * MHz;
333*4882a593Smuzhiyun case CLK_CRYPTO_SEL_200M:
334*4882a593Smuzhiyun return 200 * MHz;
335*4882a593Smuzhiyun case CLK_CRYPTO_SEL_100M:
336*4882a593Smuzhiyun return 100 * MHz;
337*4882a593Smuzhiyun case CLK_CRYPTO_SEL_24M:
338*4882a593Smuzhiyun return OSC_HZ;
339*4882a593Smuzhiyun default:
340*4882a593Smuzhiyun return -ENOENT;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
rv1106_crypto_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)344*4882a593Smuzhiyun static ulong rv1106_crypto_set_clk(struct rv1106_clk_priv *priv,
345*4882a593Smuzhiyun ulong clk_id, ulong rate)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
348*4882a593Smuzhiyun u32 sel;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (rate >= 297 * MHz)
351*4882a593Smuzhiyun sel = CLK_CRYPTO_SEL_300M;
352*4882a593Smuzhiyun else if (rate >= 198 * MHz)
353*4882a593Smuzhiyun sel = CLK_CRYPTO_SEL_200M;
354*4882a593Smuzhiyun else if (rate >= 99 * MHz)
355*4882a593Smuzhiyun sel = CLK_CRYPTO_SEL_100M;
356*4882a593Smuzhiyun else
357*4882a593Smuzhiyun sel = CLK_CRYPTO_SEL_24M;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun switch (clk_id) {
360*4882a593Smuzhiyun case CLK_CORE_CRYPTO:
361*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[6],
362*4882a593Smuzhiyun CLK_CORE_CRYPTO_SEL_MASK,
363*4882a593Smuzhiyun sel << CLK_CORE_CRYPTO_SEL_SHIFT);
364*4882a593Smuzhiyun break;
365*4882a593Smuzhiyun case CLK_PKA_CRYPTO:
366*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[6],
367*4882a593Smuzhiyun CLK_PKA_CRYPTO_SEL_MASK,
368*4882a593Smuzhiyun sel << CLK_PKA_CRYPTO_SEL_SHIFT);
369*4882a593Smuzhiyun break;
370*4882a593Smuzhiyun default:
371*4882a593Smuzhiyun return -ENOENT;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun return rv1106_crypto_get_clk(priv, clk_id);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
rv1106_mmc_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)376*4882a593Smuzhiyun static ulong rv1106_mmc_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
379*4882a593Smuzhiyun u32 div, sel, con, prate;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun switch (clk_id) {
382*4882a593Smuzhiyun case CCLK_SRC_SDMMC:
383*4882a593Smuzhiyun case HCLK_SDMMC:
384*4882a593Smuzhiyun con = readl(&cru->vi_clksel_con[1]);
385*4882a593Smuzhiyun sel = (con & CLK_SDMMC_SEL_MASK) >>
386*4882a593Smuzhiyun CLK_SDMMC_SEL_SHIFT;
387*4882a593Smuzhiyun div = (con & CLK_SDMMC_DIV_MASK) >>
388*4882a593Smuzhiyun CLK_SDMMC_DIV_SHIFT;
389*4882a593Smuzhiyun if (sel == CLK_MMC_SEL_400M)
390*4882a593Smuzhiyun prate = 400 * MHz;
391*4882a593Smuzhiyun else
392*4882a593Smuzhiyun prate = OSC_HZ;
393*4882a593Smuzhiyun return DIV_TO_RATE(prate, div);
394*4882a593Smuzhiyun case CCLK_SRC_EMMC:
395*4882a593Smuzhiyun case HCLK_EMMC:
396*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[7]);
397*4882a593Smuzhiyun sel = (con & CLK_EMMC_SEL_MASK) >>
398*4882a593Smuzhiyun CLK_EMMC_SEL_SHIFT;
399*4882a593Smuzhiyun div = (con & CLK_EMMC_DIV_MASK) >>
400*4882a593Smuzhiyun CLK_EMMC_DIV_SHIFT;
401*4882a593Smuzhiyun if (sel)
402*4882a593Smuzhiyun prate = OSC_HZ;
403*4882a593Smuzhiyun else
404*4882a593Smuzhiyun prate = 400 * MHz;
405*4882a593Smuzhiyun return DIV_TO_RATE(prate, div);
406*4882a593Smuzhiyun case SCLK_SFC:
407*4882a593Smuzhiyun case HCLK_SFC:
408*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[7]);
409*4882a593Smuzhiyun sel = (con & CLK_SFC_SEL_MASK) >>
410*4882a593Smuzhiyun CLK_SFC_SEL_SHIFT;
411*4882a593Smuzhiyun div = (con & CLK_SFC_DIV_MASK) >>
412*4882a593Smuzhiyun CLK_SFC_DIV_SHIFT;
413*4882a593Smuzhiyun if (sel == CLK_SFC_SEL_500M)
414*4882a593Smuzhiyun prate = 500 * MHz;
415*4882a593Smuzhiyun else if (sel == CLK_SFC_SEL_300M)
416*4882a593Smuzhiyun prate = 300 * MHz;
417*4882a593Smuzhiyun else if (sel == CLK_SFC_SEL_200M)
418*4882a593Smuzhiyun prate = 200 * MHz;
419*4882a593Smuzhiyun else
420*4882a593Smuzhiyun prate = OSC_HZ;
421*4882a593Smuzhiyun return DIV_TO_RATE(prate, div);
422*4882a593Smuzhiyun default:
423*4882a593Smuzhiyun return -ENOENT;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
rv1106_mmc_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)427*4882a593Smuzhiyun static ulong rv1106_mmc_set_clk(struct rv1106_clk_priv *priv,
428*4882a593Smuzhiyun ulong clk_id, ulong rate)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
431*4882a593Smuzhiyun u32 sel, src_clk_div;
432*4882a593Smuzhiyun ulong prate = 0;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun if ((OSC_HZ % rate) == 0) {
435*4882a593Smuzhiyun sel = CLK_MMC_SEL_24M;
436*4882a593Smuzhiyun prate = OSC_HZ;
437*4882a593Smuzhiyun } else {
438*4882a593Smuzhiyun sel = CLK_MMC_SEL_400M;
439*4882a593Smuzhiyun prate = 400 * MHz;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun src_clk_div = DIV_ROUND_UP(prate, rate);
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun switch (clk_id) {
444*4882a593Smuzhiyun case CCLK_SRC_SDMMC:
445*4882a593Smuzhiyun case HCLK_SDMMC:
446*4882a593Smuzhiyun if ((OSC_HZ % rate) == 0) {
447*4882a593Smuzhiyun sel = CLK_MMC_SEL_24M;
448*4882a593Smuzhiyun prate = OSC_HZ;
449*4882a593Smuzhiyun } else {
450*4882a593Smuzhiyun sel = CLK_MMC_SEL_400M;
451*4882a593Smuzhiyun prate = 400 * MHz;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun src_clk_div = DIV_ROUND_UP(prate, rate);
454*4882a593Smuzhiyun rk_clrsetreg(&cru->vi_clksel_con[1],
455*4882a593Smuzhiyun CLK_SDMMC_SEL_MASK |
456*4882a593Smuzhiyun CLK_SDMMC_DIV_MASK,
457*4882a593Smuzhiyun (sel << CLK_SDMMC_SEL_SHIFT) |
458*4882a593Smuzhiyun ((src_clk_div - 1) <<
459*4882a593Smuzhiyun CLK_SDMMC_DIV_SHIFT));
460*4882a593Smuzhiyun break;
461*4882a593Smuzhiyun case CCLK_SRC_EMMC:
462*4882a593Smuzhiyun case HCLK_EMMC:
463*4882a593Smuzhiyun if ((OSC_HZ % rate) == 0) {
464*4882a593Smuzhiyun sel = CLK_MMC_SEL_24M;
465*4882a593Smuzhiyun prate = OSC_HZ;
466*4882a593Smuzhiyun } else {
467*4882a593Smuzhiyun sel = CLK_MMC_SEL_400M;
468*4882a593Smuzhiyun prate = 400 * MHz;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun src_clk_div = DIV_ROUND_UP(prate, rate);
471*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[7],
472*4882a593Smuzhiyun CLK_EMMC_SEL_MASK |
473*4882a593Smuzhiyun CLK_EMMC_DIV_MASK,
474*4882a593Smuzhiyun (sel << CLK_EMMC_SEL_SHIFT) |
475*4882a593Smuzhiyun ((src_clk_div - 1) <<
476*4882a593Smuzhiyun CLK_EMMC_DIV_SHIFT));
477*4882a593Smuzhiyun break;
478*4882a593Smuzhiyun case SCLK_SFC:
479*4882a593Smuzhiyun case HCLK_SFC:
480*4882a593Smuzhiyun if ((OSC_HZ % rate) == 0) {
481*4882a593Smuzhiyun sel = CLK_SFC_SEL_24M;
482*4882a593Smuzhiyun prate = OSC_HZ;
483*4882a593Smuzhiyun } else if ((500 * MHz % rate) == 0) {
484*4882a593Smuzhiyun sel = CLK_SFC_SEL_500M;
485*4882a593Smuzhiyun prate = 500 * MHz;
486*4882a593Smuzhiyun } else if ((300 * MHz % rate) == 0) {
487*4882a593Smuzhiyun sel = CLK_SFC_SEL_300M;
488*4882a593Smuzhiyun prate = 300 * MHz;
489*4882a593Smuzhiyun } else {
490*4882a593Smuzhiyun sel = CLK_SFC_SEL_200M;
491*4882a593Smuzhiyun prate = 200 * MHz;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun src_clk_div = DIV_ROUND_UP(prate, rate);
494*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[7],
495*4882a593Smuzhiyun CLK_SFC_SEL_MASK |
496*4882a593Smuzhiyun CLK_SFC_DIV_MASK,
497*4882a593Smuzhiyun (sel << CLK_SFC_SEL_SHIFT) |
498*4882a593Smuzhiyun ((src_clk_div - 1) <<
499*4882a593Smuzhiyun CLK_SFC_DIV_SHIFT));
500*4882a593Smuzhiyun break;
501*4882a593Smuzhiyun default:
502*4882a593Smuzhiyun return -ENOENT;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun return rv1106_mmc_get_clk(priv, clk_id);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
rv1106_i2c_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)508*4882a593Smuzhiyun static ulong rv1106_i2c_set_clk(struct rv1106_clk_priv *priv, ulong clk_id,
509*4882a593Smuzhiyun ulong rate)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
512*4882a593Smuzhiyun int src_clk;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (rate >= 198 * MHz)
515*4882a593Smuzhiyun src_clk = CLK_I2C0_SEL_200M;
516*4882a593Smuzhiyun else if (rate >= 99 * MHz)
517*4882a593Smuzhiyun src_clk = CLK_I2C0_SEL_100M;
518*4882a593Smuzhiyun else if (rate >= 48 * MHz)
519*4882a593Smuzhiyun src_clk = CLK_I2C0_SEL_50M;
520*4882a593Smuzhiyun else
521*4882a593Smuzhiyun src_clk = CLK_I2C0_SEL_24M;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun switch (clk_id) {
524*4882a593Smuzhiyun case CLK_I2C1:
525*4882a593Smuzhiyun if (rate >= 198 * MHz)
526*4882a593Smuzhiyun src_clk = CLK_I2C1_SEL_200M;
527*4882a593Smuzhiyun else if (rate >= 99 * MHz)
528*4882a593Smuzhiyun src_clk = CLK_I2C1_SEL_100M;
529*4882a593Smuzhiyun else if (rate >= 24 * MHz)
530*4882a593Smuzhiyun src_clk = CLK_I2C1_SEL_24M;
531*4882a593Smuzhiyun else
532*4882a593Smuzhiyun src_clk = CLK_I2C1_SEL_32K;
533*4882a593Smuzhiyun rk_clrsetreg(&cru->clksel_con[71], CLK_I2C1_SEL_MASK,
534*4882a593Smuzhiyun src_clk << CLK_I2C1_SEL_SHIFT);
535*4882a593Smuzhiyun return rv1106_i2c_get_clk(priv, clk_id);
536*4882a593Smuzhiyun case CLK_I2C0:
537*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[1], CLK_I2C0_SEL_MASK,
538*4882a593Smuzhiyun src_clk << CLK_I2C0_SEL_SHIFT);
539*4882a593Smuzhiyun break;
540*4882a593Smuzhiyun case CLK_I2C2:
541*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[1], CLK_I2C2_SEL_MASK,
542*4882a593Smuzhiyun src_clk << CLK_I2C2_SEL_SHIFT);
543*4882a593Smuzhiyun break;
544*4882a593Smuzhiyun case CLK_I2C3:
545*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[1], CLK_I2C3_SEL_MASK,
546*4882a593Smuzhiyun src_clk << CLK_I2C3_SEL_SHIFT);
547*4882a593Smuzhiyun break;
548*4882a593Smuzhiyun case CLK_I2C4:
549*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[2], CLK_I2C4_SEL_MASK,
550*4882a593Smuzhiyun src_clk << CLK_I2C4_SEL_SHIFT);
551*4882a593Smuzhiyun break;
552*4882a593Smuzhiyun default:
553*4882a593Smuzhiyun return -ENOENT;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun return rv1106_i2c_get_clk(priv, clk_id);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun #endif
559*4882a593Smuzhiyun
rv1106_spi_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)560*4882a593Smuzhiyun static ulong rv1106_spi_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
563*4882a593Smuzhiyun u32 sel, con, rate;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun switch (clk_id) {
566*4882a593Smuzhiyun case CLK_SPI0:
567*4882a593Smuzhiyun con = readl(&cru->vepu_clksel_con[0]);
568*4882a593Smuzhiyun sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
569*4882a593Smuzhiyun break;
570*4882a593Smuzhiyun case CLK_SPI1:
571*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[6]);
572*4882a593Smuzhiyun sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun default:
575*4882a593Smuzhiyun return -ENOENT;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun if (sel == CLK_SPI0_SEL_200M)
578*4882a593Smuzhiyun rate = 200 * MHz;
579*4882a593Smuzhiyun else if (sel == CLK_SPI0_SEL_100M)
580*4882a593Smuzhiyun rate = 100 * MHz;
581*4882a593Smuzhiyun else if (sel == CLK_SPI0_SEL_50M)
582*4882a593Smuzhiyun rate = 50 * MHz;
583*4882a593Smuzhiyun else
584*4882a593Smuzhiyun rate = OSC_HZ;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun return rate;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun
rv1106_spi_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)589*4882a593Smuzhiyun static ulong rv1106_spi_set_clk(struct rv1106_clk_priv *priv,
590*4882a593Smuzhiyun ulong clk_id, ulong rate)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
593*4882a593Smuzhiyun int src_clk;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun if (rate >= 198 * MHz)
596*4882a593Smuzhiyun src_clk = CLK_SPI0_SEL_200M;
597*4882a593Smuzhiyun else if (rate >= 99 * MHz)
598*4882a593Smuzhiyun src_clk = CLK_SPI0_SEL_100M;
599*4882a593Smuzhiyun else if (rate >= 48 * MHz)
600*4882a593Smuzhiyun src_clk = CLK_SPI0_SEL_50M;
601*4882a593Smuzhiyun else
602*4882a593Smuzhiyun src_clk = CLK_SPI0_SEL_24M;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun switch (clk_id) {
605*4882a593Smuzhiyun case CLK_SPI0:
606*4882a593Smuzhiyun rk_clrsetreg(&cru->vepu_clksel_con[0], CLK_SPI0_SEL_MASK,
607*4882a593Smuzhiyun src_clk << CLK_SPI0_SEL_SHIFT);
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun case CLK_SPI1:
610*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[6], CLK_SPI1_SEL_MASK,
611*4882a593Smuzhiyun src_clk << CLK_SPI1_SEL_SHIFT);
612*4882a593Smuzhiyun break;
613*4882a593Smuzhiyun default:
614*4882a593Smuzhiyun return -ENOENT;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun return rv1106_spi_get_clk(priv, clk_id);
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
rv1106_pwm_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)621*4882a593Smuzhiyun static ulong rv1106_pwm_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
624*4882a593Smuzhiyun u32 sel, con;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun switch (clk_id) {
627*4882a593Smuzhiyun case CLK_PWM0_PERI:
628*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[11]);
629*4882a593Smuzhiyun sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
630*4882a593Smuzhiyun break;
631*4882a593Smuzhiyun case CLK_PWM1_PERI:
632*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[6]);
633*4882a593Smuzhiyun sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
634*4882a593Smuzhiyun break;
635*4882a593Smuzhiyun case CLK_PWM2_PERI:
636*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[6]);
637*4882a593Smuzhiyun sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
638*4882a593Smuzhiyun break;
639*4882a593Smuzhiyun default:
640*4882a593Smuzhiyun return -ENOENT;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun switch (sel) {
644*4882a593Smuzhiyun case CLK_PWM_SEL_100M:
645*4882a593Smuzhiyun return 100 * MHz;
646*4882a593Smuzhiyun case CLK_PWM_SEL_50M:
647*4882a593Smuzhiyun return 100 * MHz;
648*4882a593Smuzhiyun case CLK_PWM_SEL_24M:
649*4882a593Smuzhiyun return OSC_HZ;
650*4882a593Smuzhiyun default:
651*4882a593Smuzhiyun return -ENOENT;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
rv1106_pwm_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)655*4882a593Smuzhiyun static ulong rv1106_pwm_set_clk(struct rv1106_clk_priv *priv,
656*4882a593Smuzhiyun ulong clk_id, ulong rate)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
659*4882a593Smuzhiyun int src_clk;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun if (rate >= 99 * MHz)
662*4882a593Smuzhiyun src_clk = CLK_PWM_SEL_100M;
663*4882a593Smuzhiyun else if (rate >= 48 * MHz)
664*4882a593Smuzhiyun src_clk = CLK_PWM_SEL_50M;
665*4882a593Smuzhiyun else
666*4882a593Smuzhiyun src_clk = CLK_PWM_SEL_24M;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun switch (clk_id) {
669*4882a593Smuzhiyun case CLK_PWM0_PERI:
670*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[11],
671*4882a593Smuzhiyun CLK_PWM0_SEL_MASK,
672*4882a593Smuzhiyun src_clk << CLK_PWM0_SEL_SHIFT);
673*4882a593Smuzhiyun break;
674*4882a593Smuzhiyun case CLK_PWM1_PERI:
675*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[6],
676*4882a593Smuzhiyun CLK_PWM1_SEL_MASK,
677*4882a593Smuzhiyun src_clk << CLK_PWM1_SEL_SHIFT);
678*4882a593Smuzhiyun break;
679*4882a593Smuzhiyun case CLK_PWM2_PERI:
680*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[6],
681*4882a593Smuzhiyun CLK_PWM2_SEL_MASK,
682*4882a593Smuzhiyun src_clk << CLK_PWM2_SEL_SHIFT);
683*4882a593Smuzhiyun break;
684*4882a593Smuzhiyun default:
685*4882a593Smuzhiyun return -ENOENT;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun return rv1106_pwm_get_clk(priv, clk_id);
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun #endif
691*4882a593Smuzhiyun
rv1106_adc_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)692*4882a593Smuzhiyun static ulong rv1106_adc_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
695*4882a593Smuzhiyun u32 div, con;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun switch (clk_id) {
698*4882a593Smuzhiyun case CLK_SARADC:
699*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[6]);
700*4882a593Smuzhiyun div = (con & CLK_SARADC_DIV_MASK) >>
701*4882a593Smuzhiyun CLK_SARADC_DIV_SHIFT;
702*4882a593Smuzhiyun return DIV_TO_RATE(OSC_HZ, div);
703*4882a593Smuzhiyun case CLK_TSADC_TSEN:
704*4882a593Smuzhiyun con = readl(&cru->vo_clksel_con[3]);
705*4882a593Smuzhiyun div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
706*4882a593Smuzhiyun CLK_TSADC_TSEN_DIV_SHIFT;
707*4882a593Smuzhiyun return DIV_TO_RATE(OSC_HZ, div);
708*4882a593Smuzhiyun case CLK_TSADC:
709*4882a593Smuzhiyun con = readl(&cru->vo_clksel_con[3]);
710*4882a593Smuzhiyun div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
711*4882a593Smuzhiyun return DIV_TO_RATE(OSC_HZ, div);
712*4882a593Smuzhiyun default:
713*4882a593Smuzhiyun return -ENOENT;
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun
rv1106_adc_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)717*4882a593Smuzhiyun static ulong rv1106_adc_set_clk(struct rv1106_clk_priv *priv,
718*4882a593Smuzhiyun ulong clk_id, ulong rate)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
721*4882a593Smuzhiyun int src_clk_div;
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun switch (clk_id) {
726*4882a593Smuzhiyun case CLK_SARADC:
727*4882a593Smuzhiyun assert(src_clk_div - 1 <= 7);
728*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[6],
729*4882a593Smuzhiyun CLK_SARADC_DIV_MASK,
730*4882a593Smuzhiyun (src_clk_div - 1) <<
731*4882a593Smuzhiyun CLK_SARADC_DIV_SHIFT);
732*4882a593Smuzhiyun break;
733*4882a593Smuzhiyun case CLK_TSADC_TSEN:
734*4882a593Smuzhiyun assert(src_clk_div - 1 <= 128);
735*4882a593Smuzhiyun rk_clrsetreg(&cru->vo_clksel_con[3],
736*4882a593Smuzhiyun CLK_TSADC_TSEN_DIV_MASK,
737*4882a593Smuzhiyun (src_clk_div - 1) <<
738*4882a593Smuzhiyun CLK_TSADC_TSEN_DIV_SHIFT);
739*4882a593Smuzhiyun break;
740*4882a593Smuzhiyun case CLK_TSADC:
741*4882a593Smuzhiyun assert(src_clk_div - 1 <= 128);
742*4882a593Smuzhiyun rk_clrsetreg(&cru->vo_clksel_con[3],
743*4882a593Smuzhiyun CLK_TSADC_DIV_MASK,
744*4882a593Smuzhiyun (src_clk_div - 1) <<
745*4882a593Smuzhiyun CLK_TSADC_DIV_SHIFT);
746*4882a593Smuzhiyun break;
747*4882a593Smuzhiyun default:
748*4882a593Smuzhiyun return -ENOENT;
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun return rv1106_adc_get_clk(priv, clk_id);
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
754*4882a593Smuzhiyun /*
755*4882a593Smuzhiyun *
756*4882a593Smuzhiyun * rational_best_approximation(31415, 10000,
757*4882a593Smuzhiyun * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
758*4882a593Smuzhiyun *
759*4882a593Smuzhiyun * you may look at given_numerator as a fixed point number,
760*4882a593Smuzhiyun * with the fractional part size described in given_denominator.
761*4882a593Smuzhiyun *
762*4882a593Smuzhiyun * for theoretical background, see:
763*4882a593Smuzhiyun * http://en.wikipedia.org/wiki/Continued_fraction
764*4882a593Smuzhiyun */
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)765*4882a593Smuzhiyun static void rational_best_approximation(unsigned long given_numerator,
766*4882a593Smuzhiyun unsigned long given_denominator,
767*4882a593Smuzhiyun unsigned long max_numerator,
768*4882a593Smuzhiyun unsigned long max_denominator,
769*4882a593Smuzhiyun unsigned long *best_numerator,
770*4882a593Smuzhiyun unsigned long *best_denominator)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun unsigned long n, d, n0, d0, n1, d1;
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun n = given_numerator;
775*4882a593Smuzhiyun d = given_denominator;
776*4882a593Smuzhiyun n0 = 0;
777*4882a593Smuzhiyun d1 = 0;
778*4882a593Smuzhiyun n1 = 1;
779*4882a593Smuzhiyun d0 = 1;
780*4882a593Smuzhiyun for (;;) {
781*4882a593Smuzhiyun unsigned long t, a;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun if (n1 > max_numerator || d1 > max_denominator) {
784*4882a593Smuzhiyun n1 = n0;
785*4882a593Smuzhiyun d1 = d0;
786*4882a593Smuzhiyun break;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun if (d == 0)
789*4882a593Smuzhiyun break;
790*4882a593Smuzhiyun t = d;
791*4882a593Smuzhiyun a = n / d;
792*4882a593Smuzhiyun d = n % d;
793*4882a593Smuzhiyun n = t;
794*4882a593Smuzhiyun t = n0 + a * n1;
795*4882a593Smuzhiyun n0 = n1;
796*4882a593Smuzhiyun n1 = t;
797*4882a593Smuzhiyun t = d0 + a * d1;
798*4882a593Smuzhiyun d0 = d1;
799*4882a593Smuzhiyun d1 = t;
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun *best_numerator = n1;
802*4882a593Smuzhiyun *best_denominator = d1;
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
rv1106_uart_get_rate(struct rv1106_clk_priv * priv,ulong clk_id)805*4882a593Smuzhiyun static ulong rv1106_uart_get_rate(struct rv1106_clk_priv *priv, ulong clk_id)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
808*4882a593Smuzhiyun u32 reg, con, fracdiv, div, src, p_src, p_rate;
809*4882a593Smuzhiyun unsigned long m, n;
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun switch (clk_id) {
812*4882a593Smuzhiyun case SCLK_UART0:
813*4882a593Smuzhiyun reg = 5;
814*4882a593Smuzhiyun break;
815*4882a593Smuzhiyun case SCLK_UART1:
816*4882a593Smuzhiyun reg = 7;
817*4882a593Smuzhiyun break;
818*4882a593Smuzhiyun case SCLK_UART2:
819*4882a593Smuzhiyun reg = 9;
820*4882a593Smuzhiyun break;
821*4882a593Smuzhiyun case SCLK_UART3:
822*4882a593Smuzhiyun reg = 11;
823*4882a593Smuzhiyun break;
824*4882a593Smuzhiyun case SCLK_UART4:
825*4882a593Smuzhiyun reg = 13;
826*4882a593Smuzhiyun break;
827*4882a593Smuzhiyun case SCLK_UART5:
828*4882a593Smuzhiyun reg = 15;
829*4882a593Smuzhiyun break;
830*4882a593Smuzhiyun default:
831*4882a593Smuzhiyun return -ENOENT;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun con = readl(&cru->clksel_con[reg + 2]);
834*4882a593Smuzhiyun src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
835*4882a593Smuzhiyun con = readl(&cru->clksel_con[reg]);
836*4882a593Smuzhiyun div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
837*4882a593Smuzhiyun p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
838*4882a593Smuzhiyun if (p_src == CLK_UART_SRC_SEL_GPLL)
839*4882a593Smuzhiyun p_rate = priv->gpll_hz;
840*4882a593Smuzhiyun else if (p_src == CLK_UART_SRC_SEL_CPLL)
841*4882a593Smuzhiyun p_rate = priv->cpll_hz;
842*4882a593Smuzhiyun else
843*4882a593Smuzhiyun p_rate = 480000000;
844*4882a593Smuzhiyun if (src == CLK_UART_SEL_SRC) {
845*4882a593Smuzhiyun return DIV_TO_RATE(p_rate, div);
846*4882a593Smuzhiyun } else if (src == CLK_UART_SEL_FRAC) {
847*4882a593Smuzhiyun fracdiv = readl(&cru->clksel_con[reg + 1]);
848*4882a593Smuzhiyun n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
849*4882a593Smuzhiyun n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
850*4882a593Smuzhiyun m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
851*4882a593Smuzhiyun m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
852*4882a593Smuzhiyun return DIV_TO_RATE(p_rate, div) * n / m;
853*4882a593Smuzhiyun } else {
854*4882a593Smuzhiyun return OSC_HZ;
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun
rv1106_uart_set_rate(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)858*4882a593Smuzhiyun static ulong rv1106_uart_set_rate(struct rv1106_clk_priv *priv,
859*4882a593Smuzhiyun ulong clk_id, ulong rate)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
862*4882a593Smuzhiyun u32 reg, clk_src, uart_src, div;
863*4882a593Smuzhiyun unsigned long m = 0, n = 0, val;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun if (priv->gpll_hz % rate == 0) {
866*4882a593Smuzhiyun clk_src = CLK_UART_SRC_SEL_GPLL;
867*4882a593Smuzhiyun uart_src = CLK_UART_SEL_SRC;
868*4882a593Smuzhiyun div = DIV_ROUND_UP(priv->gpll_hz, rate);
869*4882a593Smuzhiyun } else if (priv->cpll_hz % rate == 0) {
870*4882a593Smuzhiyun clk_src = CLK_UART_SRC_SEL_CPLL;
871*4882a593Smuzhiyun uart_src = CLK_UART_SEL_SRC;
872*4882a593Smuzhiyun div = DIV_ROUND_UP(priv->gpll_hz, rate);
873*4882a593Smuzhiyun } else if (rate == OSC_HZ) {
874*4882a593Smuzhiyun clk_src = CLK_UART_SRC_SEL_GPLL;
875*4882a593Smuzhiyun uart_src = CLK_UART_SEL_XIN24M;
876*4882a593Smuzhiyun div = 2;
877*4882a593Smuzhiyun } else {
878*4882a593Smuzhiyun clk_src = CLK_UART_SRC_SEL_GPLL;
879*4882a593Smuzhiyun uart_src = CLK_UART_SEL_FRAC;
880*4882a593Smuzhiyun div = 2;
881*4882a593Smuzhiyun rational_best_approximation(rate, priv->gpll_hz / div,
882*4882a593Smuzhiyun GENMASK(16 - 1, 0),
883*4882a593Smuzhiyun GENMASK(16 - 1, 0),
884*4882a593Smuzhiyun &m, &n);
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun switch (clk_id) {
888*4882a593Smuzhiyun case SCLK_UART0:
889*4882a593Smuzhiyun reg = 5;
890*4882a593Smuzhiyun break;
891*4882a593Smuzhiyun case SCLK_UART1:
892*4882a593Smuzhiyun reg = 7;
893*4882a593Smuzhiyun break;
894*4882a593Smuzhiyun case SCLK_UART2:
895*4882a593Smuzhiyun reg = 9;
896*4882a593Smuzhiyun break;
897*4882a593Smuzhiyun case SCLK_UART3:
898*4882a593Smuzhiyun reg = 11;
899*4882a593Smuzhiyun break;
900*4882a593Smuzhiyun case SCLK_UART4:
901*4882a593Smuzhiyun reg = 13;
902*4882a593Smuzhiyun break;
903*4882a593Smuzhiyun case SCLK_UART5:
904*4882a593Smuzhiyun reg = 15;
905*4882a593Smuzhiyun break;
906*4882a593Smuzhiyun default:
907*4882a593Smuzhiyun return -ENOENT;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun rk_clrsetreg(&cru->clksel_con[reg],
910*4882a593Smuzhiyun CLK_UART_SRC_SEL_MASK |
911*4882a593Smuzhiyun CLK_UART_SRC_DIV_MASK,
912*4882a593Smuzhiyun (clk_src << CLK_UART_SRC_SEL_SHIFT) |
913*4882a593Smuzhiyun ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
914*4882a593Smuzhiyun rk_clrsetreg(&cru->clksel_con[reg + 2],
915*4882a593Smuzhiyun CLK_UART_SEL_MASK,
916*4882a593Smuzhiyun uart_src << CLK_UART_SEL_SHIFT);
917*4882a593Smuzhiyun if (m && n) {
918*4882a593Smuzhiyun val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
919*4882a593Smuzhiyun writel(val, &cru->clksel_con[reg + 1]);
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun return rv1106_uart_get_rate(priv, clk_id);
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun
rv1106_vop_get_clk(struct rv1106_clk_priv * priv,ulong clk_id)925*4882a593Smuzhiyun static ulong rv1106_vop_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
926*4882a593Smuzhiyun {
927*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
928*4882a593Smuzhiyun u32 div, sel, con;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun switch (clk_id) {
931*4882a593Smuzhiyun case ACLK_VOP_ROOT:
932*4882a593Smuzhiyun case ACLK_VOP:
933*4882a593Smuzhiyun con = readl(&cru->vo_clksel_con[1]);
934*4882a593Smuzhiyun sel = (con & ACLK_VOP_SEL_MASK) >> ACLK_VOP_SEL_SHIFT;
935*4882a593Smuzhiyun if (sel == ACLK_VOP_SEL_300M)
936*4882a593Smuzhiyun return 300 * MHz;
937*4882a593Smuzhiyun else if (sel == ACLK_VOP_SEL_200M)
938*4882a593Smuzhiyun return 200 * MHz;
939*4882a593Smuzhiyun else if (sel == ACLK_VOP_SEL_100M)
940*4882a593Smuzhiyun return 100 * MHz;
941*4882a593Smuzhiyun else
942*4882a593Smuzhiyun return OSC_HZ;
943*4882a593Smuzhiyun case DCLK_VOP_SRC:
944*4882a593Smuzhiyun case DCLK_VOP:
945*4882a593Smuzhiyun con = readl(&cru->clksel_con[23]);
946*4882a593Smuzhiyun sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
947*4882a593Smuzhiyun div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
948*4882a593Smuzhiyun if (sel == DCLK_VOP_SEL_GPLL)
949*4882a593Smuzhiyun return DIV_TO_RATE(priv->gpll_hz, div);
950*4882a593Smuzhiyun else
951*4882a593Smuzhiyun return DIV_TO_RATE(priv->cpll_hz, div);
952*4882a593Smuzhiyun default:
953*4882a593Smuzhiyun return -ENOENT;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun
rv1106_vop_set_clk(struct rv1106_clk_priv * priv,ulong clk_id,ulong rate)957*4882a593Smuzhiyun static ulong rv1106_vop_set_clk(struct rv1106_clk_priv *priv,
958*4882a593Smuzhiyun ulong clk_id, ulong rate)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
961*4882a593Smuzhiyun int div, sel;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun switch (clk_id) {
964*4882a593Smuzhiyun case ACLK_VOP_ROOT:
965*4882a593Smuzhiyun case ACLK_VOP:
966*4882a593Smuzhiyun if (rate >= 297 * MHz)
967*4882a593Smuzhiyun sel = ACLK_VOP_SEL_300M;
968*4882a593Smuzhiyun else if (rate >= 198 * MHz)
969*4882a593Smuzhiyun sel = ACLK_VOP_SEL_200M;
970*4882a593Smuzhiyun else if (rate >= 99 * MHz)
971*4882a593Smuzhiyun sel = ACLK_VOP_SEL_100M;
972*4882a593Smuzhiyun else
973*4882a593Smuzhiyun sel = ACLK_VOP_SEL_24M;
974*4882a593Smuzhiyun rk_clrsetreg(&cru->vo_clksel_con[1],
975*4882a593Smuzhiyun ACLK_VOP_SEL_MASK,
976*4882a593Smuzhiyun sel << ACLK_VOP_SEL_SHIFT);
977*4882a593Smuzhiyun break;
978*4882a593Smuzhiyun case DCLK_VOP_SRC:
979*4882a593Smuzhiyun case DCLK_VOP:
980*4882a593Smuzhiyun if ((priv->cpll_hz % rate) == 0) {
981*4882a593Smuzhiyun sel = DCLK_VOP_SEL_CPLL;
982*4882a593Smuzhiyun div = DIV_ROUND_UP(priv->cpll_hz, rate);
983*4882a593Smuzhiyun } else {
984*4882a593Smuzhiyun sel = DCLK_VOP_SEL_GPLL;
985*4882a593Smuzhiyun div = DIV_ROUND_UP(priv->gpll_hz, rate);
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun rk_clrsetreg(&cru->clksel_con[23],
988*4882a593Smuzhiyun DCLK_VOP_SEL_MASK |
989*4882a593Smuzhiyun DCLK_VOP_DIV_MASK,
990*4882a593Smuzhiyun sel << DCLK_VOP_SEL_SHIFT |
991*4882a593Smuzhiyun (div - 1) << DCLK_VOP_DIV_SHIFT);
992*4882a593Smuzhiyun break;
993*4882a593Smuzhiyun default:
994*4882a593Smuzhiyun return -ENOENT;
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun return rv1106_vop_get_clk(priv, clk_id);
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun
rv1106_decom_get_clk(struct rv1106_clk_priv * priv)1000*4882a593Smuzhiyun static ulong rv1106_decom_get_clk(struct rv1106_clk_priv *priv)
1001*4882a593Smuzhiyun {
1002*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
1003*4882a593Smuzhiyun u32 sel, con, prate;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun con = readl(&cru->peri_clksel_con[7]);
1006*4882a593Smuzhiyun sel = (con & DCLK_DECOM_SEL_MASK) >>
1007*4882a593Smuzhiyun DCLK_DECOM_SEL_SHIFT;
1008*4882a593Smuzhiyun if (sel == DCLK_DECOM_SEL_400M)
1009*4882a593Smuzhiyun prate = 400 * MHz;
1010*4882a593Smuzhiyun else if (sel == DCLK_DECOM_SEL_200M)
1011*4882a593Smuzhiyun prate = 200 * MHz;
1012*4882a593Smuzhiyun else if (sel == DCLK_DECOM_SEL_100M)
1013*4882a593Smuzhiyun prate = 100 * MHz;
1014*4882a593Smuzhiyun else
1015*4882a593Smuzhiyun prate = OSC_HZ;
1016*4882a593Smuzhiyun return prate;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
rv1106_decom_set_clk(struct rv1106_clk_priv * priv,ulong rate)1019*4882a593Smuzhiyun static ulong rv1106_decom_set_clk(struct rv1106_clk_priv *priv, ulong rate)
1020*4882a593Smuzhiyun {
1021*4882a593Smuzhiyun struct rv1106_cru *cru = priv->cru;
1022*4882a593Smuzhiyun u32 sel;
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun if (rate >= 396 * MHz)
1025*4882a593Smuzhiyun sel = DCLK_DECOM_SEL_400M;
1026*4882a593Smuzhiyun else if (rate >= 198 * MHz)
1027*4882a593Smuzhiyun sel = DCLK_DECOM_SEL_200M;
1028*4882a593Smuzhiyun else if (rate >= 99 * MHz)
1029*4882a593Smuzhiyun sel = DCLK_DECOM_SEL_100M;
1030*4882a593Smuzhiyun else
1031*4882a593Smuzhiyun sel = DCLK_DECOM_SEL_24M;
1032*4882a593Smuzhiyun rk_clrsetreg(&cru->peri_clksel_con[7], DCLK_DECOM_SEL_MASK,
1033*4882a593Smuzhiyun (sel << DCLK_DECOM_SEL_SHIFT));
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun return rv1106_decom_get_clk(priv);
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun #endif
1038*4882a593Smuzhiyun
rv1106_clk_get_rate(struct clk * clk)1039*4882a593Smuzhiyun static ulong rv1106_clk_get_rate(struct clk *clk)
1040*4882a593Smuzhiyun {
1041*4882a593Smuzhiyun struct rv1106_clk_priv *priv = dev_get_priv(clk->dev);
1042*4882a593Smuzhiyun ulong rate = 0;
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun if (!priv->gpll_hz) {
1045*4882a593Smuzhiyun printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1046*4882a593Smuzhiyun return -ENOENT;
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun switch (clk->id) {
1050*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1051*4882a593Smuzhiyun case PLL_APLL:
1052*4882a593Smuzhiyun rate = rockchip_pll_get_rate(&rv1106_pll_clks[APLL], priv->cru,
1053*4882a593Smuzhiyun APLL);
1054*4882a593Smuzhiyun break;
1055*4882a593Smuzhiyun case PLL_DPLL:
1056*4882a593Smuzhiyun rate = rockchip_pll_get_rate(&rv1106_pll_clks[DPLL], priv->cru,
1057*4882a593Smuzhiyun DPLL);
1058*4882a593Smuzhiyun break;
1059*4882a593Smuzhiyun case PLL_CPLL:
1060*4882a593Smuzhiyun rate = rockchip_pll_get_rate(&rv1106_pll_clks[CPLL], priv->cru,
1061*4882a593Smuzhiyun CPLL);
1062*4882a593Smuzhiyun break;
1063*4882a593Smuzhiyun case PLL_GPLL:
1064*4882a593Smuzhiyun rate = rockchip_pll_get_rate(&rv1106_pll_clks[GPLL], priv->cru,
1065*4882a593Smuzhiyun GPLL);
1066*4882a593Smuzhiyun break;
1067*4882a593Smuzhiyun case ACLK_PERI_ROOT:
1068*4882a593Smuzhiyun case HCLK_PERI_ROOT:
1069*4882a593Smuzhiyun case PCLK_PERI_ROOT:
1070*4882a593Smuzhiyun case ACLK_BUS_ROOT:
1071*4882a593Smuzhiyun case PCLK_TOP_ROOT:
1072*4882a593Smuzhiyun case PCLK_PMU_ROOT:
1073*4882a593Smuzhiyun case HCLK_PMU_ROOT:
1074*4882a593Smuzhiyun rate = rv1106_peri_get_clk(priv, clk->id);
1075*4882a593Smuzhiyun break;
1076*4882a593Smuzhiyun #endif
1077*4882a593Smuzhiyun case CLK_CORE_CRYPTO:
1078*4882a593Smuzhiyun case CLK_PKA_CRYPTO:
1079*4882a593Smuzhiyun case ACLK_CRYPTO:
1080*4882a593Smuzhiyun rate = rv1106_crypto_get_clk(priv, clk->id);
1081*4882a593Smuzhiyun break;
1082*4882a593Smuzhiyun case CCLK_SRC_SDMMC:
1083*4882a593Smuzhiyun case CCLK_SRC_EMMC:
1084*4882a593Smuzhiyun case SCLK_SFC:
1085*4882a593Smuzhiyun case HCLK_SDMMC:
1086*4882a593Smuzhiyun case HCLK_EMMC:
1087*4882a593Smuzhiyun case HCLK_SFC:
1088*4882a593Smuzhiyun rate = rv1106_mmc_get_clk(priv, clk->id);
1089*4882a593Smuzhiyun break;
1090*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1091*4882a593Smuzhiyun case CLK_I2C0:
1092*4882a593Smuzhiyun case CLK_I2C1:
1093*4882a593Smuzhiyun case CLK_I2C2:
1094*4882a593Smuzhiyun case CLK_I2C3:
1095*4882a593Smuzhiyun case CLK_I2C4:
1096*4882a593Smuzhiyun rate = rv1106_i2c_get_clk(priv, clk->id);
1097*4882a593Smuzhiyun break;
1098*4882a593Smuzhiyun #endif
1099*4882a593Smuzhiyun case CLK_SPI0:
1100*4882a593Smuzhiyun case CLK_SPI1:
1101*4882a593Smuzhiyun rate = rv1106_spi_get_clk(priv, clk->id);
1102*4882a593Smuzhiyun break;
1103*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1104*4882a593Smuzhiyun case CLK_PWM0_PERI:
1105*4882a593Smuzhiyun case CLK_PWM1_PERI:
1106*4882a593Smuzhiyun case CLK_PWM2_PERI:
1107*4882a593Smuzhiyun rate = rv1106_pwm_get_clk(priv, clk->id);
1108*4882a593Smuzhiyun break;
1109*4882a593Smuzhiyun #endif
1110*4882a593Smuzhiyun case CLK_SARADC:
1111*4882a593Smuzhiyun case CLK_TSADC_TSEN:
1112*4882a593Smuzhiyun case CLK_TSADC:
1113*4882a593Smuzhiyun rate = rv1106_adc_get_clk(priv, clk->id);
1114*4882a593Smuzhiyun break;
1115*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1116*4882a593Smuzhiyun case SCLK_UART0:
1117*4882a593Smuzhiyun case SCLK_UART1:
1118*4882a593Smuzhiyun case SCLK_UART2:
1119*4882a593Smuzhiyun case SCLK_UART3:
1120*4882a593Smuzhiyun case SCLK_UART4:
1121*4882a593Smuzhiyun case SCLK_UART5:
1122*4882a593Smuzhiyun rate = rv1106_uart_get_rate(priv, clk->id);
1123*4882a593Smuzhiyun break;
1124*4882a593Smuzhiyun case DCLK_VOP_SRC:
1125*4882a593Smuzhiyun case DCLK_VOP:
1126*4882a593Smuzhiyun case ACLK_VOP_ROOT:
1127*4882a593Smuzhiyun case ACLK_VOP:
1128*4882a593Smuzhiyun rate = rv1106_vop_get_clk(priv, clk->id);
1129*4882a593Smuzhiyun break;
1130*4882a593Smuzhiyun case DCLK_DECOM:
1131*4882a593Smuzhiyun rate = rv1106_decom_get_clk(priv);
1132*4882a593Smuzhiyun break;
1133*4882a593Smuzhiyun #endif
1134*4882a593Smuzhiyun default:
1135*4882a593Smuzhiyun return -ENOENT;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun return rate;
1139*4882a593Smuzhiyun };
1140*4882a593Smuzhiyun
rv1106_clk_set_rate(struct clk * clk,ulong rate)1141*4882a593Smuzhiyun static ulong rv1106_clk_set_rate(struct clk *clk, ulong rate)
1142*4882a593Smuzhiyun {
1143*4882a593Smuzhiyun struct rv1106_clk_priv *priv = dev_get_priv(clk->dev);
1144*4882a593Smuzhiyun ulong ret = 0;
1145*4882a593Smuzhiyun
1146*4882a593Smuzhiyun if (!priv->gpll_hz) {
1147*4882a593Smuzhiyun printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1148*4882a593Smuzhiyun return -ENOENT;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun switch (clk->id) {
1152*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1153*4882a593Smuzhiyun case PLL_APLL:
1154*4882a593Smuzhiyun ret = rockchip_pll_set_rate(&rv1106_pll_clks[APLL], priv->cru,
1155*4882a593Smuzhiyun APLL, rate);
1156*4882a593Smuzhiyun break;
1157*4882a593Smuzhiyun case PLL_CPLL:
1158*4882a593Smuzhiyun ret = rockchip_pll_set_rate(&rv1106_pll_clks[CPLL], priv->cru,
1159*4882a593Smuzhiyun CPLL, rate);
1160*4882a593Smuzhiyun break;
1161*4882a593Smuzhiyun case PLL_GPLL:
1162*4882a593Smuzhiyun ret = rockchip_pll_set_rate(&rv1106_pll_clks[GPLL], priv->cru,
1163*4882a593Smuzhiyun GPLL, rate);
1164*4882a593Smuzhiyun break;
1165*4882a593Smuzhiyun case ACLK_PERI_ROOT:
1166*4882a593Smuzhiyun case HCLK_PERI_ROOT:
1167*4882a593Smuzhiyun case PCLK_PERI_ROOT:
1168*4882a593Smuzhiyun case ACLK_BUS_ROOT:
1169*4882a593Smuzhiyun case PCLK_TOP_ROOT:
1170*4882a593Smuzhiyun case PCLK_PMU_ROOT:
1171*4882a593Smuzhiyun case HCLK_PMU_ROOT:
1172*4882a593Smuzhiyun ret = rv1106_peri_set_clk(priv, clk->id, rate);
1173*4882a593Smuzhiyun break;
1174*4882a593Smuzhiyun #endif
1175*4882a593Smuzhiyun case CLK_CORE_CRYPTO:
1176*4882a593Smuzhiyun case CLK_PKA_CRYPTO:
1177*4882a593Smuzhiyun case ACLK_CRYPTO:
1178*4882a593Smuzhiyun ret = rv1106_crypto_set_clk(priv, clk->id, rate);
1179*4882a593Smuzhiyun break;
1180*4882a593Smuzhiyun case CCLK_SRC_SDMMC:
1181*4882a593Smuzhiyun case CCLK_SRC_EMMC:
1182*4882a593Smuzhiyun case SCLK_SFC:
1183*4882a593Smuzhiyun case HCLK_SDMMC:
1184*4882a593Smuzhiyun case HCLK_EMMC:
1185*4882a593Smuzhiyun case HCLK_SFC:
1186*4882a593Smuzhiyun ret = rv1106_mmc_set_clk(priv, clk->id, rate);
1187*4882a593Smuzhiyun break;
1188*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1189*4882a593Smuzhiyun case CLK_I2C0:
1190*4882a593Smuzhiyun case CLK_I2C1:
1191*4882a593Smuzhiyun case CLK_I2C2:
1192*4882a593Smuzhiyun case CLK_I2C3:
1193*4882a593Smuzhiyun case CLK_I2C4:
1194*4882a593Smuzhiyun ret = rv1106_i2c_set_clk(priv, clk->id, rate);
1195*4882a593Smuzhiyun break;
1196*4882a593Smuzhiyun #endif
1197*4882a593Smuzhiyun case CLK_SPI0:
1198*4882a593Smuzhiyun case CLK_SPI1:
1199*4882a593Smuzhiyun ret = rv1106_spi_set_clk(priv, clk->id, rate);
1200*4882a593Smuzhiyun break;
1201*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1202*4882a593Smuzhiyun case CLK_PWM0_PERI:
1203*4882a593Smuzhiyun case CLK_PWM1_PERI:
1204*4882a593Smuzhiyun case CLK_PWM2_PERI:
1205*4882a593Smuzhiyun ret = rv1106_pwm_set_clk(priv, clk->id, rate);
1206*4882a593Smuzhiyun break;
1207*4882a593Smuzhiyun #endif
1208*4882a593Smuzhiyun case CLK_SARADC:
1209*4882a593Smuzhiyun case CLK_TSADC_TSEN:
1210*4882a593Smuzhiyun case CLK_TSADC:
1211*4882a593Smuzhiyun ret = rv1106_adc_set_clk(priv, clk->id, rate);
1212*4882a593Smuzhiyun break;
1213*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1214*4882a593Smuzhiyun case SCLK_UART0:
1215*4882a593Smuzhiyun case SCLK_UART1:
1216*4882a593Smuzhiyun case SCLK_UART2:
1217*4882a593Smuzhiyun case SCLK_UART3:
1218*4882a593Smuzhiyun case SCLK_UART4:
1219*4882a593Smuzhiyun case SCLK_UART5:
1220*4882a593Smuzhiyun ret = rv1106_uart_set_rate(priv, clk->id, rate);
1221*4882a593Smuzhiyun break;
1222*4882a593Smuzhiyun case DCLK_VOP_SRC:
1223*4882a593Smuzhiyun case DCLK_VOP:
1224*4882a593Smuzhiyun case ACLK_VOP_ROOT:
1225*4882a593Smuzhiyun case ACLK_VOP:
1226*4882a593Smuzhiyun rate = rv1106_vop_set_clk(priv, clk->id, rate);
1227*4882a593Smuzhiyun break;
1228*4882a593Smuzhiyun case DCLK_DECOM:
1229*4882a593Smuzhiyun rate = rv1106_decom_set_clk(priv, rate);
1230*4882a593Smuzhiyun break;
1231*4882a593Smuzhiyun #endif
1232*4882a593Smuzhiyun default:
1233*4882a593Smuzhiyun return -ENOENT;
1234*4882a593Smuzhiyun }
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun return ret;
1237*4882a593Smuzhiyun };
1238*4882a593Smuzhiyun
rv1106_clk_set_parent(struct clk * clk,struct clk * parent)1239*4882a593Smuzhiyun static int rv1106_clk_set_parent(struct clk *clk, struct clk *parent)
1240*4882a593Smuzhiyun {
1241*4882a593Smuzhiyun switch (clk->id) {
1242*4882a593Smuzhiyun default:
1243*4882a593Smuzhiyun return -ENOENT;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun return 0;
1247*4882a593Smuzhiyun }
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun static struct clk_ops rv1106_clk_ops = {
1250*4882a593Smuzhiyun .get_rate = rv1106_clk_get_rate,
1251*4882a593Smuzhiyun .set_rate = rv1106_clk_set_rate,
1252*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1253*4882a593Smuzhiyun .set_parent = rv1106_clk_set_parent,
1254*4882a593Smuzhiyun #endif
1255*4882a593Smuzhiyun };
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
rv1106_clk_init(struct rv1106_clk_priv * priv)1258*4882a593Smuzhiyun static void rv1106_clk_init(struct rv1106_clk_priv *priv)
1259*4882a593Smuzhiyun {
1260*4882a593Smuzhiyun int ret;
1261*4882a593Smuzhiyun
1262*4882a593Smuzhiyun priv->sync_kernel = false;
1263*4882a593Smuzhiyun if (!priv->armclk_enter_hz) {
1264*4882a593Smuzhiyun priv->armclk_enter_hz =
1265*4882a593Smuzhiyun rockchip_pll_get_rate(&rv1106_pll_clks[APLL],
1266*4882a593Smuzhiyun priv->cru, APLL);
1267*4882a593Smuzhiyun priv->armclk_init_hz = priv->armclk_enter_hz;
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun
1270*4882a593Smuzhiyun if (priv->armclk_init_hz != APLL_HZ) {
1271*4882a593Smuzhiyun ret = rockchip_pll_set_rate(&rv1106_pll_clks[APLL], priv->cru,
1272*4882a593Smuzhiyun APLL, APLL_HZ);
1273*4882a593Smuzhiyun if (!ret)
1274*4882a593Smuzhiyun priv->armclk_init_hz = APLL_HZ;
1275*4882a593Smuzhiyun }
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun if (priv->cpll_hz != CPLL_HZ) {
1278*4882a593Smuzhiyun ret = rockchip_pll_set_rate(&rv1106_pll_clks[CPLL], priv->cru,
1279*4882a593Smuzhiyun CPLL, CPLL_HZ);
1280*4882a593Smuzhiyun if (!ret)
1281*4882a593Smuzhiyun priv->cpll_hz = CPLL_HZ;
1282*4882a593Smuzhiyun }
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun if (priv->gpll_hz != GPLL_HZ) {
1285*4882a593Smuzhiyun ret = rockchip_pll_set_rate(&rv1106_pll_clks[GPLL], priv->cru,
1286*4882a593Smuzhiyun GPLL, GPLL_HZ);
1287*4882a593Smuzhiyun if (!ret)
1288*4882a593Smuzhiyun priv->gpll_hz = GPLL_HZ;
1289*4882a593Smuzhiyun }
1290*4882a593Smuzhiyun }
1291*4882a593Smuzhiyun #endif
1292*4882a593Smuzhiyun
rv1106_clk_probe(struct udevice * dev)1293*4882a593Smuzhiyun static int rv1106_clk_probe(struct udevice *dev)
1294*4882a593Smuzhiyun {
1295*4882a593Smuzhiyun struct rv1106_clk_priv *priv = dev_get_priv(dev);
1296*4882a593Smuzhiyun #ifndef CONFIG_ROCKCHIP_IMAGE_TINY
1297*4882a593Smuzhiyun int ret;
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun rv1106_clk_init(priv);
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1302*4882a593Smuzhiyun ret = clk_set_defaults(dev);
1303*4882a593Smuzhiyun if (ret)
1304*4882a593Smuzhiyun debug("%s clk_set_defaults failed %d\n", __func__, ret);
1305*4882a593Smuzhiyun else
1306*4882a593Smuzhiyun priv->sync_kernel = true;
1307*4882a593Smuzhiyun #else
1308*4882a593Smuzhiyun priv->gpll_hz = GPLL_HZ;
1309*4882a593Smuzhiyun priv->cpll_hz = CPLL_HZ;
1310*4882a593Smuzhiyun #endif
1311*4882a593Smuzhiyun rk_clrsetreg(&priv->cru->core_clksel_con[0],
1312*4882a593Smuzhiyun CLK_CORE_DIV_MASK,
1313*4882a593Smuzhiyun 0 << CLK_CORE_DIV_SHIFT);
1314*4882a593Smuzhiyun
1315*4882a593Smuzhiyun #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_KERNEL_BOOT)
1316*4882a593Smuzhiyun /* increase the aclk_decom frequency */
1317*4882a593Smuzhiyun rv1106_peri_set_clk(priv, ACLK_PERI_ROOT, 400 * MHz);
1318*4882a593Smuzhiyun #endif
1319*4882a593Smuzhiyun return 0;
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun
rv1106_clk_ofdata_to_platdata(struct udevice * dev)1322*4882a593Smuzhiyun static int rv1106_clk_ofdata_to_platdata(struct udevice *dev)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun struct rv1106_clk_priv *priv = dev_get_priv(dev);
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun priv->cru = dev_read_addr_ptr(dev);
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun return 0;
1329*4882a593Smuzhiyun }
1330*4882a593Smuzhiyun
rv1106_clk_bind(struct udevice * dev)1331*4882a593Smuzhiyun static int rv1106_clk_bind(struct udevice *dev)
1332*4882a593Smuzhiyun {
1333*4882a593Smuzhiyun int ret;
1334*4882a593Smuzhiyun struct udevice *sys_child, *sf_child;
1335*4882a593Smuzhiyun struct sysreset_reg *priv;
1336*4882a593Smuzhiyun struct softreset_reg *sf_priv;
1337*4882a593Smuzhiyun
1338*4882a593Smuzhiyun /* The reset driver does not have a device node, so bind it here */
1339*4882a593Smuzhiyun ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1340*4882a593Smuzhiyun &sys_child);
1341*4882a593Smuzhiyun if (ret) {
1342*4882a593Smuzhiyun debug("Warning: No sysreset driver: ret=%d\n", ret);
1343*4882a593Smuzhiyun } else {
1344*4882a593Smuzhiyun priv = malloc(sizeof(struct sysreset_reg));
1345*4882a593Smuzhiyun priv->glb_srst_fst_value = offsetof(struct rv1106_cru,
1346*4882a593Smuzhiyun glb_srst_fst);
1347*4882a593Smuzhiyun priv->glb_srst_snd_value = offsetof(struct rv1106_cru,
1348*4882a593Smuzhiyun glb_srst_snd);
1349*4882a593Smuzhiyun sys_child->priv = priv;
1350*4882a593Smuzhiyun }
1351*4882a593Smuzhiyun
1352*4882a593Smuzhiyun ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1353*4882a593Smuzhiyun dev_ofnode(dev), &sf_child);
1354*4882a593Smuzhiyun if (ret) {
1355*4882a593Smuzhiyun debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1356*4882a593Smuzhiyun } else {
1357*4882a593Smuzhiyun sf_priv = malloc(sizeof(struct softreset_reg));
1358*4882a593Smuzhiyun sf_priv->sf_reset_offset = offsetof(struct rv1106_cru,
1359*4882a593Smuzhiyun pmu_softrst_con[0]);
1360*4882a593Smuzhiyun sf_priv->sf_reset_num = 31745;
1361*4882a593Smuzhiyun sf_child->priv = sf_priv;
1362*4882a593Smuzhiyun }
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun return 0;
1365*4882a593Smuzhiyun }
1366*4882a593Smuzhiyun
1367*4882a593Smuzhiyun static const struct udevice_id rv1106_clk_ids[] = {
1368*4882a593Smuzhiyun { .compatible = "rockchip,rv1106-cru" },
1369*4882a593Smuzhiyun { }
1370*4882a593Smuzhiyun };
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_rv1106_cru) = {
1373*4882a593Smuzhiyun .name = "rockchip_rv1106_cru",
1374*4882a593Smuzhiyun .id = UCLASS_CLK,
1375*4882a593Smuzhiyun .of_match = rv1106_clk_ids,
1376*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct rv1106_clk_priv),
1377*4882a593Smuzhiyun .ofdata_to_platdata = rv1106_clk_ofdata_to_platdata,
1378*4882a593Smuzhiyun .ops = &rv1106_clk_ops,
1379*4882a593Smuzhiyun .bind = rv1106_clk_bind,
1380*4882a593Smuzhiyun .probe = rv1106_clk_probe,
1381*4882a593Smuzhiyun };
1382*4882a593Smuzhiyun
rv1106_grfclk_get_rate(struct clk * clk)1383*4882a593Smuzhiyun static ulong rv1106_grfclk_get_rate(struct clk *clk)
1384*4882a593Smuzhiyun {
1385*4882a593Smuzhiyun struct udevice *cru_dev;
1386*4882a593Smuzhiyun struct rv1106_clk_priv *cru_priv;
1387*4882a593Smuzhiyun int ret;
1388*4882a593Smuzhiyun ulong rate = 0;
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun ret = uclass_get_device_by_driver(UCLASS_CLK,
1391*4882a593Smuzhiyun DM_GET_DRIVER(rockchip_rv1106_cru),
1392*4882a593Smuzhiyun &cru_dev);
1393*4882a593Smuzhiyun if (ret) {
1394*4882a593Smuzhiyun printf("%s: could not find cru device\n", __func__);
1395*4882a593Smuzhiyun return ret;
1396*4882a593Smuzhiyun }
1397*4882a593Smuzhiyun cru_priv = dev_get_priv(cru_dev);
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun switch (clk->id) {
1400*4882a593Smuzhiyun case SCLK_EMMC_SAMPLE:
1401*4882a593Smuzhiyun rate = rv1106_mmc_get_clk(cru_priv, CCLK_SRC_EMMC) / 2;
1402*4882a593Smuzhiyun break;
1403*4882a593Smuzhiyun case SCLK_SDMMC_SAMPLE:
1404*4882a593Smuzhiyun rate = rv1106_mmc_get_clk(cru_priv, CCLK_SRC_SDMMC) / 2;
1405*4882a593Smuzhiyun break;
1406*4882a593Smuzhiyun case SCLK_SDIO_SAMPLE:
1407*4882a593Smuzhiyun rate = rv1106_mmc_get_clk(cru_priv, CCLK_SRC_SDIO) / 2;
1408*4882a593Smuzhiyun break;
1409*4882a593Smuzhiyun default:
1410*4882a593Smuzhiyun return -ENOENT;
1411*4882a593Smuzhiyun }
1412*4882a593Smuzhiyun
1413*4882a593Smuzhiyun return rate;
1414*4882a593Smuzhiyun };
1415*4882a593Smuzhiyun
1416*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAY_SEL BIT(10)
1417*4882a593Smuzhiyun #define ROCKCHIP_MMC_DEGREE_MASK 0x3
1418*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
1419*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun #define PSECS_PER_SEC 1000000000000LL
1422*4882a593Smuzhiyun /*
1423*4882a593Smuzhiyun * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1424*4882a593Smuzhiyun * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1425*4882a593Smuzhiyun */
1426*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1427*4882a593Smuzhiyun
rv1106_mmc_get_phase(struct clk * clk)1428*4882a593Smuzhiyun int rv1106_mmc_get_phase(struct clk *clk)
1429*4882a593Smuzhiyun {
1430*4882a593Smuzhiyun struct rv1106_grf_clk_priv *priv = dev_get_priv(clk->dev);
1431*4882a593Smuzhiyun u32 raw_value = 0, delay_num;
1432*4882a593Smuzhiyun u16 degrees = 0;
1433*4882a593Smuzhiyun ulong rate;
1434*4882a593Smuzhiyun
1435*4882a593Smuzhiyun rate = rv1106_grfclk_get_rate(clk);
1436*4882a593Smuzhiyun if (rate < 0)
1437*4882a593Smuzhiyun return rate;
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun if (clk->id == SCLK_EMMC_SAMPLE)
1440*4882a593Smuzhiyun raw_value = readl(&priv->grf->emmc_con1);
1441*4882a593Smuzhiyun else if (clk->id == SCLK_SDMMC_SAMPLE)
1442*4882a593Smuzhiyun raw_value = readl(&priv->grf->sdmmc_con1);
1443*4882a593Smuzhiyun else if (clk->id == SCLK_SDIO_SAMPLE)
1444*4882a593Smuzhiyun raw_value = readl(&priv->grf->sdio_con1);
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun raw_value >>= 1;
1447*4882a593Smuzhiyun degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
1448*4882a593Smuzhiyun
1449*4882a593Smuzhiyun if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1450*4882a593Smuzhiyun /* degrees/delaynum * 10000 */
1451*4882a593Smuzhiyun unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1452*4882a593Smuzhiyun 36 * (rate / 1000000);
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1455*4882a593Smuzhiyun delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1456*4882a593Smuzhiyun degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun return degrees % 360;
1460*4882a593Smuzhiyun }
1461*4882a593Smuzhiyun
rv1106_mmc_set_phase(struct clk * clk,u32 degrees)1462*4882a593Smuzhiyun int rv1106_mmc_set_phase(struct clk *clk, u32 degrees)
1463*4882a593Smuzhiyun {
1464*4882a593Smuzhiyun struct rv1106_grf_clk_priv *priv = dev_get_priv(clk->dev);
1465*4882a593Smuzhiyun u8 nineties, remainder, delay_num;
1466*4882a593Smuzhiyun u32 raw_value, delay;
1467*4882a593Smuzhiyun ulong rate;
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun rate = rv1106_grfclk_get_rate(clk);
1470*4882a593Smuzhiyun if (rate < 0)
1471*4882a593Smuzhiyun return rate;
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun nineties = degrees / 90;
1474*4882a593Smuzhiyun remainder = (degrees % 90);
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun /*
1477*4882a593Smuzhiyun * Convert to delay; do a little extra work to make sure we
1478*4882a593Smuzhiyun * don't overflow 32-bit / 64-bit numbers.
1479*4882a593Smuzhiyun */
1480*4882a593Smuzhiyun delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1481*4882a593Smuzhiyun delay *= remainder;
1482*4882a593Smuzhiyun delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1483*4882a593Smuzhiyun (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun delay_num = (u8)min_t(u32, delay, 255);
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1488*4882a593Smuzhiyun raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1489*4882a593Smuzhiyun raw_value |= nineties;
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun raw_value <<= 1;
1492*4882a593Smuzhiyun if (clk->id == SCLK_EMMC_SAMPLE)
1493*4882a593Smuzhiyun writel(raw_value | 0xffff0000, &priv->grf->emmc_con1);
1494*4882a593Smuzhiyun else if (clk->id == SCLK_SDMMC_SAMPLE)
1495*4882a593Smuzhiyun writel(raw_value | 0xffff0000, &priv->grf->sdmmc_con1);
1496*4882a593Smuzhiyun else if (clk->id == SCLK_SDIO_SAMPLE)
1497*4882a593Smuzhiyun writel(raw_value | 0xffff0000, &priv->grf->sdio_con1);
1498*4882a593Smuzhiyun
1499*4882a593Smuzhiyun debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1500*4882a593Smuzhiyun degrees, delay_num, raw_value, rv1106_mmc_get_phase(clk));
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun return 0;
1503*4882a593Smuzhiyun }
1504*4882a593Smuzhiyun
rv1106_grfclk_get_phase(struct clk * clk)1505*4882a593Smuzhiyun static int rv1106_grfclk_get_phase(struct clk *clk)
1506*4882a593Smuzhiyun {
1507*4882a593Smuzhiyun int ret;
1508*4882a593Smuzhiyun
1509*4882a593Smuzhiyun debug("%s %ld\n", __func__, clk->id);
1510*4882a593Smuzhiyun switch (clk->id) {
1511*4882a593Smuzhiyun case SCLK_EMMC_SAMPLE:
1512*4882a593Smuzhiyun case SCLK_SDMMC_SAMPLE:
1513*4882a593Smuzhiyun case SCLK_SDIO_SAMPLE:
1514*4882a593Smuzhiyun ret = rv1106_mmc_get_phase(clk);
1515*4882a593Smuzhiyun break;
1516*4882a593Smuzhiyun default:
1517*4882a593Smuzhiyun return -ENOENT;
1518*4882a593Smuzhiyun }
1519*4882a593Smuzhiyun return ret;
1520*4882a593Smuzhiyun }
1521*4882a593Smuzhiyun
rv1106_grfclk_set_phase(struct clk * clk,int degrees)1522*4882a593Smuzhiyun static int rv1106_grfclk_set_phase(struct clk *clk, int degrees)
1523*4882a593Smuzhiyun {
1524*4882a593Smuzhiyun int ret;
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun debug("%s %ld\n", __func__, clk->id);
1527*4882a593Smuzhiyun switch (clk->id) {
1528*4882a593Smuzhiyun case SCLK_EMMC_SAMPLE:
1529*4882a593Smuzhiyun case SCLK_SDMMC_SAMPLE:
1530*4882a593Smuzhiyun case SCLK_SDIO_SAMPLE:
1531*4882a593Smuzhiyun ret = rv1106_mmc_set_phase(clk, degrees);
1532*4882a593Smuzhiyun break;
1533*4882a593Smuzhiyun default:
1534*4882a593Smuzhiyun return -ENOENT;
1535*4882a593Smuzhiyun }
1536*4882a593Smuzhiyun
1537*4882a593Smuzhiyun return ret;
1538*4882a593Smuzhiyun }
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun static struct clk_ops rv1106_grfclk_ops = {
1541*4882a593Smuzhiyun .get_rate = rv1106_grfclk_get_rate,
1542*4882a593Smuzhiyun .get_phase = rv1106_grfclk_get_phase,
1543*4882a593Smuzhiyun .set_phase = rv1106_grfclk_set_phase,
1544*4882a593Smuzhiyun };
1545*4882a593Smuzhiyun
rv1106_grfclk_probe(struct udevice * dev)1546*4882a593Smuzhiyun static int rv1106_grfclk_probe(struct udevice *dev)
1547*4882a593Smuzhiyun {
1548*4882a593Smuzhiyun struct rv1106_grf_clk_priv *priv = dev_get_priv(dev);
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1551*4882a593Smuzhiyun if (IS_ERR(priv->grf))
1552*4882a593Smuzhiyun return PTR_ERR(priv->grf);
1553*4882a593Smuzhiyun
1554*4882a593Smuzhiyun return 0;
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun
rv1106_grfclk_ofdata_to_platdata(struct udevice * dev)1557*4882a593Smuzhiyun static int rv1106_grfclk_ofdata_to_platdata(struct udevice *dev)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun return 0;
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun
rv1106_grfclk_bind(struct udevice * dev)1562*4882a593Smuzhiyun static int rv1106_grfclk_bind(struct udevice *dev)
1563*4882a593Smuzhiyun {
1564*4882a593Smuzhiyun return 0;
1565*4882a593Smuzhiyun }
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun static const struct udevice_id rv1106_grfclk_ids[] = {
1568*4882a593Smuzhiyun { .compatible = "rockchip,rv1106-grf-cru" },
1569*4882a593Smuzhiyun { }
1570*4882a593Smuzhiyun };
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_rv1106_grf_cru) = {
1573*4882a593Smuzhiyun .name = "rockchip_rv1106_grf_cru",
1574*4882a593Smuzhiyun .id = UCLASS_CLK,
1575*4882a593Smuzhiyun .of_match = rv1106_grfclk_ids,
1576*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct rv1106_grf_clk_priv),
1577*4882a593Smuzhiyun .ofdata_to_platdata = rv1106_grfclk_ofdata_to_platdata,
1578*4882a593Smuzhiyun .ops = &rv1106_grfclk_ops,
1579*4882a593Smuzhiyun .bind = rv1106_grfclk_bind,
1580*4882a593Smuzhiyun .probe = rv1106_grfclk_probe,
1581*4882a593Smuzhiyun };
1582*4882a593Smuzhiyun
1583*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
1584*4882a593Smuzhiyun /**
1585*4882a593Smuzhiyun * soc_clk_dump() - Print clock frequencies
1586*4882a593Smuzhiyun * Returns zero on success
1587*4882a593Smuzhiyun *
1588*4882a593Smuzhiyun * Implementation for the clk dump command.
1589*4882a593Smuzhiyun */
soc_clk_dump(void)1590*4882a593Smuzhiyun int soc_clk_dump(void)
1591*4882a593Smuzhiyun {
1592*4882a593Smuzhiyun struct udevice *cru_dev;
1593*4882a593Smuzhiyun struct rv1106_clk_priv *priv;
1594*4882a593Smuzhiyun const struct rv1106_clk_info *clk_dump;
1595*4882a593Smuzhiyun struct clk clk;
1596*4882a593Smuzhiyun unsigned long clk_count = ARRAY_SIZE(clks_dump);
1597*4882a593Smuzhiyun unsigned long rate;
1598*4882a593Smuzhiyun int i, ret;
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun ret = uclass_get_device_by_driver(UCLASS_CLK,
1601*4882a593Smuzhiyun DM_GET_DRIVER(rockchip_rv1106_cru),
1602*4882a593Smuzhiyun &cru_dev);
1603*4882a593Smuzhiyun if (ret) {
1604*4882a593Smuzhiyun printf("%s failed to get cru device\n", __func__);
1605*4882a593Smuzhiyun return ret;
1606*4882a593Smuzhiyun }
1607*4882a593Smuzhiyun
1608*4882a593Smuzhiyun priv = dev_get_priv(cru_dev);
1609*4882a593Smuzhiyun printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1610*4882a593Smuzhiyun priv->sync_kernel ? "sync kernel" : "uboot",
1611*4882a593Smuzhiyun priv->armclk_enter_hz / 1000,
1612*4882a593Smuzhiyun priv->armclk_init_hz / 1000,
1613*4882a593Smuzhiyun priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1614*4882a593Smuzhiyun priv->set_armclk_rate ? " KHz" : "N/A");
1615*4882a593Smuzhiyun for (i = 0; i < clk_count; i++) {
1616*4882a593Smuzhiyun clk_dump = &clks_dump[i];
1617*4882a593Smuzhiyun if (clk_dump->name) {
1618*4882a593Smuzhiyun clk.id = clk_dump->id;
1619*4882a593Smuzhiyun if (clk_dump->is_cru)
1620*4882a593Smuzhiyun ret = clk_request(cru_dev, &clk);
1621*4882a593Smuzhiyun if (ret < 0)
1622*4882a593Smuzhiyun return ret;
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun rate = clk_get_rate(&clk);
1625*4882a593Smuzhiyun clk_free(&clk);
1626*4882a593Smuzhiyun if (i == 0) {
1627*4882a593Smuzhiyun if (rate < 0)
1628*4882a593Smuzhiyun printf(" %s %s\n", clk_dump->name,
1629*4882a593Smuzhiyun "unknown");
1630*4882a593Smuzhiyun else
1631*4882a593Smuzhiyun printf(" %s %lu KHz\n", clk_dump->name,
1632*4882a593Smuzhiyun rate / 1000);
1633*4882a593Smuzhiyun } else {
1634*4882a593Smuzhiyun if (rate < 0)
1635*4882a593Smuzhiyun printf(" %s %s\n", clk_dump->name,
1636*4882a593Smuzhiyun "unknown");
1637*4882a593Smuzhiyun else
1638*4882a593Smuzhiyun printf(" %s %lu KHz\n", clk_dump->name,
1639*4882a593Smuzhiyun rate / 1000);
1640*4882a593Smuzhiyun }
1641*4882a593Smuzhiyun }
1642*4882a593Smuzhiyun }
1643*4882a593Smuzhiyun
1644*4882a593Smuzhiyun return 0;
1645*4882a593Smuzhiyun }
1646*4882a593Smuzhiyun #endif
1647