1/*- 2 * Copyright (c) 2006 M. Warner Losh. All rights reserved. 3 * Copyright (c) 2010 Greg Ansley. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/kernel.h> 33#include <sys/malloc.h> 34#include <sys/module.h> 35#include <sys/time.h> 36#include <sys/bus.h> 37#include <sys/resource.h> 38#include <sys/rman.h> 39#include <sys/timetc.h> 40 41#include <machine/bus.h> 42#include <machine/cpu.h> 43#include <machine/cpufunc.h> 44#include <machine/resource.h> 45#include <machine/frame.h> 46#include <machine/intr.h> 47#include <arm/at91/at91reg.h> 48#include <arm/at91/at91var.h> 49 50#include <arm/at91/at91_pmcreg.h> 51#include <arm/at91/at91_pmcvar.h> 52 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 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); 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 */ 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 90static struct at91_pmc_clock plla = { 91 .name = "plla", // PLLA Clock, used for CPU clocking 92 .parent = &main_ck, 93 .refcnt = 1, 94 .id = 0, 95 .primary = 1, 96 .pll = 1, 97 .pmc_mask = PMC_IER_LOCKA, 98}; 99 100static struct at91_pmc_clock pllb = { 101 .name = "pllb", // PLLB Clock, used for USB functions 102 .parent = &main_ck, 103 .refcnt = 0, 104 .id = 0, 105 .primary = 1, 106 .pll = 1, 107 .pmc_mask = PMC_IER_LOCKB, 108 .set_mode = &at91_pmc_set_pllb_mode, 109}; 110 111static struct at91_pmc_clock udpck = { 112 .name = "udpck", 113 .parent = &pllb, 114 .pmc_mask = PMC_SCER_UDP, 115 .set_mode = at91_pmc_set_sys_mode 116}; 117 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 = { 126 .name = "mck", // Master (Peripheral) Clock 127 .pmc_mask = PMC_IER_MCKRDY, 128 .refcnt = 0, 129}; 130 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 138/* "+32" or the automatic peripheral clocks */ 139static struct at91_pmc_clock *clock_list[16+32] = { 140 &slck, 141 &main_ck, 142 &plla, 143 &pllb, 144 &udpck, 145 &uhpck, 146 &mck, 147 &cpu 148}; 149 150#if !defined(AT91C_MAIN_CLOCK) 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{ 165 166 return (bus_read_4(sc->mem_res, off)); 167} 168 169static inline void 170WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val) 171{ 172 173 bus_write_4(sc->mem_res, off, val); 174} 175 176void 177at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on) 178{ 179 struct at91_pmc_softc *sc = pmc_softc; 180 uint32_t value; 181 182 if (on) { 183 on = PMC_IER_LOCKB; 184 value = sc->pllb_init; 185 } else 186 value = 0; 187 188 /* Workaround RM9200 Errata #26 */ 189 if (at91_is_rm92() && 190 ((value ^ RD4(sc, CKGR_PLLBR)) & 0x03f0ff) != 0) { 191 WR4(sc, CKGR_PLLBR, value ^ 1); 192 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on) 193 continue; 194 } 195 196 WR4(sc, CKGR_PLLBR, value); 197 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on) 198 continue; 199} 200 201static void 202at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on) 203{ 204 struct at91_pmc_softc *sc = pmc_softc; 205 206 WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask); 207 if (on) 208 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask) 209 continue; 210 else 211 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask) 212 continue; 213} 214 215static void 216at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on) 217{ 218 struct at91_pmc_softc *sc = pmc_softc; 219 220 WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask); 221 if (on) 222 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask) 223 continue; 224 else 225 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask) 226 continue; 227} 228 229struct at91_pmc_clock * 230at91_pmc_clock_add(const char *name, uint32_t irq, 231 struct at91_pmc_clock *parent) 232{ 233 struct at91_pmc_clock *clk; 234 int i, buflen; 235 236 clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO); 237 if (clk == NULL) 238 goto err; 239 240 buflen = strlen(name) + 1; 241 clk->name = malloc(buflen, M_PMC, M_NOWAIT); 242 if (clk->name == NULL) 243 goto err; 244 245 strlcpy(clk->name, name, buflen); 246 clk->pmc_mask = 1 << irq; 247 clk->set_mode = &at91_pmc_set_periph_mode; 248 if (parent == NULL) 249 clk->parent = &mck; 250 else 251 clk->parent = parent; 252 253 for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) { 254 if (clock_list[i] == NULL) { 255 clock_list[i] = clk; 256 return (clk); 257 } 258 } 259err: 260 if (clk != NULL) { 261 if (clk->name != NULL) 262 free(clk->name, M_PMC); 263 free(clk, M_PMC); 264 } 265 266 panic("could not allocate pmc clock '%s'", name); 267 return (NULL); 268} 269 270static void 271at91_pmc_clock_alias(const char *name, const char *alias) 272{ 273 struct at91_pmc_clock *clk, *alias_clk; 274 275 clk = at91_pmc_clock_ref(name); 276 if (clk) 277 alias_clk = at91_pmc_clock_add(alias, 0, clk->parent); 278 279 if (clk && alias_clk) { 280 alias_clk->hz = clk->hz; 281 alias_clk->pmc_mask = clk->pmc_mask; 282 alias_clk->set_mode = clk->set_mode; 283 } 284} 285 286struct at91_pmc_clock * 287at91_pmc_clock_ref(const char *name) 288{ 289 int i; 290 291 for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) { 292 if (clock_list[i] == NULL) 293 break; 294 if (strcmp(name, clock_list[i]->name) == 0) 295 return (clock_list[i]); 296 } 297 298 //printf("at91_pmc: Warning - did not find clock '%s'", name); 299 return (NULL); 300} 301 302void 303at91_pmc_clock_deref(struct at91_pmc_clock *clk) 304{ 305 306} 307 308void 309at91_pmc_clock_enable(struct at91_pmc_clock *clk) 310{ 311 312 /* XXX LOCKING? XXX */ 313 if (clk->parent) 314 at91_pmc_clock_enable(clk->parent); 315 if (clk->refcnt++ == 0 && clk->set_mode) 316 clk->set_mode(clk, 1); 317} 318 319void 320at91_pmc_clock_disable(struct at91_pmc_clock *clk) 321{ 322 323 /* XXX LOCKING? XXX */ 324 if (--clk->refcnt == 0 && clk->set_mode) 325 clk->set_mode(clk, 0); 326 if (clk->parent) 327 at91_pmc_clock_disable(clk->parent); 328} 329 330static int 331at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg) 332{ 333 uint32_t mul, div, freq; 334 335 freq = clk->parent->hz; 336 div = (reg >> clk->pll_div_shift) & clk->pll_div_mask; 337 mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask; 338 339#if 0 340 printf("pll = (%d / %d) * %d = %d\n", 341 freq, div, mul + 1, (freq/div) * (mul+1)); 342#endif 343 344 if (div != 0 && mul != 0) { 345 freq /= div; 346 freq *= mul + 1; 347 } else 348 freq = 0; 349 clk->hz = freq; 350 351 return (freq); 352} 353 354static uint32_t 355at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq) 356{ 357 uint32_t i, div = 0, mul = 0, diff = 1 << 30; 358 359 unsigned ret = 0x3e00; 360 361 if (out_freq > clk->pll_max_out) 362 goto fail; 363 364 for (i = 1; i < 256; i++) { 365 int32_t diff1; 366 uint32_t input, mul1; 367 368 input = clk->parent->hz / i; 369 if (input < clk->pll_min_in) 370 break; 371 if (input > clk->pll_max_in) 372 continue; 373 374 mul1 = out_freq / input; 375 if (mul1 > (clk->pll_mul_mask + 1)) 376 continue; 377 if (mul1 == 0) 378 break; 379 380 diff1 = out_freq - input * mul1; 381 if (diff1 < 0) 382 diff1 = -diff1; 383 if (diff > diff1) { 384 diff = diff1; 385 div = i; 386 mul = mul1; 387 if (diff == 0) 388 break; 389 } 390 } 391 if (diff > (out_freq >> PMC_PLL_SHIFT_TOL)) 392 goto fail; 393 394 if (clk->set_outb != NULL) 395 ret |= clk->set_outb(out_freq); 396 397 return (ret | 398 ((mul - 1) << clk->pll_mul_shift) | 399 (div << clk->pll_div_shift)); 400fail: 401 return (0); 402} 403 404static void 405at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock) 406{ 407 uint32_t mckr; 408 uint32_t mdiv; 409 410 if (at91_is_sam9() || at91_is_sam9xe()) { 411 uhpck.pmc_mask = PMC_SCER_UHP_SAM9; 412 udpck.pmc_mask = PMC_SCER_UDP_SAM9; 413 } 414 mckr = RD4(sc, PMC_MCKR); 415 sc->main_clock_hz = main_clock; 416 main_ck.hz = main_clock; 417 418 at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR)); 419 420 if (at91_cpu_is(AT91_CPU_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2)) 421 plla.hz /= 2; 422 423 /* 424 * Initialize the usb clock. This sets up pllb, but disables the 425 * actual clock. 426 */ 427 sc->pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000; 428 at91_pmc_pll_rate(&pllb, sc->pllb_init); 429 430#if 0 431 /* Turn off USB clocks */ 432 at91_pmc_set_periph_mode(&ohci_clk, 0); 433 at91_pmc_set_periph_mode(&udc_clk, 0); 434#endif 435 436 if (at91_is_rm92()) { 437 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP); 438 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP); 439 } else 440 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9); 441 WR4(sc, CKGR_PLLBR, 0); 442 443 /* 444 * MCK and PCU derive from one of the primary clocks. Initialize 445 * this relationship. 446 */ 447 mck.parent = clock_list[mckr & 0x3]; 448 mck.parent->refcnt++; 449 450 cpu.hz = mck.hz = mck.parent->hz / 451 (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2)); 452 453 mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8; 454 if (at91_is_sam9() || at91_is_sam9xe()) { 455 if (mdiv > 0) 456 mck.hz /= mdiv * 2; 457 } else 458 mck.hz /= (1 + mdiv); 459 460 /* Only found on SAM9G20 */ 461 if (at91_cpu_is(AT91_CPU_SAM9G20)) 462 cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1; 463 464 at91_master_clock = mck.hz; 465 466 device_printf(sc->dev, 467 "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n", 468 sc->main_clock_hz, 469 plla.hz / 1000000, 470 cpu.hz / 1000000, mck.hz / 1000000); 471 472 /* Turn off "Progamable" clocks */ 473 WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 | 474 PMC_SCER_PCK3); 475 476 /* XXX kludge, turn on all peripherals */ 477 WR4(sc, PMC_PCER, 0xffffffff); 478 479 /* Disable all interrupts for PMC */ 480 WR4(sc, PMC_IDR, 0xffffffff); 481} 482 483static void 484at91_pmc_deactivate(device_t dev) 485{ 486 struct at91_pmc_softc *sc; 487 488 sc = device_get_softc(dev); 489 bus_generic_detach(sc->dev); 490 if (sc->mem_res) 491 bus_release_resource(dev, SYS_RES_IOPORT, 492 rman_get_rid(sc->mem_res), sc->mem_res); 493 sc->mem_res = 0; 494} 495 496static int 497at91_pmc_activate(device_t dev) 498{ 499 struct at91_pmc_softc *sc; 500 int rid; 501 502 sc = device_get_softc(dev); 503 rid = 0; 504 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 505 RF_ACTIVE); 506 if (sc->mem_res == NULL) 507 goto errout; 508 return (0); 509errout: 510 at91_pmc_deactivate(dev); 511 return (ENOMEM); 512} 513 514static int 515at91_pmc_probe(device_t dev) 516{ 517 518 device_set_desc(dev, "PMC"); 519 return (0); 520} 521 522#if !defined(AT91C_MAIN_CLOCK) 523static unsigned int 524at91_pmc_sense_mainf(struct at91_pmc_softc *sc) 525{ 526 unsigned int ckgr_val; 527 unsigned int diff, matchdiff; 528 int i, match; 529 530 ckgr_val = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11; 531 532 /* 533 * Try to find the standard frequency that match best. 534 */ 535 match = 0; 536 matchdiff = abs(ckgr_val - at91_mainf_tbl[0]); 537 for (i = 1; i < MAINF_TBL_LEN; i++) { 538 diff = abs(ckgr_val - at91_mainf_tbl[i]); 539 if (diff < matchdiff) { 540 match = i; 541 matchdiff = diff; 542 } 543 } 544 return (at91_mainf_tbl[match]); 545} 546#endif 547 548static int 549at91_pmc_attach(device_t dev) 550{ 551 unsigned int mainf; 552 int err; 553 554 pmc_softc = device_get_softc(dev); 555 pmc_softc->dev = dev; 556 if ((err = at91_pmc_activate(dev)) != 0) 557 return (err); 558 559 /* 560 * Configure main clock frequency. 561 */ 562#if !defined(AT91C_MAIN_CLOCK) 563 mainf = at91_pmc_sense_mainf(pmc_softc); 564#else 565 mainf = AT91C_MAIN_CLOCK; 566#endif 567 at91_pmc_init_clock(pmc_softc, mainf); 568 569 /* These clocks refrenced by "special" names */ 570 at91_pmc_clock_alias("ohci0", "ohci_clk"); 571 at91_pmc_clock_alias("udp0", "udp_clk"); 572 573 return (0); 574} 575 576static device_method_t at91_pmc_methods[] = { 577 DEVMETHOD(device_probe, at91_pmc_probe), 578 DEVMETHOD(device_attach, at91_pmc_attach), 579 DEVMETHOD_END 580}; 581 582static driver_t at91_pmc_driver = { 583 "at91_pmc", 584 at91_pmc_methods, 585 sizeof(struct at91_pmc_softc), 586}; 587static devclass_t at91_pmc_devclass; 588 589DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, NULL, 590 NULL); 591