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