1 /*-
2 * Copyright (c) 2006 M. Warner Losh. 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
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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
26 #include "opt_at91.h"
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: releng/8.1/sys/arm/at91/at91_pmc.c 185492 2008-11-30 22:40:11Z stas $");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.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
49 #include <arm/at91/at91_pmcreg.h>
50 #include <arm/at91/at91_pmcvar.h>
51
52 static struct at91_pmc_softc {
53 bus_space_tag_t sc_st;
54 bus_space_handle_t sc_sh;
55 struct resource *mem_res; /* Memory resource */
56 device_t dev;
57 unsigned int main_clock_hz;
58 uint32_t pllb_init;
59 } *pmc_softc;
60
61 static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
62 static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
63 static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
64
65 static struct at91_pmc_clock slck = {
66 .name = "slck", // 32,768 Hz slow clock
67 .hz = 32768,
68 .refcnt = 1,
69 .id = 0,
70 .primary = 1,
71 };
72
73 static struct at91_pmc_clock main_ck = {
74 .name = "main", // Main clock
75 .refcnt = 0,
76 .id = 1,
77 .primary = 1,
78 .pmc_mask = PMC_IER_MOSCS,
79 };
80
81 static struct at91_pmc_clock plla = {
82 .name = "plla", // PLLA Clock, used for CPU clocking
83 .parent = &main_ck,
84 .refcnt = 1,
85 .id = 0,
86 .primary = 1,
87 .pll = 1,
88 .pmc_mask = PMC_IER_LOCKA,
89 };
90
91 static struct at91_pmc_clock pllb = {
92 .name = "pllb", // PLLB Clock, used for USB functions
93 .parent = &main_ck,
94 .refcnt = 0,
95 .id = 0,
96 .primary = 1,
97 .pll = 1,
98 .pmc_mask = PMC_IER_LOCKB,
99 .set_mode = &at91_pmc_set_pllb_mode,
100 };
101
102 static struct at91_pmc_clock udpck = {
103 .name = "udpck",
104 .parent = &pllb,
105 .pmc_mask = PMC_SCER_UDP,
106 .set_mode = at91_pmc_set_sys_mode
107 };
108
109 static struct at91_pmc_clock uhpck = {
110 .name = "uhpck",
111 .parent = &pllb,
112 .pmc_mask = PMC_SCER_UHP,
113 .set_mode = at91_pmc_set_sys_mode
114 };
115
116 static struct at91_pmc_clock mck = {
117 .name = "mck",
118 .pmc_mask = PMC_IER_MCKRDY,
119 .refcnt = 0,
120 };
121
122 static struct at91_pmc_clock udc_clk = {
123 .name = "udc_clk",
124 .parent = &mck,
125 .pmc_mask = 1 << AT91RM92_IRQ_UDP,
126 .set_mode = &at91_pmc_set_periph_mode
127 };
128
129 static struct at91_pmc_clock ohci_clk = {
130 .name = "ohci_clk",
131 .parent = &mck,
132 .pmc_mask = 1 << AT91RM92_IRQ_UHP,
133 .set_mode = &at91_pmc_set_periph_mode
134 };
135
136 static struct at91_pmc_clock *const clock_list[] = {
137 &slck,
138 &main_ck,
139 &plla,
140 &pllb,
141 &udpck,
142 &uhpck,
143 &mck,
144 &udc_clk,
145 &ohci_clk
146 };
147
148 #if !defined(AT91C_MAIN_CLOCK)
149 static const unsigned int at91_mainf_tbl[] = {
150 3000000, 3276800, 3686400, 3840000, 4000000,
151 4433619, 4915200, 5000000, 5242880, 6000000,
152 6144000, 6400000, 6553600, 7159090, 7372800,
153 7864320, 8000000, 9830400, 10000000, 11059200,
154 12000000, 12288000, 13560000, 14318180, 14745600,
155 16000000, 17344700, 18432000, 20000000
156 };
157 #define MAINF_TBL_LEN (sizeof(at91_mainf_tbl) / sizeof(*at91_mainf_tbl))
158 #endif
159
160 static inline uint32_t
161 RD4(struct at91_pmc_softc *sc, bus_size_t off)
162 {
163 return bus_read_4(sc->mem_res, off);
164 }
165
166 static inline void
167 WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
168 {
169 bus_write_4(sc->mem_res, off, val);
170 }
171
172 static void
173 at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
174 {
175 struct at91_pmc_softc *sc = pmc_softc;
176 uint32_t value;
177
178 if (on) {
179 on = PMC_IER_LOCKB;
180 value = sc->pllb_init;
181 } else {
182 value = 0;
183 }
184 WR4(sc, CKGR_PLLBR, value);
185 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
186 continue;
187 }
188
189 static void
190 at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
191 {
192 struct at91_pmc_softc *sc = pmc_softc;
193
194 WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
195 if (on)
196 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
197 continue;
198 else
199 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
200 continue;
201 }
202
203 static void
204 at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
205 {
206 struct at91_pmc_softc *sc = pmc_softc;
207
208 WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
209 if (on)
210 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
211 continue;
212 else
213 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
214 continue;
215 }
216
217 struct at91_pmc_clock *
218 at91_pmc_clock_ref(const char *name)
219 {
220 int i;
221
222 for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++)
223 if (strcmp(name, clock_list[i]->name) == 0)
224 return (clock_list[i]);
225
226 return (NULL);
227 }
228
229 void
230 at91_pmc_clock_deref(struct at91_pmc_clock *clk)
231 {
232 }
233
234 void
235 at91_pmc_clock_enable(struct at91_pmc_clock *clk)
236 {
237 /* XXX LOCKING? XXX */
238 if (clk->parent)
239 at91_pmc_clock_enable(clk->parent);
240 if (clk->refcnt++ == 0 && clk->set_mode)
241 clk->set_mode(clk, 1);
242 }
243
244 void
245 at91_pmc_clock_disable(struct at91_pmc_clock *clk)
246 {
247 /* XXX LOCKING? XXX */
248 if (--clk->refcnt == 0 && clk->set_mode)
249 clk->set_mode(clk, 0);
250 if (clk->parent)
251 at91_pmc_clock_disable(clk->parent);
252 }
253
254 static int
255 at91_pmc_pll_rate(int freq, uint32_t reg, int is_pllb)
256 {
257 uint32_t mul, div;
258
259 div = reg & 0xff;
260 mul = (reg >> 16) & 0x7ff;
261 if (div != 0 && mul != 0) {
262 freq /= div;
263 freq *= mul + 1;
264 } else {
265 freq = 0;
266 }
267 if (is_pllb && (reg & (1 << 28)))
268 freq >>= 1;
269 return (freq);
270 }
271
272 static uint32_t
273 at91_pmc_pll_calc(uint32_t main_freq, uint32_t out_freq)
274 {
275 uint32_t i, div = 0, mul = 0, diff = 1 << 30;
276 unsigned ret = (out_freq > PMC_PLL_FAST_THRESH) ? 0xbe00 : 0x3e00;
277
278 if (out_freq > PMC_PLL_MAX_OUT_FREQ)
279 goto fail;
280
281 for (i = 1; i < 256; i++) {
282 int32_t diff1;
283 uint32_t input, mul1;
284
285 input = main_freq / i;
286 if (input < PMC_PLL_MIN_IN_FREQ)
287 break;
288 if (input > PMC_PLL_MAX_IN_FREQ)
289 continue;
290
291 mul1 = out_freq / input;
292 if (mul1 > PMC_PLL_MULT_MAX)
293 continue;
294 if (mul1 < PMC_PLL_MULT_MIN)
295 break;
296
297 diff1 = out_freq - input * mul1;
298 if (diff1 < 0)
299 diff1 = -diff1;
300 if (diff > diff1) {
301 diff = diff1;
302 div = i;
303 mul = mul1;
304 if (diff == 0)
305 break;
306 }
307 }
308 if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
309 goto fail;
310 return ret | ((mul - 1) << 16) | div;
311 fail:
312 return 0;
313 }
314
315 static void
316 at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock)
317 {
318 uint32_t mckr;
319 int freq;
320
321 sc->main_clock_hz = main_clock;
322 main_ck.hz = main_clock;
323 plla.hz = at91_pmc_pll_rate(main_clock, RD4(sc, CKGR_PLLAR), 0);
324
325 /*
326 * Initialize the usb clock. This sets up pllb, but disables the
327 * actual clock.
328 */
329 sc->pllb_init = at91_pmc_pll_calc(main_clock, 48000000 * 2) |0x10000000;
330 pllb.hz = at91_pmc_pll_rate(main_clock, sc->pllb_init, 1);
331 WR4(sc, PMC_PCDR, (1 << AT91RM92_IRQ_UHP) | (1 << AT91RM92_IRQ_UDP));
332 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
333 WR4(sc, CKGR_PLLBR, 0);
334 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
335
336 /*
337 * MCK and PCU derive from one of the primary clocks. Initialize
338 * this relationship.
339 */
340 mckr = RD4(sc, PMC_MCKR);
341 mck.parent = clock_list[mckr & 0x3];
342 mck.parent->refcnt++;
343 freq = mck.parent->hz / (1 << ((mckr >> 2) & 3));
344 mck.hz = freq / (1 + ((mckr >> 8) & 3));
345
346 device_printf(sc->dev,
347 "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
348 sc->main_clock_hz,
349 at91_pmc_pll_rate(main_clock, RD4(sc, CKGR_PLLAR), 0) / 1000000,
350 freq / 1000000, mck.hz / 1000000);
351 WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
352 PMC_SCER_PCK3);
353 /* XXX kludge, turn on all peripherals */
354 WR4(sc, PMC_PCER, 0xffffffff);
355 /* Disable all interrupts for PMC */
356 WR4(sc, PMC_IDR, 0xffffffff);
357 }
358
359 static void
360 at91_pmc_deactivate(device_t dev)
361 {
362 struct at91_pmc_softc *sc;
363
364 sc = device_get_softc(dev);
365 bus_generic_detach(sc->dev);
366 if (sc->mem_res)
367 bus_release_resource(dev, SYS_RES_IOPORT,
368 rman_get_rid(sc->mem_res), sc->mem_res);
369 sc->mem_res = 0;
370 return;
371 }
372
373 static int
374 at91_pmc_activate(device_t dev)
375 {
376 struct at91_pmc_softc *sc;
377 int rid;
378
379 sc = device_get_softc(dev);
380 rid = 0;
381 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
382 RF_ACTIVE);
383 if (sc->mem_res == NULL)
384 goto errout;
385 return (0);
386 errout:
387 at91_pmc_deactivate(dev);
388 return (ENOMEM);
389 }
390
391 static int
392 at91_pmc_probe(device_t dev)
393 {
394
395 device_set_desc(dev, "PMC");
396 return (0);
397 }
398
399 #if !defined(AT91C_MAIN_CLOCK)
400 static unsigned int
401 at91_pmc_sense_mainf(struct at91_pmc_softc *sc)
402 {
403 unsigned int ckgr_val;
404 unsigned int diff, matchdiff;
405 int i, match;
406
407 ckgr_val = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
408
409 /*
410 * Try to find the standard frequency that match best.
411 */
412 match = 0;
413 matchdiff = abs(ckgr_val - at91_mainf_tbl[0]);
414 for (i = 1; i < MAINF_TBL_LEN; i++) {
415 diff = abs(ckgr_val - at91_mainf_tbl[i]);
416 if (diff < matchdiff) {
417 match = i;
418 matchdiff = diff;
419 }
420 }
421 return (at91_mainf_tbl[match]);
422 }
423 #endif
424
425 static int
426 at91_pmc_attach(device_t dev)
427 {
428 unsigned int mainf;
429 int err;
430
431 pmc_softc = device_get_softc(dev);
432 pmc_softc->dev = dev;
433 if ((err = at91_pmc_activate(dev)) != 0)
434 return err;
435
436 /*
437 * Configure main clock frequency.
438 */
439 #if !defined(AT91C_MAIN_CLOCK)
440 mainf = at91_pmc_sense_mainf(pmc_softc);
441 #else
442 mainf = AT91C_MAIN_CLOCK;
443 #endif
444 at91_pmc_init_clock(pmc_softc, mainf);
445 return (0);
446 }
447
448 static device_method_t at91_pmc_methods[] = {
449 DEVMETHOD(device_probe, at91_pmc_probe),
450 DEVMETHOD(device_attach, at91_pmc_attach),
451 {0, 0},
452 };
453
454 static driver_t at91_pmc_driver = {
455 "at91_pmc",
456 at91_pmc_methods,
457 sizeof(struct at91_pmc_softc),
458 };
459 static devclass_t at91_pmc_devclass;
460
461 DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, 0, 0);
Cache object: 559eb6868af4b66a2ada8421e4f161af
|