/* * linux/arch/arm/mach-sa1100/irq.c * * Copyright (C) 1999-2001 Nicolas Pitre * * Generic IRQ handling for the SA11x0, GPIO 11-27 IRQ demultiplexing. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include "generic.h" /* * SA1100 GPIO edge detection for IRQs: * IRQs are generated on Falling-Edge, Rising-Edge, or both. * This must be called *before* the appropriate IRQ is registered. * Use this instead of directly setting GRER/GFER. */ static int GPIO_IRQ_rising_edge; static int GPIO_IRQ_falling_edge; void set_GPIO_IRQ_edge( int gpio_mask, int edge ) { if (edge & GPIO_FALLING_EDGE) GPIO_IRQ_falling_edge |= gpio_mask; else GPIO_IRQ_falling_edge &= ~gpio_mask; if (edge & GPIO_RISING_EDGE) GPIO_IRQ_rising_edge |= gpio_mask; else GPIO_IRQ_rising_edge &= ~gpio_mask; } EXPORT_SYMBOL(set_GPIO_IRQ_edge); /* * We don't need to ACK IRQs on the SA1100 unless they're GPIOs * this is for internal IRQs i.e. from 11 to 31. */ static void sa1100_mask_irq(unsigned int irq) { ICMR &= ~(1 << irq); } static void sa1100_unmask_irq(unsigned int irq) { ICMR |= (1 << irq); } /* * GPIO IRQs must be acknoledged. This is for IRQs from 0 to 10. */ static void sa1100_mask_and_ack_GPIO0_10_irq(unsigned int irq) { ICMR &= ~(1 << irq); GEDR = (1 << irq); } static void sa1100_mask_GPIO0_10_irq(unsigned int irq) { ICMR &= ~(1 << irq); } static void sa1100_unmask_GPIO0_10_irq(unsigned int irq) { GRER = (GRER & ~(1 << irq)) | (GPIO_IRQ_rising_edge & (1 << irq)); GFER = (GFER & ~(1 << irq)) | (GPIO_IRQ_falling_edge & (1 << irq)); ICMR |= (1 << irq); } /* * Install handler for GPIO 11-27 edge detect interrupts */ static int GPIO_11_27_enabled; /* enabled i.e. unmasked GPIO IRQs */ static int GPIO_11_27_spurious; /* GPIOs that triggered when masked */ static void sa1100_GPIO11_27_demux(int irq, void *dev_id, struct pt_regs *regs) { int i, spurious; while ((irq = (GEDR & 0xfffff800))) { /* * We don't want to clear GRER/GFER when the corresponding * IRQ is masked because we could miss a level transition * i.e. an IRQ which need servicing as soon as it is * unmasked. However, such situation should happen only * during the loop below. Thus all IRQs which aren't * enabled at this point are considered spurious. Those * are cleared but only de-activated if they happen twice. */ spurious = irq & ~GPIO_11_27_enabled; if (spurious) { GEDR = spurious; GRER &= ~(spurious & GPIO_11_27_spurious); GFER &= ~(spurious & GPIO_11_27_spurious); GPIO_11_27_spurious |= spurious; irq ^= spurious; if (!irq) continue; } for (i = 11; i <= 27; ++i) { if (irq & (1<