2007-04-30 19:37:19 +01:00
/*
* 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 0213 9 , USA .
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2007-04-30 19:37:19 +01:00
2009-03-20 17:29:01 -07:00
# include <mach/cputype.h>
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
# include <mach/psc.h>
# include <mach/mux.h>
2007-04-30 19:37:19 +01:00
2009-04-14 07:04:16 -05:00
# define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000
2007-07-10 13:10:04 +01:00
/* PSC register offsets */
# define EPCPR 0x070
# define PTCMD 0x120
# define PTSTAT 0x128
# define PDSTAT 0x200
# define PDCTL1 0x304
# define MDSTAT 0x800
# define MDCTL 0xA00
2007-04-30 19:37:19 +01:00
2009-03-26 19:33:21 -07:00
# define MDSTAT_STATE_MASK 0x1f
2007-04-30 19:37:19 +01:00
2009-03-20 17:29:01 -07:00
/* Return nonzero iff the domain's clock is active */
int __init davinci_psc_is_clk_active ( unsigned int id )
2007-04-30 19:37:19 +01:00
{
2009-03-20 17:29:01 -07:00
void __iomem * psc_base = IO_ADDRESS ( DAVINCI_PWR_SLEEP_CNTRL_BASE ) ;
u32 mdstat = __raw_readl ( psc_base + MDSTAT + 4 * id ) ;
/* if clocked, state can be "Enable" or "SyncReset" */
return mdstat & BIT ( 12 ) ;
2007-04-30 19:37:19 +01:00
}
/* Enable or disable a PSC domain */
void davinci_psc_config ( unsigned int domain , unsigned int id , char enable )
{
2009-03-26 19:33:21 -07:00
u32 epcpr , ptcmd , ptstat , pdstat , pdctl1 , mdstat , mdctl ;
2009-03-20 17:29:01 -07:00
void __iomem * psc_base = IO_ADDRESS ( DAVINCI_PWR_SLEEP_CNTRL_BASE ) ;
2009-03-26 19:33:21 -07:00
u32 next_state = enable ? 0x3 : 0x2 ; /* 0x3 enables, 0x2 disables */
2007-04-30 19:37:19 +01:00
2009-03-20 17:29:01 -07:00
mdctl = __raw_readl ( psc_base + MDCTL + 4 * id ) ;
2009-03-26 19:33:21 -07:00
mdctl & = ~ MDSTAT_STATE_MASK ;
mdctl | = next_state ;
2009-03-20 17:29:01 -07:00
__raw_writel ( mdctl , psc_base + MDCTL + 4 * id ) ;
2007-07-10 13:10:04 +01:00
2009-03-20 17:29:01 -07:00
pdstat = __raw_readl ( psc_base + PDSTAT ) ;
2007-07-10 13:10:04 +01:00
if ( ( pdstat & 0x00000001 ) = = 0 ) {
2009-03-20 17:29:01 -07:00
pdctl1 = __raw_readl ( psc_base + PDCTL1 ) ;
2007-07-10 13:10:04 +01:00
pdctl1 | = 0x1 ;
2009-03-20 17:29:01 -07:00
__raw_writel ( pdctl1 , psc_base + PDCTL1 ) ;
2007-07-10 13:10:04 +01:00
ptcmd = 1 < < domain ;
2009-03-20 17:29:01 -07:00
__raw_writel ( ptcmd , psc_base + PTCMD ) ;
2007-04-30 19:37:19 +01:00
2007-07-10 13:10:04 +01:00
do {
2009-03-20 17:29:01 -07:00
epcpr = __raw_readl ( psc_base + EPCPR ) ;
2007-07-10 13:10:04 +01:00
} while ( ( ( ( epcpr > > domain ) & 1 ) = = 0 ) ) ;
2007-04-30 19:37:19 +01:00
2009-03-20 17:29:01 -07:00
pdctl1 = __raw_readl ( psc_base + PDCTL1 ) ;
2007-07-10 13:10:04 +01:00
pdctl1 | = 0x100 ;
2009-03-20 17:29:01 -07:00
__raw_writel ( pdctl1 , psc_base + PDCTL1 ) ;
2007-07-10 13:10:04 +01:00
do {
2009-03-20 17:29:01 -07:00
ptstat = __raw_readl ( psc_base +
2007-07-10 13:10:04 +01:00
PTSTAT ) ;
} while ( ! ( ( ( ptstat > > domain ) & 1 ) = = 0 ) ) ;
2007-04-30 19:37:19 +01:00
} else {
2007-07-10 13:10:04 +01:00
ptcmd = 1 < < domain ;
2009-03-20 17:29:01 -07:00
__raw_writel ( ptcmd , psc_base + PTCMD ) ;
2007-07-10 13:10:04 +01:00
do {
2009-03-20 17:29:01 -07:00
ptstat = __raw_readl ( psc_base + PTSTAT ) ;
2007-07-10 13:10:04 +01:00
} while ( ! ( ( ( ptstat > > domain ) & 1 ) = = 0 ) ) ;
2007-04-30 19:37:19 +01:00
}
2007-07-10 13:10:04 +01:00
do {
2009-03-20 17:29:01 -07:00
mdstat = __raw_readl ( psc_base + MDSTAT + 4 * id ) ;
2009-03-26 19:33:21 -07:00
} while ( ! ( ( mdstat & MDSTAT_STATE_MASK ) = = next_state ) ) ;
2007-04-30 19:37:19 +01:00
}