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#include <linux/io.h> 28 29#include <mach/hardware.h> 30#include <asm/irq.h> 31 32#include <asm/mach/irq.h> 33 34#include <mach/regs-irq.h> 35#include <mach/regs-gpio.h> 36 37#include <plat/cpu.h> 38#include <plat/pm.h> 39#include <plat/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 48 /* read the current pending interrupts, and the mask 49 * for what it is available */ 50 51 subsrc = __raw_readl(S3C2410_SUBSRCPND); 52 submsk = __raw_readl(S3C2410_INTSUBMSK); 53 54 subsrc &= ~submsk; 55 subsrc >>= 13; 56 subsrc &= 3; 57 58 if (subsrc != 0) { 59 if (subsrc & 1) { 60 generic_handle_irq(IRQ_S3C2440_WDT); 61 } 62 if (subsrc & 2) { 63 generic_handle_irq(IRQ_S3C2440_AC97); 64 } 65 } 66} 67 68 69#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0)) 70 71static void 72s3c_irq_wdtac97_mask(unsigned int irqno) 73{ 74 s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13); 75} 76 77static void 78s3c_irq_wdtac97_unmask(unsigned int irqno) 79{ 80 s3c_irqsub_unmask(irqno, INTMSK_WDT); 81} 82 83static void 84s3c_irq_wdtac97_ack(unsigned int irqno) 85{ 86 s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13); 87} 88 89static struct irq_chip s3c_irq_wdtac97 = { 90 .mask = s3c_irq_wdtac97_mask, 91 .unmask = s3c_irq_wdtac97_unmask, 92 .ack = s3c_irq_wdtac97_ack, 93}; 94 95static int s3c2440_irq_add(struct sys_device *sysdev) 96{ 97 unsigned int irqno; 98 99 printk("S3C2440: IRQ Support\n"); 100 101 /* add new chained handler for wdt, ac7 */ 102 103 set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); 104 set_irq_handler(IRQ_WDT, handle_level_irq); 105 set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); 106 107 for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) { 108 set_irq_chip(irqno, &s3c_irq_wdtac97); 109 set_irq_handler(irqno, handle_level_irq); 110 set_irq_flags(irqno, IRQF_VALID); 111 } 112 113 return 0; 114} 115 116static struct sysdev_driver s3c2440_irq_driver = { 117 .add = s3c2440_irq_add, 118}; 119 120static int s3c2440_irq_init(void) 121{ 122 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver); 123} 124 125arch_initcall(s3c2440_irq_init); 126