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);
Cache object: 083ceaa8bffdebaf11d65d1c1607ccdb
|