1*9fdf0c62Smpi /* $OpenBSD: prcm.c,v 1.18 2021/10/24 17:52:28 mpi Exp $ */ 28eda2d14Spatrick /* 38eda2d14Spatrick * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> 48eda2d14Spatrick * 58eda2d14Spatrick * Permission to use, copy, modify, and distribute this software for any 68eda2d14Spatrick * purpose with or without fee is hereby granted, provided that the above 78eda2d14Spatrick * copyright notice and this permission notice appear in all copies. 88eda2d14Spatrick * 98eda2d14Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 108eda2d14Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 118eda2d14Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 128eda2d14Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 138eda2d14Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 148eda2d14Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 158eda2d14Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 168eda2d14Spatrick */ 178eda2d14Spatrick 188eda2d14Spatrick /*- 198eda2d14Spatrick * Copyright (c) 2011 208eda2d14Spatrick * Ben Gray <ben.r.gray@gmail.com>. 218eda2d14Spatrick * All rights reserved. 228eda2d14Spatrick * 238eda2d14Spatrick * Redistribution and use in source and binary forms, with or without 248eda2d14Spatrick * modification, are permitted provided that the following conditions 258eda2d14Spatrick * are met: 268eda2d14Spatrick * 1. Redistributions of source code must retain the above copyright 278eda2d14Spatrick * notice, this list of conditions and the following disclaimer. 288eda2d14Spatrick * 2. Redistributions in binary form must reproduce the above copyright 298eda2d14Spatrick * notice, this list of conditions and the following disclaimer in the 308eda2d14Spatrick * documentation and/or other materials provided with the distribution. 318eda2d14Spatrick * 3. The name of the company nor the name of the author may be used to 328eda2d14Spatrick * endorse or promote products derived from this software without specific 338eda2d14Spatrick * prior written permission. 348eda2d14Spatrick * 358eda2d14Spatrick * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR 368eda2d14Spatrick * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 378eda2d14Spatrick * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 388eda2d14Spatrick * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 398eda2d14Spatrick * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 408eda2d14Spatrick * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 418eda2d14Spatrick * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 428eda2d14Spatrick * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 438eda2d14Spatrick * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 448eda2d14Spatrick * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 458eda2d14Spatrick */ 468eda2d14Spatrick 478eda2d14Spatrick /* 488eda2d14Spatrick * Driver for the Power, Reset and Clock Management Module (PRCM). 498eda2d14Spatrick */ 508eda2d14Spatrick 518eda2d14Spatrick #include <sys/param.h> 528eda2d14Spatrick #include <sys/systm.h> 538eda2d14Spatrick #include <sys/device.h> 548eda2d14Spatrick 558eda2d14Spatrick #include <machine/bus.h> 568d957e1aSsyl #include <armv7/armv7/armv7var.h> 578eda2d14Spatrick #include <armv7/omap/prcmvar.h> 588eda2d14Spatrick 598eda2d14Spatrick #include <armv7/omap/am335x_prcmreg.h> 608eda2d14Spatrick #include <armv7/omap/omap3_prcmreg.h> 618eda2d14Spatrick #include <armv7/omap/omap4_prcmreg.h> 628eda2d14Spatrick 63d5df157eSjsg #include <dev/ofw/fdt.h> 64d5df157eSjsg 658eda2d14Spatrick #define PRCM_REVISION 0x0800 668eda2d14Spatrick #define PRCM_SYSCONFIG 0x0810 678eda2d14Spatrick 688eda2d14Spatrick uint32_t prcm_imask_mask[PRCM_REG_MAX]; 698eda2d14Spatrick uint32_t prcm_fmask_mask[PRCM_REG_MAX]; 708eda2d14Spatrick uint32_t prcm_imask_addr[PRCM_REG_MAX]; 718eda2d14Spatrick uint32_t prcm_fmask_addr[PRCM_REG_MAX]; 728eda2d14Spatrick 738eda2d14Spatrick #define SYS_CLK 13 /* SYS_CLK speed in MHz */ 742252d02cSkettenis #define PRCM_AM335X_MASTER_OSC 24000 /* kHz */ 752b401c1dSians 768eda2d14Spatrick 778eda2d14Spatrick struct prcm_softc { 788eda2d14Spatrick struct device sc_dev; 798eda2d14Spatrick bus_space_tag_t sc_iot; 808eda2d14Spatrick bus_space_handle_t sc_prcm; 818eda2d14Spatrick bus_space_handle_t sc_cm1; 828eda2d14Spatrick bus_space_handle_t sc_cm2; 838eda2d14Spatrick void (*sc_setup)(struct prcm_softc *sc); 848eda2d14Spatrick void (*sc_enablemodule)(struct prcm_softc *sc, int mod); 858eda2d14Spatrick void (*sc_setclock)(struct prcm_softc *sc, 868eda2d14Spatrick int clock, int speed); 878eda2d14Spatrick uint32_t cm1_avail; 888eda2d14Spatrick uint32_t cm2_avail; 898eda2d14Spatrick }; 908eda2d14Spatrick 918eda2d14Spatrick int prcm_match(struct device *, void *, void *); 928eda2d14Spatrick void prcm_attach(struct device *, struct device *, void *); 938eda2d14Spatrick int prcm_setup_dpll5(struct prcm_softc *); 948eda2d14Spatrick uint32_t prcm_v3_bit(int mod); 958eda2d14Spatrick uint32_t prcm_am335x_clkctrl(int mod); 968eda2d14Spatrick 978eda2d14Spatrick void prcm_am335x_enablemodule(struct prcm_softc *, int); 988eda2d14Spatrick void prcm_am335x_setclock(struct prcm_softc *, int, int); 998eda2d14Spatrick 1008eda2d14Spatrick void prcm_v3_setup(struct prcm_softc *); 1018eda2d14Spatrick void prcm_v3_enablemodule(struct prcm_softc *, int); 1028eda2d14Spatrick void prcm_v3_setclock(struct prcm_softc *, int, int); 1038eda2d14Spatrick 1048eda2d14Spatrick void prcm_v4_enablemodule(struct prcm_softc *, int); 1058eda2d14Spatrick int prcm_v4_hsusbhost_activate(int); 1068eda2d14Spatrick int prcm_v4_hsusbhost_set_source(int, int); 1078eda2d14Spatrick 108*9fdf0c62Smpi const struct cfattach prcm_ca = { 1098eda2d14Spatrick sizeof (struct prcm_softc), NULL, prcm_attach 1108eda2d14Spatrick }; 1118eda2d14Spatrick 1128eda2d14Spatrick struct cfdriver prcm_cd = { 1138eda2d14Spatrick NULL, "prcm", DV_DULL 1148eda2d14Spatrick }; 1158eda2d14Spatrick 1168eda2d14Spatrick void 1178eda2d14Spatrick prcm_attach(struct device *parent, struct device *self, void *args) 1188eda2d14Spatrick { 1198d957e1aSsyl struct armv7_attach_args *aa = args; 1208eda2d14Spatrick struct prcm_softc *sc = (struct prcm_softc *) self; 1218eda2d14Spatrick u_int32_t reg; 122d5df157eSjsg void *node; 1238eda2d14Spatrick 1248d957e1aSsyl sc->sc_iot = aa->aa_iot; 1258eda2d14Spatrick 126d5df157eSjsg node = fdt_find_node("/"); 127d5df157eSjsg if (node == NULL) 128d5df157eSjsg panic("%s: could not get fdt root node", 129d5df157eSjsg sc->sc_dev.dv_xname); 130d5df157eSjsg 131d5df157eSjsg if (fdt_is_compatible(node, "ti,am33xx")) { 1328eda2d14Spatrick sc->sc_setup = NULL; 1338eda2d14Spatrick sc->sc_enablemodule = prcm_am335x_enablemodule; 1348eda2d14Spatrick sc->sc_setclock = prcm_am335x_setclock; 135d5df157eSjsg } else if (fdt_is_compatible(node, "ti,omap3")) { 1368eda2d14Spatrick sc->sc_setup = prcm_v3_setup; 1378eda2d14Spatrick sc->sc_enablemodule = prcm_v3_enablemodule; 1388eda2d14Spatrick sc->sc_setclock = prcm_v3_setclock; 139d5df157eSjsg } else if (fdt_is_compatible(node, "ti,omap4")) { 1408eda2d14Spatrick sc->sc_setup = NULL; 1418eda2d14Spatrick sc->sc_enablemodule = prcm_v4_enablemodule; 1428eda2d14Spatrick sc->sc_setclock = NULL; 1438eda2d14Spatrick sc->cm1_avail = 1; 1448eda2d14Spatrick sc->cm2_avail = 1; 145d5df157eSjsg } else 146d5df157eSjsg panic("%s: could not find a compatible soc", 147d5df157eSjsg sc->sc_dev.dv_xname); 1488eda2d14Spatrick 1498d957e1aSsyl if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, 1508d957e1aSsyl aa->aa_dev->mem[0].size, 0, &sc->sc_prcm)) 1518eda2d14Spatrick panic("prcm_attach: bus_space_map failed!"); 1528eda2d14Spatrick 1538eda2d14Spatrick if (sc->cm1_avail && 1548d957e1aSsyl bus_space_map(sc->sc_iot, aa->aa_dev->mem[1].addr, 1558d957e1aSsyl aa->aa_dev->mem[1].size, 0, &sc->sc_cm1)) 1568eda2d14Spatrick panic("prcm_attach: bus_space_map failed!"); 1578eda2d14Spatrick 1588eda2d14Spatrick if (sc->cm2_avail && 1598d957e1aSsyl bus_space_map(sc->sc_iot, aa->aa_dev->mem[2].addr, 1608d957e1aSsyl aa->aa_dev->mem[2].size, 0, &sc->sc_cm2)) 1618eda2d14Spatrick panic("prcm_attach: bus_space_map failed!"); 1628eda2d14Spatrick 1638eda2d14Spatrick reg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_REVISION); 1648eda2d14Spatrick printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf); 1658eda2d14Spatrick 166511fd411Sdlg if (sc->sc_setup != NULL) 1678eda2d14Spatrick sc->sc_setup(sc); 1688eda2d14Spatrick } 1698eda2d14Spatrick 1708eda2d14Spatrick void 1718eda2d14Spatrick prcm_v3_setup(struct prcm_softc *sc) 1728eda2d14Spatrick { 1738eda2d14Spatrick /* Setup the 120MHZ DPLL5 clock, to be used by USB. */ 1748eda2d14Spatrick prcm_setup_dpll5(sc); 1758eda2d14Spatrick 1768eda2d14Spatrick prcm_fmask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FMASK; 1778eda2d14Spatrick prcm_imask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IMASK; 1788eda2d14Spatrick prcm_fmask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FADDR; 1798eda2d14Spatrick prcm_imask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IADDR; 1808eda2d14Spatrick 1818eda2d14Spatrick prcm_fmask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FMASK; 1828eda2d14Spatrick prcm_imask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IMASK; 1838eda2d14Spatrick prcm_fmask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FADDR; 1848eda2d14Spatrick prcm_imask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IADDR; 1858eda2d14Spatrick 1868eda2d14Spatrick prcm_fmask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FMASK; 1878eda2d14Spatrick prcm_imask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IMASK; 1888eda2d14Spatrick prcm_fmask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FADDR; 1898eda2d14Spatrick prcm_imask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IADDR; 1908eda2d14Spatrick 1915193e4e0Srapha prcm_fmask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_FMASK; 1925193e4e0Srapha prcm_imask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_IMASK; 1935193e4e0Srapha prcm_fmask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_FADDR; 1945193e4e0Srapha prcm_imask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_IADDR; 1955193e4e0Srapha 1965193e4e0Srapha prcm_fmask_mask[PRCM_REG_PER] = PRCM_REG_PER_FMASK; 1975193e4e0Srapha prcm_imask_mask[PRCM_REG_PER] = PRCM_REG_PER_IMASK; 1985193e4e0Srapha prcm_fmask_addr[PRCM_REG_PER] = PRCM_REG_PER_FADDR; 1995193e4e0Srapha prcm_imask_addr[PRCM_REG_PER] = PRCM_REG_PER_IADDR; 2005193e4e0Srapha 2018eda2d14Spatrick prcm_fmask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FMASK; 2028eda2d14Spatrick prcm_imask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IMASK; 2038eda2d14Spatrick prcm_fmask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FADDR; 2048eda2d14Spatrick prcm_imask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IADDR; 2058eda2d14Spatrick } 2068eda2d14Spatrick 2078eda2d14Spatrick void 2088eda2d14Spatrick prcm_setclock(int clock, int speed) 2098eda2d14Spatrick { 2108eda2d14Spatrick struct prcm_softc *sc = prcm_cd.cd_devs[0]; 2118eda2d14Spatrick 2128eda2d14Spatrick if (!sc->sc_setclock) 2138eda2d14Spatrick panic("%s: not initialised!", __func__); 2148eda2d14Spatrick 2158eda2d14Spatrick sc->sc_setclock(sc, clock, speed); 2168eda2d14Spatrick } 2178eda2d14Spatrick 2188eda2d14Spatrick void 2198eda2d14Spatrick prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed) 2208eda2d14Spatrick { 2218eda2d14Spatrick u_int32_t oreg, reg, mask; 2228eda2d14Spatrick 2238eda2d14Spatrick /* set CLKSEL register */ 2248eda2d14Spatrick if (clock == 1) { 2258eda2d14Spatrick oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 2268eda2d14Spatrick PRCM_AM335X_CLKSEL_TIMER2_CLK); 2278eda2d14Spatrick mask = 3; 2288eda2d14Spatrick reg = oreg & ~mask; 2298eda2d14Spatrick reg |=0x02; 2308eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, 2318eda2d14Spatrick PRCM_AM335X_CLKSEL_TIMER2_CLK, reg); 2328eda2d14Spatrick } else if (clock == 2) { 2338eda2d14Spatrick oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 2348eda2d14Spatrick PRCM_AM335X_CLKSEL_TIMER3_CLK); 2358eda2d14Spatrick mask = 3; 2368eda2d14Spatrick reg = oreg & ~mask; 2378eda2d14Spatrick reg |=0x02; 2388eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, 2398eda2d14Spatrick PRCM_AM335X_CLKSEL_TIMER3_CLK, reg); 2402b401c1dSians } else if (clock == 3) { /* DISP M1 */ 2412b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 2422b401c1dSians oreg &= ~0x7; 2432b401c1dSians oreg |= 0x4; 2442b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 2452b401c1dSians while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 2462b401c1dSians & 0x10))); 2472b401c1dSians 2482b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL); 2492b401c1dSians oreg &= 0xFFF800FF; 2502b401c1dSians oreg |= (speed & 0x7FF) << 8; 2512b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL, oreg); 2522b401c1dSians 2532b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 2542b401c1dSians oreg |= 0x7; 2552b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 2562b401c1dSians while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 2572b401c1dSians & 0x10))); 2582b401c1dSians } else if (clock == 4) { /* DISP N */ 2592b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 2602b401c1dSians oreg &= ~0x7; 2612b401c1dSians oreg |= 0x4; 2622b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 2632b401c1dSians while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 2642b401c1dSians & 0x10))); 2652b401c1dSians 2662b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL); 2672b401c1dSians oreg &= 0xFFFFFF80; 2682b401c1dSians oreg |= speed & 0x7F; 2692b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL, oreg); 2702b401c1dSians 2712b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE); 2722b401c1dSians oreg |= 0x7; 2732b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, oreg); 2742b401c1dSians while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_IDLEST 2752b401c1dSians & 0x10))); 2762b401c1dSians } else if (clock == 5) { /* DISP M2 */ 2772b401c1dSians oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_M2); 2782b401c1dSians oreg &= ~(0x1F); 2792b401c1dSians oreg |= speed & 0x1F; 2802b401c1dSians bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_M2, oreg); 2818eda2d14Spatrick } 2828eda2d14Spatrick } 2838eda2d14Spatrick 2848eda2d14Spatrick void 2858eda2d14Spatrick prcm_v3_setclock(struct prcm_softc *sc, int clock, int speed) 2868eda2d14Spatrick { 2878eda2d14Spatrick u_int32_t oreg, reg, mask; 2888eda2d14Spatrick 2898eda2d14Spatrick if (clock == 1) { 2908eda2d14Spatrick oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP); 2918eda2d14Spatrick mask = 1; 2928eda2d14Spatrick reg = (oreg &~mask) | (speed & mask); 2938eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP, reg); 2948eda2d14Spatrick } else if (clock >= 2 && clock <= 9) { 2958eda2d14Spatrick int shift = (clock-2); 2968eda2d14Spatrick oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER); 2978eda2d14Spatrick mask = 1 << (shift); 2988eda2d14Spatrick reg = (oreg & ~mask) | ( (speed << shift) & mask); 2998eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER, reg); 3008eda2d14Spatrick } else 3018eda2d14Spatrick panic("%s: invalid clock %d", __func__, clock); 3028eda2d14Spatrick } 3038eda2d14Spatrick 3048eda2d14Spatrick uint32_t 3058eda2d14Spatrick prcm_v3_bit(int mod) 3068eda2d14Spatrick { 3078eda2d14Spatrick switch(mod) { 3084d9eaee2Ssyl case PRCM_MMC0: 3098eda2d14Spatrick return PRCM_CLK_EN_MMC1; 3104d9eaee2Ssyl case PRCM_MMC1: 3114d9eaee2Ssyl return PRCM_CLK_EN_MMC2; 3124d9eaee2Ssyl case PRCM_MMC2: 3134d9eaee2Ssyl return PRCM_CLK_EN_MMC3; 3148eda2d14Spatrick case PRCM_USB: 3158eda2d14Spatrick return PRCM_CLK_EN_USB; 3165193e4e0Srapha case PRCM_GPIO0: 3175193e4e0Srapha return PRCM_CLK_EN_GPIO1; 3185193e4e0Srapha case PRCM_GPIO1: 3195193e4e0Srapha return PRCM_CLK_EN_GPIO2; 3205193e4e0Srapha case PRCM_GPIO2: 3215193e4e0Srapha return PRCM_CLK_EN_GPIO3; 3225193e4e0Srapha case PRCM_GPIO3: 3235193e4e0Srapha return PRCM_CLK_EN_GPIO4; 3245193e4e0Srapha case PRCM_GPIO4: 3255193e4e0Srapha return PRCM_CLK_EN_GPIO5; 3265193e4e0Srapha case PRCM_GPIO5: 3275193e4e0Srapha return PRCM_CLK_EN_GPIO6; 328a7c7ce51Sjsg case PRCM_I2C0: 329a7c7ce51Sjsg return PRCM_CLK_EN_I2C1; 330a7c7ce51Sjsg case PRCM_I2C1: 331a7c7ce51Sjsg return PRCM_CLK_EN_I2C2; 332a7c7ce51Sjsg case PRCM_I2C2: 333a7c7ce51Sjsg return PRCM_CLK_EN_I2C3; 3348eda2d14Spatrick default: 3354123b6a7Sderaadt panic("%s: module not found", __func__); 3368eda2d14Spatrick } 3378eda2d14Spatrick } 3388eda2d14Spatrick 3398eda2d14Spatrick uint32_t 3408eda2d14Spatrick prcm_am335x_clkctrl(int mod) 3418eda2d14Spatrick { 3428eda2d14Spatrick switch(mod) { 3438eda2d14Spatrick case PRCM_TIMER2: 3448eda2d14Spatrick return PRCM_AM335X_TIMER2_CLKCTRL; 3458eda2d14Spatrick case PRCM_TIMER3: 3468eda2d14Spatrick return PRCM_AM335X_TIMER3_CLKCTRL; 3474d9eaee2Ssyl case PRCM_MMC0: 3488eda2d14Spatrick return PRCM_AM335X_MMC0_CLKCTRL; 3494d9eaee2Ssyl case PRCM_MMC1: 3504d9eaee2Ssyl return PRCM_AM335X_MMC1_CLKCTRL; 3514d9eaee2Ssyl case PRCM_MMC2: 3524d9eaee2Ssyl return PRCM_AM335X_MMC2_CLKCTRL; 3538eda2d14Spatrick case PRCM_USB: 3548eda2d14Spatrick return PRCM_AM335X_USB0_CLKCTRL; 3555193e4e0Srapha case PRCM_GPIO0: 3565193e4e0Srapha return PRCM_AM335X_GPIO0_CLKCTRL; 3575193e4e0Srapha case PRCM_GPIO1: 3585193e4e0Srapha return PRCM_AM335X_GPIO1_CLKCTRL; 3595193e4e0Srapha case PRCM_GPIO2: 3605193e4e0Srapha return PRCM_AM335X_GPIO2_CLKCTRL; 3615193e4e0Srapha case PRCM_GPIO3: 3625193e4e0Srapha return PRCM_AM335X_GPIO3_CLKCTRL; 363e02a18b3Ssyl case PRCM_TPCC: 364e02a18b3Ssyl return PRCM_AM335X_TPCC_CLKCTRL; 365e02a18b3Ssyl case PRCM_TPTC0: 366e02a18b3Ssyl return PRCM_AM335X_TPTC0_CLKCTRL; 367e02a18b3Ssyl case PRCM_TPTC1: 368e02a18b3Ssyl return PRCM_AM335X_TPTC1_CLKCTRL; 369e02a18b3Ssyl case PRCM_TPTC2: 370e02a18b3Ssyl return PRCM_AM335X_TPTC2_CLKCTRL; 3716b4d768cSsyl case PRCM_I2C0: 3726b4d768cSsyl return PRCM_AM335X_I2C0_CLKCTRL; 3736b4d768cSsyl case PRCM_I2C1: 3746b4d768cSsyl return PRCM_AM335X_I2C1_CLKCTRL; 3756b4d768cSsyl case PRCM_I2C2: 3766b4d768cSsyl return PRCM_AM335X_I2C2_CLKCTRL; 3772b401c1dSians case PRCM_LCDC: 3782b401c1dSians return PRCM_AM335X_LCDC_CLKCTRL; 37959b39244Skettenis case PRCM_RNG: 38059b39244Skettenis return PRCM_AM335X_RNG_CLKCTRL; 3818eda2d14Spatrick default: 3824123b6a7Sderaadt panic("%s: module not found", __func__); 3838eda2d14Spatrick } 3848eda2d14Spatrick } 3858eda2d14Spatrick 3868eda2d14Spatrick void 3878eda2d14Spatrick prcm_enablemodule(int mod) 3888eda2d14Spatrick { 3898eda2d14Spatrick struct prcm_softc *sc = prcm_cd.cd_devs[0]; 3908eda2d14Spatrick 3918eda2d14Spatrick if (!sc->sc_enablemodule) 3928eda2d14Spatrick panic("%s: not initialised!", __func__); 3938eda2d14Spatrick 3948eda2d14Spatrick sc->sc_enablemodule(sc, mod); 3958eda2d14Spatrick } 3968eda2d14Spatrick 3978eda2d14Spatrick void 3988eda2d14Spatrick prcm_am335x_enablemodule(struct prcm_softc *sc, int mod) 3998eda2d14Spatrick { 4008eda2d14Spatrick uint32_t clkctrl; 4018eda2d14Spatrick int reg; 4028eda2d14Spatrick 4038eda2d14Spatrick /*set enable bits in CLKCTRL register */ 4048eda2d14Spatrick reg = prcm_am335x_clkctrl(mod); 4058eda2d14Spatrick clkctrl = bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg); 4068eda2d14Spatrick clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK; 4078eda2d14Spatrick clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE; 4088eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, reg, clkctrl); 4098eda2d14Spatrick 4108eda2d14Spatrick /* wait until module is enabled */ 4118eda2d14Spatrick while (bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg) & 0x30000) 4128eda2d14Spatrick ; 4138eda2d14Spatrick } 4148eda2d14Spatrick 4158eda2d14Spatrick void 4168eda2d14Spatrick prcm_v3_enablemodule(struct prcm_softc *sc, int mod) 4178eda2d14Spatrick { 4188eda2d14Spatrick uint32_t bit; 4198eda2d14Spatrick uint32_t fclk, iclk, fmask, imask, mbit; 4208eda2d14Spatrick int freg, ireg, reg; 4218eda2d14Spatrick 4228eda2d14Spatrick bit = prcm_v3_bit(mod); 4238eda2d14Spatrick reg = bit >> 5; 4248eda2d14Spatrick 4258eda2d14Spatrick freg = prcm_fmask_addr[reg]; 4268eda2d14Spatrick ireg = prcm_imask_addr[reg]; 4278eda2d14Spatrick fmask = prcm_fmask_mask[reg]; 4288eda2d14Spatrick imask = prcm_imask_mask[reg]; 4298eda2d14Spatrick 4308eda2d14Spatrick mbit = 1 << (bit & 0x1f); 4318eda2d14Spatrick if (fmask & mbit) { /* dont access the register if bit isn't present */ 4328eda2d14Spatrick fclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, freg); 4338eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, freg, fclk | mbit); 4348eda2d14Spatrick } 4358eda2d14Spatrick if (imask & mbit) { /* dont access the register if bit isn't present */ 4368eda2d14Spatrick iclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, ireg); 4378eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, ireg, iclk | mbit); 4388eda2d14Spatrick } 4398eda2d14Spatrick printf("\n"); 4408eda2d14Spatrick } 4418eda2d14Spatrick 4428eda2d14Spatrick void 4438eda2d14Spatrick prcm_v4_enablemodule(struct prcm_softc *sc, int mod) 4448eda2d14Spatrick { 4458eda2d14Spatrick switch (mod) { 446ef92a366Ssyl case PRCM_MMC0: 447a7c7ce51Sjsg case PRCM_MMC1: 448a7c7ce51Sjsg case PRCM_MMC2: 449a7c7ce51Sjsg case PRCM_MMC3: 450a7c7ce51Sjsg case PRCM_MMC4: 451ef92a366Ssyl break; 4528eda2d14Spatrick case PRCM_USBP1_PHY: 4538eda2d14Spatrick case PRCM_USBP2_PHY: 4548eda2d14Spatrick prcm_v4_hsusbhost_set_source(mod, 0); 4558eda2d14Spatrick case PRCM_USB: 4568eda2d14Spatrick case PRCM_USBTLL: 4578eda2d14Spatrick case PRCM_USBP1_UTMI: 4588eda2d14Spatrick case PRCM_USBP1_HSIC: 4598eda2d14Spatrick case PRCM_USBP2_UTMI: 4608eda2d14Spatrick case PRCM_USBP2_HSIC: 4618eda2d14Spatrick prcm_v4_hsusbhost_activate(mod); 4628eda2d14Spatrick return; 4635193e4e0Srapha case PRCM_GPIO0: 4645193e4e0Srapha case PRCM_GPIO1: 4655193e4e0Srapha case PRCM_GPIO2: 4665193e4e0Srapha case PRCM_GPIO3: 4675193e4e0Srapha case PRCM_GPIO4: 4685193e4e0Srapha case PRCM_GPIO5: 4695193e4e0Srapha /* XXX */ 4705193e4e0Srapha break; 471a7c7ce51Sjsg case PRCM_I2C0: 472a7c7ce51Sjsg case PRCM_I2C1: 473a7c7ce51Sjsg case PRCM_I2C2: 474a7c7ce51Sjsg case PRCM_I2C3: 475a7c7ce51Sjsg /* XXX */ 476a7c7ce51Sjsg break; 4778eda2d14Spatrick default: 4784123b6a7Sderaadt panic("%s: module not found", __func__); 4798eda2d14Spatrick } 4808eda2d14Spatrick } 4818eda2d14Spatrick 4828eda2d14Spatrick int 4838eda2d14Spatrick prcm_v4_hsusbhost_activate(int type) 4848eda2d14Spatrick { 4858eda2d14Spatrick struct prcm_softc *sc = prcm_cd.cd_devs[0]; 4868eda2d14Spatrick uint32_t i; 4878eda2d14Spatrick uint32_t clksel_reg_off; 4888eda2d14Spatrick uint32_t clksel, oclksel; 4898eda2d14Spatrick 4908eda2d14Spatrick switch (type) { 4918eda2d14Spatrick case PRCM_USB: 4928eda2d14Spatrick case PRCM_USBP1_PHY: 4938eda2d14Spatrick case PRCM_USBP2_PHY: 4948eda2d14Spatrick /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 4958eda2d14Spatrick clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58; 4968eda2d14Spatrick clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 4978eda2d14Spatrick oclksel = clksel; 4988eda2d14Spatrick /* Enable the module and also enable the optional func clocks */ 4998eda2d14Spatrick if (type == PRCM_USB) { 5008eda2d14Spatrick clksel &= ~O4_CLKCTRL_MODULEMODE_MASK; 5018eda2d14Spatrick clksel |= /*O4_CLKCTRL_MODULEMODE_ENABLE*/2; 5028eda2d14Spatrick 5038eda2d14Spatrick clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */ 5048eda2d14Spatrick } 5058eda2d14Spatrick 5068eda2d14Spatrick break; 5078eda2d14Spatrick 5088eda2d14Spatrick default: 509ddb53a58Smiod panic("%s: invalid type %d", __func__, type); 5108eda2d14Spatrick return (EINVAL); 5118eda2d14Spatrick } 5128eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel); 5138eda2d14Spatrick 5148eda2d14Spatrick /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */ 5158eda2d14Spatrick for (i = 0; i < O4_MAX_MODULE_ENABLE_WAIT; i++) { 5168eda2d14Spatrick clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 5178eda2d14Spatrick if ((clksel & O4_CLKCTRL_IDLEST_MASK) == O4_CLKCTRL_IDLEST_ENABLED) 5188eda2d14Spatrick break; 5198eda2d14Spatrick } 5208eda2d14Spatrick 5218eda2d14Spatrick /* Check the enabled state */ 5228eda2d14Spatrick if ((clksel & O4_CLKCTRL_IDLEST_MASK) != O4_CLKCTRL_IDLEST_ENABLED) { 5238eda2d14Spatrick printf("Error: HERE failed to enable module with clock %d\n", type); 5248eda2d14Spatrick printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel); 5258eda2d14Spatrick return (ETIMEDOUT); 5268eda2d14Spatrick } 5278eda2d14Spatrick 5288eda2d14Spatrick return (0); 5298eda2d14Spatrick } 5308eda2d14Spatrick 5318eda2d14Spatrick int 5328eda2d14Spatrick prcm_v4_hsusbhost_set_source(int clk, int clksrc) 5338eda2d14Spatrick { 5348eda2d14Spatrick struct prcm_softc *sc = prcm_cd.cd_devs[0]; 5358eda2d14Spatrick uint32_t clksel_reg_off; 5368eda2d14Spatrick uint32_t clksel; 5378eda2d14Spatrick unsigned int bit; 5388eda2d14Spatrick 5398eda2d14Spatrick if (clk == PRCM_USBP1_PHY) 5408eda2d14Spatrick bit = 24; 5418eda2d14Spatrick else if (clk != PRCM_USBP2_PHY) 5428eda2d14Spatrick bit = 25; 5438eda2d14Spatrick else 5448eda2d14Spatrick return (-EINVAL); 5458eda2d14Spatrick 5468eda2d14Spatrick /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 5478eda2d14Spatrick clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58; 5488eda2d14Spatrick clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off); 5498eda2d14Spatrick 5508eda2d14Spatrick /* XXX: Set the clock source to either external or internal */ 5518eda2d14Spatrick if (clksrc == 0) 5528eda2d14Spatrick clksel |= (0x1 << bit); 5538eda2d14Spatrick else 5548eda2d14Spatrick clksel &= ~(0x1 << bit); 5558eda2d14Spatrick 5568eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel); 5578eda2d14Spatrick 5588eda2d14Spatrick return (0); 5598eda2d14Spatrick } 5608eda2d14Spatrick 5618eda2d14Spatrick /* 5628eda2d14Spatrick * OMAP35xx Power, Reset, and Clock Management Reference Guide 5638eda2d14Spatrick * (sprufa5.pdf) and AM/DM37x Multimedia Device Technical Reference 5648eda2d14Spatrick * Manual (sprugn4h.pdf) note that DPLL5 provides a 120MHz clock for 5658eda2d14Spatrick * peripheral domain modules (page 107 and page 302). 5668eda2d14Spatrick * The reference clock for DPLL5 is DPLL5_ALWON_FCLK which is 5678eda2d14Spatrick * SYS_CLK, running at 13MHz. 5688eda2d14Spatrick */ 5698eda2d14Spatrick int 5708eda2d14Spatrick prcm_setup_dpll5(struct prcm_softc *sc) 5718eda2d14Spatrick { 5728eda2d14Spatrick uint32_t val; 5738eda2d14Spatrick 5748eda2d14Spatrick /* 5758eda2d14Spatrick * We need to set the multiplier and divider values for PLL. 5768eda2d14Spatrick * To end up with 120MHz we take SYS_CLK, divide by it and multiply 5778eda2d14Spatrick * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration) 5788eda2d14Spatrick */ 5798eda2d14Spatrick val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f); 5808eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL4_PLL, val); 5818eda2d14Spatrick 5828eda2d14Spatrick /* Clock divider from the PLL to the 120MHz clock. */ 5838eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL5_PLL, val); 5848eda2d14Spatrick 5858eda2d14Spatrick /* 5868eda2d14Spatrick * spruf98o.pdf, page 2319: 5878eda2d14Spatrick * PERIPH2_DPLL_FREQSEL is 0x7 1.75MHz to 2.1MHz 5888eda2d14Spatrick * EN_PERIPH2_DPLL is 0x7 5898eda2d14Spatrick */ 5908eda2d14Spatrick val = (7 << 4) | (7 << 0); 5918eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKEN2_PLL, val); 5928eda2d14Spatrick 5938eda2d14Spatrick /* Disable the interconnect clock auto-idle. */ 5948eda2d14Spatrick bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_AUTOIDLE2_PLL, 0x0); 5958eda2d14Spatrick 5968eda2d14Spatrick /* Wait until DPLL5 is locked and there's clock activity. */ 5978eda2d14Spatrick while ((val = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 5988eda2d14Spatrick CM_IDLEST_CKGEN) & 0x01) == 0x00) { 5998eda2d14Spatrick #ifdef DIAGNOSTIC 6008eda2d14Spatrick printf("CM_IDLEST_PLL = 0x%08x\n", val); 6018eda2d14Spatrick #endif 6028eda2d14Spatrick } 6038eda2d14Spatrick 6048eda2d14Spatrick return 0; 6058eda2d14Spatrick } 606