1/* linux/arch/arm/mach-s3c2440/irq.c 2 * 3 * Copyright (c) 2003,2004 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20*/ 21 22#include <linux/init.h> 23#include <linux/module.h> 24#include <linux/interrupt.h> 25#include <linux/ioport.h> 26#include <linux/sysdev.h> 27 28#include <asm/hardware.h> 29#include <asm/irq.h> 30#include <asm/io.h> 31 32#include <asm/mach/irq.h> 33 34#include <asm/arch/regs-irq.h> 35#include <asm/arch/regs-gpio.h> 36 37#include <asm/plat-s3c24xx/cpu.h> 38#include <asm/plat-s3c24xx/pm.h> 39#include <asm/plat-s3c24xx/irq.h> 40 41/* WDT/AC97 */ 42 43static void s3c_irq_demux_wdtac97(unsigned int irq, 44 struct irq_desc *desc) 45{ 46 unsigned int subsrc, submsk; 47 struct irq_desc *mydesc; 48 49 /* read the current pending interrupts, and the mask 50 * for what it is available */ 51 52 subsrc = __raw_readl(S3C2410_SUBSRCPND); 53 submsk = __raw_readl(S3C2410_INTSUBMSK); 54 55 subsrc &= ~submsk; 56 subsrc >>= 13; 57 subsrc &= 3; 58 59 if (subsrc != 0) { 60 if (subsrc & 1) { 61 mydesc = irq_desc + IRQ_S3C2440_WDT; 62 desc_handle_irq(IRQ_S3C2440_WDT, mydesc); 63 } 64 if (subsrc & 2) { 65 mydesc = irq_desc + IRQ_S3C2440_AC97; 66 desc_handle_irq(IRQ_S3C2440_AC97, mydesc); 67 } 68 } 69} 70 71 72#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0)) 73 74static void 75s3c_irq_wdtac97_mask(unsigned int irqno) 76{ 77 s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13); 78} 79 80static void 81s3c_irq_wdtac97_unmask(unsigned int irqno) 82{ 83 s3c_irqsub_unmask(irqno, INTMSK_WDT); 84} 85 86static void 87s3c_irq_wdtac97_ack(unsigned int irqno) 88{ 89 s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13); 90} 91 92static struct irq_chip s3c_irq_wdtac97 = { 93 .mask = s3c_irq_wdtac97_mask, 94 .unmask = s3c_irq_wdtac97_unmask, 95 .ack = s3c_irq_wdtac97_ack, 96}; 97 98static int s3c2440_irq_add(struct sys_device *sysdev) 99{ 100 unsigned int irqno; 101 102 printk("S3C2440: IRQ Support\n"); 103 104 /* add new chained handler for wdt, ac7 */ 105 106 set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); 107 set_irq_handler(IRQ_WDT, handle_level_irq); 108 set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); 109 110 for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) { 111 set_irq_chip(irqno, &s3c_irq_wdtac97); 112 set_irq_handler(irqno, handle_level_irq); 113 set_irq_flags(irqno, IRQF_VALID); 114 } 115 116 return 0; 117} 118 119static struct sysdev_driver s3c2440_irq_driver = { 120 .add = s3c2440_irq_add, 121}; 122 123static int s3c2440_irq_init(void) 124{ 125 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver); 126} 127 128arch_initcall(s3c2440_irq_init); 129