diff options
Diffstat (limited to 'arch/arm/mach-davinci/psc.c')
| -rw-r--r-- | arch/arm/mach-davinci/psc.c | 162 |
1 files changed, 93 insertions, 69 deletions
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index e1b0050283a..82fdc69d572 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -19,95 +19,119 @@ * */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> +#include <linux/io.h> -#include <asm/io.h> -#include <asm/hardware.h> -#include <asm/arch/psc.h> +#include <mach/cputype.h> +#include <mach/psc.h> -#define PTCMD __REG(0x01C41120) -#define PDSTAT __REG(0x01C41200) -#define PDCTL1 __REG(0x01C41304) -#define EPCPR __REG(0x01C41070) -#define PTSTAT __REG(0x01C41128) +#include "clock.h" -#define MDSTAT IO_ADDRESS(0x01C41800) -#define MDCTL IO_ADDRESS(0x01C41A00) +/* Return nonzero iff the domain's clock is active */ +int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) +{ + void __iomem *psc_base; + u32 mdstat; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { + pr_warn("PSC: Bad psc data: 0x%x[%d]\n", + (int)soc_info->psc_bases, ctlr); + return 0; + } -#define PINMUX0 __REG(0x01c40000) -#define PINMUX1 __REG(0x01c40004) -#define VDD3P3V_PWDN __REG(0x01C40048) + psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); + mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); + iounmap(psc_base); -static void davinci_psc_mux(unsigned int id) + /* if clocked, state can be "Enable" or "SyncReset" */ + return mdstat & BIT(12); +} + +/* Control "reset" line associated with PSC domain */ +void davinci_psc_reset(unsigned int ctlr, unsigned int id, bool reset) { - switch (id) { - case DAVINCI_LPSC_ATA: - PINMUX0 |= (1 << 17) | (1 << 16); - break; - case DAVINCI_LPSC_MMC_SD: - /* VDD power manupulations are done in U-Boot for CPMAC - * so applies to MMC as well - */ - /*Set up the pull regiter for MMC */ - VDD3P3V_PWDN = 0x0; - PINMUX1 &= (~(1 << 9)); - break; - case DAVINCI_LPSC_I2C: - PINMUX1 |= (1 << 7); - break; - case DAVINCI_LPSC_McBSP: - PINMUX1 |= (1 << 10); - break; - default: - break; + u32 mdctl; + void __iomem *psc_base; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { + pr_warn("PSC: Bad psc data: 0x%x[%d]\n", + (int)soc_info->psc_bases, ctlr); + return; } + + psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); + + mdctl = readl(psc_base + MDCTL + 4 * id); + if (reset) + mdctl &= ~MDCTL_LRST; + else + mdctl |= MDCTL_LRST; + writel(mdctl, psc_base + MDCTL + 4 * id); + + iounmap(psc_base); } /* Enable or disable a PSC domain */ -void davinci_psc_config(unsigned int domain, unsigned int id, char enable) +void davinci_psc_config(unsigned int domain, unsigned int ctlr, + unsigned int id, bool enable, u32 flags) { - volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id); - volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id); + u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl; + void __iomem *psc_base; + struct davinci_soc_info *soc_info = &davinci_soc_info; + u32 next_state = PSC_STATE_ENABLE; - if (id < 0) + if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { + pr_warn("PSC: Bad psc data: 0x%x[%d]\n", + (int)soc_info->psc_bases, ctlr); return; + } - if (enable) - *mdctl |= 0x00000003; /* Enable Module */ - else - *mdctl &= 0xFFFFFFF2; /* Disable Module */ + psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); + + if (!enable) { + if (flags & PSC_SWRSTDISABLE) + next_state = PSC_STATE_SWRSTDISABLE; + else + next_state = PSC_STATE_DISABLE; + } + + mdctl = __raw_readl(psc_base + MDCTL + 4 * id); + mdctl &= ~MDSTAT_STATE_MASK; + mdctl |= next_state; + if (flags & PSC_FORCE) + mdctl |= MDCTL_FORCE; + __raw_writel(mdctl, psc_base + MDCTL + 4 * id); - if ((PDSTAT & 0x00000001) == 0) { - PDCTL1 |= 0x1; - PTCMD = (1 << domain); - while ((((EPCPR >> domain) & 1) == 0)); + pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain); + if ((pdstat & PDSTAT_STATE_MASK) == 0) { + pdctl = __raw_readl(psc_base + PDCTL + 4 * domain); + pdctl |= PDCTL_NEXT; + __raw_writel(pdctl, psc_base + PDCTL + 4 * domain); - PDCTL1 |= 0x100; - while (!(((PTSTAT >> domain) & 1) == 0)); + ptcmd = 1 << domain; + __raw_writel(ptcmd, psc_base + PTCMD); + + do { + epcpr = __raw_readl(psc_base + EPCPR); + } while ((((epcpr >> domain) & 1) == 0)); + + pdctl = __raw_readl(psc_base + PDCTL + 4 * domain); + pdctl |= PDCTL_EPCGOOD; + __raw_writel(pdctl, psc_base + PDCTL + 4 * domain); } else { - PTCMD = (1 << domain); - while (!(((PTSTAT >> domain) & 1) == 0)); + ptcmd = 1 << domain; + __raw_writel(ptcmd, psc_base + PTCMD); } - if (enable) - while (!((*mdstat & 0x0000001F) == 0x3)); - else - while (!((*mdstat & 0x0000001F) == 0x2)); + do { + ptstat = __raw_readl(psc_base + PTSTAT); + } while (!(((ptstat >> domain) & 1) == 0)); - if (enable) - davinci_psc_mux(id); -} + do { + mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); + } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); -void __init davinci_psc_init(void) -{ - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1); - - /* Turn on WatchDog timer LPSC. Needed for RESET to work */ - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1); + iounmap(psc_base); } |
