at91_pmc.c (236658) | at91_pmc.c (238788) |
---|---|
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 --- 11 unchanged lines hidden (view full) --- 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> | 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 --- 11 unchanged lines hidden (view full) --- 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: head/sys/arm/at91/at91_pmc.c 236658 2012-06-06 06:19:52Z imp $"); | 28__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pmc.c 238788 2012-07-26 08:01:25Z andrew $"); |
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> --- 23 unchanged lines hidden (view full) --- 60static uint32_t pllb_init; 61 62MALLOC_DECLARE(M_PMC); 63MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors"); 64 65#define AT91_PMC_BASE 0xffffc00 66 67static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int); | 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> --- 23 unchanged lines hidden (view full) --- 60static uint32_t pllb_init; 61 62MALLOC_DECLARE(M_PMC); 63MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors"); 64 65#define AT91_PMC_BASE 0xffffc00 66 67static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int); |
68static void at91_pmc_set_upll_mode(struct at91_pmc_clock *, int); |
|
68static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int); 69static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int); 70static void at91_pmc_clock_alias(const char *name, const char *alias); 71 72static struct at91_pmc_clock slck = { 73 .name = "slck", // 32,768 Hz slow clock 74 .hz = 32768, 75 .refcnt = 1, --- 29 unchanged lines hidden (view full) --- 105 .refcnt = 0, 106 .id = 0, 107 .primary = 1, 108 .pll = 1, 109 .pmc_mask = PMC_IER_LOCKB, 110 .set_mode = &at91_pmc_set_pllb_mode, 111}; 112 | 69static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int); 70static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int); 71static void at91_pmc_clock_alias(const char *name, const char *alias); 72 73static struct at91_pmc_clock slck = { 74 .name = "slck", // 32,768 Hz slow clock 75 .hz = 32768, 76 .refcnt = 1, --- 29 unchanged lines hidden (view full) --- 106 .refcnt = 0, 107 .id = 0, 108 .primary = 1, 109 .pll = 1, 110 .pmc_mask = PMC_IER_LOCKB, 111 .set_mode = &at91_pmc_set_pllb_mode, 112}; 113 |
114/* Used by USB on at91sam9g45 */ 115static struct at91_pmc_clock upll = { 116 .name = "upll", // UTMI PLL, used for USB functions on 9G45 117 .parent = &main_ck, 118 .refcnt = 0, 119 .id = 0, 120 .primary = 1, 121 .pll = 1, 122 .pmc_mask = (1 << 6), 123 .set_mode = &at91_pmc_set_upll_mode, 124}; 125 |
|
113static struct at91_pmc_clock udpck = { 114 .name = "udpck", 115 .parent = &pllb, 116 .pmc_mask = PMC_SCER_UDP, 117 .set_mode = at91_pmc_set_sys_mode 118}; 119 120static struct at91_pmc_clock uhpck = { --- 17 unchanged lines hidden (view full) --- 138}; 139 140/* "+32" or the automatic peripheral clocks */ 141static struct at91_pmc_clock *clock_list[16+32] = { 142 &slck, 143 &main_ck, 144 &plla, 145 &pllb, | 126static struct at91_pmc_clock udpck = { 127 .name = "udpck", 128 .parent = &pllb, 129 .pmc_mask = PMC_SCER_UDP, 130 .set_mode = at91_pmc_set_sys_mode 131}; 132 133static struct at91_pmc_clock uhpck = { --- 17 unchanged lines hidden (view full) --- 151}; 152 153/* "+32" or the automatic peripheral clocks */ 154static struct at91_pmc_clock *clock_list[16+32] = { 155 &slck, 156 &main_ck, 157 &plla, 158 &pllb, |
159 &upll, |
|
146 &udpck, 147 &uhpck, 148 &mck, 149 &cpu 150}; 151 152static inline uint32_t 153RD4(struct at91_pmc_softc *sc, bus_size_t off) --- 40 unchanged lines hidden (view full) --- 194 } 195 196 WR4(sc, CKGR_PLLBR, value); 197 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on) 198 continue; 199} 200 201static void | 160 &udpck, 161 &uhpck, 162 &mck, 163 &cpu 164}; 165 166static inline uint32_t 167RD4(struct at91_pmc_softc *sc, bus_size_t off) --- 40 unchanged lines hidden (view full) --- 208 } 209 210 WR4(sc, CKGR_PLLBR, value); 211 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on) 212 continue; 213} 214 215static void |
216at91_pmc_set_upll_mode(struct at91_pmc_clock *clk, int on) 217{ 218 struct at91_pmc_softc *sc = pmc_softc; 219 uint32_t value; 220 221 if (on) { 222 on = PMC_IER_LOCKU; 223 value = CKGR_UCKR_UPLLEN | CKGR_UCKR_BIASEN; 224 } else 225 value = 0; 226 227 WR4(sc, CKGR_UCKR, RD4(sc, CKGR_UCKR) | value); 228 while ((RD4(sc, PMC_SR) & PMC_IER_LOCKU) != on) 229 continue; 230 231 WR4(sc, PMC_USB, PMC_USB_USBDIV(9) | PMC_USB_USBS); 232 WR4(sc, PMC_SCER, PMC_SCER_UHP_SAM9); 233} 234 235static 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; --- 251 unchanged lines hidden (view full) --- 461 uint32_t mdiv; 462 463 main_clock = at91_pmc_sense_main_clock(); 464 465 if (at91_is_sam9() || at91_is_sam9xe()) { 466 uhpck.pmc_mask = PMC_SCER_UHP_SAM9; 467 udpck.pmc_mask = PMC_SCER_UDP_SAM9; 468 } | 236at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on) 237{ 238 struct at91_pmc_softc *sc = pmc_softc; 239 240 WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask); 241 if (on) 242 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask) 243 continue; --- 251 unchanged lines hidden (view full) --- 495 uint32_t mdiv; 496 497 main_clock = at91_pmc_sense_main_clock(); 498 499 if (at91_is_sam9() || at91_is_sam9xe()) { 500 uhpck.pmc_mask = PMC_SCER_UHP_SAM9; 501 udpck.pmc_mask = PMC_SCER_UDP_SAM9; 502 } |
503 /* There is no pllb on AT91SAM9G45 */ 504 if (at91_cpu_is(AT91_T_SAM9G45)) { 505 uhpck.parent = &upll; 506 uhpck.pmc_mask = PMC_SCER_UHP_SAM9; 507 } 508 |
|
469 mckr = RD4(sc, PMC_MCKR); 470 main_ck.hz = main_clock; 471 472 at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR)); 473 474 if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2)) 475 plla.hz /= 2; 476 --- 24 unchanged lines hidden (view full) --- 501 mck.parent = clock_list[mckr & 0x3]; 502 mck.parent->refcnt++; 503 504 cpu.hz = mck.hz = mck.parent->hz / 505 (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2)); 506 507 mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8; 508 if (at91_is_sam9() || at91_is_sam9xe()) { | 509 mckr = RD4(sc, PMC_MCKR); 510 main_ck.hz = main_clock; 511 512 at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR)); 513 514 if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2)) 515 plla.hz /= 2; 516 --- 24 unchanged lines hidden (view full) --- 541 mck.parent = clock_list[mckr & 0x3]; 542 mck.parent->refcnt++; 543 544 cpu.hz = mck.hz = mck.parent->hz / 545 (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2)); 546 547 mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8; 548 if (at91_is_sam9() || at91_is_sam9xe()) { |
549 /* 550 * On AT91SAM9G45 when mdiv == 3 we need to divide 551 * MCK by 3 but not, for example, on 9g20. 552 */ 553 if (!at91_cpu_is(AT91_T_SAM9G45) || mdiv <= 2) 554 mdiv *= 2; |
|
509 if (mdiv > 0) | 555 if (mdiv > 0) |
510 mck.hz /= mdiv * 2; | 556 mck.hz /= mdiv; |
511 } else 512 mck.hz /= (1 + mdiv); 513 514 /* Only found on SAM9G20 */ 515 if (at91_cpu_is(AT91_T_SAM9G20)) 516 cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1; 517 518 at91_master_clock = mck.hz; --- 97 unchanged lines hidden --- | 557 } else 558 mck.hz /= (1 + mdiv); 559 560 /* Only found on SAM9G20 */ 561 if (at91_cpu_is(AT91_T_SAM9G20)) 562 cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1; 563 564 at91_master_clock = mck.hz; --- 97 unchanged lines hidden --- |