11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/arm/mach-pxa/irq.c 31da177e4SLinus Torvalds * 4e3630db1Seric miao * Generic PXA IRQ handling 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Author: Nicolas Pitre 71da177e4SLinus Torvalds * Created: Jun 15, 2001 81da177e4SLinus Torvalds * Copyright: MontaVista Software Inc. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 111da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 121da177e4SLinus Torvalds * published by the Free Software Foundation. 131da177e4SLinus Torvalds */ 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds #include <linux/init.h> 161da177e4SLinus Torvalds #include <linux/module.h> 171da177e4SLinus Torvalds #include <linux/interrupt.h> 18c0165504Seric miao #include <linux/sysdev.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #include <asm/hardware.h> 211da177e4SLinus Torvalds #include <asm/irq.h> 221da177e4SLinus Torvalds #include <asm/mach/irq.h> 231da177e4SLinus Torvalds #include <asm/arch/pxa-regs.h> 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include "generic.h" 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds /* 291da177e4SLinus Torvalds * This is for peripheral IRQs internal to the PXA chip. 301da177e4SLinus Torvalds */ 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds static void pxa_mask_low_irq(unsigned int irq) 331da177e4SLinus Torvalds { 34486c9551SEric Miao ICMR &= ~(1 << irq); 351da177e4SLinus Torvalds } 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds static void pxa_unmask_low_irq(unsigned int irq) 381da177e4SLinus Torvalds { 39486c9551SEric Miao ICMR |= (1 << irq); 401da177e4SLinus Torvalds } 411da177e4SLinus Torvalds 4238c677cbSDavid Brownell static struct irq_chip pxa_internal_chip_low = { 4338c677cbSDavid Brownell .name = "SC", 441da177e4SLinus Torvalds .ack = pxa_mask_low_irq, 451da177e4SLinus Torvalds .mask = pxa_mask_low_irq, 461da177e4SLinus Torvalds .unmask = pxa_unmask_low_irq, 471da177e4SLinus Torvalds }; 481da177e4SLinus Torvalds 4953665a50SEric Miao void __init pxa_init_irq_low(void) 5053665a50SEric Miao { 5153665a50SEric Miao int irq; 5253665a50SEric Miao 5353665a50SEric Miao /* disable all IRQs */ 5453665a50SEric Miao ICMR = 0; 5553665a50SEric Miao 5653665a50SEric Miao /* all IRQs are IRQ, not FIQ */ 5753665a50SEric Miao ICLR = 0; 5853665a50SEric Miao 5953665a50SEric Miao /* only unmasked interrupts kick us out of idle */ 6053665a50SEric Miao ICCR = 1; 6153665a50SEric Miao 6253665a50SEric Miao for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) { 6353665a50SEric Miao set_irq_chip(irq, &pxa_internal_chip_low); 6453665a50SEric Miao set_irq_handler(irq, handle_level_irq); 6553665a50SEric Miao set_irq_flags(irq, IRQF_VALID); 6653665a50SEric Miao } 6753665a50SEric Miao } 6853665a50SEric Miao 692c8086a5Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds /* 721da177e4SLinus Torvalds * This is for the second set of internal IRQs as found on the PXA27x. 731da177e4SLinus Torvalds */ 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds static void pxa_mask_high_irq(unsigned int irq) 761da177e4SLinus Torvalds { 77486c9551SEric Miao ICMR2 &= ~(1 << (irq - 32)); 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds static void pxa_unmask_high_irq(unsigned int irq) 811da177e4SLinus Torvalds { 82486c9551SEric Miao ICMR2 |= (1 << (irq - 32)); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 8538c677cbSDavid Brownell static struct irq_chip pxa_internal_chip_high = { 8638c677cbSDavid Brownell .name = "SC-hi", 871da177e4SLinus Torvalds .ack = pxa_mask_high_irq, 881da177e4SLinus Torvalds .mask = pxa_mask_high_irq, 891da177e4SLinus Torvalds .unmask = pxa_unmask_high_irq, 901da177e4SLinus Torvalds }; 911da177e4SLinus Torvalds 92c08b7b3eSEric Miao void __init pxa_init_irq_high(void) 93c08b7b3eSEric Miao { 94c08b7b3eSEric Miao int irq; 95c08b7b3eSEric Miao 96c08b7b3eSEric Miao ICMR2 = 0; 97c08b7b3eSEric Miao ICLR2 = 0; 98c08b7b3eSEric Miao 99c08b7b3eSEric Miao for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) { 100c08b7b3eSEric Miao set_irq_chip(irq, &pxa_internal_chip_high); 101c08b7b3eSEric Miao set_irq_handler(irq, handle_level_irq); 102c08b7b3eSEric Miao set_irq_flags(irq, IRQF_VALID); 103c08b7b3eSEric Miao } 104c08b7b3eSEric Miao } 1051da177e4SLinus Torvalds #endif 1061da177e4SLinus Torvalds 107c95530c7Seric miao void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)) 108c95530c7Seric miao { 109c95530c7Seric miao pxa_internal_chip_low.set_wake = set_wake; 110c95530c7Seric miao #ifdef CONFIG_PXA27x 111c95530c7Seric miao pxa_internal_chip_high.set_wake = set_wake; 112c95530c7Seric miao #endif 113a7bf4dbaSeric miao pxa_init_gpio_set_wake(set_wake); 114c95530c7Seric miao } 115c0165504Seric miao 116c0165504Seric miao #ifdef CONFIG_PM 117c0165504Seric miao static unsigned long saved_icmr[2]; 118c0165504Seric miao 119c0165504Seric miao static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) 120c0165504Seric miao { 121c0165504Seric miao switch (dev->id) { 122c0165504Seric miao case 0: 123c0165504Seric miao saved_icmr[0] = ICMR; 124c0165504Seric miao ICMR = 0; 125c0165504Seric miao break; 126c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 127c0165504Seric miao case 1: 128c0165504Seric miao saved_icmr[1] = ICMR2; 129c0165504Seric miao ICMR2 = 0; 130c0165504Seric miao break; 131c0165504Seric miao #endif 132c0165504Seric miao default: 133c0165504Seric miao return -EINVAL; 134c0165504Seric miao } 135c0165504Seric miao 136c0165504Seric miao return 0; 137c0165504Seric miao } 138c0165504Seric miao 139c0165504Seric miao static int pxa_irq_resume(struct sys_device *dev) 140c0165504Seric miao { 141c0165504Seric miao switch (dev->id) { 142c0165504Seric miao case 0: 143c0165504Seric miao ICMR = saved_icmr[0]; 144c0165504Seric miao ICLR = 0; 145c0165504Seric miao ICCR = 1; 146c0165504Seric miao break; 147c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 148c0165504Seric miao case 1: 149c0165504Seric miao ICMR2 = saved_icmr[1]; 150c0165504Seric miao ICLR2 = 0; 151c0165504Seric miao break; 152c0165504Seric miao #endif 153c0165504Seric miao default: 154c0165504Seric miao return -EINVAL; 155c0165504Seric miao } 156c0165504Seric miao 157c0165504Seric miao return 0; 158c0165504Seric miao } 159c0165504Seric miao #else 160c0165504Seric miao #define pxa_irq_suspend NULL 161c0165504Seric miao #define pxa_irq_resume NULL 162c0165504Seric miao #endif 163c0165504Seric miao 164c0165504Seric miao struct sysdev_class pxa_irq_sysclass = { 165c0165504Seric miao .name = "irq", 166c0165504Seric miao .suspend = pxa_irq_suspend, 167c0165504Seric miao .resume = pxa_irq_resume, 168c0165504Seric miao }; 169c0165504Seric miao 170c0165504Seric miao static int __init pxa_irq_init(void) 171c0165504Seric miao { 172c0165504Seric miao return sysdev_class_register(&pxa_irq_sysclass); 173c0165504Seric miao } 174c0165504Seric miao 175c0165504Seric miao core_initcall(pxa_irq_init); 176