diff options
Diffstat (limited to 'sys/arch/beagle/dev/prcm.c')
-rw-r--r-- | sys/arch/beagle/dev/prcm.c | 358 |
1 files changed, 170 insertions, 188 deletions
diff --git a/sys/arch/beagle/dev/prcm.c b/sys/arch/beagle/dev/prcm.c index 6115304082f..f32c1d5ceee 100644 --- a/sys/arch/beagle/dev/prcm.c +++ b/sys/arch/beagle/dev/prcm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: prcm.c,v 1.10 2013/05/03 17:58:15 patrick Exp $ */ +/* $OpenBSD: prcm.c,v 1.11 2013/05/14 12:01:17 rapha Exp $ */ /* * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> * @@ -32,123 +32,12 @@ #include <beagle/dev/omapvar.h> #include <beagle/dev/prcmvar.h> -#define CM_FCLKEN_IVA2 0x0000 -#define CM_CLKEN_PLL_IVA2 0x0004 -#define CM_IDLEST_IVA2 0x0020 -#define CM_IDLEST_PLL_IVA2 0x0024 -#define CM_AUTOIDLE_PLL_IVA2 0x0034 -#define CM_CLKSEL1_PLL_IVA2 0x0040 -#define CM_CLKSEL2_PLL_IVA2 0x0044 -#define CM_CLKSTCTRL_IVA2 0x0048 -#define CM_CLKSTST_IVA2 0x004c +#include <beagle/dev/am335x_prcmreg.h> +#include <beagle/dev/omap3_prcmreg.h> #define PRCM_REVISION 0x0800 #define PRCM_SYSCONFIG 0x0810 -#define CM_CLKSEL_MPU 0x0940 -#define CM_CLKSTCTRL_MPU 0x0948 -#define RM_RSTST_MPU 0x0958 -#define PM_WKDEP_MPU 0x09C8 -#define PM_EVGENCTRL_MPU 0x09D4 -#define PM_EVEGENONTIM_MPU 0x09D8 -#define PM_EVEGENOFFTIM_MPU 0x09DC -#define PM_PWSTCTRL_MPU 0x09E0 -#define PM_PWSTST_MPU 0x09E4 - -#define CM_ICLKEN1_CORE 0x0a10 -#define CM_ICLKEN1_CORE_MSK 0x7ffffed2 -#define CM_ICLKEN2_CORE 0x0a14 -#define CM_ICLKEN2_CORE_MSK 0x0000001f -#define CM_ICLKEN3_CORE 0x0a18 -#define CM_ICLKEN3_CORE_MSK 0x00000004 -#define CM_ICLKEN4_CORE 0x0a1C -#define CM_IDLEST1_CORE 0x0a20 -#define CM_IDLEST2_CORE 0x0a24 -#define CM_IDLEST4_CORE 0x0a2C -#define CM_AUTOIDLE1_CORE 0x0a30 -#define CM_AUTOIDLE2_CORE 0x0a34 -#define CM_AUTOIDLE3_CORE 0x0a38 -#define CM_AUTOIDLE4_CORE 0x0a3C -#define CM_CLKSEL1_CORE 0x0a40 -#define CM_CLKSEL2_CORE 0x0a44 -#define CM_CLKSTCTRL_CORE 0x0a48 -#define PM_WKEN1_CORE 0x0aA0 -#define PM_WKEN2_CORE 0x0aA4 -#define PM_WKST1_CORE 0x0aB0 -#define PM_WKST2_CORE 0x0aB4 -#define PM_WKDEP_CORE 0x0aC8 -#define PM_PWSTCTRL_CORE 0x0aE0 -#define PM_PWSTST_CORE 0x0aE4 -#define CM_FCLKEN_GFX 0x0b00 -#define CM_ICLKEN_GFX 0x0b10 - -#define CM_IDLEST_GFX 0x0b20 -#define CM_CLKSEL_GFX 0x0b40 -#define CM_CLKSTCTRL_GFX 0x0b48 -#define RM_RSTCTRL_GFX 0x0b50 -#define RM_RSTST_GFX 0x0b58 -#define PM_WKDEP_GFX 0x0bC8 -#define PM_PWSTCTRL_GFX 0x0bE0 -#define PM_PWSTST_GFX 0x0bE4 -#define CM_FCLKEN_WKUP 0x0c00 -#define CM_FCLKEN_WKUP_GPT1 1 -#define CM_FCLKEN_WKUP_GPIOS 4 -#define CM_FCLKEN_WKUP_MPU_WDT 8 -#define CM_ICLKEN_WKUP 0xc10 -#define CM_ICLKEN_WKUP_GPT1 0x01 -#define CM_ICLKEN_WKUP_32KSYNC 0x02 -#define CM_ICLKEN_WKUP_GPIOS 0x04 -#define CM_ICLKEN_WKUP_MPU_WDT 0x08 -#define CM_ICLKEN_WKUP_WDT1 0x10 -#define CM_ICLKEN_WKUP_OMAPCTRL 0x20 -#define CM_IDLEST_WKUP 0x0c20 -#define CM_AUTOIDLE_WKUP 0x0c30 -#define CM_CLKSEL_WKUP 0x0c40 -#define RM_RSTCTRL_WKUP 0x0c50 -#define RM_RSTTIME_WKUP 0x0c54 -#define RM_RSTST_WKUP 0x0c58 -#define PM_WKEN_WKUP 0x0cA0 -#define PM_WKST_WKUP 0x0cB0 -#define CM_CLKEN_PLL 0x0d00 -#define CM_CLKEN2_PLL 0x0d04 -#define CM_IDLEST_CKGEN 0x0d20 -#define CM_AUTOIDLE_PLL 0x0d30 -#define CM_AUTOIDLE2_PLL 0x0d34 -#define CM_CLKSEL1_PLL 0x0d40 -#define CM_CLKSEL2_PLL 0x0d44 -#define CM_CLKSEL3_PLL 0x0d48 -#define CM_CLKSEL4_PLL 0x0d4C -#define CM_CLKSEL5_PLL 0x0d50 -#define CM_FCLKEN_PER 0x1000 -#define CM_ICLKEN_PER 0x1010 -#define CM_IDLEST_PER 0x1020 -#define CM_AUTOIDLE_PER 0x1030 -#define CM_CLKSEL_PER 0x1040 -#define CM_SLEEPDEP_PER 0x1044 -#define CM_CLKSTCTRL_PER 0x1048 -#define CM_CLKSTST_PER 0x104C - -#define CM_CLKSEL1_EMU 0x5140 -#define CM_CLKSTCTRL_EMU 0x5148 -#define CM_CLKSTST_EMU 0x514C -#define CM_CLKSEL2_EMU 0x5150 -#define CM_CLKSEL3_EMU 0x5154 - -#define CM_POLCTRL 0x529C - -#define CM_IDLEST_NEON 0x5320 -#define CM_CLKSTCTRL_NEON 0x5348 - -#define CM_FCLKEN_USBHOST 0x5400 -#define CM_ICLKEN_USBHOST 0x5410 -#define CM_IDLEST_USBHOST 0x5420 -#define CM_AUTOIDLE_USBHOST 0x5430 -#define CM_SLEEPDEP_USBHOST 0x5444 -#define CM_CLKSTCTRL_USBHOST 0x5448 -#define CM_CLKSTST_USBHOST 0x544C - -uint32_t prcm_imask_cur[PRCM_REG_MAX]; -uint32_t prcm_fmask_cur[PRCM_REG_MAX]; uint32_t prcm_imask_mask[PRCM_REG_MAX]; uint32_t prcm_fmask_mask[PRCM_REG_MAX]; uint32_t prcm_imask_addr[PRCM_REG_MAX]; @@ -156,15 +45,30 @@ uint32_t prcm_fmask_addr[PRCM_REG_MAX]; #define SYS_CLK 13 /* SYS_CLK speed in MHz */ -bus_space_tag_t prcm_iot; -bus_space_handle_t prcm_ioh; +struct prcm_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + void (*sc_enablemodule)(struct prcm_softc *sc, int mod); + void (*sc_setclock)(struct prcm_softc *sc, + int clock, int speed); +}; + +int prcm_match(struct device *, void *, void *); +void prcm_attach(struct device *, struct device *, void *); +int prcm_setup_dpll5(struct prcm_softc *); +uint32_t prcm_v3_bit(int mod); +uint32_t prcm_am335x_clkctrl(int mod); -int prcm_match(struct device *, void *, void *); -void prcm_attach(struct device *, struct device *, void *); -int prcm_setup_dpll5(void); +void prcm_am335x_enablemodule(struct prcm_softc *, int); +void prcm_am335x_setclock(struct prcm_softc *, int, int); + +void prcm_v3_setup(struct prcm_softc *); +void prcm_v3_enablemodule(struct prcm_softc *, int); +void prcm_v3_setclock(struct prcm_softc *, int, int); struct cfattach prcm_ca = { - sizeof (struct device), NULL, prcm_attach + sizeof (struct prcm_softc), NULL, prcm_attach }; struct cfdriver prcm_cd = { @@ -175,47 +79,42 @@ void prcm_attach(struct device *parent, struct device *self, void *args) { struct omap_attach_args *oa = args; + struct prcm_softc *sc = (struct prcm_softc *) self; u_int32_t reg; - prcm_iot = oa->oa_iot; + sc->sc_iot = oa->oa_iot; - if (bus_space_map(prcm_iot, oa->oa_dev->mem[0].addr, - oa->oa_dev->mem[0].size, 0, &prcm_ioh)) + if (bus_space_map(sc->sc_iot, oa->oa_dev->mem[0].addr, + oa->oa_dev->mem[0].size, 0, &sc->sc_ioh)) panic("prcm_attach: bus_space_map failed!"); - reg = bus_space_read_4(prcm_iot, prcm_ioh, PRCM_REVISION); + reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PRCM_REVISION); printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf); - - /* Setup the 120MHZ DPLL5 clock, to be used by USB. */ - prcm_setup_dpll5(); - /* XXX */ -#if 1 - printf("CM_FCLKEN1_CORE %x\n", bus_space_read_4(prcm_iot, prcm_ioh, CM_FCLKEN1_CORE)); - printf("CM_ICLKEN1_CORE %x\n", bus_space_read_4(prcm_iot, prcm_ioh, CM_ICLKEN1_CORE)); - printf("CM_AUTOIDLE1_CORE %x\n", bus_space_read_4(prcm_iot, prcm_ioh, CM_AUTOIDLE1_CORE)); + switch (board_id) { + case BOARD_ID_AM335X_BEAGLEBONE: + sc->sc_enablemodule = prcm_am335x_enablemodule; + sc->sc_setclock = prcm_am335x_setclock; + break; + case BOARD_ID_OMAP3_BEAGLE: + case BOARD_ID_OMAP3_OVERO: + sc->sc_enablemodule = prcm_v3_enablemodule; + sc->sc_setclock = prcm_v3_setclock; + prcm_v3_setup(sc); + break; + case BOARD_ID_OMAP4_PANDA: + sc->sc_enablemodule = NULL; + sc->sc_setclock = NULL; + break; + } +} - printf("CM_FCLKEN_WKUP %x\n", bus_space_read_4(prcm_iot, prcm_ioh, CM_FCLKEN_WKUP)); - printf(" CM_IDLEST_WKUP %x\n", bus_space_read_4(prcm_iot, prcm_ioh, CM_IDLEST_WKUP)); -// bus_space_write_4(prcm_iot, prcm_ioh, -#endif +void +prcm_v3_setup(struct prcm_softc *sc) +{ + /* Setup the 120MHZ DPLL5 clock, to be used by USB. */ + prcm_setup_dpll5(sc); -#if 0 - reg = bus_space_read_4(prcm_iot, prcm_ioh, CM_FCLKEN1_CORE); - reg |= CM_FCLKEN1_CORE_GP3|CM_FCLKEN1_CORE_GP2; - bus_space_write_4(prcm_iot, prcm_ioh, CM_FCLKEN1_CORE, reg); - reg = bus_space_read_4(prcm_iot, prcm_ioh, CM_ICLKEN1_CORE); - reg |= CM_ICLKEN1_CORE_GP3|CM_ICLKEN1_CORE_GP2; - bus_space_write_4(prcm_iot, prcm_ioh, CM_ICLKEN1_CORE, reg); - - reg = bus_space_read_4(prcm_iot, prcm_ioh, CM_FCLKEN_WKUP); - reg |= CM_FCLKEN_WKUP_MPU_WDT | CM_FCLKEN_WKUP_GPT1; - bus_space_write_4(prcm_iot, prcm_ioh, CM_FCLKEN_WKUP, reg); - - reg = bus_space_read_4(prcm_iot, prcm_ioh, CM_ICLKEN_WKUP); - reg |= CM_ICLKEN_WKUP_MPU_WDT | CM_ICLKEN_WKUP_GPT1; - bus_space_write_4(prcm_iot, prcm_ioh, CM_ICLKEN_WKUP, reg); -#endif prcm_fmask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FMASK; prcm_imask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IMASK; prcm_fmask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FADDR; @@ -235,41 +134,133 @@ prcm_attach(struct device *parent, struct device *self, void *args) prcm_imask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IMASK; prcm_fmask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FADDR; prcm_imask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IADDR; - } void prcm_setclock(int clock, int speed) { -#if 1 + struct prcm_softc *sc = prcm_cd.cd_devs[0]; + + if (!sc->sc_setclock) + panic("%s: not initialised!", __func__); + + sc->sc_setclock(sc, clock, speed); +} + +void +prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed) +{ + u_int32_t oreg, reg, mask; + + /* set CLKSEL register */ + if (clock == 1) { + oreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PRCM_AM335X_CLKSEL_TIMER2_CLK); + mask = 3; + reg = oreg & ~mask; + reg |=0x02; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + PRCM_AM335X_CLKSEL_TIMER2_CLK, reg); + } else if (clock == 2) { + oreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PRCM_AM335X_CLKSEL_TIMER3_CLK); + mask = 3; + reg = oreg & ~mask; + reg |=0x02; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + PRCM_AM335X_CLKSEL_TIMER3_CLK, reg); + } +} + +void +prcm_v3_setclock(struct prcm_softc *sc, int clock, int speed) +{ u_int32_t oreg, reg, mask; + if (clock == 1) { - oreg = bus_space_read_4(prcm_iot, prcm_ioh, CM_CLKSEL_WKUP); + oreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CM_CLKSEL_WKUP); mask = 1; reg = (oreg &~mask) | (speed & mask); - printf(" prcm_setclock old %08x new %08x", oreg, reg ); - bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL_WKUP, reg); + printf("%s: old %08x new %08x", __func__, oreg, reg); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CM_CLKSEL_WKUP, reg); } else if (clock >= 2 && clock <= 9) { int shift = (clock-2); - oreg = bus_space_read_4(prcm_iot, prcm_ioh, CM_CLKSEL_PER); - + oreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CM_CLKSEL_PER); mask = 1 << (shift); reg = (oreg & ~mask) | ( (speed << shift) & mask); - printf(" prcm_setclock old %08x new %08x", oreg, reg); - - bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL_PER, reg); + printf("%s: old %08x new %08x", __func__, oreg, reg); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CM_CLKSEL_PER, reg); } else - panic("prcm_setclock invalid clock %d", clock); -#endif + panic("%s: invalid clock %d", __func__, clock); +} + +uint32_t +prcm_v3_bit(int mod) +{ + switch(mod) { + case PRCM_MMC: + return PRCM_CLK_EN_MMC1; + case PRCM_USB: + return PRCM_CLK_EN_USB; + default: + panic("%s: module not found\n", __func__); + } +} + +uint32_t +prcm_am335x_clkctrl(int mod) +{ + switch(mod) { + case PRCM_TIMER2: + return PRCM_AM335X_TIMER2_CLKCTRL; + case PRCM_TIMER3: + return PRCM_AM335X_TIMER3_CLKCTRL; + case PRCM_MMC: + return PRCM_AM335X_MMC0_CLKCTRL; + case PRCM_USB: + return PRCM_AM335X_USB0_CLKCTRL; + default: + panic("%s: module not found\n", __func__); + } } void -prcm_enableclock(int bit) +prcm_enablemodule(int mod) { - u_int32_t fclk, iclk, fmask, imask, mbit; + struct prcm_softc *sc = prcm_cd.cd_devs[0]; + + if (!sc->sc_enablemodule) + panic("%s: not initialised!", __func__); + + sc->sc_enablemodule(sc, mod); +} + +void +prcm_am335x_enablemodule(struct prcm_softc *sc, int mod) +{ + uint32_t clkctrl; + int reg; + + /*set enable bits in CLKCTRL register */ + reg = prcm_am335x_clkctrl(mod); + clkctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg); + clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK; + clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, clkctrl); + + /* wait until module is enabled */ + while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg) & 0x30000) + ; +} + +void +prcm_v3_enablemodule(struct prcm_softc *sc, int mod) +{ + uint32_t bit; + uint32_t fclk, iclk, fmask, imask, mbit; int freg, ireg, reg; - printf("prcm_enableclock %d:", bit); + bit = prcm_v3_bit(mod); reg = bit >> 5; freg = prcm_fmask_addr[reg]; @@ -277,25 +268,16 @@ prcm_enableclock(int bit) fmask = prcm_fmask_mask[reg]; imask = prcm_imask_mask[reg]; - mbit = 1 << (bit & 0x1f); -#if 0 - printf("reg %d faddr 0x%08x iaddr 0x%08x, fmask 0x%08x " - "imask 0x%08x mbit %x", reg, freg, ireg, fmask, imask, mbit); -#endif + mbit = 1 << (bit & 0x1f); if (fmask & mbit) { /* dont access the register if bit isn't present */ - fclk = bus_space_read_4(prcm_iot, prcm_ioh, freg); - prcm_fmask_cur[reg] = fclk | mbit; - bus_space_write_4(prcm_iot, prcm_ioh, freg, fclk | mbit); - printf(" fclk %08x %08x", fclk, fclk | mbit); + fclk = bus_space_read_4(sc->sc_iot, sc->sc_ioh, freg); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, freg, fclk | mbit); } - if (imask & mbit) { /* dont access the register if bit isn't present */ - iclk = bus_space_read_4(prcm_iot, prcm_ioh, ireg); - prcm_imask_cur[reg] = iclk | mbit; - bus_space_write_4(prcm_iot, prcm_ioh, ireg, iclk | mbit); - printf(" iclk %08x %08x", iclk, iclk | mbit); + iclk = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ireg); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, ireg, iclk | mbit); } - printf ("\n"); + printf("\n"); } /* @@ -307,7 +289,7 @@ prcm_enableclock(int bit) * SYS_CLK, running at 13MHz. */ int -prcm_setup_dpll5(void) +prcm_setup_dpll5(struct prcm_softc *sc) { uint32_t val; @@ -317,10 +299,10 @@ prcm_setup_dpll5(void) * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration) */ val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f); - bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL4_PLL, val); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CM_CLKSEL4_PLL, val); /* Clock divider from the PLL to the 120MHz clock. */ - bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL5_PLL, val); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CM_CLKSEL5_PLL, val); /* * spruf98o.pdf, page 2319: @@ -328,13 +310,13 @@ prcm_setup_dpll5(void) * EN_PERIPH2_DPLL is 0x7 */ val = (7 << 4) | (7 << 0); - bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKEN2_PLL, val); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CM_CLKEN2_PLL, val); /* Disable the interconnect clock auto-idle. */ - bus_space_write_4(prcm_iot, prcm_ioh, CM_AUTOIDLE2_PLL, 0x0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CM_AUTOIDLE2_PLL, 0x0); /* Wait until DPLL5 is locked and there's clock activity. */ - while ((val = bus_space_read_4(prcm_iot, prcm_ioh, + while ((val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CM_IDLEST_CKGEN) & 0x01) == 0x00) { #ifdef DIAGNOSTIC printf("CM_IDLEST_PLL = 0x%08x\n", val); |