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); |