2010-12-21 20:01:18 -07:00
/*
* OMAP4 powerdomain control
*
* Copyright ( C ) 2009 - 2010 Texas Instruments , Inc .
* Copyright ( C ) 2007 - 2009 Nokia Corporation
*
* Derived from mach - omap2 / powerdomain . c written by Paul Walmsley
* Rajendra Nayak < rnayak @ ti . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/io.h>
# include <linux/errno.h>
# include <linux/delay.h>
2012-03-08 10:20:14 -08:00
# include <linux/bug.h>
2010-12-21 20:01:20 -07:00
2010-12-21 21:05:16 -07:00
# include "powerdomain.h"
2010-12-21 20:01:18 -07:00
# include <plat/prcm.h>
2010-12-21 15:30:55 -07:00
# include "prm2xxx_3xxx.h"
2010-12-21 15:30:54 -07:00
# include "prm44xx.h"
2010-12-21 21:05:14 -07:00
# include "prminst44xx.h"
2010-12-21 20:01:18 -07:00
# include "prm-regbits-44xx.h"
static int omap4_pwrdm_set_next_pwrst ( struct powerdomain * pwrdm , u8 pwrst )
{
2010-12-21 21:05:14 -07:00
omap4_prminst_rmw_inst_reg_bits ( OMAP_POWERSTATE_MASK ,
( pwrst < < OMAP_POWERSTATE_SHIFT ) ,
pwrdm - > prcm_partition ,
pwrdm - > prcm_offs , OMAP4_PM_PWSTCTRL ) ;
2010-12-21 20:01:18 -07:00
return 0 ;
}
static int omap4_pwrdm_read_next_pwrst ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
u32 v ;
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTCTRL ) ;
v & = OMAP_POWERSTATE_MASK ;
v > > = OMAP_POWERSTATE_SHIFT ;
return v ;
2010-12-21 20:01:18 -07:00
}
static int omap4_pwrdm_read_pwrst ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
u32 v ;
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTST ) ;
v & = OMAP_POWERSTATEST_MASK ;
v > > = OMAP_POWERSTATEST_SHIFT ;
return v ;
2010-12-21 20:01:18 -07:00
}
static int omap4_pwrdm_read_prev_pwrst ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
u32 v ;
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTST ) ;
v & = OMAP4430_LASTPOWERSTATEENTERED_MASK ;
v > > = OMAP4430_LASTPOWERSTATEENTERED_SHIFT ;
return v ;
2010-12-21 20:01:18 -07:00
}
2010-12-21 20:01:19 -07:00
static int omap4_pwrdm_set_lowpwrstchange ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
omap4_prminst_rmw_inst_reg_bits ( OMAP4430_LOWPOWERSTATECHANGE_MASK ,
( 1 < < OMAP4430_LOWPOWERSTATECHANGE_SHIFT ) ,
pwrdm - > prcm_partition ,
pwrdm - > prcm_offs , OMAP4_PM_PWSTCTRL ) ;
2010-12-21 20:01:19 -07:00
return 0 ;
}
2010-12-21 20:01:19 -07:00
static int omap4_pwrdm_clear_all_prev_pwrst ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
omap4_prminst_rmw_inst_reg_bits ( OMAP4430_LASTPOWERSTATEENTERED_MASK ,
OMAP4430_LASTPOWERSTATEENTERED_MASK ,
pwrdm - > prcm_partition ,
pwrdm - > prcm_offs , OMAP4_PM_PWSTST ) ;
2010-12-21 20:01:19 -07:00
return 0 ;
}
2010-12-21 20:01:18 -07:00
static int omap4_pwrdm_set_logic_retst ( struct powerdomain * pwrdm , u8 pwrst )
{
u32 v ;
v = pwrst < < __ffs ( OMAP4430_LOGICRETSTATE_MASK ) ;
2010-12-21 21:05:14 -07:00
omap4_prminst_rmw_inst_reg_bits ( OMAP4430_LOGICRETSTATE_MASK , v ,
pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTCTRL ) ;
2010-12-21 20:01:18 -07:00
return 0 ;
}
2010-12-21 20:01:19 -07:00
static int omap4_pwrdm_set_mem_onst ( struct powerdomain * pwrdm , u8 bank ,
2010-12-21 21:05:14 -07:00
u8 pwrst )
2010-12-21 20:01:19 -07:00
{
u32 m ;
m = omap2_pwrdm_get_mem_bank_onstate_mask ( bank ) ;
2010-12-21 21:05:14 -07:00
omap4_prminst_rmw_inst_reg_bits ( m , ( pwrst < < __ffs ( m ) ) ,
pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTCTRL ) ;
2010-12-21 20:01:19 -07:00
return 0 ;
}
static int omap4_pwrdm_set_mem_retst ( struct powerdomain * pwrdm , u8 bank ,
2010-12-21 21:05:14 -07:00
u8 pwrst )
2010-12-21 20:01:19 -07:00
{
u32 m ;
m = omap2_pwrdm_get_mem_bank_retst_mask ( bank ) ;
2010-12-21 21:05:14 -07:00
omap4_prminst_rmw_inst_reg_bits ( m , ( pwrst < < __ffs ( m ) ) ,
pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTCTRL ) ;
2010-12-21 20:01:19 -07:00
return 0 ;
}
2010-12-21 20:01:18 -07:00
static int omap4_pwrdm_read_logic_pwrst ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
u32 v ;
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTST ) ;
v & = OMAP4430_LOGICSTATEST_MASK ;
v > > = OMAP4430_LOGICSTATEST_SHIFT ;
return v ;
2010-12-21 20:01:18 -07:00
}
static int omap4_pwrdm_read_logic_retst ( struct powerdomain * pwrdm )
{
2010-12-21 21:05:14 -07:00
u32 v ;
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTCTRL ) ;
v & = OMAP4430_LOGICRETSTATE_MASK ;
v > > = OMAP4430_LOGICRETSTATE_SHIFT ;
return v ;
2010-12-21 20:01:18 -07:00
}
2010-12-21 20:01:19 -07:00
static int omap4_pwrdm_read_mem_pwrst ( struct powerdomain * pwrdm , u8 bank )
{
2010-12-21 21:05:14 -07:00
u32 m , v ;
2010-12-21 20:01:19 -07:00
m = omap2_pwrdm_get_mem_bank_stst_mask ( bank ) ;
2010-12-21 21:05:14 -07:00
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTST ) ;
v & = m ;
v > > = __ffs ( m ) ;
return v ;
2010-12-21 20:01:19 -07:00
}
static int omap4_pwrdm_read_mem_retst ( struct powerdomain * pwrdm , u8 bank )
{
2010-12-21 21:05:14 -07:00
u32 m , v ;
2010-12-21 20:01:19 -07:00
m = omap2_pwrdm_get_mem_bank_retst_mask ( bank ) ;
2010-12-21 21:05:14 -07:00
v = omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition , pwrdm - > prcm_offs ,
OMAP4_PM_PWSTCTRL ) ;
v & = m ;
v > > = __ffs ( m ) ;
return v ;
2010-12-21 20:01:19 -07:00
}
static int omap4_pwrdm_wait_transition ( struct powerdomain * pwrdm )
{
u32 c = 0 ;
/*
* REVISIT : pwrdm_wait_transition ( ) may be better implemented
* via a callback and a periodic timer check - - how long do we expect
* powerdomain transitions to take ?
*/
/* XXX Is this udelay() value meaningful? */
2010-12-21 21:05:14 -07:00
while ( ( omap4_prminst_read_inst_reg ( pwrdm - > prcm_partition ,
pwrdm - > prcm_offs ,
OMAP4_PM_PWSTST ) &
2010-12-21 20:01:19 -07:00
OMAP_INTRANSITION_MASK ) & &
2010-12-21 21:05:14 -07:00
( c + + < PWRDM_TRANSITION_BAILOUT ) )
udelay ( 1 ) ;
2010-12-21 20:01:19 -07:00
if ( c > PWRDM_TRANSITION_BAILOUT ) {
printk ( KERN_ERR " powerdomain: waited too long for "
2010-12-21 21:05:14 -07:00
" powerdomain %s to complete transition \n " , pwrdm - > name ) ;
2010-12-21 20:01:19 -07:00
return - EAGAIN ;
}
pr_debug ( " powerdomain: completed transition in %d loops \n " , c ) ;
return 0 ;
}
2010-12-21 20:01:18 -07:00
struct pwrdm_ops omap4_pwrdm_operations = {
. pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst ,
. pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst ,
. pwrdm_read_pwrst = omap4_pwrdm_read_pwrst ,
. pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst ,
2010-12-21 20:01:19 -07:00
. pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange ,
2010-12-21 20:01:19 -07:00
. pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst ,
2010-12-21 20:01:18 -07:00
. pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst ,
. pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst ,
. pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst ,
2010-12-21 20:01:19 -07:00
. pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst ,
. pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst ,
. pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst ,
. pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst ,
. pwrdm_wait_transition = omap4_pwrdm_wait_transition ,
2010-12-21 20:01:18 -07:00
} ;