123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /*
- * linux/arch/arm/mach-pxa/irq.c
- *
- * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
- *
- * Author: Nicolas Pitre
- * Created: Jun 15, 2001
- * Copyright: MontaVista Software Inc.
- *
- * 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 <linux/init.h>
- #include <linux/module.h>
- #include <linux/interrupt.h>
- #include <linux/ptrace.h>
- #include <asm/hardware.h>
- #include <asm/irq.h>
- #include <asm/mach/irq.h>
- #include <asm/arch/pxa-regs.h>
- #include "generic.h"
- /*
- * This is for peripheral IRQs internal to the PXA chip.
- */
- static void pxa_mask_low_irq(unsigned int irq)
- {
- ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
- }
- static void pxa_unmask_low_irq(unsigned int irq)
- {
- ICMR |= (1 << (irq + PXA_IRQ_SKIP));
- }
- static struct irqchip pxa_internal_chip_low = {
- .ack = pxa_mask_low_irq,
- .mask = pxa_mask_low_irq,
- .unmask = pxa_unmask_low_irq,
- };
- #if PXA_INTERNAL_IRQS > 32
- /*
- * This is for the second set of internal IRQs as found on the PXA27x.
- */
- static void pxa_mask_high_irq(unsigned int irq)
- {
- ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
- }
- static void pxa_unmask_high_irq(unsigned int irq)
- {
- ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
- }
- static struct irqchip pxa_internal_chip_high = {
- .ack = pxa_mask_high_irq,
- .mask = pxa_mask_high_irq,
- .unmask = pxa_unmask_high_irq,
- };
- #endif
- /*
- * PXA GPIO edge detection for IRQs:
- * IRQs are generated on Falling-Edge, Rising-Edge, or both.
- * Use this instead of directly setting GRER/GFER.
- */
- static long GPIO_IRQ_rising_edge[4];
- static long GPIO_IRQ_falling_edge[4];
- static long GPIO_IRQ_mask[4];
- static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
- {
- int gpio, idx;
- gpio = IRQ_TO_GPIO(irq);
- idx = gpio >> 5;
- if (type == IRQT_PROBE) {
- /* Don't mess with enabled GPIOs using preconfigured edges or
- GPIOs set to alternate function during probe */
- if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
- GPIO_bit(gpio))
- return 0;
- if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
- return 0;
- type = __IRQT_RISEDGE | __IRQT_FALEDGE;
- }
- /* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */
- pxa_gpio_mode(gpio | GPIO_IN);
- if (type & __IRQT_RISEDGE) {
- /* printk("rising "); */
- __set_bit (gpio, GPIO_IRQ_rising_edge);
- } else
- __clear_bit (gpio, GPIO_IRQ_rising_edge);
- if (type & __IRQT_FALEDGE) {
- /* printk("falling "); */
- __set_bit (gpio, GPIO_IRQ_falling_edge);
- } else
- __clear_bit (gpio, GPIO_IRQ_falling_edge);
- /* printk("edges\n"); */
- GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
- GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
- return 0;
- }
- /*
- * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1.
- */
- static void pxa_ack_low_gpio(unsigned int irq)
- {
- GEDR0 = (1 << (irq - IRQ_GPIO0));
- }
- static struct irqchip pxa_low_gpio_chip = {
- .ack = pxa_ack_low_gpio,
- .mask = pxa_mask_low_irq,
- .unmask = pxa_unmask_low_irq,
- .set_type = pxa_gpio_irq_type,
- };
- /*
- * Demux handler for GPIO>=2 edge detect interrupts
- */
- static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
- struct pt_regs *regs)
- {
- unsigned int mask;
- int loop;
- do {
- loop = 0;
- mask = GEDR0 & ~3;
- if (mask) {
- GEDR0 = mask;
- irq = IRQ_GPIO(2);
- desc = irq_desc + irq;
- mask >>= 2;
- do {
- if (mask & 1)
- desc_handle_irq(irq, desc, regs);
- irq++;
- desc++;
- mask >>= 1;
- } while (mask);
- loop = 1;
- }
- mask = GEDR1;
- if (mask) {
- GEDR1 = mask;
- irq = IRQ_GPIO(32);
- desc = irq_desc + irq;
- do {
- if (mask & 1)
- desc_handle_irq(irq, desc, regs);
- irq++;
- desc++;
- mask >>= 1;
- } while (mask);
- loop = 1;
- }
- mask = GEDR2;
- if (mask) {
- GEDR2 = mask;
- irq = IRQ_GPIO(64);
- desc = irq_desc + irq;
- do {
- if (mask & 1)
- desc_handle_irq(irq, desc, regs);
- irq++;
- desc++;
- mask >>= 1;
- } while (mask);
- loop = 1;
- }
- #if PXA_LAST_GPIO >= 96
- mask = GEDR3;
- if (mask) {
- GEDR3 = mask;
- irq = IRQ_GPIO(96);
- desc = irq_desc + irq;
- do {
- if (mask & 1)
- desc_handle_irq(irq, desc, regs);
- irq++;
- desc++;
- mask >>= 1;
- } while (mask);
- loop = 1;
- }
- #endif
- } while (loop);
- }
- static void pxa_ack_muxed_gpio(unsigned int irq)
- {
- int gpio = irq - IRQ_GPIO(2) + 2;
- GEDR(gpio) = GPIO_bit(gpio);
- }
- static void pxa_mask_muxed_gpio(unsigned int irq)
- {
- int gpio = irq - IRQ_GPIO(2) + 2;
- __clear_bit(gpio, GPIO_IRQ_mask);
- GRER(gpio) &= ~GPIO_bit(gpio);
- GFER(gpio) &= ~GPIO_bit(gpio);
- }
- static void pxa_unmask_muxed_gpio(unsigned int irq)
- {
- int gpio = irq - IRQ_GPIO(2) + 2;
- int idx = gpio >> 5;
- __set_bit(gpio, GPIO_IRQ_mask);
- GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
- GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
- }
- static struct irqchip pxa_muxed_gpio_chip = {
- .ack = pxa_ack_muxed_gpio,
- .mask = pxa_mask_muxed_gpio,
- .unmask = pxa_unmask_muxed_gpio,
- .set_type = pxa_gpio_irq_type,
- };
- void __init pxa_init_irq(void)
- {
- int irq;
- /* disable all IRQs */
- ICMR = 0;
- /* all IRQs are IRQ, not FIQ */
- ICLR = 0;
- /* clear all GPIO edge detects */
- GFER0 = 0;
- GFER1 = 0;
- GFER2 = 0;
- GRER0 = 0;
- GRER1 = 0;
- GRER2 = 0;
- GEDR0 = GEDR0;
- GEDR1 = GEDR1;
- GEDR2 = GEDR2;
- #ifdef CONFIG_PXA27x
- /* And similarly for the extra regs on the PXA27x */
- ICMR2 = 0;
- ICLR2 = 0;
- GFER3 = 0;
- GRER3 = 0;
- GEDR3 = GEDR3;
- #endif
- /* only unmasked interrupts kick us out of idle */
- ICCR = 1;
- /* GPIO 0 and 1 must have their mask bit always set */
- GPIO_IRQ_mask[0] = 3;
- for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
- set_irq_chip(irq, &pxa_internal_chip_low);
- set_irq_handler(irq, do_level_IRQ);
- set_irq_flags(irq, IRQF_VALID);
- }
- #if PXA_INTERNAL_IRQS > 32
- for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
- set_irq_chip(irq, &pxa_internal_chip_high);
- set_irq_handler(irq, do_level_IRQ);
- set_irq_flags(irq, IRQF_VALID);
- }
- #endif
- for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
- set_irq_chip(irq, &pxa_low_gpio_chip);
- set_irq_handler(irq, do_edge_IRQ);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
- for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
- set_irq_chip(irq, &pxa_muxed_gpio_chip);
- set_irq_handler(irq, do_edge_IRQ);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
- /* Install handler for GPIO>=2 edge detect interrupts */
- set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
- set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
- }
|