1 /* $OpenBSD: prcm.c,v 1.16 2021/03/25 04:12: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/param.h> 52 #include <sys/systm.h> 53 #include <sys/device.h> 54 55 #include <machine/bus.h> 56 #include <armv7/armv7/armv7var.h> 57 #include <armv7/omap/prcmvar.h> 58 59 #include <armv7/omap/am335x_prcmreg.h> 60 #include <armv7/omap/omap3_prcmreg.h> 61 #include <armv7/omap/omap4_prcmreg.h> 62 63 #include <dev/ofw/fdt.h> 64 65 #define PRCM_REVISION 0x0800 66 #define PRCM_SYSCONFIG 0x0810 67 68 uint32_t prcm_imask_mask[PRCM_REG_MAX]; 69 uint32_t prcm_fmask_mask[PRCM_REG_MAX]; 70 uint32_t prcm_imask_addr[PRCM_REG_MAX]; 71 uint32_t prcm_fmask_addr[PRCM_REG_MAX]; 72 73 #define SYS_CLK 13 /* SYS_CLK speed in MHz */ 74 #define PRCM_AM335X_MASTER_OSC 24000 /* kHz */ 75 76 77 struct prcm_softc { 78 struct device sc_dev; 79 bus_space_tag_t sc_iot; 80 bus_space_handle_t sc_prcm; 81 bus_space_handle_t sc_cm1; 82 bus_space_handle_t sc_cm2; 83 void (*sc_setup)(struct prcm_softc *sc); 84 void (*sc_enablemodule)(struct prcm_softc *sc, int mod); 85 void (*sc_setclock)(struct prcm_softc *sc, 86 int clock, int speed); 87 uint32_t cm1_avail; 88 uint32_t cm2_avail; 89 }; 90 91 int prcm_match(struct device *, void *, void *); 92 void prcm_attach(struct device *, struct device *, void *); 93 int prcm_setup_dpll5(struct prcm_softc *); 94 uint32_t prcm_v3_bit(int mod); 95 uint32_t prcm_am335x_clkctrl(int mod); 96 97 void prcm_am335x_enablemodule(struct prcm_softc *, int); 98 void prcm_am335x_setclock(struct prcm_softc *, int, int); 99 100 void prcm_v3_setup(struct prcm_softc *); 101 void prcm_v3_enablemodule(struct prcm_softc *, int); 102 void prcm_v3_setclock(struct prcm_softc *, int, int); 103 104 void prcm_v4_enablemodule(struct prcm_softc *, int); 105 int prcm_v4_hsusbhost_activate(int); 106 int prcm_v4_hsusbhost_set_source(int, int); 107 108 struct cfattach prcm_ca = { 109 sizeof (struct prcm_softc), NULL, prcm_attach 110 }; 111 112 struct cfdriver prcm_cd = { 113 NULL, "prcm", DV_DULL 114 }; 115 116 void 117 prcm_attach(struct device *parent, struct device *self, void *args) 118 { 119 struct armv7_attach_args *aa = args; 120 struct prcm_softc *sc = (struct prcm_softc *) self; 121 u_int32_t reg; 122 void *node; 123 124 sc->sc_iot = aa->aa_iot; 125 126 node = fdt_find_node("/"); 127 if (node == NULL) 128 panic("%s: could not get fdt root node", 129 sc->sc_dev.dv_xname); 130 131 if (fdt_is_compatible(node, "ti,am33xx")) { 132 sc->sc_setup = NULL; 133 sc->sc_enablemodule = prcm_am335x_enablemodule; 134 sc->sc_setclock = prcm_am335x_setclock; 135 } else if (fdt_is_compatible(node, "ti,omap3")) { 136 sc->sc_setup = prcm_v3_setup; 137 sc->sc_enablemodule = prcm_v3_enablemodule; 138 sc->sc_setclock = prcm_v3_setclock; 139 } else if (fdt_is_compatible(node, "ti,omap4")) { 140 sc->sc_setup = NULL; 141 sc->sc_enablemodule = prcm_v4_enablemodule; 142 sc->sc_setclock = NULL; 143 sc->cm1_avail = 1; 144 sc->cm2_avail = 1; 145 } else 146 panic("%s: could not find a compatible soc", 147 sc->sc_dev.dv_xname); 148 149 if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, 150 aa->aa_dev->mem[0].size, 0, &sc->sc_prcm)) 151 panic("prcm_attach: bus_space_map failed!"); 152 153 if (sc->cm1_avail && 154 bus_space_map(sc->sc_iot, aa->aa_dev->mem[1].addr, 155 aa->aa_dev->mem[1].size, 0, &sc->sc_cm1)) 156 panic("prcm_attach: bus_space_map failed!"); 157 158 if (sc->cm2_avail && 159 bus_space_map(sc->sc_iot, aa->aa_dev->mem[2].addr, 160 aa->aa_dev->mem[2].size, 0, &sc->sc_cm2)) 161 panic("prcm_attach: bus_space_map failed!"); 162 163 reg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_REVISION); 164 printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf); 165 166 if (sc->sc_setup != NULL) 167 sc->sc_setup(sc); 168 } 169 170 void 171 prcm_v3_setup(struct prcm_softc *sc) 172 { 173 /* Setup the 120MHZ DPLL5 clock, to be used by USB. */ 174 prcm_setup_dpll5(sc); 175 176 prcm_fmask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FMASK; 177 prcm_imask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IMASK; 178 prcm_fmask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FADDR; 179 prcm_imask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IADDR; 180 181 prcm_fmask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FMASK; 182 prcm_imask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IMASK; 183 prcm_fmask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FADDR; 184 prcm_imask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IADDR; 185 186 prcm_fmask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FMASK; 187 prcm_imask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IMASK; 188 prcm_fmask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FADDR; 189 prcm_imask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IADDR; 190 191 prcm_fmask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_FMASK; 192 prcm_imask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_IMASK; 193 prcm_fmask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_FADDR; 194 prcm_imask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_IADDR; 195 196 prcm_fmask_mask[PRCM_REG_PER] = PRCM_REG_PER_FMASK; 197 prcm_imask_mask[PRCM_REG_PER] = PRCM_REG_PER_IMASK; 198 prcm_fmask_addr[PRCM_REG_PER] = PRCM_REG_PER_FADDR; 199 prcm_imask_addr[PRCM_REG_PER] = PRCM_REG_PER_IADDR; 200 201 prcm_fmask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FMASK; 202 prcm_imask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IMASK; 203 prcm_fmask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FADDR; 204 prcm_imask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IADDR; 205 } 206 207 void 208 prcm_setclock(int clock, int speed) 209 { 210 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 211 212 if (!sc->sc_setclock) 213 panic("%s: not initialised!", __func__); 214 215 sc->sc_setclock(sc, clock, speed); 216 } 217 218 void 219 prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed) 220 { 221 u_int32_t oreg, reg, mask; 222 223 /* set CLKSEL register */ 224 if (clock == 1) { 225 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 226 PRCM_AM335X_CLKSEL_TIMER2_CLK); 227 mask = 3; 228 reg = oreg & ~mask; 229 reg |=0x02; 230 bus_space_write_4(sc->sc_iot, sc->sc_prcm, 231 PRCM_AM335X_CLKSEL_TIMER2_CLK, reg); 232 } else if (clock == 2) { 233 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 234 PRCM_AM335X_CLKSEL_TIMER3_CLK); 235 mask = 3; 236 reg = oreg & ~mask; 237 reg |=0x02; 238 bus_space_write_4(sc->sc_iot, sc->sc_prcm, 239 PRCM_AM335X_CLKSEL_TIMER3_CLK, reg); 240 } else if (clock == 3) { /* DISP M1 */ 241 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 242 oreg &= ~0x7; 243 oreg |= 0x4; 244 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 245 while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 246 & 0x10))); 247 248 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL); 249 oreg &= 0xFFF800FF; 250 oreg |= (speed & 0x7FF) << 8; 251 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL, oreg); 252 253 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 254 oreg |= 0x7; 255 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 256 while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 257 & 0x10))); 258 } else if (clock == 4) { /* DISP N */ 259 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 260 oreg &= ~0x7; 261 oreg |= 0x4; 262 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 263 while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 264 & 0x10))); 265 266 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL); 267 oreg &= 0xFFFFFF80; 268 oreg |= speed & 0x7F; 269 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL, oreg); 270 271 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 272 oreg |= 0x7; 273 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 274 while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 275 & 0x10))); 276 } else if (clock == 5) { /* DISP M2 */ 277 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_M2); 278 oreg &= ~(0x1F); 279 oreg |= speed & 0x1F; 280 bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_M2, oreg); 281 } 282 } 283 284 void 285 prcm_v3_setclock(struct prcm_softc *sc, int clock, int speed) 286 { 287 u_int32_t oreg, reg, mask; 288 289 if (clock == 1) { 290 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP); 291 mask = 1; 292 reg = (oreg &~mask) | (speed & mask); 293 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP, reg); 294 } else if (clock >= 2 && clock <= 9) { 295 int shift = (clock-2); 296 oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER); 297 mask = 1 << (shift); 298 reg = (oreg & ~mask) | ( (speed << shift) & mask); 299 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER, reg); 300 } else 301 panic("%s: invalid clock %d", __func__, clock); 302 } 303 304 uint32_t 305 prcm_v3_bit(int mod) 306 { 307 switch(mod) { 308 case PRCM_MMC0: 309 return PRCM_CLK_EN_MMC1; 310 case PRCM_MMC1: 311 return PRCM_CLK_EN_MMC2; 312 case PRCM_MMC2: 313 return PRCM_CLK_EN_MMC3; 314 case PRCM_USB: 315 return PRCM_CLK_EN_USB; 316 case PRCM_GPIO0: 317 return PRCM_CLK_EN_GPIO1; 318 case PRCM_GPIO1: 319 return PRCM_CLK_EN_GPIO2; 320 case PRCM_GPIO2: 321 return PRCM_CLK_EN_GPIO3; 322 case PRCM_GPIO3: 323 return PRCM_CLK_EN_GPIO4; 324 case PRCM_GPIO4: 325 return PRCM_CLK_EN_GPIO5; 326 case PRCM_GPIO5: 327 return PRCM_CLK_EN_GPIO6; 328 case PRCM_I2C0: 329 return PRCM_CLK_EN_I2C1; 330 case PRCM_I2C1: 331 return PRCM_CLK_EN_I2C2; 332 case PRCM_I2C2: 333 return PRCM_CLK_EN_I2C3; 334 default: 335 panic("%s: module not found\n", __func__); 336 } 337 } 338 339 uint32_t 340 prcm_am335x_clkctrl(int mod) 341 { 342 switch(mod) { 343 case PRCM_TIMER2: 344 return PRCM_AM335X_TIMER2_CLKCTRL; 345 case PRCM_TIMER3: 346 return PRCM_AM335X_TIMER3_CLKCTRL; 347 case PRCM_MMC0: 348 return PRCM_AM335X_MMC0_CLKCTRL; 349 case PRCM_MMC1: 350 return PRCM_AM335X_MMC1_CLKCTRL; 351 case PRCM_MMC2: 352 return PRCM_AM335X_MMC2_CLKCTRL; 353 case PRCM_USB: 354 return PRCM_AM335X_USB0_CLKCTRL; 355 case PRCM_GPIO0: 356 return PRCM_AM335X_GPIO0_CLKCTRL; 357 case PRCM_GPIO1: 358 return PRCM_AM335X_GPIO1_CLKCTRL; 359 case PRCM_GPIO2: 360 return PRCM_AM335X_GPIO2_CLKCTRL; 361 case PRCM_GPIO3: 362 return PRCM_AM335X_GPIO3_CLKCTRL; 363 case PRCM_TPCC: 364 return PRCM_AM335X_TPCC_CLKCTRL; 365 case PRCM_TPTC0: 366 return PRCM_AM335X_TPTC0_CLKCTRL; 367 case PRCM_TPTC1: 368 return PRCM_AM335X_TPTC1_CLKCTRL; 369 case PRCM_TPTC2: 370 return PRCM_AM335X_TPTC2_CLKCTRL; 371 case PRCM_I2C0: 372 return PRCM_AM335X_I2C0_CLKCTRL; 373 case PRCM_I2C1: 374 return PRCM_AM335X_I2C1_CLKCTRL; 375 case PRCM_I2C2: 376 return PRCM_AM335X_I2C2_CLKCTRL; 377 case PRCM_LCDC: 378 return PRCM_AM335X_LCDC_CLKCTRL; 379 case PRCM_RNG: 380 return PRCM_AM335X_RNG_CLKCTRL; 381 default: 382 panic("%s: module not found\n", __func__); 383 } 384 } 385 386 void 387 prcm_enablemodule(int mod) 388 { 389 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 390 391 if (!sc->sc_enablemodule) 392 panic("%s: not initialised!", __func__); 393 394 sc->sc_enablemodule(sc, mod); 395 } 396 397 void 398 prcm_am335x_enablemodule(struct prcm_softc *sc, int mod) 399 { 400 uint32_t clkctrl; 401 int reg; 402 403 /*set enable bits in CLKCTRL register */ 404 reg = prcm_am335x_clkctrl(mod); 405 clkctrl = bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg); 406 clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK; 407 clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE; 408 bus_space_write_4(sc->sc_iot, sc->sc_prcm, reg, clkctrl); 409 410 /* wait until module is enabled */ 411 while (bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg) & 0x30000) 412 ; 413 } 414 415 void 416 prcm_v3_enablemodule(struct prcm_softc *sc, int mod) 417 { 418 uint32_t bit; 419 uint32_t fclk, iclk, fmask, imask, mbit; 420 int freg, ireg, reg; 421 422 bit = prcm_v3_bit(mod); 423 reg = bit >> 5; 424 425 freg = prcm_fmask_addr[reg]; 426 ireg = prcm_imask_addr[reg]; 427 fmask = prcm_fmask_mask[reg]; 428 imask = prcm_imask_mask[reg]; 429 430 mbit = 1 << (bit & 0x1f); 431 if (fmask & mbit) { /* dont access the register if bit isn't present */ 432 fclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, freg); 433 bus_space_write_4(sc->sc_iot, sc->sc_prcm, freg, fclk | mbit); 434 } 435 if (imask & mbit) { /* dont access the register if bit isn't present */ 436 iclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, ireg); 437 bus_space_write_4(sc->sc_iot, sc->sc_prcm, ireg, iclk | mbit); 438 } 439 printf("\n"); 440 } 441 442 void 443 prcm_v4_enablemodule(struct prcm_softc *sc, int mod) 444 { 445 switch (mod) { 446 case PRCM_MMC0: 447 case PRCM_MMC1: 448 case PRCM_MMC2: 449 case PRCM_MMC3: 450 case PRCM_MMC4: 451 break; 452 case PRCM_USBP1_PHY: 453 case PRCM_USBP2_PHY: 454 prcm_v4_hsusbhost_set_source(mod, 0); 455 case PRCM_USB: 456 case PRCM_USBTLL: 457 case PRCM_USBP1_UTMI: 458 case PRCM_USBP1_HSIC: 459 case PRCM_USBP2_UTMI: 460 case PRCM_USBP2_HSIC: 461 prcm_v4_hsusbhost_activate(mod); 462 return; 463 case PRCM_GPIO0: 464 case PRCM_GPIO1: 465 case PRCM_GPIO2: 466 case PRCM_GPIO3: 467 case PRCM_GPIO4: 468 case PRCM_GPIO5: 469 /* XXX */ 470 break; 471 case PRCM_I2C0: 472 case PRCM_I2C1: 473 case PRCM_I2C2: 474 case PRCM_I2C3: 475 /* XXX */ 476 break; 477 default: 478 panic("%s: module not found\n", __func__); 479 } 480 } 481 482 int 483 prcm_v4_hsusbhost_activate(int type) 484 { 485 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 486 uint32_t i; 487 uint32_t clksel_reg_off; 488 uint32_t clksel, oclksel; 489 490 switch (type) { 491 case PRCM_USB: 492 case PRCM_USBP1_PHY: 493 case PRCM_USBP2_PHY: 494 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 495 clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58; 496 clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 497 oclksel = clksel; 498 /* Enable the module and also enable the optional func clocks */ 499 if (type == PRCM_USB) { 500 clksel &= ~O4_CLKCTRL_MODULEMODE_MASK; 501 clksel |= /*O4_CLKCTRL_MODULEMODE_ENABLE*/2; 502 503 clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */ 504 } 505 506 break; 507 508 default: 509 panic("%s: invalid type %d", __func__, type); 510 return (EINVAL); 511 } 512 bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel); 513 514 /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */ 515 for (i = 0; i < O4_MAX_MODULE_ENABLE_WAIT; i++) { 516 clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 517 if ((clksel & O4_CLKCTRL_IDLEST_MASK) == O4_CLKCTRL_IDLEST_ENABLED) 518 break; 519 } 520 521 /* Check the enabled state */ 522 if ((clksel & O4_CLKCTRL_IDLEST_MASK) != O4_CLKCTRL_IDLEST_ENABLED) { 523 printf("Error: HERE failed to enable module with clock %d\n", type); 524 printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel); 525 return (ETIMEDOUT); 526 } 527 528 return (0); 529 } 530 531 int 532 prcm_v4_hsusbhost_set_source(int clk, int clksrc) 533 { 534 struct prcm_softc *sc = prcm_cd.cd_devs[0]; 535 uint32_t clksel_reg_off; 536 uint32_t clksel; 537 unsigned int bit; 538 539 if (clk == PRCM_USBP1_PHY) 540 bit = 24; 541 else if (clk != PRCM_USBP2_PHY) 542 bit = 25; 543 else 544 return (-EINVAL); 545 546 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 547 clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58; 548 clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 549 550 /* XXX: Set the clock source to either external or internal */ 551 if (clksrc == 0) 552 clksel |= (0x1 << bit); 553 else 554 clksel &= ~(0x1 << bit); 555 556 bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel); 557 558 return (0); 559 } 560 561 /* 562 * OMAP35xx Power, Reset, and Clock Management Reference Guide 563 * (sprufa5.pdf) and AM/DM37x Multimedia Device Technical Reference 564 * Manual (sprugn4h.pdf) note that DPLL5 provides a 120MHz clock for 565 * peripheral domain modules (page 107 and page 302). 566 * The reference clock for DPLL5 is DPLL5_ALWON_FCLK which is 567 * SYS_CLK, running at 13MHz. 568 */ 569 int 570 prcm_setup_dpll5(struct prcm_softc *sc) 571 { 572 uint32_t val; 573 574 /* 575 * We need to set the multiplier and divider values for PLL. 576 * To end up with 120MHz we take SYS_CLK, divide by it and multiply 577 * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration) 578 */ 579 val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f); 580 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL4_PLL, val); 581 582 /* Clock divider from the PLL to the 120MHz clock. */ 583 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL5_PLL, val); 584 585 /* 586 * spruf98o.pdf, page 2319: 587 * PERIPH2_DPLL_FREQSEL is 0x7 1.75MHz to 2.1MHz 588 * EN_PERIPH2_DPLL is 0x7 589 */ 590 val = (7 << 4) | (7 << 0); 591 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKEN2_PLL, val); 592 593 /* Disable the interconnect clock auto-idle. */ 594 bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_AUTOIDLE2_PLL, 0x0); 595 596 /* Wait until DPLL5 is locked and there's clock activity. */ 597 while ((val = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 598 CM_IDLEST_CKGEN) & 0x01) == 0x00) { 599 #ifdef DIAGNOSTIC 600 printf("CM_IDLEST_PLL = 0x%08x\n", val); 601 #endif 602 } 603 604 return 0; 605 } 606