1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  * Author: Andy Yan <andy.yan@rock-chips.com>
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <syscon.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/cru_rk3368.h>
14 #include <asm/arch/hardware.h>
15 #include <asm/io.h>
16 #include <dm/lists.h>
17 #include <dt-bindings/clock/rk3368-cru.h>
18 
19 DECLARE_GLOBAL_DATA_PTR;
20 
21 struct pll_div {
22 	u32 nr;
23 	u32 nf;
24 	u32 no;
25 };
26 
27 #define OSC_HZ		(24 * 1000 * 1000)
28 #define APLL_L_HZ	(800 * 1000 * 1000)
29 #define APLL_B_HZ	(816 * 1000 * 1000)
30 #define GPLL_HZ		(576 * 1000 * 1000)
31 #define CPLL_HZ		(400 * 1000 * 1000)
32 
33 #define RATE_TO_DIV(input_rate, output_rate) \
34 		((input_rate) / (output_rate) - 1);
35 
36 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
37 
38 #define PLL_DIVISORS(hz, _nr, _no) { \
39 	.nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no}; \
40 	_Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
41 		       (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \
42 		       "divisors on line " __stringify(__LINE__));
43 
44 static const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2);
45 static const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2);
46 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2);
47 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6);
48 
49 /* Get pll rate by id */
50 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru,
51 				   enum rk3368_pll_id pll_id)
52 {
53 	uint32_t nr, no, nf;
54 	uint32_t con;
55 	struct rk3368_pll *pll = &cru->pll[pll_id];
56 
57 	con = readl(&pll->con3);
58 
59 	switch ((con & PLL_MODE_MASK) >> PLL_MODE_SHIFT) {
60 	case PLL_MODE_SLOW:
61 		return OSC_HZ;
62 	case PLL_MODE_NORMAL:
63 		con = readl(&pll->con0);
64 		no = ((con & PLL_OD_MASK) >> PLL_OD_SHIFT) + 1;
65 		nr = ((con & PLL_NR_MASK) >> PLL_NR_SHIFT) + 1;
66 		con = readl(&pll->con1);
67 		nf = ((con & PLL_NF_MASK) >> PLL_NF_SHIFT) + 1;
68 
69 		return (24 * nf / (nr * no)) * 1000000;
70 	case PLL_MODE_DEEP_SLOW:
71 	default:
72 		return 32768;
73 	}
74 }
75 
76 static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id,
77 			 const struct pll_div *div, bool has_bwadj)
78 {
79 	struct rk3368_pll *pll = &cru->pll[pll_id];
80 	/* All PLLs have same VCO and output frequency range restrictions*/
81 	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
82 	uint output_hz = vco_hz / div->no;
83 
84 	debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
85 	      pll, div->nf, div->nr, div->no, vco_hz, output_hz);
86 
87 	/* enter slow mode and reset pll */
88 	rk_clrsetreg(&pll->con3, PLL_MODE_MASK | PLL_RESET_MASK,
89 		     PLL_RESET << PLL_RESET_SHIFT);
90 
91 	rk_clrsetreg(&pll->con0, PLL_NR_MASK | PLL_OD_MASK,
92 		     ((div->nr - 1) << PLL_NR_SHIFT) |
93 		     ((div->no - 1) << PLL_OD_SHIFT));
94 	writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1);
95 	udelay(10);
96 
97 	/* return from reset */
98 	rk_clrreg(&pll->con3, PLL_RESET_MASK);
99 
100 	/* waiting for pll lock */
101 	while (!(readl(&pll->con1) & PLL_LOCK_STA))
102 		udelay(1);
103 
104 	rk_clrsetreg(&pll->con3, PLL_MODE_MASK,
105 		     PLL_MODE_NORMAL << PLL_MODE_SHIFT);
106 
107 	return 0;
108 }
109 
110 static void rkclk_init(struct rk3368_cru *cru)
111 {
112 	u32 apllb, aplll, dpll, cpll, gpll;
113 
114 	rkclk_set_pll(cru, APLLB, &apll_b_init_cfg, false);
115 	rkclk_set_pll(cru, APLLL, &apll_l_init_cfg, false);
116 	rkclk_set_pll(cru, GPLL, &gpll_init_cfg, false);
117 	rkclk_set_pll(cru, CPLL, &cpll_init_cfg, false);
118 
119 	apllb = rkclk_pll_get_rate(cru, APLLB);
120 	aplll = rkclk_pll_get_rate(cru, APLLL);
121 	dpll = rkclk_pll_get_rate(cru, DPLL);
122 	cpll = rkclk_pll_get_rate(cru, CPLL);
123 	gpll = rkclk_pll_get_rate(cru, GPLL);
124 
125 	debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n",
126 	       __func__, apllb, aplll, dpll, cpll, gpll);
127 }
128 
129 static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id)
130 {
131 	u32 div, con, con_id, rate;
132 	u32 pll_rate;
133 
134 	switch (clk_id) {
135 	case SCLK_SDMMC:
136 		con_id = 50;
137 		break;
138 	case SCLK_EMMC:
139 		con_id = 51;
140 		break;
141 	case SCLK_SDIO0:
142 		con_id = 48;
143 		break;
144 	default:
145 		return -EINVAL;
146 	}
147 
148 	con = readl(&cru->clksel_con[con_id]);
149 	switch ((con & MMC_PLL_SEL_MASK) >> MMC_PLL_SEL_SHIFT) {
150 	case MMC_PLL_SEL_GPLL:
151 		pll_rate = rkclk_pll_get_rate(cru, GPLL);
152 		break;
153 	case MMC_PLL_SEL_24M:
154 		pll_rate = OSC_HZ;
155 		break;
156 	case MMC_PLL_SEL_CPLL:
157 	case MMC_PLL_SEL_USBPHY_480M:
158 	default:
159 		return -EINVAL;
160 	}
161 	div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT;
162 	rate = DIV_TO_RATE(pll_rate, div);
163 
164 	return rate >> 1;
165 }
166 
167 static ulong rk3368_mmc_set_clk(struct rk3368_cru *cru,
168 				ulong clk_id, ulong rate)
169 {
170 	u32 div;
171 	u32 con_id;
172 	u32 gpll_rate = rkclk_pll_get_rate(cru, GPLL);
173 
174 	div = RATE_TO_DIV(gpll_rate, rate << 1);
175 
176 	switch (clk_id) {
177 	case SCLK_SDMMC:
178 		con_id = 50;
179 		break;
180 	case SCLK_EMMC:
181 		con_id = 51;
182 		break;
183 	case SCLK_SDIO0:
184 		con_id = 48;
185 		break;
186 	default:
187 		return -EINVAL;
188 	}
189 
190 	if (div > 0x3f) {
191 		div = RATE_TO_DIV(OSC_HZ, rate);
192 		rk_clrsetreg(&cru->clksel_con[con_id],
193 			     MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK,
194 			     (MMC_PLL_SEL_24M << MMC_PLL_SEL_SHIFT) |
195 			     (div << MMC_CLK_DIV_SHIFT));
196 	} else {
197 		rk_clrsetreg(&cru->clksel_con[con_id],
198 			     MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK,
199 			     (MMC_PLL_SEL_GPLL << MMC_PLL_SEL_SHIFT) |
200 			     div << MMC_CLK_DIV_SHIFT);
201 	}
202 
203 	return rk3368_mmc_get_clk(cru, clk_id);
204 }
205 
206 static ulong rk3368_clk_get_rate(struct clk *clk)
207 {
208 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
209 	ulong rate = 0;
210 
211 	debug("%s id:%ld\n", __func__, clk->id);
212 	switch (clk->id) {
213 	case HCLK_SDMMC:
214 	case HCLK_EMMC:
215 		rate = rk3368_mmc_get_clk(priv->cru, clk->id);
216 		break;
217 	default:
218 		return -ENOENT;
219 	}
220 
221 	return rate;
222 }
223 
224 static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
225 {
226 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
227 	ulong ret = 0;
228 
229 	debug("%s id:%ld rate:%ld\n", __func__, clk->id, rate);
230 	switch (clk->id) {
231 	case SCLK_SDMMC:
232 	case SCLK_EMMC:
233 		ret = rk3368_mmc_set_clk(priv->cru, clk->id, rate);
234 		break;
235 	default:
236 		return -ENOENT;
237 	}
238 
239 	return ret;
240 }
241 
242 static struct clk_ops rk3368_clk_ops = {
243 	.get_rate = rk3368_clk_get_rate,
244 	.set_rate = rk3368_clk_set_rate,
245 };
246 
247 static int rk3368_clk_probe(struct udevice *dev)
248 {
249 	struct rk3368_clk_priv *priv = dev_get_priv(dev);
250 
251 	rkclk_init(priv->cru);
252 
253 	return 0;
254 }
255 
256 static int rk3368_clk_ofdata_to_platdata(struct udevice *dev)
257 {
258 	struct rk3368_clk_priv *priv = dev_get_priv(dev);
259 
260 	priv->cru = (struct rk3368_cru *)devfdt_get_addr(dev);
261 
262 	return 0;
263 }
264 
265 static int rk3368_clk_bind(struct udevice *dev)
266 {
267 	int ret;
268 
269 	/* The reset driver does not have a device node, so bind it here */
270 	ret = device_bind_driver(gd->dm_root, "rk3368_sysreset", "reset", &dev);
271 	if (ret)
272 		error("bind RK3368 reset driver failed: ret=%d\n", ret);
273 
274 	return ret;
275 }
276 
277 static const struct udevice_id rk3368_clk_ids[] = {
278 	{ .compatible = "rockchip,rk3368-cru" },
279 	{ }
280 };
281 
282 U_BOOT_DRIVER(rockchip_rk3368_cru) = {
283 	.name		= "rockchip_rk3368_cru",
284 	.id		= UCLASS_CLK,
285 	.of_match	= rk3368_clk_ids,
286 	.priv_auto_alloc_size = sizeof(struct rk3368_cru),
287 	.ofdata_to_platdata = rk3368_clk_ofdata_to_platdata,
288 	.ops		= &rk3368_clk_ops,
289 	.bind		= rk3368_clk_bind,
290 	.probe		= rk3368_clk_probe,
291 };
292