1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Clock driver for DA8xx/AM17xx/AM18xx/OMAP-L13x CFGCHIP |
4 | * |
5 | * Copyright (C) 2018 David Lechner <david@lechnology.com> |
6 | */ |
7 | |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/clk.h> |
10 | #include <linux/clkdev.h> |
11 | #include <linux/init.h> |
12 | #include <linux/mfd/da8xx-cfgchip.h> |
13 | #include <linux/mfd/syscon.h> |
14 | #include <linux/of.h> |
15 | #include <linux/platform_data/clk-da8xx-cfgchip.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/property.h> |
18 | #include <linux/regmap.h> |
19 | #include <linux/slab.h> |
20 | |
21 | /* --- Gate clocks --- */ |
22 | |
23 | #define DA8XX_GATE_CLOCK_IS_DIV4P5 BIT(1) |
24 | |
25 | struct da8xx_cfgchip_gate_clk_info { |
26 | const char *name; |
27 | u32 cfgchip; |
28 | u32 bit; |
29 | u32 flags; |
30 | }; |
31 | |
32 | struct da8xx_cfgchip_gate_clk { |
33 | struct clk_hw hw; |
34 | struct regmap *regmap; |
35 | u32 reg; |
36 | u32 mask; |
37 | }; |
38 | |
39 | #define to_da8xx_cfgchip_gate_clk(_hw) \ |
40 | container_of((_hw), struct da8xx_cfgchip_gate_clk, hw) |
41 | |
42 | static int da8xx_cfgchip_gate_clk_enable(struct clk_hw *hw) |
43 | { |
44 | struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw); |
45 | |
46 | return regmap_write_bits(map: clk->regmap, reg: clk->reg, mask: clk->mask, val: clk->mask); |
47 | } |
48 | |
49 | static void da8xx_cfgchip_gate_clk_disable(struct clk_hw *hw) |
50 | { |
51 | struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw); |
52 | |
53 | regmap_write_bits(map: clk->regmap, reg: clk->reg, mask: clk->mask, val: 0); |
54 | } |
55 | |
56 | static int da8xx_cfgchip_gate_clk_is_enabled(struct clk_hw *hw) |
57 | { |
58 | struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw); |
59 | unsigned int val; |
60 | |
61 | regmap_read(map: clk->regmap, reg: clk->reg, val: &val); |
62 | |
63 | return !!(val & clk->mask); |
64 | } |
65 | |
66 | static unsigned long da8xx_cfgchip_div4p5_recalc_rate(struct clk_hw *hw, |
67 | unsigned long parent_rate) |
68 | { |
69 | /* this clock divides by 4.5 */ |
70 | return parent_rate * 2 / 9; |
71 | } |
72 | |
73 | static const struct clk_ops da8xx_cfgchip_gate_clk_ops = { |
74 | .enable = da8xx_cfgchip_gate_clk_enable, |
75 | .disable = da8xx_cfgchip_gate_clk_disable, |
76 | .is_enabled = da8xx_cfgchip_gate_clk_is_enabled, |
77 | }; |
78 | |
79 | static const struct clk_ops da8xx_cfgchip_div4p5_clk_ops = { |
80 | .enable = da8xx_cfgchip_gate_clk_enable, |
81 | .disable = da8xx_cfgchip_gate_clk_disable, |
82 | .is_enabled = da8xx_cfgchip_gate_clk_is_enabled, |
83 | .recalc_rate = da8xx_cfgchip_div4p5_recalc_rate, |
84 | }; |
85 | |
86 | static struct da8xx_cfgchip_gate_clk * __init |
87 | da8xx_cfgchip_gate_clk_register(struct device *dev, |
88 | const struct da8xx_cfgchip_gate_clk_info *info, |
89 | struct regmap *regmap) |
90 | { |
91 | struct clk *parent; |
92 | const char *parent_name; |
93 | struct da8xx_cfgchip_gate_clk *gate; |
94 | struct clk_init_data init; |
95 | int ret; |
96 | |
97 | parent = devm_clk_get(dev, NULL); |
98 | if (IS_ERR(ptr: parent)) |
99 | return ERR_CAST(ptr: parent); |
100 | |
101 | parent_name = __clk_get_name(clk: parent); |
102 | |
103 | gate = devm_kzalloc(dev, size: sizeof(*gate), GFP_KERNEL); |
104 | if (!gate) |
105 | return ERR_PTR(error: -ENOMEM); |
106 | |
107 | init.name = info->name; |
108 | if (info->flags & DA8XX_GATE_CLOCK_IS_DIV4P5) |
109 | init.ops = &da8xx_cfgchip_div4p5_clk_ops; |
110 | else |
111 | init.ops = &da8xx_cfgchip_gate_clk_ops; |
112 | init.parent_names = &parent_name; |
113 | init.num_parents = 1; |
114 | init.flags = 0; |
115 | |
116 | gate->hw.init = &init; |
117 | gate->regmap = regmap; |
118 | gate->reg = info->cfgchip; |
119 | gate->mask = info->bit; |
120 | |
121 | ret = devm_clk_hw_register(dev, hw: &gate->hw); |
122 | if (ret < 0) |
123 | return ERR_PTR(error: ret); |
124 | |
125 | return gate; |
126 | } |
127 | |
128 | static const struct da8xx_cfgchip_gate_clk_info da8xx_tbclksync_info __initconst = { |
129 | .name = "ehrpwm_tbclk" , |
130 | .cfgchip = CFGCHIP(1), |
131 | .bit = CFGCHIP1_TBCLKSYNC, |
132 | }; |
133 | |
134 | static int __init da8xx_cfgchip_register_tbclk(struct device *dev, |
135 | struct regmap *regmap) |
136 | { |
137 | struct da8xx_cfgchip_gate_clk *gate; |
138 | |
139 | gate = da8xx_cfgchip_gate_clk_register(dev, info: &da8xx_tbclksync_info, |
140 | regmap); |
141 | if (IS_ERR(ptr: gate)) |
142 | return PTR_ERR(ptr: gate); |
143 | |
144 | clk_hw_register_clkdev(&gate->hw, "tbclk" , "ehrpwm.0" ); |
145 | clk_hw_register_clkdev(&gate->hw, "tbclk" , "ehrpwm.1" ); |
146 | |
147 | return 0; |
148 | } |
149 | |
150 | static const struct da8xx_cfgchip_gate_clk_info da8xx_div4p5ena_info __initconst = { |
151 | .name = "div4.5" , |
152 | .cfgchip = CFGCHIP(3), |
153 | .bit = CFGCHIP3_DIV45PENA, |
154 | .flags = DA8XX_GATE_CLOCK_IS_DIV4P5, |
155 | }; |
156 | |
157 | static int __init da8xx_cfgchip_register_div4p5(struct device *dev, |
158 | struct regmap *regmap) |
159 | { |
160 | struct da8xx_cfgchip_gate_clk *gate; |
161 | |
162 | gate = da8xx_cfgchip_gate_clk_register(dev, info: &da8xx_div4p5ena_info, regmap); |
163 | |
164 | return PTR_ERR_OR_ZERO(ptr: gate); |
165 | } |
166 | |
167 | static int __init |
168 | of_da8xx_cfgchip_gate_clk_init(struct device *dev, |
169 | const struct da8xx_cfgchip_gate_clk_info *info, |
170 | struct regmap *regmap) |
171 | { |
172 | struct da8xx_cfgchip_gate_clk *gate; |
173 | |
174 | gate = da8xx_cfgchip_gate_clk_register(dev, info, regmap); |
175 | if (IS_ERR(ptr: gate)) |
176 | return PTR_ERR(ptr: gate); |
177 | |
178 | return devm_of_clk_add_hw_provider(dev, get: of_clk_hw_simple_get, data: gate); |
179 | } |
180 | |
181 | static int __init of_da8xx_tbclksync_init(struct device *dev, |
182 | struct regmap *regmap) |
183 | { |
184 | return of_da8xx_cfgchip_gate_clk_init(dev, info: &da8xx_tbclksync_info, regmap); |
185 | } |
186 | |
187 | static int __init of_da8xx_div4p5ena_init(struct device *dev, |
188 | struct regmap *regmap) |
189 | { |
190 | return of_da8xx_cfgchip_gate_clk_init(dev, info: &da8xx_div4p5ena_info, regmap); |
191 | } |
192 | |
193 | /* --- MUX clocks --- */ |
194 | |
195 | struct da8xx_cfgchip_mux_clk_info { |
196 | const char *name; |
197 | const char *parent0; |
198 | const char *parent1; |
199 | u32 cfgchip; |
200 | u32 bit; |
201 | }; |
202 | |
203 | struct da8xx_cfgchip_mux_clk { |
204 | struct clk_hw hw; |
205 | struct regmap *regmap; |
206 | u32 reg; |
207 | u32 mask; |
208 | }; |
209 | |
210 | #define to_da8xx_cfgchip_mux_clk(_hw) \ |
211 | container_of((_hw), struct da8xx_cfgchip_mux_clk, hw) |
212 | |
213 | static int da8xx_cfgchip_mux_clk_set_parent(struct clk_hw *hw, u8 index) |
214 | { |
215 | struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw); |
216 | unsigned int val = index ? clk->mask : 0; |
217 | |
218 | return regmap_write_bits(map: clk->regmap, reg: clk->reg, mask: clk->mask, val); |
219 | } |
220 | |
221 | static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw) |
222 | { |
223 | struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw); |
224 | unsigned int val; |
225 | |
226 | regmap_read(map: clk->regmap, reg: clk->reg, val: &val); |
227 | |
228 | return (val & clk->mask) ? 1 : 0; |
229 | } |
230 | |
231 | static const struct clk_ops da8xx_cfgchip_mux_clk_ops = { |
232 | .determine_rate = clk_hw_determine_rate_no_reparent, |
233 | .set_parent = da8xx_cfgchip_mux_clk_set_parent, |
234 | .get_parent = da8xx_cfgchip_mux_clk_get_parent, |
235 | }; |
236 | |
237 | static struct da8xx_cfgchip_mux_clk * __init |
238 | da8xx_cfgchip_mux_clk_register(struct device *dev, |
239 | const struct da8xx_cfgchip_mux_clk_info *info, |
240 | struct regmap *regmap) |
241 | { |
242 | const char * const parent_names[] = { info->parent0, info->parent1 }; |
243 | struct da8xx_cfgchip_mux_clk *mux; |
244 | struct clk_init_data init; |
245 | int ret; |
246 | |
247 | mux = devm_kzalloc(dev, size: sizeof(*mux), GFP_KERNEL); |
248 | if (!mux) |
249 | return ERR_PTR(error: -ENOMEM); |
250 | |
251 | init.name = info->name; |
252 | init.ops = &da8xx_cfgchip_mux_clk_ops; |
253 | init.parent_names = parent_names; |
254 | init.num_parents = 2; |
255 | init.flags = 0; |
256 | |
257 | mux->hw.init = &init; |
258 | mux->regmap = regmap; |
259 | mux->reg = info->cfgchip; |
260 | mux->mask = info->bit; |
261 | |
262 | ret = devm_clk_hw_register(dev, hw: &mux->hw); |
263 | if (ret < 0) |
264 | return ERR_PTR(error: ret); |
265 | |
266 | return mux; |
267 | } |
268 | |
269 | static const struct da8xx_cfgchip_mux_clk_info da850_async1_info __initconst = { |
270 | .name = "async1" , |
271 | .parent0 = "pll0_sysclk3" , |
272 | .parent1 = "div4.5" , |
273 | .cfgchip = CFGCHIP(3), |
274 | .bit = CFGCHIP3_EMA_CLKSRC, |
275 | }; |
276 | |
277 | static int __init da8xx_cfgchip_register_async1(struct device *dev, |
278 | struct regmap *regmap) |
279 | { |
280 | struct da8xx_cfgchip_mux_clk *mux; |
281 | |
282 | mux = da8xx_cfgchip_mux_clk_register(dev, info: &da850_async1_info, regmap); |
283 | if (IS_ERR(ptr: mux)) |
284 | return PTR_ERR(ptr: mux); |
285 | |
286 | clk_hw_register_clkdev(&mux->hw, "async1" , "da850-psc0" ); |
287 | |
288 | return 0; |
289 | } |
290 | |
291 | static const struct da8xx_cfgchip_mux_clk_info da850_async3_info __initconst = { |
292 | .name = "async3" , |
293 | .parent0 = "pll0_sysclk2" , |
294 | .parent1 = "pll1_sysclk2" , |
295 | .cfgchip = CFGCHIP(3), |
296 | .bit = CFGCHIP3_ASYNC3_CLKSRC, |
297 | }; |
298 | |
299 | static int __init da850_cfgchip_register_async3(struct device *dev, |
300 | struct regmap *regmap) |
301 | { |
302 | struct da8xx_cfgchip_mux_clk *mux; |
303 | struct clk_hw *parent; |
304 | |
305 | mux = da8xx_cfgchip_mux_clk_register(dev, info: &da850_async3_info, regmap); |
306 | if (IS_ERR(ptr: mux)) |
307 | return PTR_ERR(ptr: mux); |
308 | |
309 | clk_hw_register_clkdev(&mux->hw, "async3" , "da850-psc1" ); |
310 | |
311 | /* pll1_sysclk2 is not affected by CPU scaling, so use it for async3 */ |
312 | parent = clk_hw_get_parent_by_index(hw: &mux->hw, index: 1); |
313 | if (parent) |
314 | clk_set_parent(clk: mux->hw.clk, parent: parent->clk); |
315 | else |
316 | dev_warn(dev, "Failed to find async3 parent clock\n" ); |
317 | |
318 | return 0; |
319 | } |
320 | |
321 | static int __init |
322 | of_da8xx_cfgchip_init_mux_clock(struct device *dev, |
323 | const struct da8xx_cfgchip_mux_clk_info *info, |
324 | struct regmap *regmap) |
325 | { |
326 | struct da8xx_cfgchip_mux_clk *mux; |
327 | |
328 | mux = da8xx_cfgchip_mux_clk_register(dev, info, regmap); |
329 | if (IS_ERR(ptr: mux)) |
330 | return PTR_ERR(ptr: mux); |
331 | |
332 | return devm_of_clk_add_hw_provider(dev, get: of_clk_hw_simple_get, data: &mux->hw); |
333 | } |
334 | |
335 | static int __init of_da850_async1_init(struct device *dev, struct regmap *regmap) |
336 | { |
337 | return of_da8xx_cfgchip_init_mux_clock(dev, info: &da850_async1_info, regmap); |
338 | } |
339 | |
340 | static int __init of_da850_async3_init(struct device *dev, struct regmap *regmap) |
341 | { |
342 | return of_da8xx_cfgchip_init_mux_clock(dev, info: &da850_async3_info, regmap); |
343 | } |
344 | |
345 | /* --- USB 2.0 PHY clock --- */ |
346 | |
347 | struct da8xx_usb0_clk48 { |
348 | struct clk_hw hw; |
349 | struct clk *fck; |
350 | struct regmap *regmap; |
351 | }; |
352 | |
353 | #define to_da8xx_usb0_clk48(_hw) \ |
354 | container_of((_hw), struct da8xx_usb0_clk48, hw) |
355 | |
356 | static int da8xx_usb0_clk48_prepare(struct clk_hw *hw) |
357 | { |
358 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
359 | |
360 | /* The USB 2.0 PSC clock is only needed temporarily during the USB 2.0 |
361 | * PHY clock enable, but since clk_prepare() can't be called in an |
362 | * atomic context (i.e. in clk_enable()), we have to prepare it here. |
363 | */ |
364 | return clk_prepare(clk: usb0->fck); |
365 | } |
366 | |
367 | static void da8xx_usb0_clk48_unprepare(struct clk_hw *hw) |
368 | { |
369 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
370 | |
371 | clk_unprepare(clk: usb0->fck); |
372 | } |
373 | |
374 | static int da8xx_usb0_clk48_enable(struct clk_hw *hw) |
375 | { |
376 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
377 | unsigned int mask, val; |
378 | int ret; |
379 | |
380 | /* Locking the USB 2.O PLL requires that the USB 2.O PSC is enabled |
381 | * temporaily. It can be turned back off once the PLL is locked. |
382 | */ |
383 | clk_enable(clk: usb0->fck); |
384 | |
385 | /* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1 |
386 | * PHY may use the USB 2.0 PLL clock without USB 2.0 OTG being used. |
387 | */ |
388 | mask = CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_PHY_PLLON; |
389 | val = CFGCHIP2_PHY_PLLON; |
390 | |
391 | regmap_write_bits(map: usb0->regmap, CFGCHIP(2), mask, val); |
392 | ret = regmap_read_poll_timeout(usb0->regmap, CFGCHIP(2), val, |
393 | val & CFGCHIP2_PHYCLKGD, 0, 500000); |
394 | |
395 | clk_disable(clk: usb0->fck); |
396 | |
397 | return ret; |
398 | } |
399 | |
400 | static void da8xx_usb0_clk48_disable(struct clk_hw *hw) |
401 | { |
402 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
403 | unsigned int val; |
404 | |
405 | val = CFGCHIP2_PHYPWRDN; |
406 | regmap_write_bits(map: usb0->regmap, CFGCHIP(2), mask: val, val); |
407 | } |
408 | |
409 | static int da8xx_usb0_clk48_is_enabled(struct clk_hw *hw) |
410 | { |
411 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
412 | unsigned int val; |
413 | |
414 | regmap_read(map: usb0->regmap, CFGCHIP(2), val: &val); |
415 | |
416 | return !!(val & CFGCHIP2_PHYCLKGD); |
417 | } |
418 | |
419 | static unsigned long da8xx_usb0_clk48_recalc_rate(struct clk_hw *hw, |
420 | unsigned long parent_rate) |
421 | { |
422 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
423 | unsigned int mask, val; |
424 | |
425 | /* The parent clock rate must be one of the following */ |
426 | mask = CFGCHIP2_REFFREQ_MASK; |
427 | switch (parent_rate) { |
428 | case 12000000: |
429 | val = CFGCHIP2_REFFREQ_12MHZ; |
430 | break; |
431 | case 13000000: |
432 | val = CFGCHIP2_REFFREQ_13MHZ; |
433 | break; |
434 | case 19200000: |
435 | val = CFGCHIP2_REFFREQ_19_2MHZ; |
436 | break; |
437 | case 20000000: |
438 | val = CFGCHIP2_REFFREQ_20MHZ; |
439 | break; |
440 | case 24000000: |
441 | val = CFGCHIP2_REFFREQ_24MHZ; |
442 | break; |
443 | case 26000000: |
444 | val = CFGCHIP2_REFFREQ_26MHZ; |
445 | break; |
446 | case 38400000: |
447 | val = CFGCHIP2_REFFREQ_38_4MHZ; |
448 | break; |
449 | case 40000000: |
450 | val = CFGCHIP2_REFFREQ_40MHZ; |
451 | break; |
452 | case 48000000: |
453 | val = CFGCHIP2_REFFREQ_48MHZ; |
454 | break; |
455 | default: |
456 | return 0; |
457 | } |
458 | |
459 | regmap_write_bits(map: usb0->regmap, CFGCHIP(2), mask, val); |
460 | |
461 | /* USB 2.0 PLL always supplies 48MHz */ |
462 | return 48000000; |
463 | } |
464 | |
465 | static int da8xx_usb0_clk48_determine_rate(struct clk_hw *hw, |
466 | struct clk_rate_request *req) |
467 | { |
468 | req->rate = 48000000; |
469 | |
470 | return 0; |
471 | } |
472 | |
473 | static int da8xx_usb0_clk48_set_parent(struct clk_hw *hw, u8 index) |
474 | { |
475 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
476 | |
477 | return regmap_write_bits(map: usb0->regmap, CFGCHIP(2), |
478 | CFGCHIP2_USB2PHYCLKMUX, |
479 | val: index ? CFGCHIP2_USB2PHYCLKMUX : 0); |
480 | } |
481 | |
482 | static u8 da8xx_usb0_clk48_get_parent(struct clk_hw *hw) |
483 | { |
484 | struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw); |
485 | unsigned int val; |
486 | |
487 | regmap_read(map: usb0->regmap, CFGCHIP(2), val: &val); |
488 | |
489 | return (val & CFGCHIP2_USB2PHYCLKMUX) ? 1 : 0; |
490 | } |
491 | |
492 | static const struct clk_ops da8xx_usb0_clk48_ops = { |
493 | .prepare = da8xx_usb0_clk48_prepare, |
494 | .unprepare = da8xx_usb0_clk48_unprepare, |
495 | .enable = da8xx_usb0_clk48_enable, |
496 | .disable = da8xx_usb0_clk48_disable, |
497 | .is_enabled = da8xx_usb0_clk48_is_enabled, |
498 | .recalc_rate = da8xx_usb0_clk48_recalc_rate, |
499 | .determine_rate = da8xx_usb0_clk48_determine_rate, |
500 | .set_parent = da8xx_usb0_clk48_set_parent, |
501 | .get_parent = da8xx_usb0_clk48_get_parent, |
502 | }; |
503 | |
504 | static struct da8xx_usb0_clk48 * |
505 | da8xx_cfgchip_register_usb0_clk48(struct device *dev, |
506 | struct regmap *regmap) |
507 | { |
508 | const char * const parent_names[] = { "usb_refclkin" , "pll0_auxclk" }; |
509 | struct clk *fck_clk; |
510 | struct da8xx_usb0_clk48 *usb0; |
511 | struct clk_init_data init; |
512 | int ret; |
513 | |
514 | fck_clk = devm_clk_get(dev, id: "fck" ); |
515 | if (IS_ERR(ptr: fck_clk)) { |
516 | dev_err_probe(dev, err: PTR_ERR(ptr: fck_clk), fmt: "Missing fck clock\n" ); |
517 | return ERR_CAST(ptr: fck_clk); |
518 | } |
519 | |
520 | usb0 = devm_kzalloc(dev, size: sizeof(*usb0), GFP_KERNEL); |
521 | if (!usb0) |
522 | return ERR_PTR(error: -ENOMEM); |
523 | |
524 | init.name = "usb0_clk48" ; |
525 | init.ops = &da8xx_usb0_clk48_ops; |
526 | init.parent_names = parent_names; |
527 | init.num_parents = 2; |
528 | |
529 | usb0->hw.init = &init; |
530 | usb0->fck = fck_clk; |
531 | usb0->regmap = regmap; |
532 | |
533 | ret = devm_clk_hw_register(dev, hw: &usb0->hw); |
534 | if (ret < 0) |
535 | return ERR_PTR(error: ret); |
536 | |
537 | return usb0; |
538 | } |
539 | |
540 | /* --- USB 1.1 PHY clock --- */ |
541 | |
542 | struct da8xx_usb1_clk48 { |
543 | struct clk_hw hw; |
544 | struct regmap *regmap; |
545 | }; |
546 | |
547 | #define to_da8xx_usb1_clk48(_hw) \ |
548 | container_of((_hw), struct da8xx_usb1_clk48, hw) |
549 | |
550 | static int da8xx_usb1_clk48_set_parent(struct clk_hw *hw, u8 index) |
551 | { |
552 | struct da8xx_usb1_clk48 *usb1 = to_da8xx_usb1_clk48(hw); |
553 | |
554 | return regmap_write_bits(map: usb1->regmap, CFGCHIP(2), |
555 | CFGCHIP2_USB1PHYCLKMUX, |
556 | val: index ? CFGCHIP2_USB1PHYCLKMUX : 0); |
557 | } |
558 | |
559 | static u8 da8xx_usb1_clk48_get_parent(struct clk_hw *hw) |
560 | { |
561 | struct da8xx_usb1_clk48 *usb1 = to_da8xx_usb1_clk48(hw); |
562 | unsigned int val; |
563 | |
564 | regmap_read(map: usb1->regmap, CFGCHIP(2), val: &val); |
565 | |
566 | return (val & CFGCHIP2_USB1PHYCLKMUX) ? 1 : 0; |
567 | } |
568 | |
569 | static const struct clk_ops da8xx_usb1_clk48_ops = { |
570 | .determine_rate = clk_hw_determine_rate_no_reparent, |
571 | .set_parent = da8xx_usb1_clk48_set_parent, |
572 | .get_parent = da8xx_usb1_clk48_get_parent, |
573 | }; |
574 | |
575 | /** |
576 | * da8xx_cfgchip_register_usb1_clk48 - Register a new USB 1.1 PHY clock |
577 | * @dev: The device |
578 | * @regmap: The CFGCHIP regmap |
579 | */ |
580 | static struct da8xx_usb1_clk48 * |
581 | da8xx_cfgchip_register_usb1_clk48(struct device *dev, |
582 | struct regmap *regmap) |
583 | { |
584 | const char * const parent_names[] = { "usb0_clk48" , "usb_refclkin" }; |
585 | struct da8xx_usb1_clk48 *usb1; |
586 | struct clk_init_data init; |
587 | int ret; |
588 | |
589 | usb1 = devm_kzalloc(dev, size: sizeof(*usb1), GFP_KERNEL); |
590 | if (!usb1) |
591 | return ERR_PTR(error: -ENOMEM); |
592 | |
593 | init.name = "usb1_clk48" ; |
594 | init.ops = &da8xx_usb1_clk48_ops; |
595 | init.parent_names = parent_names; |
596 | init.num_parents = 2; |
597 | |
598 | usb1->hw.init = &init; |
599 | usb1->regmap = regmap; |
600 | |
601 | ret = devm_clk_hw_register(dev, hw: &usb1->hw); |
602 | if (ret < 0) |
603 | return ERR_PTR(error: ret); |
604 | |
605 | return usb1; |
606 | } |
607 | |
608 | static int da8xx_cfgchip_register_usb_phy_clk(struct device *dev, |
609 | struct regmap *regmap) |
610 | { |
611 | struct da8xx_usb0_clk48 *usb0; |
612 | struct da8xx_usb1_clk48 *usb1; |
613 | struct clk_hw *parent; |
614 | |
615 | usb0 = da8xx_cfgchip_register_usb0_clk48(dev, regmap); |
616 | if (IS_ERR(ptr: usb0)) |
617 | return PTR_ERR(ptr: usb0); |
618 | |
619 | /* |
620 | * All existing boards use pll0_auxclk as the parent and new boards |
621 | * should use device tree, so hard-coding the value (1) here. |
622 | */ |
623 | parent = clk_hw_get_parent_by_index(hw: &usb0->hw, index: 1); |
624 | if (parent) |
625 | clk_set_parent(clk: usb0->hw.clk, parent: parent->clk); |
626 | else |
627 | dev_warn(dev, "Failed to find usb0 parent clock\n" ); |
628 | |
629 | usb1 = da8xx_cfgchip_register_usb1_clk48(dev, regmap); |
630 | if (IS_ERR(ptr: usb1)) |
631 | return PTR_ERR(ptr: usb1); |
632 | |
633 | /* |
634 | * All existing boards use usb0_clk48 as the parent and new boards |
635 | * should use device tree, so hard-coding the value (0) here. |
636 | */ |
637 | parent = clk_hw_get_parent_by_index(hw: &usb1->hw, index: 0); |
638 | if (parent) |
639 | clk_set_parent(clk: usb1->hw.clk, parent: parent->clk); |
640 | else |
641 | dev_warn(dev, "Failed to find usb1 parent clock\n" ); |
642 | |
643 | clk_hw_register_clkdev(&usb0->hw, "usb0_clk48" , "da8xx-usb-phy" ); |
644 | clk_hw_register_clkdev(&usb1->hw, "usb1_clk48" , "da8xx-usb-phy" ); |
645 | |
646 | return 0; |
647 | } |
648 | |
649 | static int of_da8xx_usb_phy_clk_init(struct device *dev, struct regmap *regmap) |
650 | { |
651 | struct clk_hw_onecell_data *clk_data; |
652 | struct da8xx_usb0_clk48 *usb0; |
653 | struct da8xx_usb1_clk48 *usb1; |
654 | |
655 | clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, 2), |
656 | GFP_KERNEL); |
657 | if (!clk_data) |
658 | return -ENOMEM; |
659 | |
660 | clk_data->num = 2; |
661 | |
662 | usb0 = da8xx_cfgchip_register_usb0_clk48(dev, regmap); |
663 | if (IS_ERR(ptr: usb0)) { |
664 | if (PTR_ERR(ptr: usb0) == -EPROBE_DEFER) |
665 | return -EPROBE_DEFER; |
666 | |
667 | dev_warn(dev, "Failed to register usb0_clk48 (%ld)\n" , |
668 | PTR_ERR(usb0)); |
669 | |
670 | clk_data->hws[0] = ERR_PTR(error: -ENOENT); |
671 | } else { |
672 | clk_data->hws[0] = &usb0->hw; |
673 | } |
674 | |
675 | usb1 = da8xx_cfgchip_register_usb1_clk48(dev, regmap); |
676 | if (IS_ERR(ptr: usb1)) { |
677 | if (PTR_ERR(ptr: usb1) == -EPROBE_DEFER) |
678 | return -EPROBE_DEFER; |
679 | |
680 | dev_warn(dev, "Failed to register usb1_clk48 (%ld)\n" , |
681 | PTR_ERR(usb1)); |
682 | |
683 | clk_data->hws[1] = ERR_PTR(error: -ENOENT); |
684 | } else { |
685 | clk_data->hws[1] = &usb1->hw; |
686 | } |
687 | |
688 | return devm_of_clk_add_hw_provider(dev, get: of_clk_hw_onecell_get, data: clk_data); |
689 | } |
690 | |
691 | /* --- platform device --- */ |
692 | |
693 | static const struct of_device_id da8xx_cfgchip_of_match[] = { |
694 | { |
695 | .compatible = "ti,da830-tbclksync" , |
696 | .data = of_da8xx_tbclksync_init, |
697 | }, |
698 | { |
699 | .compatible = "ti,da830-div4p5ena" , |
700 | .data = of_da8xx_div4p5ena_init, |
701 | }, |
702 | { |
703 | .compatible = "ti,da850-async1-clksrc" , |
704 | .data = of_da850_async1_init, |
705 | }, |
706 | { |
707 | .compatible = "ti,da850-async3-clksrc" , |
708 | .data = of_da850_async3_init, |
709 | }, |
710 | { |
711 | .compatible = "ti,da830-usb-phy-clocks" , |
712 | .data = of_da8xx_usb_phy_clk_init, |
713 | }, |
714 | { } |
715 | }; |
716 | |
717 | static const struct platform_device_id da8xx_cfgchip_id_table[] = { |
718 | { |
719 | .name = "da830-tbclksync" , |
720 | .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_tbclk, |
721 | }, |
722 | { |
723 | .name = "da830-div4p5ena" , |
724 | .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_div4p5, |
725 | }, |
726 | { |
727 | .name = "da850-async1-clksrc" , |
728 | .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_async1, |
729 | }, |
730 | { |
731 | .name = "da850-async3-clksrc" , |
732 | .driver_data = (kernel_ulong_t)da850_cfgchip_register_async3, |
733 | }, |
734 | { |
735 | .name = "da830-usb-phy-clks" , |
736 | .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_usb_phy_clk, |
737 | }, |
738 | { } |
739 | }; |
740 | |
741 | typedef int (*da8xx_cfgchip_init)(struct device *dev, struct regmap *regmap); |
742 | |
743 | static int da8xx_cfgchip_probe(struct platform_device *pdev) |
744 | { |
745 | struct device *dev = &pdev->dev; |
746 | struct da8xx_cfgchip_clk_platform_data *pdata = dev->platform_data; |
747 | da8xx_cfgchip_init clk_init = NULL; |
748 | struct regmap *regmap = NULL; |
749 | |
750 | clk_init = device_get_match_data(dev); |
751 | if (clk_init) { |
752 | struct device_node *parent; |
753 | |
754 | parent = of_get_parent(node: dev->of_node); |
755 | regmap = syscon_node_to_regmap(np: parent); |
756 | of_node_put(node: parent); |
757 | } else if (pdev->id_entry && pdata) { |
758 | clk_init = (void *)pdev->id_entry->driver_data; |
759 | regmap = pdata->cfgchip; |
760 | } |
761 | |
762 | if (!clk_init) { |
763 | dev_err(dev, "unable to find driver data\n" ); |
764 | return -EINVAL; |
765 | } |
766 | |
767 | if (IS_ERR_OR_NULL(ptr: regmap)) { |
768 | dev_err(dev, "no regmap for CFGCHIP syscon\n" ); |
769 | return regmap ? PTR_ERR(ptr: regmap) : -ENOENT; |
770 | } |
771 | |
772 | return clk_init(dev, regmap); |
773 | } |
774 | |
775 | static struct platform_driver da8xx_cfgchip_driver = { |
776 | .probe = da8xx_cfgchip_probe, |
777 | .driver = { |
778 | .name = "da8xx-cfgchip-clk" , |
779 | .of_match_table = da8xx_cfgchip_of_match, |
780 | }, |
781 | .id_table = da8xx_cfgchip_id_table, |
782 | }; |
783 | |
784 | static int __init da8xx_cfgchip_driver_init(void) |
785 | { |
786 | return platform_driver_register(&da8xx_cfgchip_driver); |
787 | } |
788 | |
789 | /* has to be postcore_initcall because PSC devices depend on the async3 clock */ |
790 | postcore_initcall(da8xx_cfgchip_driver_init); |
791 | |