linux/arch/arm/mach-davinci/psc.c
Sekhar Nori aad70de20f davinci: enable forced transitions on PSC
Some DaVinci modules like the SATA on DA850
need forced module state transitions.

Define a "force" flag which can be passed to
the PSC config function to enable it to make
forced transitions.

Forced transitions shouldn't normally be attempted,
unless the TRM explicitly specifies its usage.

ChangeLog:
v2:
Modified to take care of the fact that
davinci_psc_config() now takes the flags
directly.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
2011-07-08 11:10:09 +05:30

113 lines
3.1 KiB
C

/*
* TI DaVinci Power and Sleep Controller (PSC)
*
* Copyright (C) 2006 Texas Instruments.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <mach/cputype.h>
#include <mach/psc.h>
#include "clock.h"
/* 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_warning("PSC: Bad psc data: 0x%x[%d]\n",
(int)soc_info->psc_bases, ctlr);
return 0;
}
psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
iounmap(psc_base);
/* if clocked, state can be "Enable" or "SyncReset" */
return mdstat & BIT(12);
}
/* Enable or disable a PSC domain */
void davinci_psc_config(unsigned int domain, unsigned int ctlr,
unsigned int id, bool enable, u32 flags)
{
u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
void __iomem *psc_base;
struct davinci_soc_info *soc_info = &davinci_soc_info;
u32 next_state = PSC_STATE_ENABLE;
if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
pr_warning("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);
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);
pdstat = __raw_readl(psc_base + PDSTAT);
if ((pdstat & 0x00000001) == 0) {
pdctl1 = __raw_readl(psc_base + PDCTL1);
pdctl1 |= 0x1;
__raw_writel(pdctl1, psc_base + PDCTL1);
ptcmd = 1 << domain;
__raw_writel(ptcmd, psc_base + PTCMD);
do {
epcpr = __raw_readl(psc_base + EPCPR);
} while ((((epcpr >> domain) & 1) == 0));
pdctl1 = __raw_readl(psc_base + PDCTL1);
pdctl1 |= 0x100;
__raw_writel(pdctl1, psc_base + PDCTL1);
} else {
ptcmd = 1 << domain;
__raw_writel(ptcmd, psc_base + PTCMD);
}
do {
ptstat = __raw_readl(psc_base + PTSTAT);
} while (!(((ptstat >> domain) & 1) == 0));
do {
mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
} while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
iounmap(psc_base);
}