2012-01-10 15:50:01 +09:00
/*
* r8a7779 Power management support
*
* Copyright ( C ) 2011 Renesas Solutions Corp .
* Copyright ( C ) 2011 Magnus Damm
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/pm.h>
# include <linux/suspend.h>
# include <linux/err.h>
# include <linux/pm_clock.h>
2014-06-17 16:47:53 +09:00
# include <linux/pm_domain.h>
2012-01-10 15:50:01 +09:00
# include <linux/platform_device.h>
# include <linux/delay.h>
# include <linux/irq.h>
# include <linux/interrupt.h>
# include <linux/console.h>
2014-06-20 18:53:05 +02:00
2012-01-10 15:50:01 +09:00
# include <asm/io.h>
2014-06-20 18:53:05 +02:00
2014-06-17 16:47:37 +09:00
# include "common.h"
2014-06-17 16:47:53 +09:00
# include "pm-rcar.h"
2014-06-20 18:53:05 +02:00
# include "r8a7779.h"
2012-01-10 15:50:01 +09:00
/* SYSC */
# define SYSCIER 0x0c
# define SYSCIMR 0x10
2014-06-17 16:47:53 +09:00
struct r8a7779_pm_domain {
struct generic_pm_domain genpd ;
struct rcar_sysc_ch ch ;
} ;
static inline struct rcar_sysc_ch * to_r8a7779_ch ( struct generic_pm_domain * d )
{
return & container_of ( d , struct r8a7779_pm_domain , genpd ) - > ch ;
}
2012-01-10 17:44:39 +09:00
# if defined(CONFIG_PM) || defined(CONFIG_SMP)
2012-01-10 15:50:01 +09:00
static void __init r8a7779_sysc_init ( void )
{
2014-01-15 16:43:08 +09:00
void __iomem * base = rcar_sysc_init ( 0xffd85000 ) ;
2012-01-10 15:50:01 +09:00
/* enable all interrupt sources, but do not use interrupt handler */
2014-01-15 16:43:08 +09:00
iowrite32 ( 0x0131000e , base + SYSCIER ) ;
iowrite32 ( 0 , base + SYSCIMR ) ;
2012-01-10 15:50:01 +09:00
}
2012-01-10 17:44:39 +09:00
# else /* CONFIG_PM || CONFIG_SMP */
static inline void r8a7779_sysc_init ( void ) { }
# endif /* CONFIG_PM || CONFIG_SMP */
# ifdef CONFIG_PM
2012-01-10 15:50:01 +09:00
static int pd_power_down ( struct generic_pm_domain * genpd )
{
2014-01-15 16:43:08 +09:00
return rcar_sysc_power_down ( to_r8a7779_ch ( genpd ) ) ;
2012-01-10 15:50:01 +09:00
}
static int pd_power_up ( struct generic_pm_domain * genpd )
{
2014-01-15 16:43:08 +09:00
return rcar_sysc_power_up ( to_r8a7779_ch ( genpd ) ) ;
2012-01-10 15:50:01 +09:00
}
static bool pd_is_off ( struct generic_pm_domain * genpd )
{
2014-01-15 16:43:08 +09:00
return rcar_sysc_power_is_off ( to_r8a7779_ch ( genpd ) ) ;
2012-01-10 15:50:01 +09:00
}
static bool pd_active_wakeup ( struct device * dev )
{
return true ;
}
2012-08-07 01:14:14 +02:00
static void r8a7779_init_pm_domain ( struct r8a7779_pm_domain * r8a7779_pd )
2012-01-10 15:50:01 +09:00
{
struct generic_pm_domain * genpd = & r8a7779_pd - > genpd ;
pm_genpd_init ( genpd , NULL , false ) ;
genpd - > dev_ops . stop = pm_clk_suspend ;
genpd - > dev_ops . start = pm_clk_resume ;
genpd - > dev_ops . active_wakeup = pd_active_wakeup ;
genpd - > dev_irq_safe = true ;
genpd - > power_off = pd_power_down ;
genpd - > power_on = pd_power_up ;
if ( pd_is_off ( & r8a7779_pd - > genpd ) )
pd_power_up ( & r8a7779_pd - > genpd ) ;
}
2012-08-07 01:14:14 +02:00
static struct r8a7779_pm_domain r8a7779_pm_domains [ ] = {
{
. genpd . name = " SH4A " ,
. ch = {
. chan_offs = 0x80 , /* PWRSR1 .. PWRER1 */
. isr_bit = 16 , /* SH4A */
} ,
} ,
{
. genpd . name = " SGX " ,
. ch = {
. chan_offs = 0xc0 , /* PWRSR2 .. PWRER2 */
. isr_bit = 20 , /* SGX */
} ,
} ,
{
. genpd . name = " VDP1 " ,
. ch = {
. chan_offs = 0x100 , /* PWRSR3 .. PWRER3 */
. isr_bit = 21 , /* VDP */
} ,
} ,
{
. genpd . name = " IMPX3 " ,
. ch = {
. chan_offs = 0x140 , /* PWRSR4 .. PWRER4 */
. isr_bit = 24 , /* IMP */
} ,
} ,
2012-01-10 15:50:01 +09:00
} ;
2012-08-07 01:14:14 +02:00
void __init r8a7779_init_pm_domains ( void )
{
int j ;
2012-01-10 15:50:01 +09:00
2012-08-07 01:14:14 +02:00
for ( j = 0 ; j < ARRAY_SIZE ( r8a7779_pm_domains ) ; j + + )
r8a7779_init_pm_domain ( & r8a7779_pm_domains [ j ] ) ;
}
2012-01-10 15:50:01 +09:00
# endif /* CONFIG_PM */
void __init r8a7779_pm_init ( void )
{
2012-01-10 17:44:39 +09:00
static int once ;
if ( ! once + + )
r8a7779_sysc_init ( ) ;
2012-01-10 15:50:01 +09:00
}