xref: /openbmc/linux/arch/arm/mach-pxa/irq.c (revision 7a26d3a3)
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 
1817a26d3a3Seric miao #define GEDR_BITS	(sizeof(gedr) * BITS_PER_BYTE)
1827a26d3a3Seric miao 
18310dd5ce2SRussell King static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
1841da177e4SLinus Torvalds {
1857a26d3a3Seric miao 	int loop, bit, n;
1867a26d3a3Seric miao 	unsigned long gedr[4];
1871da177e4SLinus Torvalds 
1881da177e4SLinus Torvalds 	do {
1897a26d3a3Seric miao 		gedr[0] = GEDR0 & GPIO_IRQ_mask[0] & ~3;
1907a26d3a3Seric miao 		gedr[1] = GEDR1 & GPIO_IRQ_mask[1];
1917a26d3a3Seric miao 		gedr[2] = GEDR2 & GPIO_IRQ_mask[2];
1927a26d3a3Seric miao 		gedr[3] = GEDR3 & GPIO_IRQ_mask[3];
1937a26d3a3Seric miao 
1947a26d3a3Seric miao 		GEDR0 = gedr[0]; GEDR1 = gedr[1];
1957a26d3a3Seric miao 		GEDR2 = gedr[2]; GEDR3 = gedr[3];
1967a26d3a3Seric miao 
1971da177e4SLinus Torvalds 		loop = 0;
1987a26d3a3Seric miao 		bit = find_first_bit(gedr, GEDR_BITS);
1997a26d3a3Seric miao 		while (bit < GEDR_BITS) {
2001da177e4SLinus Torvalds 			loop = 1;
2011da177e4SLinus Torvalds 
2027a26d3a3Seric miao 			n = PXA_GPIO_IRQ_BASE + bit;
2037a26d3a3Seric miao 			desc_handle_irq(n, irq_desc + n);
2041da177e4SLinus Torvalds 
2057a26d3a3Seric miao 			bit = find_next_bit(gedr, GEDR_BITS, bit + 1);
2061da177e4SLinus Torvalds 		}
2071da177e4SLinus Torvalds 	} while (loop);
2081da177e4SLinus Torvalds }
2091da177e4SLinus Torvalds 
2101da177e4SLinus Torvalds static void pxa_ack_muxed_gpio(unsigned int irq)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	int gpio = irq - IRQ_GPIO(2) + 2;
2131da177e4SLinus Torvalds 	GEDR(gpio) = GPIO_bit(gpio);
2141da177e4SLinus Torvalds }
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds static void pxa_mask_muxed_gpio(unsigned int irq)
2171da177e4SLinus Torvalds {
2181da177e4SLinus Torvalds 	int gpio = irq - IRQ_GPIO(2) + 2;
2191da177e4SLinus Torvalds 	__clear_bit(gpio, GPIO_IRQ_mask);
2201da177e4SLinus Torvalds 	GRER(gpio) &= ~GPIO_bit(gpio);
2211da177e4SLinus Torvalds 	GFER(gpio) &= ~GPIO_bit(gpio);
2221da177e4SLinus Torvalds }
2231da177e4SLinus Torvalds 
2241da177e4SLinus Torvalds static void pxa_unmask_muxed_gpio(unsigned int irq)
2251da177e4SLinus Torvalds {
2261da177e4SLinus Torvalds 	int gpio = irq - IRQ_GPIO(2) + 2;
2271da177e4SLinus Torvalds 	int idx = gpio >> 5;
2281da177e4SLinus Torvalds 	__set_bit(gpio, GPIO_IRQ_mask);
2291da177e4SLinus Torvalds 	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
2301da177e4SLinus Torvalds 	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
2311da177e4SLinus Torvalds }
2321da177e4SLinus Torvalds 
23338c677cbSDavid Brownell static struct irq_chip pxa_muxed_gpio_chip = {
23438c677cbSDavid Brownell 	.name		= "GPIO",
2351da177e4SLinus Torvalds 	.ack		= pxa_ack_muxed_gpio,
2361da177e4SLinus Torvalds 	.mask		= pxa_mask_muxed_gpio,
2371da177e4SLinus Torvalds 	.unmask		= pxa_unmask_muxed_gpio,
2387801907bSRussell King 	.set_type	= pxa_gpio_irq_type,
2391da177e4SLinus Torvalds };
2401da177e4SLinus Torvalds 
241348f2e3bSEric Miao void __init pxa_init_irq_gpio(int gpio_nr)
2421da177e4SLinus Torvalds {
243348f2e3bSEric Miao 	int irq, i;
2441da177e4SLinus Torvalds 
24530f0b408Seric miao 	pxa_last_gpio = gpio_nr - 1;
24630f0b408Seric miao 
2471da177e4SLinus Torvalds 	/* clear all GPIO edge detects */
248348f2e3bSEric Miao 	for (i = 0; i < gpio_nr; i += 32) {
249348f2e3bSEric Miao 		GFER(i) = 0;
250348f2e3bSEric Miao 		GRER(i) = 0;
251348f2e3bSEric Miao 		GEDR(i) = GEDR(i);
252348f2e3bSEric Miao 	}
2531da177e4SLinus Torvalds 
2541da177e4SLinus Torvalds 	/* GPIO 0 and 1 must have their mask bit always set */
2551da177e4SLinus Torvalds 	GPIO_IRQ_mask[0] = 3;
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
2581da177e4SLinus Torvalds 		set_irq_chip(irq, &pxa_low_gpio_chip);
25910dd5ce2SRussell King 		set_irq_handler(irq, handle_edge_irq);
2601da177e4SLinus Torvalds 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
2611da177e4SLinus Torvalds 	}
2621da177e4SLinus Torvalds 
263fd51bcc5SSamuel 	for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
2641da177e4SLinus Torvalds 		set_irq_chip(irq, &pxa_muxed_gpio_chip);
26510dd5ce2SRussell King 		set_irq_handler(irq, handle_edge_irq);
2661da177e4SLinus Torvalds 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
2671da177e4SLinus Torvalds 	}
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	/* Install handler for GPIO>=2 edge detect interrupts */
2701da177e4SLinus Torvalds 	set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
2711da177e4SLinus Torvalds 	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
2721c44f5f1SPhilipp Zabel 
2731c44f5f1SPhilipp Zabel 	pxa_init_gpio(gpio_nr);
2741da177e4SLinus Torvalds }
275c95530c7Seric miao 
276c95530c7Seric miao void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
277c95530c7Seric miao {
278c95530c7Seric miao 	pxa_internal_chip_low.set_wake = set_wake;
279c95530c7Seric miao #ifdef CONFIG_PXA27x
280c95530c7Seric miao 	pxa_internal_chip_high.set_wake = set_wake;
281c95530c7Seric miao #endif
282c95530c7Seric miao 	pxa_low_gpio_chip.set_wake = set_wake;
283c95530c7Seric miao 	pxa_muxed_gpio_chip.set_wake = set_wake;
284c95530c7Seric miao }
285c0165504Seric miao 
286c0165504Seric miao #ifdef CONFIG_PM
287c0165504Seric miao static unsigned long saved_icmr[2];
288c0165504Seric miao 
289c0165504Seric miao static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
290c0165504Seric miao {
291c0165504Seric miao 	switch (dev->id) {
292c0165504Seric miao 	case 0:
293c0165504Seric miao 		saved_icmr[0] = ICMR;
294c0165504Seric miao 		ICMR = 0;
295c0165504Seric miao 		break;
296c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
297c0165504Seric miao 	case 1:
298c0165504Seric miao 		saved_icmr[1] = ICMR2;
299c0165504Seric miao 		ICMR2 = 0;
300c0165504Seric miao 		break;
301c0165504Seric miao #endif
302c0165504Seric miao 	default:
303c0165504Seric miao 		return -EINVAL;
304c0165504Seric miao 	}
305c0165504Seric miao 
306c0165504Seric miao 	return 0;
307c0165504Seric miao }
308c0165504Seric miao 
309c0165504Seric miao static int pxa_irq_resume(struct sys_device *dev)
310c0165504Seric miao {
311c0165504Seric miao 	switch (dev->id) {
312c0165504Seric miao 	case 0:
313c0165504Seric miao 		ICMR = saved_icmr[0];
314c0165504Seric miao 		ICLR = 0;
315c0165504Seric miao 		ICCR = 1;
316c0165504Seric miao 		break;
317c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
318c0165504Seric miao 	case 1:
319c0165504Seric miao 		ICMR2 = saved_icmr[1];
320c0165504Seric miao 		ICLR2 = 0;
321c0165504Seric miao 		break;
322c0165504Seric miao #endif
323c0165504Seric miao 	default:
324c0165504Seric miao 		return -EINVAL;
325c0165504Seric miao 	}
326c0165504Seric miao 
327c0165504Seric miao 	return 0;
328c0165504Seric miao }
329c0165504Seric miao #else
330c0165504Seric miao #define pxa_irq_suspend		NULL
331c0165504Seric miao #define pxa_irq_resume		NULL
332c0165504Seric miao #endif
333c0165504Seric miao 
334c0165504Seric miao struct sysdev_class pxa_irq_sysclass = {
335c0165504Seric miao 	.name		= "irq",
336c0165504Seric miao 	.suspend	= pxa_irq_suspend,
337c0165504Seric miao 	.resume		= pxa_irq_resume,
338c0165504Seric miao };
339c0165504Seric miao 
340c0165504Seric miao static int __init pxa_irq_init(void)
341c0165504Seric miao {
342c0165504Seric miao 	return sysdev_class_register(&pxa_irq_sysclass);
343c0165504Seric miao }
344c0165504Seric miao 
345c0165504Seric miao core_initcall(pxa_irq_init);
346