]> Git Repo - u-boot.git/blob - drivers/clk/at91/compat.c
common: Drop asm/global_data.h from common header
[u-boot.git] / drivers / clk / at91 / compat.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Compatible code for non CCF AT91 platforms.
4  *
5  * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
6  *
7  * Author: Claudiu Beznea <[email protected]>
8  */
9 #include <common.h>
10 #include <clk-uclass.h>
11 #include <dm.h>
12 #include <asm/global_data.h>
13 #include <dm/device_compat.h>
14 #include <dm/lists.h>
15 #include <dm/util.h>
16 #include <mach/at91_pmc.h>
17 #include <mach/at91_sfr.h>
18 #include <regmap.h>
19 #include <syscon.h>
20
21 #include "pmc.h"
22
23 DECLARE_GLOBAL_DATA_PTR;
24
25 struct pmc_plat {
26         struct at91_pmc *reg_base;
27         struct regmap *regmap_sfr;
28 };
29
30 static const struct udevice_id at91_pmc_match[] = {
31         { .compatible = "atmel,at91rm9200-pmc" },
32         { .compatible = "atmel,at91sam9260-pmc" },
33         { .compatible = "atmel,at91sam9g45-pmc" },
34         { .compatible = "atmel,at91sam9n12-pmc" },
35         { .compatible = "atmel,at91sam9x5-pmc" },
36         { .compatible = "atmel,sama5d3-pmc" },
37         { .compatible = "atmel,sama5d2-pmc" },
38         {}
39 };
40
41 U_BOOT_DRIVER(at91_pmc) = {
42         .name = "at91-pmc",
43         .id = UCLASS_SIMPLE_BUS,
44         .of_match = at91_pmc_match,
45 };
46
47 static int at91_pmc_core_probe(struct udevice *dev)
48 {
49         struct pmc_plat *plat = dev_get_plat(dev);
50
51         dev = dev_get_parent(dev);
52
53         plat->reg_base = dev_read_addr_ptr(dev);
54
55         return 0;
56 }
57
58 /**
59  * at91_clk_sub_device_bind() - for the at91 clock driver
60  * Recursively bind its children as clk devices.
61  *
62  * @return: 0 on success, or negative error code on failure
63  */
64 int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
65 {
66         ofnode parent = dev_ofnode(dev);
67         ofnode node;
68         bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
69         const char *name;
70         int ret;
71
72         ofnode_for_each_subnode(node, parent) {
73                 if (pre_reloc_only && !ofnode_pre_reloc(node))
74                         continue;
75                 /*
76                  * If this node has "compatible" property, this is not
77                  * a clock sub-node, but a normal device. skip.
78                  */
79                 if (ofnode_read_prop(node, "compatible", NULL))
80                         continue;
81
82                 if (ret != -FDT_ERR_NOTFOUND)
83                         return ret;
84
85                 name = ofnode_get_name(node);
86                 if (!name)
87                         return -EINVAL;
88                 ret = device_bind_driver_to_node(dev, drv_name, name, node,
89                                                  NULL);
90                 if (ret)
91                         return ret;
92         }
93
94         return 0;
95 }
96
97 int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
98 {
99         int periph;
100
101         if (args->args_count) {
102                 debug("Invalid args_count: %d\n", args->args_count);
103                 return -EINVAL;
104         }
105
106         periph = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(clk->dev), "reg",
107                                  -1);
108         if (periph < 0)
109                 return -EINVAL;
110
111         clk->id = periph;
112
113         return 0;
114 }
115
116 int at91_clk_probe(struct udevice *dev)
117 {
118         struct udevice *dev_periph_container, *dev_pmc;
119         struct pmc_plat *plat = dev_get_plat(dev);
120
121         dev_periph_container = dev_get_parent(dev);
122         dev_pmc = dev_get_parent(dev_periph_container);
123
124         plat->reg_base = dev_read_addr_ptr(dev_pmc);
125
126         return 0;
127 }
128
129 /* SCKC specific code. */
130 static const struct udevice_id at91_sckc_match[] = {
131         { .compatible = "atmel,at91sam9x5-sckc" },
132         {}
133 };
134
135 U_BOOT_DRIVER(at91_sckc) = {
136         .name = "at91-sckc",
137         .id = UCLASS_SIMPLE_BUS,
138         .of_match = at91_sckc_match,
139 };
140
141 /* Slow clock specific code. */
142 static int at91_slow_clk_enable(struct clk *clk)
143 {
144         return 0;
145 }
146
147 static ulong at91_slow_clk_get_rate(struct clk *clk)
148 {
149         return CONFIG_SYS_AT91_SLOW_CLOCK;
150 }
151
152 static struct clk_ops at91_slow_clk_ops = {
153         .enable = at91_slow_clk_enable,
154         .get_rate = at91_slow_clk_get_rate,
155 };
156
157 static const struct udevice_id at91_slow_clk_match[] = {
158         { .compatible = "atmel,at91sam9x5-clk-slow" },
159         {}
160 };
161
162 U_BOOT_DRIVER(at91_slow_clk) = {
163         .name = "at91-slow-clk",
164         .id = UCLASS_CLK,
165         .of_match = at91_slow_clk_match,
166         .ops = &at91_slow_clk_ops,
167 };
168
169 /* Master clock specific code. */
170 static ulong at91_master_clk_get_rate(struct clk *clk)
171 {
172         return gd->arch.mck_rate_hz;
173 }
174
175 static struct clk_ops at91_master_clk_ops = {
176         .get_rate = at91_master_clk_get_rate,
177 };
178
179 static const struct udevice_id at91_master_clk_match[] = {
180         { .compatible = "atmel,at91rm9200-clk-master" },
181         { .compatible = "atmel,at91sam9x5-clk-master" },
182         {}
183 };
184
185 U_BOOT_DRIVER(at91_master_clk) = {
186         .name = "at91-master-clk",
187         .id = UCLASS_CLK,
188         .of_match = at91_master_clk_match,
189         .ops = &at91_master_clk_ops,
190 };
191
192 /* Main osc clock specific code. */
193 static int main_osc_clk_enable(struct clk *clk)
194 {
195         struct pmc_plat *plat = dev_get_plat(clk->dev);
196         struct at91_pmc *pmc = plat->reg_base;
197
198         if (readl(&pmc->sr) & AT91_PMC_MOSCSELS)
199                 return 0;
200
201         return -EINVAL;
202 }
203
204 static ulong main_osc_clk_get_rate(struct clk *clk)
205 {
206         return gd->arch.main_clk_rate_hz;
207 }
208
209 static struct clk_ops main_osc_clk_ops = {
210         .enable = main_osc_clk_enable,
211         .get_rate = main_osc_clk_get_rate,
212 };
213
214 static int main_osc_clk_probe(struct udevice *dev)
215 {
216         return at91_pmc_core_probe(dev);
217 }
218
219 static const struct udevice_id main_osc_clk_match[] = {
220         { .compatible = "atmel,at91sam9x5-clk-main" },
221         {}
222 };
223
224 U_BOOT_DRIVER(at91sam9x5_main_osc_clk) = {
225         .name = "at91sam9x5-main-osc-clk",
226         .id = UCLASS_CLK,
227         .of_match = main_osc_clk_match,
228         .probe = main_osc_clk_probe,
229         .plat_auto      = sizeof(struct pmc_plat),
230         .ops = &main_osc_clk_ops,
231 };
232
233 /* PLLA clock specific code. */
234 static int plla_clk_enable(struct clk *clk)
235 {
236         struct pmc_plat *plat = dev_get_plat(clk->dev);
237         struct at91_pmc *pmc = plat->reg_base;
238
239         if (readl(&pmc->sr) & AT91_PMC_LOCKA)
240                 return 0;
241
242         return -EINVAL;
243 }
244
245 static ulong plla_clk_get_rate(struct clk *clk)
246 {
247         return gd->arch.plla_rate_hz;
248 }
249
250 static struct clk_ops plla_clk_ops = {
251         .enable = plla_clk_enable,
252         .get_rate = plla_clk_get_rate,
253 };
254
255 static int plla_clk_probe(struct udevice *dev)
256 {
257         return at91_pmc_core_probe(dev);
258 }
259
260 static const struct udevice_id plla_clk_match[] = {
261         { .compatible = "atmel,sama5d3-clk-pll" },
262         {}
263 };
264
265 U_BOOT_DRIVER(at91_plla_clk) = {
266         .name = "at91-plla-clk",
267         .id = UCLASS_CLK,
268         .of_match = plla_clk_match,
269         .probe = plla_clk_probe,
270         .plat_auto      = sizeof(struct pmc_plat),
271         .ops = &plla_clk_ops,
272 };
273
274 /* PLLA DIV clock specific code. */
275 static int at91_plladiv_clk_enable(struct clk *clk)
276 {
277         return 0;
278 }
279
280 static ulong at91_plladiv_clk_get_rate(struct clk *clk)
281 {
282         struct pmc_plat *plat = dev_get_plat(clk->dev);
283         struct at91_pmc *pmc = plat->reg_base;
284         struct clk source;
285         ulong clk_rate;
286         int ret;
287
288         ret = clk_get_by_index(clk->dev, 0, &source);
289         if (ret)
290                 return -EINVAL;
291
292         clk_rate = clk_get_rate(&source);
293         if (readl(&pmc->mckr) & AT91_PMC_MCKR_PLLADIV_2)
294                 clk_rate /= 2;
295
296         return clk_rate;
297 }
298
299 static ulong at91_plladiv_clk_set_rate(struct clk *clk, ulong rate)
300 {
301         struct pmc_plat *plat = dev_get_plat(clk->dev);
302         struct at91_pmc *pmc = plat->reg_base;
303         struct clk source;
304         ulong parent_rate;
305         int ret;
306
307         ret = clk_get_by_index(clk->dev, 0, &source);
308         if (ret)
309                 return -EINVAL;
310
311         parent_rate = clk_get_rate(&source);
312         if ((parent_rate != rate) && ((parent_rate) / 2 != rate))
313                 return -EINVAL;
314
315         if (parent_rate != rate) {
316                 writel((readl(&pmc->mckr) | AT91_PMC_MCKR_PLLADIV_2),
317                        &pmc->mckr);
318         }
319
320         return 0;
321 }
322
323 static struct clk_ops at91_plladiv_clk_ops = {
324         .enable = at91_plladiv_clk_enable,
325         .get_rate = at91_plladiv_clk_get_rate,
326         .set_rate = at91_plladiv_clk_set_rate,
327 };
328
329 static int at91_plladiv_clk_probe(struct udevice *dev)
330 {
331         return at91_pmc_core_probe(dev);
332 }
333
334 static const struct udevice_id at91_plladiv_clk_match[] = {
335         { .compatible = "atmel,at91sam9x5-clk-plldiv" },
336         {}
337 };
338
339 U_BOOT_DRIVER(at91_plladiv_clk) = {
340         .name = "at91-plladiv-clk",
341         .id = UCLASS_CLK,
342         .of_match = at91_plladiv_clk_match,
343         .probe = at91_plladiv_clk_probe,
344         .plat_auto      = sizeof(struct pmc_plat),
345         .ops = &at91_plladiv_clk_ops,
346 };
347
348 /* System clock specific code. */
349 #define SYSTEM_MAX_ID           31
350
351 /**
352  * at91_system_clk_bind() - for the system clock driver
353  * Recursively bind its children as clk devices.
354  *
355  * @return: 0 on success, or negative error code on failure
356  */
357 static int at91_system_clk_bind(struct udevice *dev)
358 {
359         return at91_clk_sub_device_bind(dev, "system-clk");
360 }
361
362 static const struct udevice_id at91_system_clk_match[] = {
363         { .compatible = "atmel,at91rm9200-clk-system" },
364         {}
365 };
366
367 U_BOOT_DRIVER(at91_system_clk) = {
368         .name = "at91-system-clk",
369         .id = UCLASS_MISC,
370         .of_match = at91_system_clk_match,
371         .bind = at91_system_clk_bind,
372 };
373
374 static inline int is_pck(int id)
375 {
376         return (id >= 8) && (id <= 15);
377 }
378
379 static ulong system_clk_get_rate(struct clk *clk)
380 {
381         struct clk clk_dev;
382         int ret;
383
384         ret = clk_get_by_index(clk->dev, 0, &clk_dev);
385         if (ret)
386                 return -EINVAL;
387
388         return clk_get_rate(&clk_dev);
389 }
390
391 static ulong system_clk_set_rate(struct clk *clk, ulong rate)
392 {
393         struct clk clk_dev;
394         int ret;
395
396         ret = clk_get_by_index(clk->dev, 0, &clk_dev);
397         if (ret)
398                 return -EINVAL;
399
400         return clk_set_rate(&clk_dev, rate);
401 }
402
403 static int system_clk_enable(struct clk *clk)
404 {
405         struct pmc_plat *plat = dev_get_plat(clk->dev);
406         struct at91_pmc *pmc = plat->reg_base;
407         u32 mask;
408
409         if (clk->id > SYSTEM_MAX_ID)
410                 return -EINVAL;
411
412         mask = BIT(clk->id);
413
414         writel(mask, &pmc->scer);
415
416         /**
417          * For the programmable clocks the Ready status in the PMC
418          * status register should be checked after enabling.
419          * For other clocks this is unnecessary.
420          */
421         if (!is_pck(clk->id))
422                 return 0;
423
424         while (!(readl(&pmc->sr) & mask))
425                 ;
426
427         return 0;
428 }
429
430 static struct clk_ops system_clk_ops = {
431         .of_xlate = at91_clk_of_xlate,
432         .get_rate = system_clk_get_rate,
433         .set_rate = system_clk_set_rate,
434         .enable = system_clk_enable,
435 };
436
437 U_BOOT_DRIVER(system_clk) = {
438         .name = "system-clk",
439         .id = UCLASS_CLK,
440         .probe = at91_clk_probe,
441         .plat_auto      = sizeof(struct pmc_plat),
442         .ops = &system_clk_ops,
443 };
444
445 /* Peripheral clock specific code. */
446 #define PERIPHERAL_ID_MIN       2
447 #define PERIPHERAL_ID_MAX       31
448 #define PERIPHERAL_MASK(id)     (1 << ((id) & PERIPHERAL_ID_MAX))
449
450 enum periph_clk_type {
451         CLK_PERIPH_AT91RM9200 = 0,
452         CLK_PERIPH_AT91SAM9X5,
453 };
454
455 /**
456  * sam9x5_periph_clk_bind() - for the periph clock driver
457  * Recursively bind its children as clk devices.
458  *
459  * @return: 0 on success, or negative error code on failure
460  */
461 static int sam9x5_periph_clk_bind(struct udevice *dev)
462 {
463         return at91_clk_sub_device_bind(dev, "periph-clk");
464 }
465
466 static const struct udevice_id sam9x5_periph_clk_match[] = {
467         {
468                 .compatible = "atmel,at91rm9200-clk-peripheral",
469                 .data = CLK_PERIPH_AT91RM9200,
470         },
471         {
472                 .compatible = "atmel,at91sam9x5-clk-peripheral",
473                 .data = CLK_PERIPH_AT91SAM9X5,
474         },
475         {}
476 };
477
478 U_BOOT_DRIVER(sam9x5_periph_clk) = {
479         .name = "sam9x5-periph-clk",
480         .id = UCLASS_MISC,
481         .of_match = sam9x5_periph_clk_match,
482         .bind = sam9x5_periph_clk_bind,
483 };
484
485 static int periph_clk_enable(struct clk *clk)
486 {
487         struct pmc_plat *plat = dev_get_plat(clk->dev);
488         struct at91_pmc *pmc = plat->reg_base;
489         enum periph_clk_type clk_type;
490         void *addr;
491
492         if (clk->id < PERIPHERAL_ID_MIN)
493                 return -1;
494
495         clk_type = dev_get_driver_data(dev_get_parent(clk->dev));
496         if (clk_type == CLK_PERIPH_AT91RM9200) {
497                 addr = &pmc->pcer;
498                 if (clk->id > PERIPHERAL_ID_MAX)
499                         addr = &pmc->pcer1;
500
501                 setbits_le32(addr, PERIPHERAL_MASK(clk->id));
502         } else {
503                 writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
504                 setbits_le32(&pmc->pcr,
505                              AT91_PMC_PCR_CMD_WRITE | AT91_PMC_PCR_EN);
506         }
507
508         return 0;
509 }
510
511 static ulong periph_get_rate(struct clk *clk)
512 {
513         struct udevice *dev;
514         struct clk clk_dev;
515         ulong clk_rate;
516         int ret;
517
518         dev = dev_get_parent(clk->dev);
519
520         ret = clk_get_by_index(dev, 0, &clk_dev);
521         if (ret)
522                 return ret;
523
524         clk_rate = clk_get_rate(&clk_dev);
525
526         clk_free(&clk_dev);
527
528         return clk_rate;
529 }
530
531 static struct clk_ops periph_clk_ops = {
532         .of_xlate = at91_clk_of_xlate,
533         .enable = periph_clk_enable,
534         .get_rate = periph_get_rate,
535 };
536
537 U_BOOT_DRIVER(clk_periph) = {
538         .name   = "periph-clk",
539         .id     = UCLASS_CLK,
540         .plat_auto      = sizeof(struct pmc_plat),
541         .probe = at91_clk_probe,
542         .ops    = &periph_clk_ops,
543 };
544
545 /* UTMI clock specific code. */
546 #ifdef CONFIG_AT91_UTMI
547
548 /*
549  * The purpose of this clock is to generate a 480 MHz signal. A different
550  * rate can't be configured.
551  */
552 #define UTMI_RATE       480000000
553
554 static int utmi_clk_enable(struct clk *clk)
555 {
556         struct pmc_plat *plat = dev_get_plat(clk->dev);
557         struct at91_pmc *pmc = plat->reg_base;
558         struct clk clk_dev;
559         ulong clk_rate;
560         u32 utmi_ref_clk_freq;
561         u32 tmp;
562         int err;
563         int timeout = 2000000;
564
565         if (readl(&pmc->sr) & AT91_PMC_LOCKU)
566                 return 0;
567
568         /*
569          * If mainck rate is different from 12 MHz, we have to configure the
570          * FREQ field of the SFR_UTMICKTRIM register to generate properly
571          * the utmi clock.
572          */
573         err = clk_get_by_index(clk->dev, 0, &clk_dev);
574         if (err)
575                 return -EINVAL;
576
577         clk_rate = clk_get_rate(&clk_dev);
578         switch (clk_rate) {
579         case 12000000:
580                 utmi_ref_clk_freq = 0;
581                 break;
582         case 16000000:
583                 utmi_ref_clk_freq = 1;
584                 break;
585         case 24000000:
586                 utmi_ref_clk_freq = 2;
587                 break;
588         /*
589          * Not supported on SAMA5D2 but it's not an issue since MAINCK
590          * maximum value is 24 MHz.
591          */
592         case 48000000:
593                 utmi_ref_clk_freq = 3;
594                 break;
595         default:
596                 printf("UTMICK: unsupported mainck rate\n");
597                 return -EINVAL;
598         }
599
600         if (plat->regmap_sfr) {
601                 err = regmap_read(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, &tmp);
602                 if (err)
603                         return -EINVAL;
604
605                 tmp &= ~AT91_UTMICKTRIM_FREQ;
606                 tmp |= utmi_ref_clk_freq;
607                 err = regmap_write(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, tmp);
608                 if (err)
609                         return -EINVAL;
610         } else if (utmi_ref_clk_freq) {
611                 printf("UTMICK: sfr node required\n");
612                 return -EINVAL;
613         }
614
615         tmp = readl(&pmc->uckr);
616         tmp |= AT91_PMC_UPLLEN |
617                AT91_PMC_UPLLCOUNT |
618                AT91_PMC_BIASEN;
619         writel(tmp, &pmc->uckr);
620
621         while ((--timeout) && !(readl(&pmc->sr) & AT91_PMC_LOCKU))
622                 ;
623         if (!timeout) {
624                 printf("UTMICK: timeout waiting for UPLL lock\n");
625                 return -ETIMEDOUT;
626         }
627
628         return 0;
629 }
630
631 static ulong utmi_clk_get_rate(struct clk *clk)
632 {
633         /* UTMI clk rate is fixed. */
634         return UTMI_RATE;
635 }
636
637 static struct clk_ops utmi_clk_ops = {
638         .enable = utmi_clk_enable,
639         .get_rate = utmi_clk_get_rate,
640 };
641
642 static int utmi_clk_of_to_plat(struct udevice *dev)
643 {
644         struct pmc_plat *plat = dev_get_plat(dev);
645         struct udevice *syscon;
646
647         uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
648                                      "regmap-sfr", &syscon);
649
650         if (syscon)
651                 plat->regmap_sfr = syscon_get_regmap(syscon);
652
653         return 0;
654 }
655
656 static int utmi_clk_probe(struct udevice *dev)
657 {
658         return at91_pmc_core_probe(dev);
659 }
660
661 static const struct udevice_id utmi_clk_match[] = {
662         { .compatible = "atmel,at91sam9x5-clk-utmi" },
663         {}
664 };
665
666 U_BOOT_DRIVER(at91sam9x5_utmi_clk) = {
667         .name = "at91sam9x5-utmi-clk",
668         .id = UCLASS_CLK,
669         .of_match = utmi_clk_match,
670         .probe = utmi_clk_probe,
671         .of_to_plat = utmi_clk_of_to_plat,
672         .plat_auto      = sizeof(struct pmc_plat),
673         .ops = &utmi_clk_ops,
674 };
675
676 #endif /* CONFIG_AT91_UTMI */
677
678 /* H32MX clock specific code. */
679 #ifdef CONFIG_AT91_H32MX
680
681 #define H32MX_MAX_FREQ  90000000
682
683 static ulong sama5d4_h32mx_clk_get_rate(struct clk *clk)
684 {
685         struct pmc_plat *plat = dev_get_plat(clk->dev);
686         struct at91_pmc *pmc = plat->reg_base;
687         ulong rate = gd->arch.mck_rate_hz;
688
689         if (readl(&pmc->mckr) & AT91_PMC_MCKR_H32MXDIV)
690                 rate /= 2;
691
692         if (rate > H32MX_MAX_FREQ)
693                 dev_dbg(clk->dev, "H32MX clock is too fast\n");
694
695         return rate;
696 }
697
698 static struct clk_ops sama5d4_h32mx_clk_ops = {
699         .get_rate = sama5d4_h32mx_clk_get_rate,
700 };
701
702 static int sama5d4_h32mx_clk_probe(struct udevice *dev)
703 {
704         return at91_pmc_core_probe(dev);
705 }
706
707 static const struct udevice_id sama5d4_h32mx_clk_match[] = {
708         { .compatible = "atmel,sama5d4-clk-h32mx" },
709         {}
710 };
711
712 U_BOOT_DRIVER(sama5d4_h32mx_clk) = {
713         .name = "sama5d4-h32mx-clk",
714         .id = UCLASS_CLK,
715         .of_match = sama5d4_h32mx_clk_match,
716         .probe = sama5d4_h32mx_clk_probe,
717         .plat_auto      = sizeof(struct pmc_plat),
718         .ops = &sama5d4_h32mx_clk_ops,
719 };
720
721 #endif /* CONFIG_AT91_H32MX */
722
723 /* Generic clock specific code. */
724 #ifdef CONFIG_AT91_GENERIC_CLK
725
726 #define GENERATED_SOURCE_MAX    6
727 #define GENERATED_MAX_DIV       255
728
729 /**
730  * generated_clk_bind() - for the generated clock driver
731  * Recursively bind its children as clk devices.
732  *
733  * @return: 0 on success, or negative error code on failure
734  */
735 static int generated_clk_bind(struct udevice *dev)
736 {
737         return at91_clk_sub_device_bind(dev, "generic-clk");
738 }
739
740 static const struct udevice_id generated_clk_match[] = {
741         { .compatible = "atmel,sama5d2-clk-generated" },
742         {}
743 };
744
745 U_BOOT_DRIVER(generated_clk) = {
746         .name = "generated-clk",
747         .id = UCLASS_MISC,
748         .of_match = generated_clk_match,
749         .bind = generated_clk_bind,
750 };
751
752 struct generic_clk_priv {
753         u32 num_parents;
754 };
755
756 static ulong generic_clk_get_rate(struct clk *clk)
757 {
758         struct pmc_plat *plat = dev_get_plat(clk->dev);
759         struct at91_pmc *pmc = plat->reg_base;
760         struct clk parent;
761         ulong clk_rate;
762         u32 tmp, gckdiv;
763         u8 clock_source, parent_index;
764         int ret;
765
766         writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
767         tmp = readl(&pmc->pcr);
768         clock_source = (tmp >> AT91_PMC_PCR_GCKCSS_OFFSET) &
769                     AT91_PMC_PCR_GCKCSS_MASK;
770         gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK;
771
772         parent_index = clock_source - 1;
773         ret = clk_get_by_index(dev_get_parent(clk->dev), parent_index, &parent);
774         if (ret)
775                 return 0;
776
777         clk_rate = clk_get_rate(&parent) / (gckdiv + 1);
778
779         clk_free(&parent);
780
781         return clk_rate;
782 }
783
784 static ulong generic_clk_set_rate(struct clk *clk, ulong rate)
785 {
786         struct pmc_plat *plat = dev_get_plat(clk->dev);
787         struct at91_pmc *pmc = plat->reg_base;
788         struct generic_clk_priv *priv = dev_get_priv(clk->dev);
789         struct clk parent, best_parent;
790         ulong tmp_rate, best_rate = rate, parent_rate;
791         int tmp_diff, best_diff = -1;
792         u32 div, best_div = 0;
793         u8 best_parent_index, best_clock_source = 0;
794         u8 i;
795         u32 tmp;
796         int ret;
797
798         for (i = 0; i < priv->num_parents; i++) {
799                 ret = clk_get_by_index(dev_get_parent(clk->dev), i, &parent);
800                 if (ret)
801                         return ret;
802
803                 parent_rate = clk_get_rate(&parent);
804                 if (IS_ERR_VALUE(parent_rate))
805                         return parent_rate;
806
807                 for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
808                         tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
809                         tmp_diff = abs(rate - tmp_rate);
810
811                         if (best_diff < 0 || best_diff > tmp_diff) {
812                                 best_rate = tmp_rate;
813                                 best_diff = tmp_diff;
814
815                                 best_div = div - 1;
816                                 best_parent = parent;
817                                 best_parent_index = i;
818                                 best_clock_source = best_parent_index + 1;
819                         }
820
821                         if (!best_diff || tmp_rate < rate)
822                                 break;
823                 }
824
825                 if (!best_diff)
826                         break;
827         }
828
829         debug("GCK: best parent: %s, best_rate = %ld, best_div = %d\n",
830               best_parent.dev->name, best_rate, best_div);
831
832         ret = clk_enable(&best_parent);
833         if (ret)
834                 return ret;
835
836         writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
837         tmp = readl(&pmc->pcr);
838         tmp &= ~(AT91_PMC_PCR_GCKDIV | AT91_PMC_PCR_GCKCSS);
839         tmp |= AT91_PMC_PCR_GCKCSS_(best_clock_source) |
840                AT91_PMC_PCR_CMD_WRITE |
841                AT91_PMC_PCR_GCKDIV_(best_div) |
842                AT91_PMC_PCR_GCKEN;
843         writel(tmp, &pmc->pcr);
844
845         while (!(readl(&pmc->sr) & AT91_PMC_GCKRDY))
846                 ;
847
848         return 0;
849 }
850
851 static struct clk_ops generic_clk_ops = {
852         .of_xlate = at91_clk_of_xlate,
853         .get_rate = generic_clk_get_rate,
854         .set_rate = generic_clk_set_rate,
855 };
856
857 static int generic_clk_of_to_plat(struct udevice *dev)
858 {
859         struct generic_clk_priv *priv = dev_get_priv(dev);
860         u32 cells[GENERATED_SOURCE_MAX];
861         u32 num_parents;
862
863         num_parents = fdtdec_get_int_array_count(gd->fdt_blob,
864                         dev_of_offset(dev_get_parent(dev)), "clocks", cells,
865                         GENERATED_SOURCE_MAX);
866
867         if (!num_parents)
868                 return -1;
869
870         priv->num_parents = num_parents;
871
872         return 0;
873 }
874
875 U_BOOT_DRIVER(generic_clk) = {
876         .name = "generic-clk",
877         .id = UCLASS_CLK,
878         .probe = at91_clk_probe,
879         .of_to_plat = generic_clk_of_to_plat,
880         .priv_auto      = sizeof(struct generic_clk_priv),
881         .plat_auto      = sizeof(struct pmc_plat),
882         .ops = &generic_clk_ops,
883 };
884
885 #endif /* CONFIG_AT91_GENERIC_CLK */
886
887 /* USB clock specific code. */
888 #ifdef CONFIG_AT91_USB_CLK
889
890 #define AT91_USB_CLK_SOURCE_MAX 2
891 #define AT91_USB_CLK_MAX_DIV    15
892
893 struct at91_usb_clk_priv {
894         u32 num_clksource;
895 };
896
897 static ulong at91_usb_clk_get_rate(struct clk *clk)
898 {
899         struct pmc_plat *plat = dev_get_plat(clk->dev);
900         struct at91_pmc *pmc = plat->reg_base;
901         struct clk source;
902         u32 tmp, usbdiv;
903         u8 source_index;
904         int ret;
905
906         tmp = readl(&pmc->pcr);
907         source_index = (tmp >> AT91_PMC_USB_USBS_OFFSET) &
908                         AT91_PMC_USB_USBS_MASK;
909         usbdiv = (tmp >> AT91_PMC_USB_DIV_OFFSET) & AT91_PMC_USB_DIV_MASK;
910
911         ret = clk_get_by_index(clk->dev, source_index, &source);
912         if (ret)
913                 return 0;
914
915         return clk_get_rate(&source) / (usbdiv + 1);
916 }
917
918 static ulong at91_usb_clk_set_rate(struct clk *clk, ulong rate)
919 {
920         struct pmc_plat *plat = dev_get_plat(clk->dev);
921         struct at91_pmc *pmc = plat->reg_base;
922         struct at91_usb_clk_priv *priv = dev_get_priv(clk->dev);
923         struct clk source, best_source;
924         ulong tmp_rate, best_rate = rate, source_rate;
925         int tmp_diff, best_diff = -1;
926         u32 div, best_div = 0;
927         u8 best_source_index = 0;
928         u8 i;
929         u32 tmp;
930         int ret;
931
932         for (i = 0; i < priv->num_clksource; i++) {
933                 ret = clk_get_by_index(clk->dev, i, &source);
934                 if (ret)
935                         return ret;
936
937                 source_rate = clk_get_rate(&source);
938                 if (IS_ERR_VALUE(source_rate))
939                         return source_rate;
940
941                 for (div = 1; div < AT91_USB_CLK_MAX_DIV + 2; div++) {
942                         tmp_rate = DIV_ROUND_CLOSEST(source_rate, div);
943                         tmp_diff = abs(rate - tmp_rate);
944
945                         if (best_diff < 0 || best_diff > tmp_diff) {
946                                 best_rate = tmp_rate;
947                                 best_diff = tmp_diff;
948
949                                 best_div = div - 1;
950                                 best_source = source;
951                                 best_source_index = i;
952                         }
953
954                         if (!best_diff || tmp_rate < rate)
955                                 break;
956                 }
957
958                 if (!best_diff)
959                         break;
960         }
961
962         debug("AT91 USB: best sourc: %s, best_rate = %ld, best_div = %d\n",
963               best_source.dev->name, best_rate, best_div);
964
965         ret = clk_enable(&best_source);
966         if (ret)
967                 return ret;
968
969         tmp = AT91_PMC_USB_USBS_(best_source_index) |
970               AT91_PMC_USB_DIV_(best_div);
971         writel(tmp, &pmc->usb);
972
973         return 0;
974 }
975
976 static struct clk_ops at91_usb_clk_ops = {
977         .get_rate = at91_usb_clk_get_rate,
978         .set_rate = at91_usb_clk_set_rate,
979 };
980
981 static int at91_usb_clk_of_to_plat(struct udevice *dev)
982 {
983         struct at91_usb_clk_priv *priv = dev_get_priv(dev);
984         u32 cells[AT91_USB_CLK_SOURCE_MAX];
985         u32 num_clksource;
986
987         num_clksource = fdtdec_get_int_array_count(gd->fdt_blob,
988                                                    dev_of_offset(dev),
989                                                    "clocks", cells,
990                                                    AT91_USB_CLK_SOURCE_MAX);
991
992         if (!num_clksource)
993                 return -1;
994
995         priv->num_clksource = num_clksource;
996
997         return 0;
998 }
999
1000 static int at91_usb_clk_probe(struct udevice *dev)
1001 {
1002         return at91_pmc_core_probe(dev);
1003 }
1004
1005 static const struct udevice_id at91_usb_clk_match[] = {
1006         { .compatible = "atmel,at91sam9x5-clk-usb" },
1007         {}
1008 };
1009
1010 U_BOOT_DRIVER(at91_usb_clk) = {
1011         .name = "at91-usb-clk",
1012         .id = UCLASS_CLK,
1013         .of_match = at91_usb_clk_match,
1014         .probe = at91_usb_clk_probe,
1015         .of_to_plat = at91_usb_clk_of_to_plat,
1016         .priv_auto      = sizeof(struct at91_usb_clk_priv),
1017         .plat_auto      = sizeof(struct pmc_plat),
1018         .ops = &at91_usb_clk_ops,
1019 };
1020
1021 #endif /* CONFIG_AT91_USB_CLK */
This page took 0.087445 seconds and 4 git commands to generate.