2008-12-12 00:24:10 +00:00
/* linux/arch/arm/plat-s3c24xx/irq-om.c
*
2009-11-13 22:54:13 +00:00
* Copyright ( c ) 2003 - 2004 Simtec Electronics
2008-12-12 00:24:10 +00:00
* Ben Dooks < ben @ simtec . co . uk >
* http : //armlinux.simtec.co.uk/
*
* S3C24XX - IRQ PM code
*
* 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/init.h>
# include <linux/module.h>
# include <linux/interrupt.h>
2011-01-03 19:15:54 +09:00
# include <linux/irq.h>
2013-01-29 10:25:22 -08:00
# include <linux/syscore_ops.h>
2013-02-12 14:23:01 -08:00
# include <linux/io.h>
2008-12-12 00:24:10 +00:00
# include <plat/cpu.h>
# include <plat/pm.h>
2013-02-12 14:23:01 -08:00
# include <plat/map-base.h>
# include <plat/map-s3c.h>
# include <mach/regs-irq.h>
# include <mach/regs-gpio.h>
2008-12-12 00:24:10 +00:00
2011-01-03 19:15:54 +09:00
# include <asm/irq.h>
2008-12-12 00:24:10 +00:00
/* state for IRQs over sleep */
/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
*
* set bit to 1 in allow bitfield to enable the wakeup settings on it
*/
2013-01-29 10:25:22 -08:00
unsigned long s3c_irqwake_intallow = 1L < < 30 | 0xfL ;
2008-12-12 00:24:10 +00:00
unsigned long s3c_irqwake_eintallow = 0x0000fff0L ;
2011-01-03 19:15:54 +09:00
int s3c_irq_wake ( struct irq_data * data , unsigned int state )
2008-12-12 00:24:10 +00:00
{
2013-01-29 10:25:22 -08:00
unsigned long irqbit = 1 < < data - > hwirq ;
2008-12-12 00:24:10 +00:00
if ( ! ( s3c_irqwake_intallow & irqbit ) )
return - ENOENT ;
2013-01-29 10:25:22 -08:00
pr_info ( " wake %s for hwirq %lu \n " ,
state ? " enabled " : " disabled " , data - > hwirq ) ;
2008-12-12 00:24:10 +00:00
if ( ! state )
s3c_irqwake_intmask | = irqbit ;
else
s3c_irqwake_intmask & = ~ irqbit ;
return 0 ;
}
static struct sleep_save irq_save [ ] = {
SAVE_ITEM ( S3C2410_INTMSK ) ,
SAVE_ITEM ( S3C2410_INTSUBMSK ) ,
} ;
/* the extint values move between the s3c2410/s3c2440 and the s3c2412
* so we use an array to hold them , and to calculate the address of
* the register at run - time
*/
static unsigned long save_extint [ 3 ] ;
static unsigned long save_eintflt [ 4 ] ;
static unsigned long save_eintmask ;
2013-01-29 10:25:22 -08:00
static int s3c24xx_irq_suspend ( void )
2008-12-12 00:24:10 +00:00
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( save_extint ) ; i + + )
save_extint [ i ] = __raw_readl ( S3C24XX_EXTINT0 + ( i * 4 ) ) ;
for ( i = 0 ; i < ARRAY_SIZE ( save_eintflt ) ; i + + )
save_eintflt [ i ] = __raw_readl ( S3C24XX_EINFLT0 + ( i * 4 ) ) ;
s3c_pm_do_save ( irq_save , ARRAY_SIZE ( irq_save ) ) ;
save_eintmask = __raw_readl ( S3C24XX_EINTMASK ) ;
return 0 ;
}
2013-01-29 10:25:22 -08:00
static void s3c24xx_irq_resume ( void )
2008-12-12 00:24:10 +00:00
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( save_extint ) ; i + + )
__raw_writel ( save_extint [ i ] , S3C24XX_EXTINT0 + ( i * 4 ) ) ;
for ( i = 0 ; i < ARRAY_SIZE ( save_eintflt ) ; i + + )
__raw_writel ( save_eintflt [ i ] , S3C24XX_EINFLT0 + ( i * 4 ) ) ;
s3c_pm_do_restore ( irq_save , ARRAY_SIZE ( irq_save ) ) ;
__raw_writel ( save_eintmask , S3C24XX_EINTMASK ) ;
}
2013-01-29 10:25:22 -08:00
struct syscore_ops s3c24xx_irq_syscore_ops = {
. suspend = s3c24xx_irq_suspend ,
. resume = s3c24xx_irq_resume ,
} ;
2013-01-29 10:25:22 -08:00
# ifdef CONFIG_CPU_S3C2416
static struct sleep_save s3c2416_irq_save [ ] = {
SAVE_ITEM ( S3C2416_INTMSK2 ) ,
} ;
static int s3c2416_irq_suspend ( void )
{
s3c_pm_do_save ( s3c2416_irq_save , ARRAY_SIZE ( s3c2416_irq_save ) ) ;
return 0 ;
}
static void s3c2416_irq_resume ( void )
{
s3c_pm_do_restore ( s3c2416_irq_save , ARRAY_SIZE ( s3c2416_irq_save ) ) ;
}
struct syscore_ops s3c2416_irq_syscore_ops = {
. suspend = s3c2416_irq_suspend ,
. resume = s3c2416_irq_resume ,
} ;
# endif