1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2019 DENX Software Engineering
4 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
5 */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <div64.h>
10 #include <malloc.h>
11 #include <clk-uclass.h>
12 #include <dm/device.h>
13 #include <dm/devres.h>
14 #include <dm/uclass.h>
15 #include <clk.h>
16 #include "clk.h"
17 #include <linux/err.h>
18
19 #define UBOOT_DM_CLK_IMX_PLLV3_GENERIC "imx_clk_pllv3_generic"
20 #define UBOOT_DM_CLK_IMX_PLLV3_SYS "imx_clk_pllv3_sys"
21 #define UBOOT_DM_CLK_IMX_PLLV3_USB "imx_clk_pllv3_usb"
22 #define UBOOT_DM_CLK_IMX_PLLV3_AV "imx_clk_pllv3_av"
23 #define UBOOT_DM_CLK_IMX_PLLV3_ENET "imx_clk_pllv3_enet"
24 #define UBOOT_DM_CLK_IMX_PLLV3_GENV2 "imx_clk_pllv3_genericv2"
25
26 #define PLL_NUM_OFFSET 0x10
27 #define PLL_DENOM_OFFSET 0x20
28
29 #define BM_PLL_POWER (0x1 << 12)
30 #define BM_PLL_POWER_V2 (0x1 << 21)
31 #define BM_PLL_ENABLE (0x1 << 13)
32 #define BM_PLL_LOCK (0x1 << 31)
33 #define BM_PLL_LOCK_V2 (0x1 << 29)
34
35 struct clk_pllv3 {
36 struct clk clk;
37 void __iomem *base;
38 u32 power_bit;
39 bool powerup_set;
40 u32 lock_bit;
41 u32 enable_bit;
42 u32 div_mask;
43 u32 div_shift;
44 unsigned long ref_clock;
45 };
46
47 #define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk)
48
clk_pllv3_genericv2_get_rate(struct clk * clk)49 static ulong clk_pllv3_genericv2_get_rate(struct clk *clk)
50 {
51 struct clk_pllv3 *pll = to_clk_pllv3(dev_get_clk_ptr(clk->dev));
52 unsigned long parent_rate = clk_get_parent_rate(clk);
53
54 u32 div = (readl(pll->base) >> pll->div_shift) & pll->div_mask;
55
56 return (div == 0) ? parent_rate * 22 : parent_rate * 20;
57 }
58
clk_pllv3_genericv2_set_rate(struct clk * clk,ulong rate)59 static ulong clk_pllv3_genericv2_set_rate(struct clk *clk, ulong rate)
60 {
61 struct clk_pllv3 *pll = to_clk_pllv3(clk);
62 unsigned long parent_rate = clk_get_parent_rate(clk);
63
64 u32 div = (readl(pll->base) >> pll->div_shift) & pll->div_mask;
65 u32 val = (div == 0) ? parent_rate * 22 : parent_rate * 20;
66
67 if (rate == val)
68 return 0;
69
70 return -EINVAL;
71 }
72
clk_pllv3_generic_get_rate(struct clk * clk)73 static ulong clk_pllv3_generic_get_rate(struct clk *clk)
74 {
75 struct clk_pllv3 *pll = to_clk_pllv3(dev_get_clk_ptr(clk->dev));
76 unsigned long parent_rate = clk_get_parent_rate(clk);
77
78 u32 div = (readl(pll->base) >> pll->div_shift) & pll->div_mask;
79
80 return (div == 1) ? parent_rate * 22 : parent_rate * 20;
81 }
82
clk_pllv3_generic_set_rate(struct clk * clk,ulong rate)83 static ulong clk_pllv3_generic_set_rate(struct clk *clk, ulong rate)
84 {
85 struct clk_pllv3 *pll = to_clk_pllv3(clk);
86 unsigned long parent_rate = clk_get_parent_rate(clk);
87 u32 val, div;
88
89 if (rate == parent_rate * 22)
90 div = 1;
91 else if (rate == parent_rate * 20)
92 div = 0;
93 else
94 return -EINVAL;
95
96 val = readl(pll->base);
97 val &= ~(pll->div_mask << pll->div_shift);
98 val |= (div << pll->div_shift);
99 writel(val, pll->base);
100
101 /* Wait for PLL to lock */
102 while (!(readl(pll->base) & pll->lock_bit))
103 ;
104
105 return 0;
106 }
107
clk_pllv3_generic_enable(struct clk * clk)108 static int clk_pllv3_generic_enable(struct clk *clk)
109 {
110 struct clk_pllv3 *pll = to_clk_pllv3(clk);
111 u32 val;
112
113 val = readl(pll->base);
114 if (pll->powerup_set)
115 val |= pll->power_bit;
116 else
117 val &= ~pll->power_bit;
118
119 val |= pll->enable_bit;
120
121 writel(val, pll->base);
122
123 return 0;
124 }
125
clk_pllv3_generic_disable(struct clk * clk)126 static int clk_pllv3_generic_disable(struct clk *clk)
127 {
128 struct clk_pllv3 *pll = to_clk_pllv3(clk);
129 u32 val;
130
131 val = readl(pll->base);
132 if (pll->powerup_set)
133 val &= ~pll->power_bit;
134 else
135 val |= pll->power_bit;
136
137 val &= ~pll->enable_bit;
138
139 writel(val, pll->base);
140
141 return 0;
142 }
143
144 static const struct clk_ops clk_pllv3_generic_ops = {
145 .get_rate = clk_pllv3_generic_get_rate,
146 .enable = clk_pllv3_generic_enable,
147 .disable = clk_pllv3_generic_disable,
148 .set_rate = clk_pllv3_generic_set_rate,
149 };
150
151 static const struct clk_ops clk_pllv3_genericv2_ops = {
152 .get_rate = clk_pllv3_genericv2_get_rate,
153 .enable = clk_pllv3_generic_enable,
154 .disable = clk_pllv3_generic_disable,
155 .set_rate = clk_pllv3_genericv2_set_rate,
156 };
157
clk_pllv3_sys_get_rate(struct clk * clk)158 static ulong clk_pllv3_sys_get_rate(struct clk *clk)
159 {
160 struct clk_pllv3 *pll = to_clk_pllv3(clk);
161 unsigned long parent_rate = clk_get_parent_rate(clk);
162 u32 div = readl(pll->base) & pll->div_mask;
163
164 return parent_rate * div / 2;
165 }
166
clk_pllv3_sys_set_rate(struct clk * clk,ulong rate)167 static ulong clk_pllv3_sys_set_rate(struct clk *clk, ulong rate)
168 {
169 struct clk_pllv3 *pll = to_clk_pllv3(clk);
170 unsigned long parent_rate = clk_get_parent_rate(clk);
171 unsigned long min_rate;
172 unsigned long max_rate;
173 u32 val, div;
174
175 if (parent_rate == 0)
176 return -EINVAL;
177
178 min_rate = parent_rate * 54 / 2;
179 max_rate = parent_rate * 108 / 2;
180
181 if (rate < min_rate || rate > max_rate)
182 return -EINVAL;
183
184 div = rate * 2 / parent_rate;
185 val = readl(pll->base);
186 val &= ~pll->div_mask;
187 val |= div;
188 writel(val, pll->base);
189
190 /* Wait for PLL to lock */
191 while (!(readl(pll->base) & pll->lock_bit))
192 ;
193
194 return 0;
195 }
196
197 static const struct clk_ops clk_pllv3_sys_ops = {
198 .enable = clk_pllv3_generic_enable,
199 .disable = clk_pllv3_generic_disable,
200 .get_rate = clk_pllv3_sys_get_rate,
201 .set_rate = clk_pllv3_sys_set_rate,
202 };
203
clk_pllv3_av_get_rate(struct clk * clk)204 static ulong clk_pllv3_av_get_rate(struct clk *clk)
205 {
206 struct clk_pllv3 *pll = to_clk_pllv3(clk);
207 unsigned long parent_rate = clk_get_parent_rate(clk);
208 u32 mfn = readl(pll->base + PLL_NUM_OFFSET);
209 u32 mfd = readl(pll->base + PLL_DENOM_OFFSET);
210 u32 div = readl(pll->base) & pll->div_mask;
211 u64 temp64 = (u64)parent_rate;
212
213 if (mfd == 0)
214 return -EIO;
215
216 temp64 *= mfn;
217 do_div(temp64, mfd);
218
219 return parent_rate * div + (unsigned long)temp64;
220 }
221
clk_pllv3_av_set_rate(struct clk * clk,ulong rate)222 static ulong clk_pllv3_av_set_rate(struct clk *clk, ulong rate)
223 {
224 struct clk_pllv3 *pll = to_clk_pllv3(clk);
225 unsigned long parent_rate = clk_get_parent_rate(clk);
226 unsigned long min_rate;
227 unsigned long max_rate;
228 u32 val, div;
229 u32 mfn, mfd = 1000000;
230 u32 max_mfd = 0x3FFFFFFF;
231 u64 temp64;
232
233 if (parent_rate == 0)
234 return -EINVAL;
235
236 min_rate = parent_rate * 27;
237 max_rate = parent_rate * 54;
238
239 if (rate < min_rate || rate > max_rate)
240 return -EINVAL;
241
242 if (parent_rate <= max_mfd)
243 mfd = parent_rate;
244
245 div = rate / parent_rate;
246 temp64 = (u64)(rate - div * parent_rate);
247 temp64 *= mfd;
248 do_div(temp64, parent_rate);
249 mfn = temp64;
250
251 val = readl(pll->base);
252 val &= ~pll->div_mask;
253 val |= div;
254 writel(val, pll->base);
255 writel(mfn, pll->base + PLL_NUM_OFFSET);
256 writel(mfd, pll->base + PLL_DENOM_OFFSET);
257
258 /* Wait for PLL to lock */
259 while (!(readl(pll->base) & pll->lock_bit))
260 ;
261
262 return 0;
263 }
264
265 static const struct clk_ops clk_pllv3_av_ops = {
266 .enable = clk_pllv3_generic_enable,
267 .disable = clk_pllv3_generic_disable,
268 .get_rate = clk_pllv3_av_get_rate,
269 .set_rate = clk_pllv3_av_set_rate,
270 };
271
clk_pllv3_enet_get_rate(struct clk * clk)272 static ulong clk_pllv3_enet_get_rate(struct clk *clk)
273 {
274 struct clk_pllv3 *pll = to_clk_pllv3(clk);
275
276 return pll->ref_clock;
277 }
278
279 static const struct clk_ops clk_pllv3_enet_ops = {
280 .enable = clk_pllv3_generic_enable,
281 .disable = clk_pllv3_generic_disable,
282 .get_rate = clk_pllv3_enet_get_rate,
283 };
284
imx_clk_pllv3(enum imx_pllv3_type type,const char * name,const char * parent_name,void __iomem * base,u32 div_mask)285 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
286 const char *parent_name, void __iomem *base,
287 u32 div_mask)
288 {
289 struct clk_pllv3 *pll;
290 struct clk *clk;
291 char *drv_name;
292 int ret;
293
294 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
295 if (!pll)
296 return ERR_PTR(-ENOMEM);
297
298 pll->power_bit = BM_PLL_POWER;
299 pll->enable_bit = BM_PLL_ENABLE;
300 pll->lock_bit = BM_PLL_LOCK;
301
302 switch (type) {
303 case IMX_PLLV3_GENERIC:
304 drv_name = UBOOT_DM_CLK_IMX_PLLV3_GENERIC;
305 pll->div_shift = 0;
306 pll->powerup_set = false;
307 break;
308 case IMX_PLLV3_GENERICV2:
309 pll->power_bit = BM_PLL_POWER_V2;
310 pll->lock_bit = BM_PLL_LOCK_V2;
311 drv_name = UBOOT_DM_CLK_IMX_PLLV3_GENV2;
312 pll->div_shift = 0;
313 pll->powerup_set = false;
314 break;
315 case IMX_PLLV3_SYS:
316 drv_name = UBOOT_DM_CLK_IMX_PLLV3_SYS;
317 pll->div_shift = 0;
318 pll->powerup_set = false;
319 break;
320 case IMX_PLLV3_USB:
321 drv_name = UBOOT_DM_CLK_IMX_PLLV3_USB;
322 pll->div_shift = 1;
323 pll->powerup_set = true;
324 break;
325 case IMX_PLLV3_AV:
326 drv_name = UBOOT_DM_CLK_IMX_PLLV3_AV;
327 pll->div_shift = 0;
328 pll->powerup_set = false;
329 break;
330 case IMX_PLLV3_ENET:
331 drv_name = UBOOT_DM_CLK_IMX_PLLV3_ENET;
332 pll->ref_clock = 500000000;
333 break;
334 default:
335 kfree(pll);
336 return ERR_PTR(-EINVAL);
337 }
338
339 pll->base = base;
340 pll->div_mask = div_mask;
341 clk = &pll->clk;
342
343 ret = clk_register(clk, drv_name, name, parent_name);
344 if (ret) {
345 kfree(pll);
346 return ERR_PTR(ret);
347 }
348
349 return clk;
350 }
351
352 U_BOOT_DRIVER(clk_pllv3_generic) = {
353 .name = UBOOT_DM_CLK_IMX_PLLV3_GENERIC,
354 .id = UCLASS_CLK,
355 .ops = &clk_pllv3_generic_ops,
356 .flags = DM_FLAG_PRE_RELOC,
357 };
358
359 U_BOOT_DRIVER(clk_pllv3_genericv2) = {
360 .name = UBOOT_DM_CLK_IMX_PLLV3_GENV2,
361 .id = UCLASS_CLK,
362 .ops = &clk_pllv3_genericv2_ops,
363 .flags = DM_FLAG_PRE_RELOC,
364 };
365
366 U_BOOT_DRIVER(clk_pllv3_sys) = {
367 .name = UBOOT_DM_CLK_IMX_PLLV3_SYS,
368 .id = UCLASS_CLK,
369 .ops = &clk_pllv3_sys_ops,
370 .flags = DM_FLAG_PRE_RELOC,
371 };
372
373 U_BOOT_DRIVER(clk_pllv3_usb) = {
374 .name = UBOOT_DM_CLK_IMX_PLLV3_USB,
375 .id = UCLASS_CLK,
376 .ops = &clk_pllv3_generic_ops,
377 .flags = DM_FLAG_PRE_RELOC,
378 };
379
380 U_BOOT_DRIVER(clk_pllv3_av) = {
381 .name = UBOOT_DM_CLK_IMX_PLLV3_AV,
382 .id = UCLASS_CLK,
383 .ops = &clk_pllv3_av_ops,
384 .flags = DM_FLAG_PRE_RELOC,
385 };
386
387 U_BOOT_DRIVER(clk_pllv3_enet) = {
388 .name = UBOOT_DM_CLK_IMX_PLLV3_ENET,
389 .id = UCLASS_CLK,
390 .ops = &clk_pllv3_enet_ops,
391 };
392