11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/arm/mach-pxa/irq.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc. 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 1071da177e4SLinus Torvalds /* 1081da177e4SLinus Torvalds * PXA GPIO edge detection for IRQs: 1091da177e4SLinus Torvalds * IRQs are generated on Falling-Edge, Rising-Edge, or both. 1101da177e4SLinus Torvalds * Use this instead of directly setting GRER/GFER. 1111da177e4SLinus Torvalds */ 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds static long GPIO_IRQ_rising_edge[4]; 1141da177e4SLinus Torvalds static long GPIO_IRQ_falling_edge[4]; 1151da177e4SLinus Torvalds static long GPIO_IRQ_mask[4]; 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) 1181da177e4SLinus Torvalds { 1191da177e4SLinus Torvalds int gpio, idx; 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds gpio = IRQ_TO_GPIO(irq); 1221da177e4SLinus Torvalds idx = gpio >> 5; 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds if (type == IRQT_PROBE) { 1251da177e4SLinus Torvalds /* Don't mess with enabled GPIOs using preconfigured edges or 126e033108bSGuennadi Liakhovetski GPIOs set to alternate function or to output during probe */ 127e033108bSGuennadi Liakhovetski if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx] | GPDR(gpio)) & 1281da177e4SLinus Torvalds GPIO_bit(gpio)) 1291da177e4SLinus Torvalds return 0; 1301da177e4SLinus Torvalds if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2))) 1311da177e4SLinus Torvalds return 0; 1321da177e4SLinus Torvalds type = __IRQT_RISEDGE | __IRQT_FALEDGE; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */ 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds pxa_gpio_mode(gpio | GPIO_IN); 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds if (type & __IRQT_RISEDGE) { 1401da177e4SLinus Torvalds /* printk("rising "); */ 1411da177e4SLinus Torvalds __set_bit (gpio, GPIO_IRQ_rising_edge); 1424fe4a2bfSPhilipp Zabel } else { 1431da177e4SLinus Torvalds __clear_bit (gpio, GPIO_IRQ_rising_edge); 1444fe4a2bfSPhilipp Zabel } 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds if (type & __IRQT_FALEDGE) { 1471da177e4SLinus Torvalds /* printk("falling "); */ 1481da177e4SLinus Torvalds __set_bit (gpio, GPIO_IRQ_falling_edge); 1494fe4a2bfSPhilipp Zabel } else { 1501da177e4SLinus Torvalds __clear_bit (gpio, GPIO_IRQ_falling_edge); 1514fe4a2bfSPhilipp Zabel } 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds /* printk("edges\n"); */ 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx]; 1561da177e4SLinus Torvalds GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx]; 1571da177e4SLinus Torvalds return 0; 1581da177e4SLinus Torvalds } 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds /* 1611da177e4SLinus Torvalds * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1. 1621da177e4SLinus Torvalds */ 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds static void pxa_ack_low_gpio(unsigned int irq) 1651da177e4SLinus Torvalds { 1661da177e4SLinus Torvalds GEDR0 = (1 << (irq - IRQ_GPIO0)); 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 16938c677cbSDavid Brownell static struct irq_chip pxa_low_gpio_chip = { 17038c677cbSDavid Brownell .name = "GPIO-l", 1711da177e4SLinus Torvalds .ack = pxa_ack_low_gpio, 1721da177e4SLinus Torvalds .mask = pxa_mask_low_irq, 1731da177e4SLinus Torvalds .unmask = pxa_unmask_low_irq, 1747801907bSRussell King .set_type = pxa_gpio_irq_type, 1751da177e4SLinus Torvalds }; 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds /* 1781da177e4SLinus Torvalds * Demux handler for GPIO>=2 edge detect interrupts 1791da177e4SLinus Torvalds */ 1801da177e4SLinus Torvalds 18110dd5ce2SRussell King static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) 1821da177e4SLinus Torvalds { 1831da177e4SLinus Torvalds unsigned int mask; 1841da177e4SLinus Torvalds int loop; 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds do { 1871da177e4SLinus Torvalds loop = 0; 1881da177e4SLinus Torvalds 1894a3dcd35SEric Miao mask = GEDR0 & GPIO_IRQ_mask[0] & ~3; 1901da177e4SLinus Torvalds if (mask) { 1911da177e4SLinus Torvalds GEDR0 = mask; 1921da177e4SLinus Torvalds irq = IRQ_GPIO(2); 1931da177e4SLinus Torvalds desc = irq_desc + irq; 1941da177e4SLinus Torvalds mask >>= 2; 1951da177e4SLinus Torvalds do { 1961da177e4SLinus Torvalds if (mask & 1) 1970cd61b68SLinus Torvalds desc_handle_irq(irq, desc); 1981da177e4SLinus Torvalds irq++; 1991da177e4SLinus Torvalds desc++; 2001da177e4SLinus Torvalds mask >>= 1; 2011da177e4SLinus Torvalds } while (mask); 2021da177e4SLinus Torvalds loop = 1; 2031da177e4SLinus Torvalds } 2041da177e4SLinus Torvalds 2054a3dcd35SEric Miao mask = GEDR1 & GPIO_IRQ_mask[1]; 2061da177e4SLinus Torvalds if (mask) { 2071da177e4SLinus Torvalds GEDR1 = mask; 2081da177e4SLinus Torvalds irq = IRQ_GPIO(32); 2091da177e4SLinus Torvalds desc = irq_desc + irq; 2101da177e4SLinus Torvalds do { 2111da177e4SLinus Torvalds if (mask & 1) 2120cd61b68SLinus Torvalds desc_handle_irq(irq, desc); 2131da177e4SLinus Torvalds irq++; 2141da177e4SLinus Torvalds desc++; 2151da177e4SLinus Torvalds mask >>= 1; 2161da177e4SLinus Torvalds } while (mask); 2171da177e4SLinus Torvalds loop = 1; 2181da177e4SLinus Torvalds } 2191da177e4SLinus Torvalds 2204a3dcd35SEric Miao mask = GEDR2 & GPIO_IRQ_mask[2]; 2211da177e4SLinus Torvalds if (mask) { 2221da177e4SLinus Torvalds GEDR2 = mask; 2231da177e4SLinus Torvalds irq = IRQ_GPIO(64); 2241da177e4SLinus Torvalds desc = irq_desc + irq; 2251da177e4SLinus Torvalds do { 2261da177e4SLinus Torvalds if (mask & 1) 2270cd61b68SLinus Torvalds desc_handle_irq(irq, desc); 2281da177e4SLinus Torvalds irq++; 2291da177e4SLinus Torvalds desc++; 2301da177e4SLinus Torvalds mask >>= 1; 2311da177e4SLinus Torvalds } while (mask); 2321da177e4SLinus Torvalds loop = 1; 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds 2354a3dcd35SEric Miao mask = GEDR3 & GPIO_IRQ_mask[3]; 2361da177e4SLinus Torvalds if (mask) { 2371da177e4SLinus Torvalds GEDR3 = mask; 2381da177e4SLinus Torvalds irq = IRQ_GPIO(96); 2391da177e4SLinus Torvalds desc = irq_desc + irq; 2401da177e4SLinus Torvalds do { 2411da177e4SLinus Torvalds if (mask & 1) 2420cd61b68SLinus Torvalds desc_handle_irq(irq, desc); 2431da177e4SLinus Torvalds irq++; 2441da177e4SLinus Torvalds desc++; 2451da177e4SLinus Torvalds mask >>= 1; 2461da177e4SLinus Torvalds } while (mask); 2471da177e4SLinus Torvalds loop = 1; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds } while (loop); 2501da177e4SLinus Torvalds } 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds static void pxa_ack_muxed_gpio(unsigned int irq) 2531da177e4SLinus Torvalds { 2541da177e4SLinus Torvalds int gpio = irq - IRQ_GPIO(2) + 2; 2551da177e4SLinus Torvalds GEDR(gpio) = GPIO_bit(gpio); 2561da177e4SLinus Torvalds } 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds static void pxa_mask_muxed_gpio(unsigned int irq) 2591da177e4SLinus Torvalds { 2601da177e4SLinus Torvalds int gpio = irq - IRQ_GPIO(2) + 2; 2611da177e4SLinus Torvalds __clear_bit(gpio, GPIO_IRQ_mask); 2621da177e4SLinus Torvalds GRER(gpio) &= ~GPIO_bit(gpio); 2631da177e4SLinus Torvalds GFER(gpio) &= ~GPIO_bit(gpio); 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds static void pxa_unmask_muxed_gpio(unsigned int irq) 2671da177e4SLinus Torvalds { 2681da177e4SLinus Torvalds int gpio = irq - IRQ_GPIO(2) + 2; 2691da177e4SLinus Torvalds int idx = gpio >> 5; 2701da177e4SLinus Torvalds __set_bit(gpio, GPIO_IRQ_mask); 2711da177e4SLinus Torvalds GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx]; 2721da177e4SLinus Torvalds GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx]; 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 27538c677cbSDavid Brownell static struct irq_chip pxa_muxed_gpio_chip = { 27638c677cbSDavid Brownell .name = "GPIO", 2771da177e4SLinus Torvalds .ack = pxa_ack_muxed_gpio, 2781da177e4SLinus Torvalds .mask = pxa_mask_muxed_gpio, 2791da177e4SLinus Torvalds .unmask = pxa_unmask_muxed_gpio, 2807801907bSRussell King .set_type = pxa_gpio_irq_type, 2811da177e4SLinus Torvalds }; 2821da177e4SLinus Torvalds 283348f2e3bSEric Miao void __init pxa_init_irq_gpio(int gpio_nr) 2841da177e4SLinus Torvalds { 285348f2e3bSEric Miao int irq, i; 2861da177e4SLinus Torvalds 28730f0b408Seric miao pxa_last_gpio = gpio_nr - 1; 28830f0b408Seric miao 2891da177e4SLinus Torvalds /* clear all GPIO edge detects */ 290348f2e3bSEric Miao for (i = 0; i < gpio_nr; i += 32) { 291348f2e3bSEric Miao GFER(i) = 0; 292348f2e3bSEric Miao GRER(i) = 0; 293348f2e3bSEric Miao GEDR(i) = GEDR(i); 294348f2e3bSEric Miao } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds /* GPIO 0 and 1 must have their mask bit always set */ 2971da177e4SLinus Torvalds GPIO_IRQ_mask[0] = 3; 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvalds for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { 3001da177e4SLinus Torvalds set_irq_chip(irq, &pxa_low_gpio_chip); 30110dd5ce2SRussell King set_irq_handler(irq, handle_edge_irq); 3021da177e4SLinus Torvalds set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds 305fd51bcc5SSamuel for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) { 3061da177e4SLinus Torvalds set_irq_chip(irq, &pxa_muxed_gpio_chip); 30710dd5ce2SRussell King set_irq_handler(irq, handle_edge_irq); 3081da177e4SLinus Torvalds set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 3091da177e4SLinus Torvalds } 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds /* Install handler for GPIO>=2 edge detect interrupts */ 3121da177e4SLinus Torvalds set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low); 3131da177e4SLinus Torvalds set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); 3141da177e4SLinus Torvalds } 315c95530c7Seric miao 316c95530c7Seric miao void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)) 317c95530c7Seric miao { 318c95530c7Seric miao pxa_internal_chip_low.set_wake = set_wake; 319c95530c7Seric miao #ifdef CONFIG_PXA27x 320c95530c7Seric miao pxa_internal_chip_high.set_wake = set_wake; 321c95530c7Seric miao #endif 322c95530c7Seric miao pxa_low_gpio_chip.set_wake = set_wake; 323c95530c7Seric miao pxa_muxed_gpio_chip.set_wake = set_wake; 324c95530c7Seric miao } 325c0165504Seric miao 326c0165504Seric miao #ifdef CONFIG_PM 327c0165504Seric miao static unsigned long saved_icmr[2]; 328c0165504Seric miao 329c0165504Seric miao static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) 330c0165504Seric miao { 331c0165504Seric miao switch (dev->id) { 332c0165504Seric miao case 0: 333c0165504Seric miao saved_icmr[0] = ICMR; 334c0165504Seric miao ICMR = 0; 335c0165504Seric miao break; 336c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 337c0165504Seric miao case 1: 338c0165504Seric miao saved_icmr[1] = ICMR2; 339c0165504Seric miao ICMR2 = 0; 340c0165504Seric miao break; 341c0165504Seric miao #endif 342c0165504Seric miao default: 343c0165504Seric miao return -EINVAL; 344c0165504Seric miao } 345c0165504Seric miao 346c0165504Seric miao return 0; 347c0165504Seric miao } 348c0165504Seric miao 349c0165504Seric miao static int pxa_irq_resume(struct sys_device *dev) 350c0165504Seric miao { 351c0165504Seric miao switch (dev->id) { 352c0165504Seric miao case 0: 353c0165504Seric miao ICMR = saved_icmr[0]; 354c0165504Seric miao ICLR = 0; 355c0165504Seric miao ICCR = 1; 356c0165504Seric miao break; 357c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 358c0165504Seric miao case 1: 359c0165504Seric miao ICMR2 = saved_icmr[1]; 360c0165504Seric miao ICLR2 = 0; 361c0165504Seric miao break; 362c0165504Seric miao #endif 363c0165504Seric miao default: 364c0165504Seric miao return -EINVAL; 365c0165504Seric miao } 366c0165504Seric miao 367c0165504Seric miao return 0; 368c0165504Seric miao } 369c0165504Seric miao #else 370c0165504Seric miao #define pxa_irq_suspend NULL 371c0165504Seric miao #define pxa_irq_resume NULL 372c0165504Seric miao #endif 373c0165504Seric miao 374c0165504Seric miao struct sysdev_class pxa_irq_sysclass = { 375c0165504Seric miao .name = "irq", 376c0165504Seric miao .suspend = pxa_irq_suspend, 377c0165504Seric miao .resume = pxa_irq_resume, 378c0165504Seric miao }; 379c0165504Seric miao 380c0165504Seric miao static int __init pxa_irq_init(void) 381c0165504Seric miao { 382c0165504Seric miao return sysdev_class_register(&pxa_irq_sysclass); 383c0165504Seric miao } 384c0165504Seric miao 385c0165504Seric miao core_initcall(pxa_irq_init); 386