1 /* $OpenBSD: prcm.c,v 1.11 2016/07/18 15:03:01 jsg Exp $ */ 2 /* 3 * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /*- 19 * Copyright (c) 2011 20 * Ben Gray <ben.r.gray@gmail.com>. 21 * All rights reserved. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. The name of the company nor the name of the author may be used to 32 * endorse or promote products derived from this software without specific 33 * prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR 36 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 38 * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 40 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 41 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 42 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 43 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 44 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 */ 46 47 /* 48 * Driver for the Power, Reset and Clock Management Module (PRCM). 49 */ 50 51 #include <sys/types.h> 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/kernel.h> 55 #include <sys/time.h> 56 #include <sys/device.h> 57 58 #include <machine/bus.h> 59 #include <machine/intr.h> 60 #include <arm/cpufunc.h> 61 #include <armv7/armv7/armv7var.h> 62 #include <armv7/omap/prcmvar.h> 63 64 #include <armv7/omap/am335x_prcmreg.h> 65 #include <armv7/omap/omap3_prcmreg.h> 66 #include <armv7/omap/omap4_prcmreg.h> 67 68 #include <dev/ofw/fdt.h> 69 70 #define PRCM_REVISION 0x0800 71 #define PRCM_SYSCONFIG 0x0810 72 73 uint32_t prcm_imask_mask[PRCM_REG_MAX]; 74 uint32_t prcm_fmask_mask[PRCM_REG_MAX]; 75 uint32_t prcm_imask_addr[PRCM_REG_MAX]; 76 uint32_t prcm_fmask_addr[PRCM_REG_MAX]; 77 78 #define SYS_CLK 13 /* SYS_CLK speed in MHz */ 79 80 struct prcm_softc { 81 struct device sc_dev; 82 bus_space_tag_t sc_iot; 83 bus_space_handle_t sc_prcm; 84 bus_space_handle_t sc_cm1; 85 bus_space_handle_t sc_cm2; 86 void (*sc_setup)(struct prcm_softc *sc); 87 void (*sc_enablemodule)(struct prcm_softc *sc, int mod); 88 void (*sc_setclock)(struct prcm_softc *sc, 89 int clock, int speed); 90 uint32_t cm1_avail; 91 uint32_t cm2_avail; 92 }; 93 94 int prcm_match(struct device *, void *, void *); 95 void prcm_attach(struct device *, struct device *, void *); 96 int prcm_setup_dpll5(struct prcm_softc *); 97 uint32_t prcm_v3_bit(int mod); 98 uint32_t prcm_am335x_clkctrl(int mod); 99 100 void prcm_am335x_enablemodule(struct prcm_softc *, int); 101 void prcm_am335x_setclock(struct prcm_softc *, int, int); 102 103 void prcm_v3_setup(struct prcm_softc *); 104 void prcm_v3_enablemodule(struct prcm_softc *, int); 105 void prcm_v3_setclock(struct prcm_softc *, int, int); 106 107 void prcm_v4_enablemodule(struct prcm_softc *, int); 108 int prcm_v4_hsusbhost_activate(int); 109 int prcm_v4_hsusbhost_set_source(int, int); 110 111 struct cfattach prcm_ca = { 112 sizeof (struct prcm_softc), NULL, prcm_attach 113 }; 114 115 struct cfdriver prcm_cd = { 116 NULL, "prcm", DV_DULL 117 }; 118 119 void 120 prcm_attach(struct device *parent, struct device *self, void *args) 121 { 122 struct armv7_attach_args *aa = args; 123 struct prcm_softc *sc = (struct prcm_softc *) self; 124 u_int32_t reg; 125 void *node; 126 127 sc->sc_iot = aa->aa_iot; 128 129 node = fdt_find_node("/"); 130 if (node == NULL) 131 panic("%s: could not get fdt root node", 132 sc->sc_dev.dv_xname); 133 134 if (fdt_is_compatible(node, "ti,am33xx")) { 135 sc->sc_setup = NULL; 136 sc->sc_enablemodule = prcm_am335x_enablemodule; 137 sc->sc_setclock = prcm_am335x_setclock; 138 } else if (fdt_is_compatible(node, "ti,omap3")) { 139 sc->sc_setup = prcm_v3_setup; 140 sc->sc_enablemodule = prcm_v3_enablemodule; 141 sc->sc_setclock = prcm_v3_setclock; 142 } else if (fdt_is_compatible(node, "ti,omap4")) { 143 sc->sc_setup = NULL; 144 sc->sc_enablemodule = prcm_v4_enablemodule; 145 sc->sc_setclock = NULL; 146 sc->cm1_avail = 1; 147 sc->cm2_avail = 1; 148 } else 149 panic("%s: could not find a compatible soc", 150 sc->sc_dev.dv_xname); 151 152 if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, 153 aa->aa_dev->mem[0].size, 0, &sc->sc_prcm)) 154 panic("prcm_attach: bus_space_map failed!"); 155 156 if (sc->cm1_avail && 157 bus_space_map(sc->sc_iot, aa->aa_dev->mem[1].addr, 158 aa->aa_dev->mem[1].size, 0, &sc->sc_cm1)) 159 panic("prcm_attach: bus_space_map failed!"); 160 161 if (sc->cm2_avail && 162 bus_space_map(sc->sc_iot, aa->aa_dev->mem[2].addr, 163 aa->aa_dev->mem[2].size, 0, &sc->sc_cm2)) 164 panic("prcm_attach: bus_space_map failed!"); 165 166 reg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_REVISION); 167 printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf); 168 169 if (sc->sc_setup != NULL) 170 sc->sc_setup(sc); 171 } 172 173 void 174 prcm_v3_setup(struct prcm_softc *sc) 175 { 176 /* Setup the 120MHZ DPLL5 clock, to be used by USB. */ 177 prcm_setup_dpll5(sc); 178 179 prcm_fmask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FMASK; 180 prcm_imask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IMASK; 181 prcm_fmask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FADDR; 182 prcm_imask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IADDR; 183 184 prcm_fmask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FMASK; 185 prcm_imask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IMASK; 186 prcm_fmask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FADDR; 187 prcm_imask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IADDR; 188 189 prcm_fmask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FMASK; 190 prcm_imask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IMASK; 191 prcm_fmask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FADDR; 192 prcm_imask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IADDR; 193 194 prcm_fmask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_FMASK; 195 prcm_imask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_IMASK; 196 prcm_fmask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_FADDR; 197 prcm_imask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_IADDR; 198 199 prcm_fmask_mask[PRCM_REG_PER] = PRCM_REG_PER_FMASK; 200 prcm_imask_mask[PRCM_REG_PER] = PRCM_REG_PER_IMASK; 201 prcm_fmask_addr[PRCM_REG_PER] = PRCM_REG_PER_FADDR; 202 prcm_imask_addr[PRCM_REG_PER] = PRCM_REG_PER_IADDR; 203 204 prcm_fmask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FMASK; 205 prcm_imask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IMASK; 206 prcm_fmask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FADDR; 207 prcm_imask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IADDR; 208 } 209 210 void 211 prcm_setclock(int clock, int speed) 212 { 213 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 214 215 if (!sc->sc_setclock) 216 panic("%s: not initialised!", __func__); 217 218 sc->sc_setclock(sc, clock, speed); 219 } 220 221 void 222 prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed) 223 { 224 u_int32_t oreg, reg, mask; 225 226 /* set CLKSEL register */ 227 if (clock == 1) { 228 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 229 PRCM_AM335X_CLKSEL_TIMER2_CLK); 230 mask = 3; 231 reg = oreg & ~mask; 232 reg |=0x02; 233 bus_space_write_4(sc->sc_iot, sc->sc_prcm, 234 PRCM_AM335X_CLKSEL_TIMER2_CLK, reg); 235 } else if (clock == 2) { 236 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 237 PRCM_AM335X_CLKSEL_TIMER3_CLK); 238 mask = 3; 239 reg = oreg & ~mask; 240 reg |=0x02; 241 bus_space_write_4(sc->sc_iot, sc->sc_prcm, 242 PRCM_AM335X_CLKSEL_TIMER3_CLK, reg); 243 } 244 } 245 246 void 247 prcm_v3_setclock(struct prcm_softc *sc, int clock, int speed) 248 { 249 u_int32_t oreg, reg, mask; 250 251 if (clock == 1) { 252 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP); 253 mask = 1; 254 reg = (oreg &~mask) | (speed & mask); 255 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP, reg); 256 } else if (clock >= 2 && clock <= 9) { 257 int shift = (clock-2); 258 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER); 259 mask = 1 << (shift); 260 reg = (oreg & ~mask) | ( (speed << shift) & mask); 261 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER, reg); 262 } else 263 panic("%s: invalid clock %d", __func__, clock); 264 } 265 266 uint32_t 267 prcm_v3_bit(int mod) 268 { 269 switch(mod) { 270 case PRCM_MMC0: 271 return PRCM_CLK_EN_MMC1; 272 case PRCM_MMC1: 273 return PRCM_CLK_EN_MMC2; 274 case PRCM_MMC2: 275 return PRCM_CLK_EN_MMC3; 276 case PRCM_USB: 277 return PRCM_CLK_EN_USB; 278 case PRCM_GPIO0: 279 return PRCM_CLK_EN_GPIO1; 280 case PRCM_GPIO1: 281 return PRCM_CLK_EN_GPIO2; 282 case PRCM_GPIO2: 283 return PRCM_CLK_EN_GPIO3; 284 case PRCM_GPIO3: 285 return PRCM_CLK_EN_GPIO4; 286 case PRCM_GPIO4: 287 return PRCM_CLK_EN_GPIO5; 288 case PRCM_GPIO5: 289 return PRCM_CLK_EN_GPIO6; 290 case PRCM_I2C0: 291 return PRCM_CLK_EN_I2C1; 292 case PRCM_I2C1: 293 return PRCM_CLK_EN_I2C2; 294 case PRCM_I2C2: 295 return PRCM_CLK_EN_I2C3; 296 default: 297 panic("%s: module not found\n", __func__); 298 } 299 } 300 301 uint32_t 302 prcm_am335x_clkctrl(int mod) 303 { 304 switch(mod) { 305 case PRCM_TIMER2: 306 return PRCM_AM335X_TIMER2_CLKCTRL; 307 case PRCM_TIMER3: 308 return PRCM_AM335X_TIMER3_CLKCTRL; 309 case PRCM_MMC0: 310 return PRCM_AM335X_MMC0_CLKCTRL; 311 case PRCM_MMC1: 312 return PRCM_AM335X_MMC1_CLKCTRL; 313 case PRCM_MMC2: 314 return PRCM_AM335X_MMC2_CLKCTRL; 315 case PRCM_USB: 316 return PRCM_AM335X_USB0_CLKCTRL; 317 case PRCM_GPIO0: 318 return PRCM_AM335X_GPIO0_CLKCTRL; 319 case PRCM_GPIO1: 320 return PRCM_AM335X_GPIO1_CLKCTRL; 321 case PRCM_GPIO2: 322 return PRCM_AM335X_GPIO2_CLKCTRL; 323 case PRCM_GPIO3: 324 return PRCM_AM335X_GPIO3_CLKCTRL; 325 case PRCM_TPCC: 326 return PRCM_AM335X_TPCC_CLKCTRL; 327 case PRCM_TPTC0: 328 return PRCM_AM335X_TPTC0_CLKCTRL; 329 case PRCM_TPTC1: 330 return PRCM_AM335X_TPTC1_CLKCTRL; 331 case PRCM_TPTC2: 332 return PRCM_AM335X_TPTC2_CLKCTRL; 333 case PRCM_I2C0: 334 return PRCM_AM335X_I2C0_CLKCTRL; 335 case PRCM_I2C1: 336 return PRCM_AM335X_I2C1_CLKCTRL; 337 case PRCM_I2C2: 338 return PRCM_AM335X_I2C2_CLKCTRL; 339 default: 340 panic("%s: module not found\n", __func__); 341 } 342 } 343 344 void 345 prcm_enablemodule(int mod) 346 { 347 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 348 349 if (!sc->sc_enablemodule) 350 panic("%s: not initialised!", __func__); 351 352 sc->sc_enablemodule(sc, mod); 353 } 354 355 void 356 prcm_am335x_enablemodule(struct prcm_softc *sc, int mod) 357 { 358 uint32_t clkctrl; 359 int reg; 360 361 /*set enable bits in CLKCTRL register */ 362 reg = prcm_am335x_clkctrl(mod); 363 clkctrl = bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg); 364 clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK; 365 clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE; 366 bus_space_write_4(sc->sc_iot, sc->sc_prcm, reg, clkctrl); 367 368 /* wait until module is enabled */ 369 while (bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg) & 0x30000) 370 ; 371 } 372 373 void 374 prcm_v3_enablemodule(struct prcm_softc *sc, int mod) 375 { 376 uint32_t bit; 377 uint32_t fclk, iclk, fmask, imask, mbit; 378 int freg, ireg, reg; 379 380 bit = prcm_v3_bit(mod); 381 reg = bit >> 5; 382 383 freg = prcm_fmask_addr[reg]; 384 ireg = prcm_imask_addr[reg]; 385 fmask = prcm_fmask_mask[reg]; 386 imask = prcm_imask_mask[reg]; 387 388 mbit = 1 << (bit & 0x1f); 389 if (fmask & mbit) { /* dont access the register if bit isn't present */ 390 fclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, freg); 391 bus_space_write_4(sc->sc_iot, sc->sc_prcm, freg, fclk | mbit); 392 } 393 if (imask & mbit) { /* dont access the register if bit isn't present */ 394 iclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, ireg); 395 bus_space_write_4(sc->sc_iot, sc->sc_prcm, ireg, iclk | mbit); 396 } 397 printf("\n"); 398 } 399 400 void 401 prcm_v4_enablemodule(struct prcm_softc *sc, int mod) 402 { 403 switch (mod) { 404 case PRCM_MMC0: 405 case PRCM_MMC1: 406 case PRCM_MMC2: 407 case PRCM_MMC3: 408 case PRCM_MMC4: 409 break; 410 case PRCM_USBP1_PHY: 411 case PRCM_USBP2_PHY: 412 prcm_v4_hsusbhost_set_source(mod, 0); 413 case PRCM_USB: 414 case PRCM_USBTLL: 415 case PRCM_USBP1_UTMI: 416 case PRCM_USBP1_HSIC: 417 case PRCM_USBP2_UTMI: 418 case PRCM_USBP2_HSIC: 419 prcm_v4_hsusbhost_activate(mod); 420 return; 421 case PRCM_GPIO0: 422 case PRCM_GPIO1: 423 case PRCM_GPIO2: 424 case PRCM_GPIO3: 425 case PRCM_GPIO4: 426 case PRCM_GPIO5: 427 /* XXX */ 428 break; 429 case PRCM_I2C0: 430 case PRCM_I2C1: 431 case PRCM_I2C2: 432 case PRCM_I2C3: 433 /* XXX */ 434 break; 435 default: 436 panic("%s: module not found\n", __func__); 437 } 438 } 439 440 int 441 prcm_v4_hsusbhost_activate(int type) 442 { 443 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 444 uint32_t i; 445 uint32_t clksel_reg_off; 446 uint32_t clksel, oclksel; 447 448 switch (type) { 449 case PRCM_USB: 450 case PRCM_USBP1_PHY: 451 case PRCM_USBP2_PHY: 452 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 453 clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58; 454 clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 455 oclksel = clksel; 456 /* Enable the module and also enable the optional func clocks */ 457 if (type == PRCM_USB) { 458 clksel &= ~O4_CLKCTRL_MODULEMODE_MASK; 459 clksel |= /*O4_CLKCTRL_MODULEMODE_ENABLE*/2; 460 461 clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */ 462 } 463 464 break; 465 466 default: 467 panic("%s: invalid type %d", __func__, type); 468 return (EINVAL); 469 } 470 bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel); 471 472 /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */ 473 for (i = 0; i < O4_MAX_MODULE_ENABLE_WAIT; i++) { 474 clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 475 if ((clksel & O4_CLKCTRL_IDLEST_MASK) == O4_CLKCTRL_IDLEST_ENABLED) 476 break; 477 } 478 479 /* Check the enabled state */ 480 if ((clksel & O4_CLKCTRL_IDLEST_MASK) != O4_CLKCTRL_IDLEST_ENABLED) { 481 printf("Error: HERE failed to enable module with clock %d\n", type); 482 printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel); 483 return (ETIMEDOUT); 484 } 485 486 return (0); 487 } 488 489 int 490 prcm_v4_hsusbhost_set_source(int clk, int clksrc) 491 { 492 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 493 uint32_t clksel_reg_off; 494 uint32_t clksel; 495 unsigned int bit; 496 497 if (clk == PRCM_USBP1_PHY) 498 bit = 24; 499 else if (clk != PRCM_USBP2_PHY) 500 bit = 25; 501 else 502 return (-EINVAL); 503 504 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 505 clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58; 506 clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 507 508 /* XXX: Set the clock source to either external or internal */ 509 if (clksrc == 0) 510 clksel |= (0x1 << bit); 511 else 512 clksel &= ~(0x1 << bit); 513 514 bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel); 515 516 return (0); 517 } 518 519 /* 520 * OMAP35xx Power, Reset, and Clock Management Reference Guide 521 * (sprufa5.pdf) and AM/DM37x Multimedia Device Technical Reference 522 * Manual (sprugn4h.pdf) note that DPLL5 provides a 120MHz clock for 523 * peripheral domain modules (page 107 and page 302). 524 * The reference clock for DPLL5 is DPLL5_ALWON_FCLK which is 525 * SYS_CLK, running at 13MHz. 526 */ 527 int 528 prcm_setup_dpll5(struct prcm_softc *sc) 529 { 530 uint32_t val; 531 532 /* 533 * We need to set the multiplier and divider values for PLL. 534 * To end up with 120MHz we take SYS_CLK, divide by it and multiply 535 * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration) 536 */ 537 val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f); 538 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL4_PLL, val); 539 540 /* Clock divider from the PLL to the 120MHz clock. */ 541 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL5_PLL, val); 542 543 /* 544 * spruf98o.pdf, page 2319: 545 * PERIPH2_DPLL_FREQSEL is 0x7 1.75MHz to 2.1MHz 546 * EN_PERIPH2_DPLL is 0x7 547 */ 548 val = (7 << 4) | (7 << 0); 549 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKEN2_PLL, val); 550 551 /* Disable the interconnect clock auto-idle. */ 552 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_AUTOIDLE2_PLL, 0x0); 553 554 /* Wait until DPLL5 is locked and there's clock activity. */ 555 while ((val = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 556 CM_IDLEST_CKGEN) & 0x01) == 0x00) { 557 #ifdef DIAGNOSTIC 558 printf("CM_IDLEST_PLL = 0x%08x\n", val); 559 #endif 560 } 561 562 return 0; 563 } 564