1/* linux/arch/arm/plat-s3c24xx/irq-om.c 2 * 3 * Copyright (c) 2003-2004 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * http://armlinux.simtec.co.uk/ 6 * 7 * S3C24XX - IRQ PM code 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14#include <linux/init.h> 15#include <linux/module.h> 16#include <linux/interrupt.h> 17#include <linux/irq.h> 18#include <linux/syscore_ops.h> 19#include <linux/io.h> 20 21#include <plat/cpu.h> 22#include <plat/pm.h> 23#include <plat/map-base.h> 24#include <plat/map-s3c.h> 25 26#include <mach/regs-irq.h> 27#include <mach/regs-gpio.h> 28 29#include <asm/irq.h> 30 31/* state for IRQs over sleep */ 32 33/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources 34 * 35 * set bit to 1 in allow bitfield to enable the wakeup settings on it 36*/ 37 38unsigned long s3c_irqwake_intallow = 1L << 30 | 0xfL; 39unsigned long s3c_irqwake_eintallow = 0x0000fff0L; 40 41int s3c_irq_wake(struct irq_data *data, unsigned int state) 42{ 43 unsigned long irqbit = 1 << data->hwirq; 44 45 if (!(s3c_irqwake_intallow & irqbit)) 46 return -ENOENT; 47 48 pr_info("wake %s for hwirq %lu\n", 49 state ? "enabled" : "disabled", data->hwirq); 50 51 if (!state) 52 s3c_irqwake_intmask |= irqbit; 53 else 54 s3c_irqwake_intmask &= ~irqbit; 55 56 return 0; 57} 58 59static struct sleep_save irq_save[] = { 60 SAVE_ITEM(S3C2410_INTMSK), 61 SAVE_ITEM(S3C2410_INTSUBMSK), 62}; 63 64/* the extint values move between the s3c2410/s3c2440 and the s3c2412 65 * so we use an array to hold them, and to calculate the address of 66 * the register at run-time 67*/ 68 69static unsigned long save_extint[3]; 70static unsigned long save_eintflt[4]; 71static unsigned long save_eintmask; 72 73static int s3c24xx_irq_suspend(void) 74{ 75 unsigned int i; 76 77 for (i = 0; i < ARRAY_SIZE(save_extint); i++) 78 save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4)); 79 80 for (i = 0; i < ARRAY_SIZE(save_eintflt); i++) 81 save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4)); 82 83 s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); 84 save_eintmask = __raw_readl(S3C24XX_EINTMASK); 85 86 return 0; 87} 88 89static void s3c24xx_irq_resume(void) 90{ 91 unsigned int i; 92 93 for (i = 0; i < ARRAY_SIZE(save_extint); i++) 94 __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4)); 95 96 for (i = 0; i < ARRAY_SIZE(save_eintflt); i++) 97 __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4)); 98 99 s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); 100 __raw_writel(save_eintmask, S3C24XX_EINTMASK); 101} 102 103struct syscore_ops s3c24xx_irq_syscore_ops = { 104 .suspend = s3c24xx_irq_suspend, 105 .resume = s3c24xx_irq_resume, 106}; 107 108#ifdef CONFIG_CPU_S3C2416 109static struct sleep_save s3c2416_irq_save[] = { 110 SAVE_ITEM(S3C2416_INTMSK2), 111}; 112 113static int s3c2416_irq_suspend(void) 114{ 115 s3c_pm_do_save(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); 116 117 return 0; 118} 119 120static void s3c2416_irq_resume(void) 121{ 122 s3c_pm_do_restore(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); 123} 124 125struct syscore_ops s3c2416_irq_syscore_ops = { 126 .suspend = s3c2416_irq_suspend, 127 .resume = s3c2416_irq_resume, 128}; 129#endif 130