]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/arm/at91/at91_pmc.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / arm / at91 / at91_pmc.c
1 /*-
2  * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
3  * Copyright (c) 2010 Greg Ansley.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/module.h>
35 #include <sys/time.h>
36 #include <sys/bus.h>
37 #include <sys/resource.h>
38 #include <sys/rman.h>
39 #include <sys/timetc.h>
40
41 #include <machine/bus.h>
42 #include <machine/cpu.h>
43 #include <machine/cpufunc.h>
44 #include <machine/resource.h>
45 #include <machine/frame.h>
46 #include <machine/intr.h>
47 #include <arm/at91/at91reg.h>
48 #include <arm/at91/at91var.h>
49
50 #include <arm/at91/at91_pmcreg.h>
51 #include <arm/at91/at91_pmcvar.h>
52
53 static struct at91_pmc_softc {
54         bus_space_tag_t         sc_st;
55         bus_space_handle_t      sc_sh;
56         struct resource *mem_res;       /* Memory resource */
57         device_t                dev;
58         unsigned int            main_clock_hz;
59         uint32_t                pllb_init;
60 } *pmc_softc;
61
62 MALLOC_DECLARE(M_PMC);
63 MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors");
64
65 static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
66 static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
67 static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
68 static void at91_pmc_clock_alias(const char *name, const char *alias);
69
70 static struct at91_pmc_clock slck = {
71         .name = "slck",         // 32,768 Hz slow clock
72         .hz = 32768,
73         .refcnt = 1,
74         .id = 0,
75         .primary = 1,
76 };
77
78 /*
79  * NOTE: Clocks for "ordinary peripheral" devices e.g. spi0, udp0, uhp0 etc.
80  * are now created automatically. Only "system" clocks need be defined here.
81  */
82 static struct at91_pmc_clock main_ck = {
83         .name = "main",         // Main clock
84         .refcnt = 0,
85         .id = 1,
86         .primary = 1,
87         .pmc_mask = PMC_IER_MOSCS,
88 };
89
90 static struct at91_pmc_clock plla = {
91         .name = "plla",         // PLLA Clock, used for CPU clocking
92         .parent = &main_ck,
93         .refcnt = 1,
94         .id = 0,
95         .primary = 1,
96         .pll = 1,
97         .pmc_mask = PMC_IER_LOCKA,
98 };
99
100 static struct at91_pmc_clock pllb = {
101         .name = "pllb",         // PLLB Clock, used for USB functions
102         .parent = &main_ck,
103         .refcnt = 0,
104         .id = 0,
105         .primary = 1,
106         .pll = 1,
107         .pmc_mask = PMC_IER_LOCKB,
108         .set_mode = &at91_pmc_set_pllb_mode,
109 };
110
111 static struct at91_pmc_clock udpck = {
112         .name = "udpck",
113         .parent = &pllb,
114         .pmc_mask = PMC_SCER_UDP,
115         .set_mode = at91_pmc_set_sys_mode
116 };
117
118 static struct at91_pmc_clock uhpck = {
119         .name = "uhpck",
120         .parent = &pllb,
121         .pmc_mask = PMC_SCER_UHP,
122         .set_mode = at91_pmc_set_sys_mode
123 };
124
125 static struct at91_pmc_clock mck = {
126         .name = "mck",          // Master (Peripheral) Clock
127         .pmc_mask = PMC_IER_MCKRDY,
128         .refcnt = 0,
129 };
130
131 static struct at91_pmc_clock cpu = {
132         .name = "cpu",          // CPU Clock
133         .parent = &plla,
134         .pmc_mask = PMC_SCER_PCK,
135         .refcnt = 0,
136 };
137
138 /* "+32" or the automatic peripheral clocks */
139 static struct at91_pmc_clock *clock_list[16+32] = {
140         &slck,
141         &main_ck,
142         &plla,
143         &pllb,
144         &udpck,
145         &uhpck,
146         &mck,
147         &cpu
148 };
149
150 #if !defined(AT91C_MAIN_CLOCK)
151 static const unsigned int at91_mainf_tbl[] = {
152         3000000, 3276800, 3686400, 3840000, 4000000,
153         4433619, 4915200, 5000000, 5242880, 6000000,
154         6144000, 6400000, 6553600, 7159090, 7372800,
155         7864320, 8000000, 9830400, 10000000, 11059200,
156         12000000, 12288000, 13560000, 14318180, 14745600,
157         16000000, 17344700, 18432000, 20000000
158 };
159 #define MAINF_TBL_LEN   (sizeof(at91_mainf_tbl) / sizeof(*at91_mainf_tbl))
160 #endif
161
162 static inline uint32_t
163 RD4(struct at91_pmc_softc *sc, bus_size_t off)
164 {
165
166         return (bus_read_4(sc->mem_res, off));
167 }
168
169 static inline void
170 WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
171 {
172
173         bus_write_4(sc->mem_res, off, val);
174 }
175
176 void
177 at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
178 {
179         struct at91_pmc_softc *sc = pmc_softc;
180         uint32_t value;
181
182         if (on) {
183                 on = PMC_IER_LOCKB;
184                 value = sc->pllb_init;
185         } else
186                 value = 0;
187
188         /* Workaround RM9200 Errata #26 */
189         if (at91_is_rm92() &&
190            ((value ^ RD4(sc, CKGR_PLLBR)) & 0x03f0ff) != 0) {
191                 WR4(sc, CKGR_PLLBR, value ^ 1);
192                 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
193                         continue;
194         }
195
196         WR4(sc, CKGR_PLLBR, value);
197         while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
198                 continue;
199 }
200
201 static void
202 at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
203 {
204         struct at91_pmc_softc *sc = pmc_softc;
205
206         WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
207         if (on)
208                 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
209                         continue;
210         else
211                 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
212                         continue;
213 }
214
215 static void
216 at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
217 {
218         struct at91_pmc_softc *sc = pmc_softc;
219
220         WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
221         if (on)
222                 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
223                         continue;
224         else
225                 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
226                         continue;
227 }
228
229 struct at91_pmc_clock *
230 at91_pmc_clock_add(const char *name, uint32_t irq,
231     struct at91_pmc_clock *parent)
232 {
233         struct at91_pmc_clock *clk;
234         int i, buflen;
235
236         clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO);
237         if (clk == NULL)
238                 goto err;
239
240         buflen = strlen(name) + 1;
241         clk->name = malloc(buflen, M_PMC, M_NOWAIT);
242         if (clk->name == NULL)
243                 goto err;
244
245         strlcpy(clk->name, name, buflen);
246         clk->pmc_mask = 1 << irq;
247         clk->set_mode = &at91_pmc_set_periph_mode;
248         if (parent == NULL)
249                 clk->parent = &mck;
250         else
251                 clk->parent = parent;
252
253         for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
254                 if (clock_list[i] == NULL) {
255                         clock_list[i] = clk;
256                         return (clk);
257                 }
258         }
259 err:
260         if (clk != NULL) {
261                 if (clk->name != NULL)
262                         free(clk->name, M_PMC);
263                 free(clk, M_PMC);
264         }
265
266         panic("could not allocate pmc clock '%s'", name);
267         return (NULL);
268 }
269
270 static void
271 at91_pmc_clock_alias(const char *name, const char *alias)
272 {
273         struct at91_pmc_clock *clk, *alias_clk;
274
275         clk = at91_pmc_clock_ref(name);
276         if (clk)
277                 alias_clk = at91_pmc_clock_add(alias, 0, clk->parent);
278
279         if (clk && alias_clk) {
280                 alias_clk->hz = clk->hz;
281                 alias_clk->pmc_mask = clk->pmc_mask;
282                 alias_clk->set_mode = clk->set_mode;
283         }
284 }
285
286 struct at91_pmc_clock *
287 at91_pmc_clock_ref(const char *name)
288 {
289         int i;
290
291         for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
292                 if (clock_list[i] == NULL)
293                     break;
294                 if (strcmp(name, clock_list[i]->name) == 0)
295                         return (clock_list[i]);
296         }
297
298         //printf("at91_pmc: Warning - did not find clock '%s'", name);
299         return (NULL);
300 }
301
302 void
303 at91_pmc_clock_deref(struct at91_pmc_clock *clk)
304 {
305
306 }
307
308 void
309 at91_pmc_clock_enable(struct at91_pmc_clock *clk)
310 {
311
312         /* XXX LOCKING? XXX */
313         if (clk->parent)
314                 at91_pmc_clock_enable(clk->parent);
315         if (clk->refcnt++ == 0 && clk->set_mode)
316                 clk->set_mode(clk, 1);
317 }
318
319 void
320 at91_pmc_clock_disable(struct at91_pmc_clock *clk)
321 {
322
323         /* XXX LOCKING? XXX */
324         if (--clk->refcnt == 0 && clk->set_mode)
325                 clk->set_mode(clk, 0);
326         if (clk->parent)
327                 at91_pmc_clock_disable(clk->parent);
328 }
329
330 static int
331 at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
332 {
333         uint32_t mul, div, freq;
334
335         freq = clk->parent->hz;
336         div = (reg >> clk->pll_div_shift) & clk->pll_div_mask;
337         mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask;
338
339 #if 0
340         printf("pll = (%d /  %d) * %d = %d\n",
341             freq, div, mul + 1, (freq/div) * (mul+1));
342 #endif
343
344         if (div != 0 && mul != 0) {
345                 freq /= div;
346                 freq *= mul + 1;
347         } else
348                 freq = 0;
349         clk->hz = freq;
350
351         return (freq);
352 }
353
354 static uint32_t
355 at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
356 {
357         uint32_t i, div = 0, mul = 0, diff = 1 << 30;
358
359         unsigned ret = 0x3e00;
360
361         if (out_freq > clk->pll_max_out)
362                 goto fail;
363
364         for (i = 1; i < 256; i++) {
365                 int32_t diff1;
366                 uint32_t input, mul1;
367
368                 input = clk->parent->hz / i;
369                 if (input < clk->pll_min_in)
370                         break;
371                 if (input > clk->pll_max_in)
372                         continue;
373
374                 mul1 = out_freq / input;
375                 if (mul1 > (clk->pll_mul_mask + 1))
376                         continue;
377                 if (mul1 == 0)
378                         break;
379
380                 diff1 = out_freq - input * mul1;
381                 if (diff1 < 0)
382                         diff1 = -diff1;
383                 if (diff > diff1) {
384                         diff = diff1;
385                         div = i;
386                         mul = mul1;
387                         if (diff == 0)
388                                 break;
389                 }
390         }
391         if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
392                 goto fail;
393
394         if (clk->set_outb != NULL)
395                 ret |= clk->set_outb(out_freq);
396
397         return (ret |
398                 ((mul - 1) << clk->pll_mul_shift) |
399                 (div << clk->pll_div_shift));
400 fail:
401         return (0);
402 }
403
404 static void
405 at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock)
406 {
407         uint32_t mckr;
408         uint32_t mdiv;
409
410         if (at91_is_sam9() || at91_is_sam9xe()) {
411                 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
412                 udpck.pmc_mask = PMC_SCER_UDP_SAM9;
413         }
414         mckr = RD4(sc, PMC_MCKR);
415         sc->main_clock_hz = main_clock;
416         main_ck.hz = main_clock;
417
418         at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
419
420         if (at91_cpu_is(AT91_CPU_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
421                 plla.hz /= 2;
422
423         /*
424          * Initialize the usb clock.  This sets up pllb, but disables the
425          * actual clock.
426          */
427         sc->pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
428         at91_pmc_pll_rate(&pllb, sc->pllb_init);
429
430 #if 0
431         /* Turn off USB clocks */
432         at91_pmc_set_periph_mode(&ohci_clk, 0);
433         at91_pmc_set_periph_mode(&udc_clk, 0);
434 #endif
435
436         if (at91_is_rm92()) {
437                 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
438                 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
439         } else
440                 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
441         WR4(sc, CKGR_PLLBR, 0);
442
443         /*
444          * MCK and PCU derive from one of the primary clocks.  Initialize
445          * this relationship.
446          */
447         mck.parent = clock_list[mckr & 0x3];
448         mck.parent->refcnt++;
449
450         cpu.hz = mck.hz = mck.parent->hz /
451             (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
452
453         mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
454         if (at91_is_sam9() || at91_is_sam9xe()) {
455                 if (mdiv > 0)
456                         mck.hz /= mdiv * 2;
457         } else
458                 mck.hz /= (1 + mdiv);
459
460         /* Only found on SAM9G20 */
461         if (at91_cpu_is(AT91_CPU_SAM9G20))
462                 cpu.hz /= (mckr & PMC_MCKR_PDIV) ?  2 : 1;
463
464         at91_master_clock = mck.hz;
465
466         device_printf(sc->dev,
467             "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
468             sc->main_clock_hz,
469             plla.hz / 1000000,
470             cpu.hz / 1000000, mck.hz / 1000000);
471
472         /* Turn off "Progamable" clocks */
473         WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
474             PMC_SCER_PCK3);
475
476         /* XXX kludge, turn on all peripherals */
477         WR4(sc, PMC_PCER, 0xffffffff);
478
479         /* Disable all interrupts for PMC */
480         WR4(sc, PMC_IDR, 0xffffffff);
481 }
482
483 static void
484 at91_pmc_deactivate(device_t dev)
485 {
486         struct at91_pmc_softc *sc;
487
488         sc = device_get_softc(dev);
489         bus_generic_detach(sc->dev);
490         if (sc->mem_res)
491                 bus_release_resource(dev, SYS_RES_IOPORT,
492                     rman_get_rid(sc->mem_res), sc->mem_res);
493         sc->mem_res = 0;
494 }
495
496 static int
497 at91_pmc_activate(device_t dev)
498 {
499         struct at91_pmc_softc *sc;
500         int rid;
501
502         sc = device_get_softc(dev);
503         rid = 0;
504         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
505             RF_ACTIVE);
506         if (sc->mem_res == NULL)
507                 goto errout;
508         return (0);
509 errout:
510         at91_pmc_deactivate(dev);
511         return (ENOMEM);
512 }
513
514 static int
515 at91_pmc_probe(device_t dev)
516 {
517
518         device_set_desc(dev, "PMC");
519         return (0);
520 }
521
522 #if !defined(AT91C_MAIN_CLOCK)
523 static unsigned int
524 at91_pmc_sense_mainf(struct at91_pmc_softc *sc)
525 {
526         unsigned int ckgr_val;
527         unsigned int diff, matchdiff;
528         int i, match;
529
530         ckgr_val = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
531
532         /*
533          * Try to find the standard frequency that match best.
534          */
535         match = 0;
536         matchdiff = abs(ckgr_val - at91_mainf_tbl[0]);
537         for (i = 1; i < MAINF_TBL_LEN; i++) {
538                 diff = abs(ckgr_val - at91_mainf_tbl[i]);
539                 if (diff < matchdiff) {
540                         match = i;
541                         matchdiff = diff;
542                 }
543         }
544         return (at91_mainf_tbl[match]);
545 }
546 #endif
547
548 static int
549 at91_pmc_attach(device_t dev)
550 {
551         unsigned int mainf;
552         int err;
553
554         pmc_softc = device_get_softc(dev);
555         pmc_softc->dev = dev;
556         if ((err = at91_pmc_activate(dev)) != 0)
557                 return (err);
558
559         /*
560          * Configure main clock frequency.
561          */
562 #if !defined(AT91C_MAIN_CLOCK)
563         mainf = at91_pmc_sense_mainf(pmc_softc);
564 #else
565         mainf = AT91C_MAIN_CLOCK;
566 #endif
567         at91_pmc_init_clock(pmc_softc, mainf);
568
569         /* These clocks refrenced by "special" names */
570         at91_pmc_clock_alias("ohci0", "ohci_clk");
571         at91_pmc_clock_alias("udp0",  "udp_clk");
572
573         return (0);
574 }
575
576 static device_method_t at91_pmc_methods[] = {
577         DEVMETHOD(device_probe, at91_pmc_probe),
578         DEVMETHOD(device_attach, at91_pmc_attach),
579         DEVMETHOD_END
580 };
581
582 static driver_t at91_pmc_driver = {
583         "at91_pmc",
584         at91_pmc_methods,
585         sizeof(struct at91_pmc_softc),
586 };
587 static devclass_t at91_pmc_devclass;
588
589 DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, NULL,
590     NULL);