Deleted Added
full compact
at91_pmc.c (210040) at91_pmc.c (213496)
1/*-
2 * Copyright (c) 2006 M. Warner Losh. All rights reserved.
1/*-
2 * Copyright (c) 2006 M. Warner Losh. All rights reserved.
3 * Copyright (c) 2010 Greg Ansley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the

--- 7 unchanged lines hidden (view full) ---

18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
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

--- 7 unchanged lines hidden (view full) ---

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
26#include "opt_at91.h"
27
28#include <sys/cdefs.h>
27#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pmc.c 210040 2010-07-14 00:48:53Z cognet $");
28__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pmc.c 213496 2010-10-06 22:25:21Z cognet $");
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
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>
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/at91rm92reg.h>
48#include <arm/at91/at91sam9g20reg.h>
47#include
48#include <arm/at91/at91var.h>
49
50#include <arm/at91/at91_pmcreg.h>
51#include <arm/at91/at91_pmcvar.h>
52
53static 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
49
50#include <arm/at91/at91_pmcreg.h>
51#include <arm/at91/at91_pmcvar.h>
52
53static 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
62MALLOC_DECLARE(M_PMC);
63MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors");
64
62static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
63static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
64static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
65static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
66static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
67static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
68static void at91_pmc_clock_alias(const char *name, const char *alias);
65
66static struct at91_pmc_clock slck = {
67 .name = "slck", // 32,768 Hz slow clock
68 .hz = 32768,
69 .refcnt = 1,
70 .id = 0,
71 .primary = 1,
72};
73
69
70static 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 */
74static struct at91_pmc_clock main_ck = {
75 .name = "main", // Main clock
76 .refcnt = 0,
77 .id = 1,
78 .primary = 1,
79 .pmc_mask = PMC_IER_MOSCS,
80};
81

--- 28 unchanged lines hidden (view full) ---

110static struct at91_pmc_clock uhpck = {
111 .name = "uhpck",
112 .parent = &pllb,
113 .pmc_mask = PMC_SCER_UHP,
114 .set_mode = at91_pmc_set_sys_mode
115};
116
117static struct at91_pmc_clock mck = {
82static 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

--- 28 unchanged lines hidden (view full) ---

118static 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
125static struct at91_pmc_clock mck = {
118 .name = "mck",
126 .name = "mck", // Master (Peripheral) Clock
119 .pmc_mask = PMC_IER_MCKRDY,
120 .refcnt = 0,
121};
122
127 .pmc_mask = PMC_IER_MCKRDY,
128 .refcnt = 0,
129};
130
123#ifdef AT91SAM9G20
124#define IRQ_UDP AT91SAM9G20_IRQ_UDP
125#define IRQ_UHP AT91SAM9G20_IRQ_UHP
126#else
127#define IRQ_UDP AT91RM92_IRQ_UDP
128#define IRQ_UHP AT91RM92_IRQ_UHP
129#endif /* AT91SAM9G20 */
130
131static struct at91_pmc_clock udc_clk = {
132 .name = "udc_clk",
133 .parent = &mck,
134 .pmc_mask = 1 << IRQ_UDP,
135 .set_mode = &at91_pmc_set_periph_mode
131static struct at91_pmc_clock cpu = {
132 .name = "cpu", // CPU Clock
133 .parent = &plla,
134 .pmc_mask = PMC_SCER_PCK,
135 .refcnt = 0,
136};
137
136};
137
138static struct at91_pmc_clock ohci_clk = {
139 .name = "ohci_clk",
140 .parent = &mck,
141 .pmc_mask = 1 << IRQ_UHP,
142 .set_mode = &at91_pmc_set_periph_mode
143};
144
145#ifdef AT91SAM9G20
146static struct at91_pmc_clock macb_clk = {
147 .name = "macb_clk",
148 .parent = &mck,
149
150 .pmc_mask = 1 << 21,
151 .set_mode = &at91_pmc_set_periph_mode
152};
153
154static struct at91_pmc_clock spi0_clk = {
155 .name = "spi0_clk",
156 .parent = &mck,
157
158 .pmc_mask = 1 << 12,
159 .set_mode = &at91_pmc_set_periph_mode
160};
161
162static struct at91_pmc_clock spi1_clk = {
163 .name = "spi1_clk",
164 .parent = &mck,
165 .pmc_mask = 1 << 13,
166 .set_mode = &at91_pmc_set_periph_mode
167};
168
169#endif /* AT91SAM9G20 */
170
171static struct at91_pmc_clock *const clock_list[] = {
138/* "+32" or the automatic peripheral clocks */
139static struct at91_pmc_clock *clock_list[16+32] = {
172 &slck,
173 &main_ck,
174 &plla,
175 &pllb,
176 &udpck,
177 &uhpck,
178 &mck,
140 &slck,
141 &main_ck,
142 &plla,
143 &pllb,
144 &udpck,
145 &uhpck,
146 &mck,
179 &udc_clk,
180#ifdef AT91SAM9G20
181 &macb_clk,
182 &spi0_clk,
183 &spi1_clk,
184#endif /* AT91SAM9G20 */
185 &ohci_clk
147 &cpu
186};
187
188#if !defined(AT91C_MAIN_CLOCK)
189static const unsigned int at91_mainf_tbl[] = {
190 3000000, 3276800, 3686400, 3840000, 4000000,
191 4433619, 4915200, 5000000, 5242880, 6000000,
192 6144000, 6400000, 6553600, 7159090, 7372800,
193 7864320, 8000000, 9830400, 10000000, 11059200,
194 12000000, 12288000, 13560000, 14318180, 14745600,
195 16000000, 17344700, 18432000, 20000000
196};
197#define MAINF_TBL_LEN (sizeof(at91_mainf_tbl) / sizeof(*at91_mainf_tbl))
198#endif
199
200static inline uint32_t
201RD4(struct at91_pmc_softc *sc, bus_size_t off)
202{
148};
149
150#if !defined(AT91C_MAIN_CLOCK)
151static 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
162static inline uint32_t
163RD4(struct at91_pmc_softc *sc, bus_size_t off)
164{
203 return bus_read_4(sc->mem_res, off);
165 return (bus_read_4(sc->mem_res, off));
204}
205
206static inline void
207WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
208{
209 bus_write_4(sc->mem_res, off, val);
210}
211
166}
167
168static inline void
169WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
170{
171 bus_write_4(sc->mem_res, off, val);
172}
173
212static void
174void
213at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
214{
215 struct at91_pmc_softc *sc = pmc_softc;
216 uint32_t value;
217
218 if (on) {
219 on = PMC_IER_LOCKB;
220 value = sc->pllb_init;
221 } else {
222 value = 0;
223 }
175at91_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
224 WR4(sc, CKGR_PLLBR, value);
225 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
226 continue;
227}
228
229static void
230at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
231{

--- 18 unchanged lines hidden (view full) ---

250 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
251 continue;
252 else
253 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
254 continue;
255}
256
257struct at91_pmc_clock *
195 WR4(sc, CKGR_PLLBR, value);
196 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
197 continue;
198}
199
200static void
201at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
202{

--- 18 unchanged lines hidden (view full) ---

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
228struct at91_pmc_clock *
229at91_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 }
257err:
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
268static void
269at91_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
284struct at91_pmc_clock *
258at91_pmc_clock_ref(const char *name)
259{
260 int i;
261
285at91_pmc_clock_ref(const char *name)
286{
287 int i;
288
262 for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++)
289 for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
290 if (clock_list[i] == NULL)
291 break;
263 if (strcmp(name, clock_list[i]->name) == 0)
264 return (clock_list[i]);
292 if (strcmp(name, clock_list[i]->name) == 0)
293 return (clock_list[i]);
294 }
265
295
296 //printf("at91_pmc: Warning - did not find clock '%s'", name);
266 return (NULL);
267}
268
269void
270at91_pmc_clock_deref(struct at91_pmc_clock *clk)
271{
272}
273

--- 13 unchanged lines hidden (view full) ---

287 /* XXX LOCKING? XXX */
288 if (--clk->refcnt == 0 && clk->set_mode)
289 clk->set_mode(clk, 0);
290 if (clk->parent)
291 at91_pmc_clock_disable(clk->parent);
292}
293
294static int
297 return (NULL);
298}
299
300void
301at91_pmc_clock_deref(struct at91_pmc_clock *clk)
302{
303}
304

--- 13 unchanged lines hidden (view full) ---

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
325static int
295at91_pmc_pll_rate(int freq, uint32_t reg, int is_pllb)
326at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
296{
327{
297 uint32_t mul, div;
328 uint32_t mul, div, freq;;
298
329
299 div = reg & 0xff;
300#ifdef AT91SAM9G20
301 if (is_pllb)
302 mul = (reg >> 16) & 0x3f;
303 else
304 mul = (reg >> 16) & 0xff;
305#else
306 mul = (reg >> 16) & 0x7ff;
307#endif
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
308 if (div != 0 && mul != 0) {
309 freq /= div;
310 freq *= mul + 1;
311 } else {
312 freq = 0;
313 }
334 if (div != 0 && mul != 0) {
335 freq /= div;
336 freq *= mul + 1;
337 } else {
338 freq = 0;
339 }
314#ifndef AT91SAM9G20
315 if (is_pllb && (reg & (1 << 28)))
316 freq >>= 1;
317#endif
340 clk->hz = freq;
318 return (freq);
319}
320
321static uint32_t
341 return (freq);
342}
343
344static uint32_t
322at91_pmc_pll_calc(uint32_t main_freq, uint32_t out_freq)
345at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
323{
324 uint32_t i, div = 0, mul = 0, diff = 1 << 30;
346{
347 uint32_t i, div = 0, mul = 0, diff = 1 << 30;
325 unsigned ret = (out_freq > PMC_PLL_FAST_THRESH) ? 0xbe00 : 0x3e00;
326
348
327 if (out_freq > PMC_PLL_MAX_OUT_FREQ)
349 unsigned ret = 0x3e00;
350
351 if (out_freq > clk->pll_max_out)
328 goto fail;
329
330 for (i = 1; i < 256; i++) {
331 int32_t diff1;
332 uint32_t input, mul1;
333
352 goto fail;
353
354 for (i = 1; i < 256; i++) {
355 int32_t diff1;
356 uint32_t input, mul1;
357
334 input = main_freq / i;
335 if (input < PMC_PLL_MIN_IN_FREQ)
358 input = clk->parent->hz / i;
359 if (input < clk->pll_min_in)
336 break;
360 break;
337 if (input > PMC_PLL_MAX_IN_FREQ)
361 if (input > clk->pll_max_in)
338 continue;
339
340 mul1 = out_freq / input;
362 continue;
363
364 mul1 = out_freq / input;
341 if (mul1 > PMC_PLL_MULT_MAX)
365 if (mul1 > (clk->pll_mul_mask + 1))
342 continue;
366 continue;
343 if (mul1 < PMC_PLL_MULT_MIN)
367 if (mul1 == 0)
344 break;
345
346 diff1 = out_freq - input * mul1;
347 if (diff1 < 0)
348 diff1 = -diff1;
349 if (diff > diff1) {
350 diff = diff1;
351 div = i;
352 mul = mul1;
353 if (diff == 0)
354 break;
355 }
356 }
357 if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
358 goto fail;
368 break;
369
370 diff1 = out_freq - input * mul1;
371 if (diff1 < 0)
372 diff1 = -diff1;
373 if (diff > diff1) {
374 diff = diff1;
375 div = i;
376 mul = mul1;
377 if (diff == 0)
378 break;
379 }
380 }
381 if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
382 goto fail;
359 return ret | ((mul - 1) << 16) | div;
383
384 if (clk->set_outb != NULL)
385 ret |= clk->set_outb(out_freq);
386
387 return (ret |
388 ((mul - 1) << clk->pll_mul_shift) |
389 (div << clk->pll_div_shift));
360fail:
390fail:
361 return 0;
391 return (0);
362}
363
364static void
365at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock)
366{
367 uint32_t mckr;
392}
393
394static void
395at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock)
396{
397 uint32_t mckr;
368 int freq;
398 uint32_t mdiv;
369
399
400 if (at91_is_sam9()) {
401 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
402 udpck.pmc_mask = PMC_SCER_UDP_SAM9;
403 }
404 mckr = RD4(sc, PMC_MCKR);
370 sc->main_clock_hz = main_clock;
371 main_ck.hz = main_clock;
405 sc->main_clock_hz = main_clock;
406 main_ck.hz = main_clock;
372 plla.hz = at91_pmc_pll_rate(main_clock, RD4(sc, CKGR_PLLAR), 0);
373
407
408 at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
409
410 if (at91_cpu_is(AT91_CPU_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
411 plla.hz /= 2;
412
374 /*
375 * Initialize the usb clock. This sets up pllb, but disables the
376 * actual clock.
377 */
413 /*
414 * Initialize the usb clock. This sets up pllb, but disables the
415 * actual clock.
416 */
378 sc->pllb_init = at91_pmc_pll_calc(main_clock, 48000000 * 2) |0x10000000;
379 pllb.hz = at91_pmc_pll_rate(main_clock, sc->pllb_init, 1);
380 WR4(sc, PMC_PCDR, (1 << IRQ_UHP) | (1 << IRQ_UDP));
381 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
382 WR4(sc, CKGR_PLLBR, 0);
383#ifndef AT91SAM9G20
384 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
417 sc->pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
418 at91_pmc_pll_rate(&pllb, sc->pllb_init);
419
420#if 0
421 /* Turn off USB clocks */
422 at91_pmc_set_periph_mode(&ohci_clk, 0);
423 at91_pmc_set_periph_mode(&udc_clk, 0);
385#endif
386
424#endif
425
426 if (at91_is_rm92()) {
427 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
428 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
429 } else {
430 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
431 }
432 WR4(sc, CKGR_PLLBR, 0);
433
387 /*
388 * MCK and PCU derive from one of the primary clocks. Initialize
389 * this relationship.
390 */
434 /*
435 * MCK and PCU derive from one of the primary clocks. Initialize
436 * this relationship.
437 */
391 mckr = RD4(sc, PMC_MCKR);
392 mck.parent = clock_list[mckr & 0x3];
393 mck.parent->refcnt++;
438 mck.parent = clock_list[mckr & 0x3];
439 mck.parent->refcnt++;
394 freq = mck.parent->hz / (1 << ((mckr >> 2) & 3));
395 mck.hz = freq / (1 + ((mckr >> 8) & 3));
396
440
441 cpu.hz =
442 mck.hz = mck.parent->hz /
443 (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
444
445 mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
446 if (at91_is_sam9()) {
447 mck.hz /= (mdiv) ? (mdiv * 2) : 1;
448 } else
449 mck.hz /= (1 + mdiv);
450
451 /* Only found on SAM9G20 */
452 if (at91_cpu_is(AT91_CPU_SAM9G20))
453 cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1;
454
455 at91_master_clock = mck.hz;
456
397 device_printf(sc->dev,
398 "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
399 sc->main_clock_hz,
457 device_printf(sc->dev,
458 "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
459 sc->main_clock_hz,
400 at91_pmc_pll_rate(main_clock, RD4(sc, CKGR_PLLAR), 0) / 1000000,
401 freq / 1000000, mck.hz / 1000000);
460 plla.hz / 1000000,
461 cpu.hz / 1000000, mck.hz / 1000000);
462
463 /* Turn off "Progamable" clocks */
402 WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
403 PMC_SCER_PCK3);
464 WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
465 PMC_SCER_PCK3);
466
404 /* XXX kludge, turn on all peripherals */
405 WR4(sc, PMC_PCER, 0xffffffff);
467 /* XXX kludge, turn on all peripherals */
468 WR4(sc, PMC_PCER, 0xffffffff);
469
406 /* Disable all interrupts for PMC */
407 WR4(sc, PMC_IDR, 0xffffffff);
408}
409
410static void
411at91_pmc_deactivate(device_t dev)
412{
413 struct at91_pmc_softc *sc;

--- 63 unchanged lines hidden (view full) ---

477at91_pmc_attach(device_t dev)
478{
479 unsigned int mainf;
480 int err;
481
482 pmc_softc = device_get_softc(dev);
483 pmc_softc->dev = dev;
484 if ((err = at91_pmc_activate(dev)) != 0)
470 /* Disable all interrupts for PMC */
471 WR4(sc, PMC_IDR, 0xffffffff);
472}
473
474static void
475at91_pmc_deactivate(device_t dev)
476{
477 struct at91_pmc_softc *sc;

--- 63 unchanged lines hidden (view full) ---

541at91_pmc_attach(device_t dev)
542{
543 unsigned int mainf;
544 int err;
545
546 pmc_softc = device_get_softc(dev);
547 pmc_softc->dev = dev;
548 if ((err = at91_pmc_activate(dev)) != 0)
485 return err;
549 return (err);
486
487 /*
488 * Configure main clock frequency.
489 */
490#if !defined(AT91C_MAIN_CLOCK)
491 mainf = at91_pmc_sense_mainf(pmc_softc);
492#else
493 mainf = AT91C_MAIN_CLOCK;
494#endif
495 at91_pmc_init_clock(pmc_softc, mainf);
550
551 /*
552 * Configure main clock frequency.
553 */
554#if !defined(AT91C_MAIN_CLOCK)
555 mainf = at91_pmc_sense_mainf(pmc_softc);
556#else
557 mainf = AT91C_MAIN_CLOCK;
558#endif
559 at91_pmc_init_clock(pmc_softc, mainf);
560
561 /* These clocks refrenced by "special" names */
562 at91_pmc_clock_alias("ohci0", "ohci_clk");
563 at91_pmc_clock_alias("udp0", "udp_clk");
564
496 return (0);
497}
498
499static device_method_t at91_pmc_methods[] = {
500 DEVMETHOD(device_probe, at91_pmc_probe),
501 DEVMETHOD(device_attach, at91_pmc_attach),
502 {0, 0},
503};
504
505static driver_t at91_pmc_driver = {
506 "at91_pmc",
507 at91_pmc_methods,
508 sizeof(struct at91_pmc_softc),
509};
510static devclass_t at91_pmc_devclass;
511
512DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, 0, 0);
565 return (0);
566}
567
568static device_method_t at91_pmc_methods[] = {
569 DEVMETHOD(device_probe, at91_pmc_probe),
570 DEVMETHOD(device_attach, at91_pmc_attach),
571 {0, 0},
572};
573
574static driver_t at91_pmc_driver = {
575 "at91_pmc",
576 at91_pmc_methods,
577 sizeof(struct at91_pmc_softc),
578};
579static devclass_t at91_pmc_devclass;
580
581DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, 0, 0);