2012-10-21 11:01:10 +04:00
/*
* OMAP2xxx PRM module functions
*
* Copyright ( C ) 2010 - 2012 Texas Instruments , Inc .
* Copyright ( C ) 2010 Nokia Corporation
* Benoît Cousson
* 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/kernel.h>
# include <linux/errno.h>
# include <linux/err.h>
# include <linux/io.h>
# include <linux/irq.h>
# include "powerdomain.h"
2012-10-21 11:01:11 +04:00
# include "clockdomain.h"
2012-10-21 11:01:10 +04:00
# include "prm2xxx.h"
# include "cm2xxx_3xxx.h"
# include "prm-regbits-24xx.h"
ARM: OMAP2/3: PRM: fix bogus OMAP2xxx powerstate return values
On OMAP2xxx chips, the register bitfields for the
PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED are
different than those used on OMAP3/4. The order is reversed. So, for
example, on OMAP2xxx, 0x0 indicates 'ON'; but on OMAP3/4, 0x0
indicates 'OFF'. Similarly, on OMAP2xxx, 0x3 indicates 'OFF', but on
OMAP3/4, 0x3 indicates 'ON'.
To fix this, we treat the OMAP3/4 values as the powerdomain API
values, and create new low-level powerdomain functions for the
OMAP2xxx chips which translate between the OMAP2xxx values and the
OMAP3/4 values.
Without this patch, the conversion of the OMAP2xxx PM code to the
functional powerstate code results in a non-booting kernel.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
2012-12-28 13:10:44 +04:00
/*
* OMAP24xx PM_PWSTCTRL_ * . POWERSTATE and PM_PWSTST_ * . LASTSTATEENTERED bits -
* these are reversed from the bits used on OMAP3 +
*/
# define OMAP24XX_PWRDM_POWER_ON 0x0
# define OMAP24XX_PWRDM_POWER_RET 0x1
# define OMAP24XX_PWRDM_POWER_OFF 0x3
2012-10-21 11:01:13 +04:00
/*
* omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
* hardware register ( which are specific to the OMAP2xxx SoCs ) to
* reset source ID bit shifts ( which is an OMAP SoC - independent
* enumeration )
*/
static struct prm_reset_src_map omap2xxx_prm_reset_src_map [ ] = {
{ OMAP_GLOBALCOLD_RST_SHIFT , OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT } ,
{ OMAP_GLOBALWARM_RST_SHIFT , OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT } ,
{ OMAP24XX_SECU_VIOL_RST_SHIFT , OMAP_SECU_VIOL_RST_SRC_ID_SHIFT } ,
{ OMAP24XX_MPU_WD_RST_SHIFT , OMAP_MPU_WD_RST_SRC_ID_SHIFT } ,
{ OMAP24XX_SECU_WD_RST_SHIFT , OMAP_SECU_WD_RST_SRC_ID_SHIFT } ,
{ OMAP24XX_EXTWMPU_RST_SHIFT , OMAP_EXTWARM_RST_SRC_ID_SHIFT } ,
{ - 1 , - 1 } ,
} ;
/**
* omap2xxx_prm_read_reset_sources - return the last SoC reset source
*
* Return a u32 representing the last reset sources of the SoC . The
* returned reset source bits are standardized across OMAP SoCs .
*/
static u32 omap2xxx_prm_read_reset_sources ( void )
{
struct prm_reset_src_map * p ;
u32 r = 0 ;
u32 v ;
v = omap2_prm_read_mod_reg ( WKUP_MOD , OMAP2_RM_RSTST ) ;
p = omap2xxx_prm_reset_src_map ;
while ( p - > reg_shift > = 0 & & p - > std_shift > = 0 ) {
if ( v & ( 1 < < p - > reg_shift ) )
r | = 1 < < p - > std_shift ;
p + + ;
}
return r ;
}
ARM: OMAP2/3: PRM: fix bogus OMAP2xxx powerstate return values
On OMAP2xxx chips, the register bitfields for the
PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED are
different than those used on OMAP3/4. The order is reversed. So, for
example, on OMAP2xxx, 0x0 indicates 'ON'; but on OMAP3/4, 0x0
indicates 'OFF'. Similarly, on OMAP2xxx, 0x3 indicates 'OFF', but on
OMAP3/4, 0x3 indicates 'ON'.
To fix this, we treat the OMAP3/4 values as the powerdomain API
values, and create new low-level powerdomain functions for the
OMAP2xxx chips which translate between the OMAP2xxx values and the
OMAP3/4 values.
Without this patch, the conversion of the OMAP2xxx PM code to the
functional powerstate code results in a non-booting kernel.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
2012-12-28 13:10:44 +04:00
/**
* omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
* @ omap2xxx_pwrst : OMAP2xxx hardware power state to convert
*
* Return the common power state bits corresponding to the OMAP2xxx
* hardware power state bits @ omap2xxx_pwrst , or - EINVAL upon error .
*/
static int omap2xxx_pwrst_to_common_pwrst ( u8 omap2xxx_pwrst )
{
u8 pwrst ;
switch ( omap2xxx_pwrst ) {
case OMAP24XX_PWRDM_POWER_OFF :
pwrst = PWRDM_POWER_OFF ;
break ;
case OMAP24XX_PWRDM_POWER_RET :
pwrst = PWRDM_POWER_RET ;
break ;
case OMAP24XX_PWRDM_POWER_ON :
pwrst = PWRDM_POWER_ON ;
break ;
default :
return - EINVAL ;
}
return pwrst ;
}
2012-10-30 06:55:46 +04:00
/**
* omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
*
* Set the DPLL reset bit , which should reboot the SoC . This is the
* recommended way to restart the SoC . No return value .
*/
2014-10-27 18:39:26 +03:00
static void omap2xxx_prm_dpll_reset ( void )
2012-10-30 06:55:46 +04:00
{
omap2_prm_set_mod_reg_bits ( OMAP_RST_DPLL3_MASK , WKUP_MOD ,
OMAP2_RM_RSTCTRL ) ;
/* OCP barrier */
omap2_prm_read_mod_reg ( WKUP_MOD , OMAP2_RM_RSTCTRL ) ;
}
2014-02-26 17:31:05 +04:00
/**
* omap2xxx_prm_clear_mod_irqs - clear wakeup status bits for a module
* @ module : PRM module to clear wakeups from
* @ regs : register offset to clear
* @ wkst_mask : wakeup status mask to clear
*
* Clears wakeup status bits for a given module , so that the device can
* re - enter idle .
*/
2014-04-04 13:31:51 +04:00
static int omap2xxx_prm_clear_mod_irqs ( s16 module , u8 regs , u32 wkst_mask )
2014-02-26 17:31:05 +04:00
{
u32 wkst ;
wkst = omap2_prm_read_mod_reg ( module , regs ) ;
wkst & = wkst_mask ;
omap2_prm_write_mod_reg ( wkst , module , regs ) ;
2014-04-04 13:31:51 +04:00
return 0 ;
2014-02-26 17:31:05 +04:00
}
2012-10-21 11:01:11 +04:00
int omap2xxx_clkdm_sleep ( struct clockdomain * clkdm )
{
omap2_prm_set_mod_reg_bits ( OMAP24XX_FORCESTATE_MASK ,
clkdm - > pwrdm . ptr - > prcm_offs ,
OMAP2_PM_PWSTCTRL ) ;
return 0 ;
}
int omap2xxx_clkdm_wakeup ( struct clockdomain * clkdm )
{
omap2_prm_clear_mod_reg_bits ( OMAP24XX_FORCESTATE_MASK ,
clkdm - > pwrdm . ptr - > prcm_offs ,
OMAP2_PM_PWSTCTRL ) ;
return 0 ;
}
ARM: OMAP2/3: PRM: fix bogus OMAP2xxx powerstate return values
On OMAP2xxx chips, the register bitfields for the
PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED are
different than those used on OMAP3/4. The order is reversed. So, for
example, on OMAP2xxx, 0x0 indicates 'ON'; but on OMAP3/4, 0x0
indicates 'OFF'. Similarly, on OMAP2xxx, 0x3 indicates 'OFF', but on
OMAP3/4, 0x3 indicates 'ON'.
To fix this, we treat the OMAP3/4 values as the powerdomain API
values, and create new low-level powerdomain functions for the
OMAP2xxx chips which translate between the OMAP2xxx values and the
OMAP3/4 values.
Without this patch, the conversion of the OMAP2xxx PM code to the
functional powerstate code results in a non-booting kernel.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
2012-12-28 13:10:44 +04:00
static int omap2xxx_pwrdm_set_next_pwrst ( struct powerdomain * pwrdm , u8 pwrst )
{
u8 omap24xx_pwrst ;
switch ( pwrst ) {
case PWRDM_POWER_OFF :
omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF ;
break ;
case PWRDM_POWER_RET :
omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET ;
break ;
case PWRDM_POWER_ON :
omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON ;
break ;
default :
return - EINVAL ;
}
omap2_prm_rmw_mod_reg_bits ( OMAP_POWERSTATE_MASK ,
( omap24xx_pwrst < < OMAP_POWERSTATE_SHIFT ) ,
pwrdm - > prcm_offs , OMAP2_PM_PWSTCTRL ) ;
return 0 ;
}
static int omap2xxx_pwrdm_read_next_pwrst ( struct powerdomain * pwrdm )
{
u8 omap2xxx_pwrst ;
omap2xxx_pwrst = omap2_prm_read_mod_bits_shift ( pwrdm - > prcm_offs ,
OMAP2_PM_PWSTCTRL ,
OMAP_POWERSTATE_MASK ) ;
return omap2xxx_pwrst_to_common_pwrst ( omap2xxx_pwrst ) ;
}
static int omap2xxx_pwrdm_read_pwrst ( struct powerdomain * pwrdm )
{
u8 omap2xxx_pwrst ;
omap2xxx_pwrst = omap2_prm_read_mod_bits_shift ( pwrdm - > prcm_offs ,
OMAP2_PM_PWSTST ,
OMAP_POWERSTATEST_MASK ) ;
return omap2xxx_pwrst_to_common_pwrst ( omap2xxx_pwrst ) ;
}
2012-10-21 11:01:10 +04:00
struct pwrdm_ops omap2_pwrdm_operations = {
ARM: OMAP2/3: PRM: fix bogus OMAP2xxx powerstate return values
On OMAP2xxx chips, the register bitfields for the
PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED are
different than those used on OMAP3/4. The order is reversed. So, for
example, on OMAP2xxx, 0x0 indicates 'ON'; but on OMAP3/4, 0x0
indicates 'OFF'. Similarly, on OMAP2xxx, 0x3 indicates 'OFF', but on
OMAP3/4, 0x3 indicates 'ON'.
To fix this, we treat the OMAP3/4 values as the powerdomain API
values, and create new low-level powerdomain functions for the
OMAP2xxx chips which translate between the OMAP2xxx values and the
OMAP3/4 values.
Without this patch, the conversion of the OMAP2xxx PM code to the
functional powerstate code results in a non-booting kernel.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
2012-12-28 13:10:44 +04:00
. pwrdm_set_next_pwrst = omap2xxx_pwrdm_set_next_pwrst ,
. pwrdm_read_next_pwrst = omap2xxx_pwrdm_read_next_pwrst ,
. pwrdm_read_pwrst = omap2xxx_pwrdm_read_pwrst ,
2012-10-21 11:01:10 +04:00
. pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst ,
. pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst ,
. pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst ,
. pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst ,
. pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst ,
. pwrdm_wait_transition = omap2_pwrdm_wait_transition ,
} ;
2012-10-21 11:01:13 +04:00
/*
*
*/
static struct prm_ll_data omap2xxx_prm_ll_data = {
. read_reset_sources = & omap2xxx_prm_read_reset_sources ,
2014-10-27 18:39:24 +03:00
. assert_hardreset = & omap2_prm_assert_hardreset ,
2014-10-27 18:39:25 +03:00
. deassert_hardreset = & omap2_prm_deassert_hardreset ,
2014-10-27 18:39:25 +03:00
. is_hardreset_asserted = & omap2_prm_is_hardreset_asserted ,
2014-10-27 18:39:26 +03:00
. reset_system = & omap2xxx_prm_dpll_reset ,
2014-04-04 13:31:51 +04:00
. clear_mod_irqs = & omap2xxx_prm_clear_mod_irqs ,
2012-10-21 11:01:13 +04:00
} ;
2014-11-20 16:02:59 +03:00
int __init omap2xxx_prm_init ( const struct omap_prcm_init_data * data )
2012-10-21 11:01:13 +04:00
{
return prm_register ( & omap2xxx_prm_ll_data ) ;
}
static void __exit omap2xxx_prm_exit ( void )
{
2014-05-12 05:54:58 +04:00
prm_unregister ( & omap2xxx_prm_ll_data ) ;
2012-10-21 11:01:13 +04:00
}
__exitcall ( omap2xxx_prm_exit ) ;