2017-12-25 22:54:32 +03:00
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2003-2004 Simtec Electronics
// Ben Dooks <ben@simtec.co.uk>
// http://armlinux.simtec.co.uk/
//
// S3C24XX - IRQ PM code
2008-12-12 03:24:10 +03:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/interrupt.h>
2011-01-03 13:15:54 +03:00
# include <linux/irq.h>
2013-01-29 22:25:22 +04:00
# include <linux/syscore_ops.h>
2013-02-13 02:23:01 +04:00
# include <linux/io.h>
2008-12-12 03:24:10 +03:00
2019-09-02 19:37:30 +03:00
# include "cpu.h"
# include "pm.h"
2022-04-02 13:29:36 +03:00
# include "map-base.h"
2019-09-02 19:37:30 +03:00
# include "map-s3c.h"
2013-02-13 02:23:01 +04:00
2019-09-02 19:37:30 +03:00
# include "regs-irq.h"
# include "regs-gpio.h"
# include "pm-core.h"
2008-12-12 03:24:10 +03:00
2011-01-03 13:15:54 +03:00
# include <asm/irq.h>
int s3c_irq_wake ( struct irq_data * data , unsigned int state )
2008-12-12 03:24:10 +03:00
{
2013-01-29 22:25:22 +04:00
unsigned long irqbit = 1 < < data - > hwirq ;
2008-12-12 03:24:10 +03:00
if ( ! ( s3c_irqwake_intallow & irqbit ) )
return - ENOENT ;
2013-01-29 22:25:22 +04:00
pr_info ( " wake %s for hwirq %lu \n " ,
state ? " enabled " : " disabled " , data - > hwirq ) ;
2008-12-12 03:24:10 +03: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 22:25:22 +04:00
static int s3c24xx_irq_suspend ( void )
2008-12-12 03:24:10 +03: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 22:25:22 +04:00
static void s3c24xx_irq_resume ( void )
2008-12-12 03:24:10 +03: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 22:25:22 +04:00
struct syscore_ops s3c24xx_irq_syscore_ops = {
. suspend = s3c24xx_irq_suspend ,
. resume = s3c24xx_irq_resume ,
} ;
2013-01-29 22:25:22 +04: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