Deleted Added
full compact
at91_pmc.c (298352) at91_pmc.c (298848)
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 "opt_platform.h"
28
29#include <sys/cdefs.h>
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 "opt_platform.h"
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pmc.c 298352 2016-04-20 15:45:55Z pfg $");
30__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pmc.c 298848 2016-04-30 14:41:18Z pfg $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/time.h>
38#include <sys/bus.h>
39#include <sys/resource.h>
40#include <sys/rman.h>
41#include <sys/timetc.h>
42
43#include <machine/bus.h>
44#include <machine/cpu.h>
45#include <machine/cpufunc.h>
46#include <machine/resource.h>
47#include <machine/intr.h>
48#include <arm/at91/at91reg.h>
49#include <arm/at91/at91var.h>
50
51#include <arm/at91/at91_pmcreg.h>
52#include <arm/at91/at91_pmcvar.h>
53
54#ifdef FDT
55#include <dev/fdt/fdt_common.h>
56#include <dev/ofw/ofw_bus.h>
57#include <dev/ofw/ofw_bus_subr.h>
58#endif
59
60static struct at91_pmc_softc {
61 bus_space_tag_t sc_st;
62 bus_space_handle_t sc_sh;
63 struct resource *mem_res; /* Memory resource */
64 device_t dev;
65} *pmc_softc;
66
67static uint32_t pllb_init;
68
69MALLOC_DECLARE(M_PMC);
70MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors");
71
72#define AT91_PMC_BASE 0xffffc00
73
74static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
75static void at91_pmc_set_upll_mode(struct at91_pmc_clock *, int);
76static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
77static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
78static void at91_pmc_clock_alias(const char *name, const char *alias);
79
80static struct at91_pmc_clock slck = {
81 .name = "slck", /* 32,768 Hz slow clock */
82 .hz = 32768,
83 .refcnt = 1,
84 .id = 0,
85 .primary = 1,
86};
87
88/*
89 * NOTE: Clocks for "ordinary peripheral" devices e.g. spi0, udp0, uhp0 etc.
90 * are now created automatically. Only "system" clocks need be defined here.
91 */
92static struct at91_pmc_clock main_ck = {
93 .name = "main", /* Main clock */
94 .refcnt = 0,
95 .id = 1,
96 .primary = 1,
97 .pmc_mask = PMC_IER_MOSCS,
98};
99
100static struct at91_pmc_clock plla = {
101 .name = "plla", /* PLLA Clock, used for CPU clocking */
102 .parent = &main_ck,
103 .refcnt = 1,
104 .id = 0,
105 .primary = 1,
106 .pll = 1,
107 .pmc_mask = PMC_IER_LOCKA,
108};
109
110static struct at91_pmc_clock pllb = {
111 .name = "pllb", /* PLLB Clock, used for USB functions */
112 .parent = &main_ck,
113 .refcnt = 0,
114 .id = 0,
115 .primary = 1,
116 .pll = 1,
117 .pmc_mask = PMC_IER_LOCKB,
118 .set_mode = &at91_pmc_set_pllb_mode,
119};
120
121/* Used by USB on at91sam9g45 */
122static struct at91_pmc_clock upll = {
123 .name = "upll", /* UTMI PLL, used for USB functions on 9G45 family */
124 .parent = &main_ck,
125 .refcnt = 0,
126 .id = 0,
127 .primary = 1,
128 .pll = 1,
129 .pmc_mask = (1 << 6),
130 .set_mode = &at91_pmc_set_upll_mode,
131};
132
133static struct at91_pmc_clock udpck = {
134 .name = "udpck",
135 .parent = &pllb,
136 .pmc_mask = PMC_SCER_UDP,
137 .set_mode = at91_pmc_set_sys_mode
138};
139
140static struct at91_pmc_clock uhpck = {
141 .name = "uhpck",
142 .parent = &pllb,
143 .pmc_mask = PMC_SCER_UHP,
144 .set_mode = at91_pmc_set_sys_mode
145};
146
147static struct at91_pmc_clock mck = {
148 .name = "mck", /* Master (Peripheral) Clock */
149 .pmc_mask = PMC_IER_MCKRDY,
150 .refcnt = 0,
151};
152
153static struct at91_pmc_clock cpu = {
154 .name = "cpu", /* CPU Clock */
155 .parent = &plla,
156 .pmc_mask = PMC_SCER_PCK,
157 .refcnt = 0,
158};
159
160/* "+32" or the automatic peripheral clocks */
161static struct at91_pmc_clock *clock_list[16+32] = {
162 &slck,
163 &main_ck,
164 &plla,
165 &pllb,
166 &upll,
167 &udpck,
168 &uhpck,
169 &mck,
170 &cpu
171};
172
173static inline uint32_t
174RD4(struct at91_pmc_softc *sc, bus_size_t off)
175{
176
177 if (sc == NULL) {
178 uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
179
180 return *p;
181 }
182 return (bus_read_4(sc->mem_res, off));
183}
184
185static inline void
186WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
187{
188
189 if (sc == NULL) {
190 uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
191
192 *p = val;
193 } else
194 bus_write_4(sc->mem_res, off, val);
195}
196
197/*
198 * The following is unused currently since we don't ever set the PLLA
199 * frequency of the device. If we did, we'd have to also pay attention
200 * to the ICPLLA bit in the PMC_PLLICPR register for frequencies lower
201 * than ~600MHz, which the PMC code doesn't do right now.
202 */
203uint32_t
204at91_pmc_800mhz_plla_outb(int freq)
205{
206 uint32_t outa;
207
208 /*
209 * Set OUTA, per the data sheet. See Table 46-16 titled
210 * PLLA Frequency Regarding ICPLLA and OUTA in the SAM9X25 doc,
211 * Table 46-17 in the SAM9G20 doc, or Table 46-16 in the SAM9G45 doc.
212 * Note: the frequencies overlap by 5MHz, so we add 3 here to
213 * center shoot the transition.
214 */
215
216 freq /= 1000000; /* MHz */
217 if (freq >= 800)
218 freq = 800;
219 freq += 3; /* Allow for overlap. */
220 outa = 3 - ((freq / 50) & 3); /* 750 / 50 = 7, see table */
221 return (1 << 29)| (outa << 14);
222}
223
224uint32_t
225at91_pmc_800mhz_pllb_outb(int freq)
226{
227
228 return (0);
229}
230
231void
232at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
233{
234 struct at91_pmc_softc *sc = pmc_softc;
235 uint32_t value;
236
237 value = on ? pllb_init : 0;
238
239 /*
240 * Only write to the register if the value is changing. Besides being
241 * good common sense, this works around RM9200 Errata #26 (CKGR_PLL[AB]R
242 * must not be written with the same value currently in the register).
243 */
244 if (RD4(sc, CKGR_PLLBR) != value) {
245 WR4(sc, CKGR_PLLBR, value);
246 while (on && (RD4(sc, PMC_SR) & PMC_IER_LOCKB) != PMC_IER_LOCKB)
247 continue;
248 }
249}
250
251static void
252at91_pmc_set_upll_mode(struct at91_pmc_clock *clk, int on)
253{
254 struct at91_pmc_softc *sc = pmc_softc;
255 uint32_t value;
256
257 if (on) {
258 on = PMC_IER_LOCKU;
259 value = CKGR_UCKR_UPLLEN | CKGR_UCKR_BIASEN;
260 } else
261 value = 0;
262
263 WR4(sc, CKGR_UCKR, RD4(sc, CKGR_UCKR) | value);
264 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKU) != on)
265 continue;
266
267 WR4(sc, PMC_USB, PMC_USB_USBDIV(9) | PMC_USB_USBS);
268 WR4(sc, PMC_SCER, PMC_SCER_UHP_SAM9);
269}
270
271static void
272at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
273{
274 struct at91_pmc_softc *sc = pmc_softc;
275
276 WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
277 if (on)
278 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
279 continue;
280 else
281 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
282 continue;
283}
284
285static void
286at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
287{
288 struct at91_pmc_softc *sc = pmc_softc;
289
290 WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
291 if (on)
292 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
293 continue;
294 else
295 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
296 continue;
297}
298
299struct at91_pmc_clock *
300at91_pmc_clock_add(const char *name, uint32_t irq,
301 struct at91_pmc_clock *parent)
302{
303 struct at91_pmc_clock *clk;
304 int i, buflen;
305
306 clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO);
307 if (clk == NULL)
308 goto err;
309
310 buflen = strlen(name) + 1;
311 clk->name = malloc(buflen, M_PMC, M_NOWAIT);
312 if (clk->name == NULL)
313 goto err;
314
315 strlcpy(clk->name, name, buflen);
316 clk->pmc_mask = 1 << irq;
317 clk->set_mode = &at91_pmc_set_periph_mode;
318 if (parent == NULL)
319 clk->parent = &mck;
320 else
321 clk->parent = parent;
322
323 for (i = 0; i < nitems(clock_list); i++) {
324 if (clock_list[i] == NULL) {
325 clock_list[i] = clk;
326 return (clk);
327 }
328 }
329err:
330 if (clk != NULL) {
331 if (clk->name != NULL)
332 free(clk->name, M_PMC);
333 free(clk, M_PMC);
334 }
335
336 panic("could not allocate pmc clock '%s'", name);
337 return (NULL);
338}
339
340static void
341at91_pmc_clock_alias(const char *name, const char *alias)
342{
343 struct at91_pmc_clock *clk, *alias_clk;
344
345 clk = at91_pmc_clock_ref(name);
346 if (clk)
347 alias_clk = at91_pmc_clock_add(alias, 0, clk->parent);
348
349 if (clk && alias_clk) {
350 alias_clk->hz = clk->hz;
351 alias_clk->pmc_mask = clk->pmc_mask;
352 alias_clk->set_mode = clk->set_mode;
353 }
354}
355
356struct at91_pmc_clock *
357at91_pmc_clock_ref(const char *name)
358{
359 int i;
360
361 for (i = 0; i < nitems(clock_list); i++) {
362 if (clock_list[i] == NULL)
363 break;
364 if (strcmp(name, clock_list[i]->name) == 0)
365 return (clock_list[i]);
366 }
367
368 return (NULL);
369}
370
371void
372at91_pmc_clock_deref(struct at91_pmc_clock *clk)
373{
374 if (clk == NULL)
375 return;
376}
377
378void
379at91_pmc_clock_enable(struct at91_pmc_clock *clk)
380{
381 if (clk == NULL)
382 return;
383
384 /* XXX LOCKING? XXX */
385 if (clk->parent)
386 at91_pmc_clock_enable(clk->parent);
387 if (clk->refcnt++ == 0 && clk->set_mode)
388 clk->set_mode(clk, 1);
389}
390
391void
392at91_pmc_clock_disable(struct at91_pmc_clock *clk)
393{
394 if (clk == NULL)
395 return;
396
397 /* XXX LOCKING? XXX */
398 if (--clk->refcnt == 0 && clk->set_mode)
399 clk->set_mode(clk, 0);
400 if (clk->parent)
401 at91_pmc_clock_disable(clk->parent);
402}
403
404static int
405at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
406{
407 uint32_t mul, div, freq;
408
409 freq = clk->parent->hz;
410 div = (reg >> clk->pll_div_shift) & clk->pll_div_mask;
411 mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask;
412
413#if 0
414 printf("pll = (%d / %d) * %d = %d\n",
415 freq, div, mul + 1, (freq/div) * (mul+1));
416#endif
417
418 if (div != 0 && mul != 0) {
419 freq /= div;
420 freq *= mul + 1;
421 } else
422 freq = 0;
423 clk->hz = freq;
424
425 return (freq);
426}
427
428static uint32_t
429at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
430{
431 uint32_t i, div = 0, mul = 0, diff = 1 << 30;
432
433 unsigned ret = 0x3e00;
434
435 if (out_freq > clk->pll_max_out)
436 goto fail;
437
438 for (i = 1; i < 256; i++) {
439 int32_t diff1;
440 uint32_t input, mul1;
441
442 input = clk->parent->hz / i;
443 if (input < clk->pll_min_in)
444 break;
445 if (input > clk->pll_max_in)
446 continue;
447
448 mul1 = out_freq / input;
449 if (mul1 > (clk->pll_mul_mask + 1))
450 continue;
451 if (mul1 == 0)
452 break;
453
454 diff1 = out_freq - input * mul1;
455 if (diff1 < 0)
456 diff1 = -diff1;
457 if (diff > diff1) {
458 diff = diff1;
459 div = i;
460 mul = mul1;
461 if (diff == 0)
462 break;
463 }
464 }
465 if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
466 goto fail;
467
468 if (clk->set_outb != NULL)
469 ret |= clk->set_outb(out_freq);
470
471 return (ret |
472 ((mul - 1) << clk->pll_mul_shift) |
473 (div << clk->pll_div_shift));
474fail:
475 return (0);
476}
477
478#if !defined(AT91C_MAIN_CLOCK)
479static const unsigned int at91_main_clock_tbl[] = {
480 3000000, 3276800, 3686400, 3840000, 4000000,
481 4433619, 4915200, 5000000, 5242880, 6000000,
482 6144000, 6400000, 6553600, 7159090, 7372800,
483 7864320, 8000000, 9830400, 10000000, 11059200,
484 12000000, 12288000, 13560000, 14318180, 14745600,
485 16000000, 17344700, 18432000, 20000000
486};
487#define MAIN_CLOCK_TBL_LEN nitems(at91_main_clock_tbl)
488#endif
489
490static unsigned int
491at91_pmc_sense_main_clock(void)
492{
493#if !defined(AT91C_MAIN_CLOCK)
494 unsigned int ckgr_val;
495 unsigned int diff, matchdiff, freq;
496 int i;
497
498 ckgr_val = (RD4(NULL, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
499
500 /*
501 * Clocks up to 50MHz can be connected to some models. If
502 * the frequency is >= 21MHz, assume that the slow clock can
503 * measure it correctly, and that any error can be adequately
504 * compensated for by roudning to the nearest 500Hz. Users
505 * with fast, or odd-ball clocks will need to set
506 * AT91C_MAIN_CLOCK in the kernel config file.
507 */
508 if (ckgr_val >= 21000000)
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/time.h>
38#include <sys/bus.h>
39#include <sys/resource.h>
40#include <sys/rman.h>
41#include <sys/timetc.h>
42
43#include <machine/bus.h>
44#include <machine/cpu.h>
45#include <machine/cpufunc.h>
46#include <machine/resource.h>
47#include <machine/intr.h>
48#include <arm/at91/at91reg.h>
49#include <arm/at91/at91var.h>
50
51#include <arm/at91/at91_pmcreg.h>
52#include <arm/at91/at91_pmcvar.h>
53
54#ifdef FDT
55#include <dev/fdt/fdt_common.h>
56#include <dev/ofw/ofw_bus.h>
57#include <dev/ofw/ofw_bus_subr.h>
58#endif
59
60static struct at91_pmc_softc {
61 bus_space_tag_t sc_st;
62 bus_space_handle_t sc_sh;
63 struct resource *mem_res; /* Memory resource */
64 device_t dev;
65} *pmc_softc;
66
67static uint32_t pllb_init;
68
69MALLOC_DECLARE(M_PMC);
70MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors");
71
72#define AT91_PMC_BASE 0xffffc00
73
74static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
75static void at91_pmc_set_upll_mode(struct at91_pmc_clock *, int);
76static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
77static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
78static void at91_pmc_clock_alias(const char *name, const char *alias);
79
80static struct at91_pmc_clock slck = {
81 .name = "slck", /* 32,768 Hz slow clock */
82 .hz = 32768,
83 .refcnt = 1,
84 .id = 0,
85 .primary = 1,
86};
87
88/*
89 * NOTE: Clocks for "ordinary peripheral" devices e.g. spi0, udp0, uhp0 etc.
90 * are now created automatically. Only "system" clocks need be defined here.
91 */
92static struct at91_pmc_clock main_ck = {
93 .name = "main", /* Main clock */
94 .refcnt = 0,
95 .id = 1,
96 .primary = 1,
97 .pmc_mask = PMC_IER_MOSCS,
98};
99
100static struct at91_pmc_clock plla = {
101 .name = "plla", /* PLLA Clock, used for CPU clocking */
102 .parent = &main_ck,
103 .refcnt = 1,
104 .id = 0,
105 .primary = 1,
106 .pll = 1,
107 .pmc_mask = PMC_IER_LOCKA,
108};
109
110static struct at91_pmc_clock pllb = {
111 .name = "pllb", /* PLLB Clock, used for USB functions */
112 .parent = &main_ck,
113 .refcnt = 0,
114 .id = 0,
115 .primary = 1,
116 .pll = 1,
117 .pmc_mask = PMC_IER_LOCKB,
118 .set_mode = &at91_pmc_set_pllb_mode,
119};
120
121/* Used by USB on at91sam9g45 */
122static struct at91_pmc_clock upll = {
123 .name = "upll", /* UTMI PLL, used for USB functions on 9G45 family */
124 .parent = &main_ck,
125 .refcnt = 0,
126 .id = 0,
127 .primary = 1,
128 .pll = 1,
129 .pmc_mask = (1 << 6),
130 .set_mode = &at91_pmc_set_upll_mode,
131};
132
133static struct at91_pmc_clock udpck = {
134 .name = "udpck",
135 .parent = &pllb,
136 .pmc_mask = PMC_SCER_UDP,
137 .set_mode = at91_pmc_set_sys_mode
138};
139
140static struct at91_pmc_clock uhpck = {
141 .name = "uhpck",
142 .parent = &pllb,
143 .pmc_mask = PMC_SCER_UHP,
144 .set_mode = at91_pmc_set_sys_mode
145};
146
147static struct at91_pmc_clock mck = {
148 .name = "mck", /* Master (Peripheral) Clock */
149 .pmc_mask = PMC_IER_MCKRDY,
150 .refcnt = 0,
151};
152
153static struct at91_pmc_clock cpu = {
154 .name = "cpu", /* CPU Clock */
155 .parent = &plla,
156 .pmc_mask = PMC_SCER_PCK,
157 .refcnt = 0,
158};
159
160/* "+32" or the automatic peripheral clocks */
161static struct at91_pmc_clock *clock_list[16+32] = {
162 &slck,
163 &main_ck,
164 &plla,
165 &pllb,
166 &upll,
167 &udpck,
168 &uhpck,
169 &mck,
170 &cpu
171};
172
173static inline uint32_t
174RD4(struct at91_pmc_softc *sc, bus_size_t off)
175{
176
177 if (sc == NULL) {
178 uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
179
180 return *p;
181 }
182 return (bus_read_4(sc->mem_res, off));
183}
184
185static inline void
186WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
187{
188
189 if (sc == NULL) {
190 uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
191
192 *p = val;
193 } else
194 bus_write_4(sc->mem_res, off, val);
195}
196
197/*
198 * The following is unused currently since we don't ever set the PLLA
199 * frequency of the device. If we did, we'd have to also pay attention
200 * to the ICPLLA bit in the PMC_PLLICPR register for frequencies lower
201 * than ~600MHz, which the PMC code doesn't do right now.
202 */
203uint32_t
204at91_pmc_800mhz_plla_outb(int freq)
205{
206 uint32_t outa;
207
208 /*
209 * Set OUTA, per the data sheet. See Table 46-16 titled
210 * PLLA Frequency Regarding ICPLLA and OUTA in the SAM9X25 doc,
211 * Table 46-17 in the SAM9G20 doc, or Table 46-16 in the SAM9G45 doc.
212 * Note: the frequencies overlap by 5MHz, so we add 3 here to
213 * center shoot the transition.
214 */
215
216 freq /= 1000000; /* MHz */
217 if (freq >= 800)
218 freq = 800;
219 freq += 3; /* Allow for overlap. */
220 outa = 3 - ((freq / 50) & 3); /* 750 / 50 = 7, see table */
221 return (1 << 29)| (outa << 14);
222}
223
224uint32_t
225at91_pmc_800mhz_pllb_outb(int freq)
226{
227
228 return (0);
229}
230
231void
232at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
233{
234 struct at91_pmc_softc *sc = pmc_softc;
235 uint32_t value;
236
237 value = on ? pllb_init : 0;
238
239 /*
240 * Only write to the register if the value is changing. Besides being
241 * good common sense, this works around RM9200 Errata #26 (CKGR_PLL[AB]R
242 * must not be written with the same value currently in the register).
243 */
244 if (RD4(sc, CKGR_PLLBR) != value) {
245 WR4(sc, CKGR_PLLBR, value);
246 while (on && (RD4(sc, PMC_SR) & PMC_IER_LOCKB) != PMC_IER_LOCKB)
247 continue;
248 }
249}
250
251static void
252at91_pmc_set_upll_mode(struct at91_pmc_clock *clk, int on)
253{
254 struct at91_pmc_softc *sc = pmc_softc;
255 uint32_t value;
256
257 if (on) {
258 on = PMC_IER_LOCKU;
259 value = CKGR_UCKR_UPLLEN | CKGR_UCKR_BIASEN;
260 } else
261 value = 0;
262
263 WR4(sc, CKGR_UCKR, RD4(sc, CKGR_UCKR) | value);
264 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKU) != on)
265 continue;
266
267 WR4(sc, PMC_USB, PMC_USB_USBDIV(9) | PMC_USB_USBS);
268 WR4(sc, PMC_SCER, PMC_SCER_UHP_SAM9);
269}
270
271static void
272at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
273{
274 struct at91_pmc_softc *sc = pmc_softc;
275
276 WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
277 if (on)
278 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
279 continue;
280 else
281 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
282 continue;
283}
284
285static void
286at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
287{
288 struct at91_pmc_softc *sc = pmc_softc;
289
290 WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
291 if (on)
292 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
293 continue;
294 else
295 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
296 continue;
297}
298
299struct at91_pmc_clock *
300at91_pmc_clock_add(const char *name, uint32_t irq,
301 struct at91_pmc_clock *parent)
302{
303 struct at91_pmc_clock *clk;
304 int i, buflen;
305
306 clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO);
307 if (clk == NULL)
308 goto err;
309
310 buflen = strlen(name) + 1;
311 clk->name = malloc(buflen, M_PMC, M_NOWAIT);
312 if (clk->name == NULL)
313 goto err;
314
315 strlcpy(clk->name, name, buflen);
316 clk->pmc_mask = 1 << irq;
317 clk->set_mode = &at91_pmc_set_periph_mode;
318 if (parent == NULL)
319 clk->parent = &mck;
320 else
321 clk->parent = parent;
322
323 for (i = 0; i < nitems(clock_list); i++) {
324 if (clock_list[i] == NULL) {
325 clock_list[i] = clk;
326 return (clk);
327 }
328 }
329err:
330 if (clk != NULL) {
331 if (clk->name != NULL)
332 free(clk->name, M_PMC);
333 free(clk, M_PMC);
334 }
335
336 panic("could not allocate pmc clock '%s'", name);
337 return (NULL);
338}
339
340static void
341at91_pmc_clock_alias(const char *name, const char *alias)
342{
343 struct at91_pmc_clock *clk, *alias_clk;
344
345 clk = at91_pmc_clock_ref(name);
346 if (clk)
347 alias_clk = at91_pmc_clock_add(alias, 0, clk->parent);
348
349 if (clk && alias_clk) {
350 alias_clk->hz = clk->hz;
351 alias_clk->pmc_mask = clk->pmc_mask;
352 alias_clk->set_mode = clk->set_mode;
353 }
354}
355
356struct at91_pmc_clock *
357at91_pmc_clock_ref(const char *name)
358{
359 int i;
360
361 for (i = 0; i < nitems(clock_list); i++) {
362 if (clock_list[i] == NULL)
363 break;
364 if (strcmp(name, clock_list[i]->name) == 0)
365 return (clock_list[i]);
366 }
367
368 return (NULL);
369}
370
371void
372at91_pmc_clock_deref(struct at91_pmc_clock *clk)
373{
374 if (clk == NULL)
375 return;
376}
377
378void
379at91_pmc_clock_enable(struct at91_pmc_clock *clk)
380{
381 if (clk == NULL)
382 return;
383
384 /* XXX LOCKING? XXX */
385 if (clk->parent)
386 at91_pmc_clock_enable(clk->parent);
387 if (clk->refcnt++ == 0 && clk->set_mode)
388 clk->set_mode(clk, 1);
389}
390
391void
392at91_pmc_clock_disable(struct at91_pmc_clock *clk)
393{
394 if (clk == NULL)
395 return;
396
397 /* XXX LOCKING? XXX */
398 if (--clk->refcnt == 0 && clk->set_mode)
399 clk->set_mode(clk, 0);
400 if (clk->parent)
401 at91_pmc_clock_disable(clk->parent);
402}
403
404static int
405at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
406{
407 uint32_t mul, div, freq;
408
409 freq = clk->parent->hz;
410 div = (reg >> clk->pll_div_shift) & clk->pll_div_mask;
411 mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask;
412
413#if 0
414 printf("pll = (%d / %d) * %d = %d\n",
415 freq, div, mul + 1, (freq/div) * (mul+1));
416#endif
417
418 if (div != 0 && mul != 0) {
419 freq /= div;
420 freq *= mul + 1;
421 } else
422 freq = 0;
423 clk->hz = freq;
424
425 return (freq);
426}
427
428static uint32_t
429at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
430{
431 uint32_t i, div = 0, mul = 0, diff = 1 << 30;
432
433 unsigned ret = 0x3e00;
434
435 if (out_freq > clk->pll_max_out)
436 goto fail;
437
438 for (i = 1; i < 256; i++) {
439 int32_t diff1;
440 uint32_t input, mul1;
441
442 input = clk->parent->hz / i;
443 if (input < clk->pll_min_in)
444 break;
445 if (input > clk->pll_max_in)
446 continue;
447
448 mul1 = out_freq / input;
449 if (mul1 > (clk->pll_mul_mask + 1))
450 continue;
451 if (mul1 == 0)
452 break;
453
454 diff1 = out_freq - input * mul1;
455 if (diff1 < 0)
456 diff1 = -diff1;
457 if (diff > diff1) {
458 diff = diff1;
459 div = i;
460 mul = mul1;
461 if (diff == 0)
462 break;
463 }
464 }
465 if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
466 goto fail;
467
468 if (clk->set_outb != NULL)
469 ret |= clk->set_outb(out_freq);
470
471 return (ret |
472 ((mul - 1) << clk->pll_mul_shift) |
473 (div << clk->pll_div_shift));
474fail:
475 return (0);
476}
477
478#if !defined(AT91C_MAIN_CLOCK)
479static const unsigned int at91_main_clock_tbl[] = {
480 3000000, 3276800, 3686400, 3840000, 4000000,
481 4433619, 4915200, 5000000, 5242880, 6000000,
482 6144000, 6400000, 6553600, 7159090, 7372800,
483 7864320, 8000000, 9830400, 10000000, 11059200,
484 12000000, 12288000, 13560000, 14318180, 14745600,
485 16000000, 17344700, 18432000, 20000000
486};
487#define MAIN_CLOCK_TBL_LEN nitems(at91_main_clock_tbl)
488#endif
489
490static unsigned int
491at91_pmc_sense_main_clock(void)
492{
493#if !defined(AT91C_MAIN_CLOCK)
494 unsigned int ckgr_val;
495 unsigned int diff, matchdiff, freq;
496 int i;
497
498 ckgr_val = (RD4(NULL, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
499
500 /*
501 * Clocks up to 50MHz can be connected to some models. If
502 * the frequency is >= 21MHz, assume that the slow clock can
503 * measure it correctly, and that any error can be adequately
504 * compensated for by roudning to the nearest 500Hz. Users
505 * with fast, or odd-ball clocks will need to set
506 * AT91C_MAIN_CLOCK in the kernel config file.
507 */
508 if (ckgr_val >= 21000000)
509 return ((ckgr_val + 250) / 500 * 500);
509 return (rounddown(ckgr_val + 250, 500));
510
511 /*
512 * Try to find the standard frequency that match best.
513 */
514 freq = at91_main_clock_tbl[0];
515 matchdiff = abs(ckgr_val - at91_main_clock_tbl[0]);
516 for (i = 1; i < MAIN_CLOCK_TBL_LEN; i++) {
517 diff = abs(ckgr_val - at91_main_clock_tbl[i]);
518 if (diff < matchdiff) {
519 freq = at91_main_clock_tbl[i];
520 matchdiff = diff;
521 }
522 }
523 return (freq);
524#else
525 return (AT91C_MAIN_CLOCK);
526#endif
527}
528
529void
530at91_pmc_init_clock(void)
531{
532 struct at91_pmc_softc *sc = NULL;
533 unsigned int main_clock;
534 uint32_t mckr;
535 uint32_t mdiv;
536
537 soc_info.soc_data->soc_clock_init();
538
539 main_clock = at91_pmc_sense_main_clock();
540
541 if (at91_is_sam9() || at91_is_sam9xe()) {
542 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
543 udpck.pmc_mask = PMC_SCER_UDP_SAM9;
544 }
545
546 /* There is no pllb on AT91SAM9G45 */
547 if (at91_cpu_is(AT91_T_SAM9G45)) {
548 uhpck.parent = &upll;
549 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
550 }
551
552 mckr = RD4(sc, PMC_MCKR);
553 main_ck.hz = main_clock;
554
555 /*
556 * Note: this means outa calc code for plla never used since
557 * we never change it. If we did, we'd also have to mind
558 * ICPLLA to get the charge pump current right.
559 */
560 at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
561
562 if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
563 plla.hz /= 2;
564
565 /*
566 * Initialize the usb clock. This sets up pllb, but disables the
567 * actual clock. XXX except for the if 0 :(
568 */
569 if (!at91_cpu_is(AT91_T_SAM9G45)) {
570 pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
571 at91_pmc_pll_rate(&pllb, pllb_init);
572#if 0
573 /* Turn off USB clocks */
574 at91_pmc_set_periph_mode(&ohci_clk, 0);
575 at91_pmc_set_periph_mode(&udc_clk, 0);
576#endif
577 }
578
579 if (at91_is_rm92()) {
580 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
581 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
582 } else
583 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
584
585 /*
586 * MCK and PCU derive from one of the primary clocks. Initialize
587 * this relationship.
588 */
589 mck.parent = clock_list[mckr & 0x3];
590 mck.parent->refcnt++;
591
592 cpu.hz = mck.hz = mck.parent->hz /
593 (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
594
595 mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
596 if (at91_is_sam9() || at91_is_sam9xe()) {
597 /*
598 * On AT91SAM9G45 when mdiv == 3 we need to divide
599 * MCK by 3 but not, for example, on 9g20.
600 */
601 if (!at91_cpu_is(AT91_T_SAM9G45) || mdiv <= 2)
602 mdiv *= 2;
603 if (mdiv > 0)
604 mck.hz /= mdiv;
605 } else
606 mck.hz /= (1 + mdiv);
607
608 /* Only found on SAM9G20 */
609 if (at91_cpu_is(AT91_T_SAM9G20))
610 cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1;
611
612 at91_master_clock = mck.hz;
613
614 /* These clocks refrenced by "special" names */
615 at91_pmc_clock_alias("ohci0", "ohci_clk");
616 at91_pmc_clock_alias("udp0", "udp_clk");
617
618 /* Turn off "Progamable" clocks */
619 WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
620 PMC_SCER_PCK3);
621
622 /* XXX kludge, turn on all peripherals */
623 WR4(sc, PMC_PCER, 0xffffffff);
624
625 /* Disable all interrupts for PMC */
626 WR4(sc, PMC_IDR, 0xffffffff);
627}
628
629static void
630at91_pmc_deactivate(device_t dev)
631{
632 struct at91_pmc_softc *sc;
633
634 sc = device_get_softc(dev);
635 bus_generic_detach(sc->dev);
636 if (sc->mem_res)
637 bus_release_resource(dev, SYS_RES_IOPORT,
638 rman_get_rid(sc->mem_res), sc->mem_res);
639 sc->mem_res = NULL;
640}
641
642static int
643at91_pmc_activate(device_t dev)
644{
645 struct at91_pmc_softc *sc;
646 int rid;
647
648 sc = device_get_softc(dev);
649 rid = 0;
650 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
651 RF_ACTIVE);
652 if (sc->mem_res == NULL)
653 goto errout;
654 return (0);
655errout:
656 at91_pmc_deactivate(dev);
657 return (ENOMEM);
658}
659
660static int
661at91_pmc_probe(device_t dev)
662{
663#ifdef FDT
664 if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-pmc") &&
665 !ofw_bus_is_compatible(dev, "atmel,at91sam9260-pmc") &&
666 !ofw_bus_is_compatible(dev, "atmel,at91sam9g45-pmc") &&
667 !ofw_bus_is_compatible(dev, "atmel,at91sam9x5-pmc"))
668 return (ENXIO);
669#endif
670 device_set_desc(dev, "PMC");
671 return (0);
672}
673
674static int
675at91_pmc_attach(device_t dev)
676{
677 int err;
678
679 pmc_softc = device_get_softc(dev);
680 pmc_softc->dev = dev;
681 if ((err = at91_pmc_activate(dev)) != 0)
682 return (err);
683
684 /*
685 * Configure main clock frequency.
686 */
687 at91_pmc_init_clock();
688
689 /*
690 * Display info about clocks previously computed
691 */
692 device_printf(dev,
693 "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
694 main_ck.hz,
695 plla.hz / 1000000,
696 cpu.hz / 1000000, mck.hz / 1000000);
697
698 return (0);
699}
700
701static device_method_t at91_pmc_methods[] = {
702 DEVMETHOD(device_probe, at91_pmc_probe),
703 DEVMETHOD(device_attach, at91_pmc_attach),
704 DEVMETHOD_END
705};
706
707static driver_t at91_pmc_driver = {
708 "at91_pmc",
709 at91_pmc_methods,
710 sizeof(struct at91_pmc_softc),
711};
712static devclass_t at91_pmc_devclass;
713
714#ifdef FDT
715EARLY_DRIVER_MODULE(at91_pmc, simplebus, at91_pmc_driver, at91_pmc_devclass,
716 NULL, NULL, BUS_PASS_CPU);
717#else
718EARLY_DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass,
719 NULL, NULL, BUS_PASS_CPU);
720#endif
510
511 /*
512 * Try to find the standard frequency that match best.
513 */
514 freq = at91_main_clock_tbl[0];
515 matchdiff = abs(ckgr_val - at91_main_clock_tbl[0]);
516 for (i = 1; i < MAIN_CLOCK_TBL_LEN; i++) {
517 diff = abs(ckgr_val - at91_main_clock_tbl[i]);
518 if (diff < matchdiff) {
519 freq = at91_main_clock_tbl[i];
520 matchdiff = diff;
521 }
522 }
523 return (freq);
524#else
525 return (AT91C_MAIN_CLOCK);
526#endif
527}
528
529void
530at91_pmc_init_clock(void)
531{
532 struct at91_pmc_softc *sc = NULL;
533 unsigned int main_clock;
534 uint32_t mckr;
535 uint32_t mdiv;
536
537 soc_info.soc_data->soc_clock_init();
538
539 main_clock = at91_pmc_sense_main_clock();
540
541 if (at91_is_sam9() || at91_is_sam9xe()) {
542 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
543 udpck.pmc_mask = PMC_SCER_UDP_SAM9;
544 }
545
546 /* There is no pllb on AT91SAM9G45 */
547 if (at91_cpu_is(AT91_T_SAM9G45)) {
548 uhpck.parent = &upll;
549 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
550 }
551
552 mckr = RD4(sc, PMC_MCKR);
553 main_ck.hz = main_clock;
554
555 /*
556 * Note: this means outa calc code for plla never used since
557 * we never change it. If we did, we'd also have to mind
558 * ICPLLA to get the charge pump current right.
559 */
560 at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
561
562 if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
563 plla.hz /= 2;
564
565 /*
566 * Initialize the usb clock. This sets up pllb, but disables the
567 * actual clock. XXX except for the if 0 :(
568 */
569 if (!at91_cpu_is(AT91_T_SAM9G45)) {
570 pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
571 at91_pmc_pll_rate(&pllb, pllb_init);
572#if 0
573 /* Turn off USB clocks */
574 at91_pmc_set_periph_mode(&ohci_clk, 0);
575 at91_pmc_set_periph_mode(&udc_clk, 0);
576#endif
577 }
578
579 if (at91_is_rm92()) {
580 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
581 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
582 } else
583 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
584
585 /*
586 * MCK and PCU derive from one of the primary clocks. Initialize
587 * this relationship.
588 */
589 mck.parent = clock_list[mckr & 0x3];
590 mck.parent->refcnt++;
591
592 cpu.hz = mck.hz = mck.parent->hz /
593 (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
594
595 mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
596 if (at91_is_sam9() || at91_is_sam9xe()) {
597 /*
598 * On AT91SAM9G45 when mdiv == 3 we need to divide
599 * MCK by 3 but not, for example, on 9g20.
600 */
601 if (!at91_cpu_is(AT91_T_SAM9G45) || mdiv <= 2)
602 mdiv *= 2;
603 if (mdiv > 0)
604 mck.hz /= mdiv;
605 } else
606 mck.hz /= (1 + mdiv);
607
608 /* Only found on SAM9G20 */
609 if (at91_cpu_is(AT91_T_SAM9G20))
610 cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1;
611
612 at91_master_clock = mck.hz;
613
614 /* These clocks refrenced by "special" names */
615 at91_pmc_clock_alias("ohci0", "ohci_clk");
616 at91_pmc_clock_alias("udp0", "udp_clk");
617
618 /* Turn off "Progamable" clocks */
619 WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
620 PMC_SCER_PCK3);
621
622 /* XXX kludge, turn on all peripherals */
623 WR4(sc, PMC_PCER, 0xffffffff);
624
625 /* Disable all interrupts for PMC */
626 WR4(sc, PMC_IDR, 0xffffffff);
627}
628
629static void
630at91_pmc_deactivate(device_t dev)
631{
632 struct at91_pmc_softc *sc;
633
634 sc = device_get_softc(dev);
635 bus_generic_detach(sc->dev);
636 if (sc->mem_res)
637 bus_release_resource(dev, SYS_RES_IOPORT,
638 rman_get_rid(sc->mem_res), sc->mem_res);
639 sc->mem_res = NULL;
640}
641
642static int
643at91_pmc_activate(device_t dev)
644{
645 struct at91_pmc_softc *sc;
646 int rid;
647
648 sc = device_get_softc(dev);
649 rid = 0;
650 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
651 RF_ACTIVE);
652 if (sc->mem_res == NULL)
653 goto errout;
654 return (0);
655errout:
656 at91_pmc_deactivate(dev);
657 return (ENOMEM);
658}
659
660static int
661at91_pmc_probe(device_t dev)
662{
663#ifdef FDT
664 if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-pmc") &&
665 !ofw_bus_is_compatible(dev, "atmel,at91sam9260-pmc") &&
666 !ofw_bus_is_compatible(dev, "atmel,at91sam9g45-pmc") &&
667 !ofw_bus_is_compatible(dev, "atmel,at91sam9x5-pmc"))
668 return (ENXIO);
669#endif
670 device_set_desc(dev, "PMC");
671 return (0);
672}
673
674static int
675at91_pmc_attach(device_t dev)
676{
677 int err;
678
679 pmc_softc = device_get_softc(dev);
680 pmc_softc->dev = dev;
681 if ((err = at91_pmc_activate(dev)) != 0)
682 return (err);
683
684 /*
685 * Configure main clock frequency.
686 */
687 at91_pmc_init_clock();
688
689 /*
690 * Display info about clocks previously computed
691 */
692 device_printf(dev,
693 "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
694 main_ck.hz,
695 plla.hz / 1000000,
696 cpu.hz / 1000000, mck.hz / 1000000);
697
698 return (0);
699}
700
701static device_method_t at91_pmc_methods[] = {
702 DEVMETHOD(device_probe, at91_pmc_probe),
703 DEVMETHOD(device_attach, at91_pmc_attach),
704 DEVMETHOD_END
705};
706
707static driver_t at91_pmc_driver = {
708 "at91_pmc",
709 at91_pmc_methods,
710 sizeof(struct at91_pmc_softc),
711};
712static devclass_t at91_pmc_devclass;
713
714#ifdef FDT
715EARLY_DRIVER_MODULE(at91_pmc, simplebus, at91_pmc_driver, at91_pmc_devclass,
716 NULL, NULL, BUS_PASS_CPU);
717#else
718EARLY_DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass,
719 NULL, NULL, BUS_PASS_CPU);
720#endif