]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/arm/at91/at91_pmc.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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         return (bus_read_4(sc->mem_res, off));
166 }
167
168 static inline void
169 WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
170 {
171         bus_write_4(sc->mem_res, off, val);
172 }
173
174 void
175 at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
176 {
177         struct at91_pmc_softc *sc = pmc_softc;
178         uint32_t value;
179
180         if (on) {
181                 on = PMC_IER_LOCKB;
182                 value = sc->pllb_init;
183         } else {
184                 value = 0;
185         }
186
187         /* Workaround RM9200 Errata #26 */
188         if (at91_is_rm92() &&
189            ((value ^ RD4(sc, CKGR_PLLBR)) & 0x03f0ff) != 0) {
190                 WR4(sc, CKGR_PLLBR, value ^ 1);
191                 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
192                         continue;
193         }
194
195         WR4(sc, CKGR_PLLBR, value);
196         while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
197                 continue;
198 }
199
200 static void
201 at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
202 {
203         struct at91_pmc_softc *sc = pmc_softc;
204
205         WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
206         if (on)
207                 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
208                         continue;
209         else
210                 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
211                         continue;
212 }
213
214 static void
215 at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
216 {
217         struct at91_pmc_softc *sc = pmc_softc;
218
219         WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
220         if (on)
221                 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
222                         continue;
223         else
224                 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
225                         continue;
226 }
227
228 struct at91_pmc_clock *
229 at91_pmc_clock_add(const char *name, uint32_t irq, struct at91_pmc_clock *parent)
230 {
231         struct at91_pmc_clock *clk;
232         int i, buflen;
233
234         clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO);
235         if (clk == NULL) 
236                 goto err;
237
238         buflen = strlen(name) + 1;
239         clk->name = malloc(buflen, M_PMC, M_NOWAIT);
240         if (clk->name == NULL) 
241                 goto err;
242
243         strlcpy(clk->name, name, buflen);
244         clk->pmc_mask = 1 << irq;
245         clk->set_mode = &at91_pmc_set_periph_mode;
246         if (parent == NULL)
247                 clk->parent = &mck;
248         else
249                 clk->parent = parent;
250
251         for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
252                 if (clock_list[i] == NULL) {
253                         clock_list[i] = clk;
254                         return (clk);
255                 }
256         }
257 err:
258         if (clk != NULL) {
259                 if (clk->name != NULL) 
260                         free(clk->name, M_PMC);
261                 free(clk, M_PMC);
262         }
263
264         panic("could not allocate pmc clock '%s'", name);
265         return (NULL);
266 }
267
268 static void
269 at91_pmc_clock_alias(const char *name, const char *alias)
270 {
271         struct at91_pmc_clock *clk, *alias_clk;
272
273         clk = at91_pmc_clock_ref(name);
274         if (clk)
275                 alias_clk = at91_pmc_clock_add(alias, 0, clk->parent);
276
277         if (clk && alias_clk) {
278                 alias_clk->hz = clk->hz;
279                 alias_clk->pmc_mask = clk->pmc_mask;
280                 alias_clk->set_mode = clk->set_mode;
281         }
282 }
283
284 struct at91_pmc_clock *
285 at91_pmc_clock_ref(const char *name)
286 {
287         int i;
288
289         for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
290                 if (clock_list[i] == NULL)
291                     break;
292                 if (strcmp(name, clock_list[i]->name) == 0)
293                         return (clock_list[i]);
294         }
295
296         //printf("at91_pmc: Warning - did not find clock '%s'", name);
297         return (NULL);
298 }
299
300 void
301 at91_pmc_clock_deref(struct at91_pmc_clock *clk)
302 {
303 }
304
305 void
306 at91_pmc_clock_enable(struct at91_pmc_clock *clk)
307 {
308         /* XXX LOCKING? XXX */
309         if (clk->parent)
310                 at91_pmc_clock_enable(clk->parent);
311         if (clk->refcnt++ == 0 && clk->set_mode)
312                 clk->set_mode(clk, 1);
313 }
314
315 void
316 at91_pmc_clock_disable(struct at91_pmc_clock *clk)
317 {
318         /* XXX LOCKING? XXX */
319         if (--clk->refcnt == 0 && clk->set_mode)
320                 clk->set_mode(clk, 0);
321         if (clk->parent)
322                 at91_pmc_clock_disable(clk->parent);
323 }
324
325 static int
326 at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
327 {
328         uint32_t mul, div, freq;
329
330         freq = clk->parent->hz;
331         div = (reg >> clk->pll_div_shift) & clk->pll_div_mask;
332         mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask;
333
334 //      printf("pll = (%d /  %d) * %d = %d\n",
335 //          freq, div ,mul + 1, (freq/div) * (mul+1));
336
337         if (div != 0 && mul != 0) {
338                 freq /= div;
339                 freq *= mul + 1;
340         } else {
341                 freq = 0;
342         }
343         clk->hz = freq;
344
345
346         return (freq);
347 }
348
349 static uint32_t
350 at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
351 {
352         uint32_t i, div = 0, mul = 0, diff = 1 << 30;
353
354         unsigned ret = 0x3e00;
355
356         if (out_freq > clk->pll_max_out)
357                 goto fail;
358
359         for (i = 1; i < 256; i++) {
360                 int32_t diff1;
361                 uint32_t input, mul1;
362
363                 input = clk->parent->hz / i;
364                 if (input < clk->pll_min_in)
365                         break;
366                 if (input > clk->pll_max_in)
367                         continue;
368
369                 mul1 = out_freq / input;
370                 if (mul1 > (clk->pll_mul_mask + 1))
371                         continue;
372                 if (mul1 == 0)
373                         break;
374
375                 diff1 = out_freq - input * mul1;
376                 if (diff1 < 0)
377                         diff1 = -diff1;
378                 if (diff > diff1) {
379                         diff = diff1;
380                         div = i;
381                         mul = mul1;
382                         if (diff == 0)
383                                 break;
384                 }
385         }
386         if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
387                 goto fail;
388
389         if (clk->set_outb != NULL)
390                 ret |= clk->set_outb(out_freq);
391
392         return (ret |
393                 ((mul - 1) << clk->pll_mul_shift) |
394                 (div << clk->pll_div_shift));
395 fail:
396         return (0);
397 }
398
399 static void
400 at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock)
401 {
402         uint32_t mckr;
403         uint32_t mdiv;
404
405         if (at91_is_sam9()) {
406                 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
407                 udpck.pmc_mask = PMC_SCER_UDP_SAM9;
408         }
409         mckr = RD4(sc, PMC_MCKR);
410         sc->main_clock_hz = main_clock;
411         main_ck.hz = main_clock;
412
413         at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
414
415         if (at91_cpu_is(AT91_CPU_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
416                 plla.hz /= 2;
417
418         /*
419          * Initialize the usb clock.  This sets up pllb, but disables the
420          * actual clock.
421          */
422         sc->pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
423         at91_pmc_pll_rate(&pllb, sc->pllb_init);
424
425 #if 0
426         /* Turn off USB clocks */
427         at91_pmc_set_periph_mode(&ohci_clk, 0);
428         at91_pmc_set_periph_mode(&udc_clk, 0);
429 #endif
430
431         if (at91_is_rm92()) {
432                 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
433                 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
434         } else {
435                 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
436         }
437         WR4(sc, CKGR_PLLBR, 0);
438
439         /*
440          * MCK and PCU derive from one of the primary clocks.  Initialize
441          * this relationship.
442          */
443         mck.parent = clock_list[mckr & 0x3];
444         mck.parent->refcnt++;
445
446         cpu.hz = 
447         mck.hz = mck.parent->hz /
448              (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
449
450         mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
451         if (at91_is_sam9()) {
452                 if (mdiv > 0)
453                         mck.hz /= mdiv * 2;
454         } else 
455                 mck.hz /= (1 + mdiv);
456
457         /* Only found on SAM9G20 */
458         if (at91_cpu_is(AT91_CPU_SAM9G20))
459                 cpu.hz /= (mckr & PMC_MCKR_PDIV) ?  2 : 1;
460
461         at91_master_clock = mck.hz;
462
463         device_printf(sc->dev,
464             "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
465             sc->main_clock_hz,
466             plla.hz / 1000000,
467             cpu.hz / 1000000, mck.hz / 1000000);
468
469         /* Turn off "Progamable" clocks */
470         WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
471             PMC_SCER_PCK3);
472
473         /* XXX kludge, turn on all peripherals */
474         WR4(sc, PMC_PCER, 0xffffffff);
475
476         /* Disable all interrupts for PMC */
477         WR4(sc, PMC_IDR, 0xffffffff);
478 }
479
480 static void
481 at91_pmc_deactivate(device_t dev)
482 {
483         struct at91_pmc_softc *sc;
484
485         sc = device_get_softc(dev);
486         bus_generic_detach(sc->dev);
487         if (sc->mem_res)
488                 bus_release_resource(dev, SYS_RES_IOPORT,
489                     rman_get_rid(sc->mem_res), sc->mem_res);
490         sc->mem_res = 0;
491         return;
492 }
493
494 static int
495 at91_pmc_activate(device_t dev)
496 {
497         struct at91_pmc_softc *sc;
498         int rid;
499
500         sc = device_get_softc(dev);
501         rid = 0;
502         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
503             RF_ACTIVE);
504         if (sc->mem_res == NULL)
505                 goto errout;
506         return (0);
507 errout:
508         at91_pmc_deactivate(dev);
509         return (ENOMEM);
510 }
511
512 static int
513 at91_pmc_probe(device_t dev)
514 {
515
516         device_set_desc(dev, "PMC");
517         return (0);
518 }
519
520 #if !defined(AT91C_MAIN_CLOCK)
521 static unsigned int
522 at91_pmc_sense_mainf(struct at91_pmc_softc *sc)
523 {
524         unsigned int ckgr_val;
525         unsigned int diff, matchdiff;
526         int i, match;
527
528         ckgr_val = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
529
530         /*
531          * Try to find the standard frequency that match best.
532          */
533         match = 0;
534         matchdiff = abs(ckgr_val - at91_mainf_tbl[0]);
535         for (i = 1; i < MAINF_TBL_LEN; i++) {
536                 diff = abs(ckgr_val - at91_mainf_tbl[i]);
537                 if (diff < matchdiff) {
538                         match = i;
539                         matchdiff = diff;
540                 }
541         }
542         return (at91_mainf_tbl[match]);
543 }
544 #endif
545
546 static int
547 at91_pmc_attach(device_t dev)
548 {
549         unsigned int mainf;
550         int err;
551
552         pmc_softc = device_get_softc(dev);
553         pmc_softc->dev = dev;
554         if ((err = at91_pmc_activate(dev)) != 0)
555                 return (err);
556
557         /*
558          * Configure main clock frequency.
559          */
560 #if !defined(AT91C_MAIN_CLOCK)
561         mainf = at91_pmc_sense_mainf(pmc_softc);
562 #else
563         mainf = AT91C_MAIN_CLOCK;
564 #endif
565         at91_pmc_init_clock(pmc_softc, mainf);
566
567         /* These clocks refrenced by "special" names */
568         at91_pmc_clock_alias("ohci0", "ohci_clk");
569         at91_pmc_clock_alias("udp0",  "udp_clk");
570
571         return (0);
572 }
573
574 static device_method_t at91_pmc_methods[] = {
575         DEVMETHOD(device_probe, at91_pmc_probe),
576         DEVMETHOD(device_attach, at91_pmc_attach),
577         {0, 0},
578 };
579
580 static driver_t at91_pmc_driver = {
581         "at91_pmc",
582         at91_pmc_methods,
583         sizeof(struct at91_pmc_softc),
584 };
585 static devclass_t at91_pmc_devclass;
586
587 DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, 0, 0);