1/* 2 * linux/arch/arm/mach-imx/irq.c 3 * 4 * Copyright (C) 1999 ARM Limited 5 * Copyright (C) 2002 Shane Nay (shane@minirl.com) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * 03/03/2004 Sascha Hauer <sascha@saschahauer.de> 22 * Copied from the motorola bsp package and added gpio demux 23 * interrupt handler 24 */ 25 26#include <linux/init.h> 27#include <linux/list.h> 28#include <linux/timer.h> 29 30#include <asm/hardware.h> 31#include <asm/irq.h> 32#include <asm/io.h> 33 34#include <asm/mach/irq.h> 35 36 37#define INTENNUM_OFF 0x8 38#define INTDISNUM_OFF 0xC 39 40#define VA_AITC_BASE IO_ADDRESS(IMX_AITC_BASE) 41#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF) 42#define IMX_AITC_INTENNUM (VA_AITC_BASE + INTENNUM_OFF) 43 44#define DEBUG_IRQ(fmt...) do { } while (0) 45 46static void 47imx_mask_irq(unsigned int irq) 48{ 49 __raw_writel(irq, IMX_AITC_INTDISNUM); 50} 51 52static void 53imx_unmask_irq(unsigned int irq) 54{ 55 __raw_writel(irq, IMX_AITC_INTENNUM); 56} 57 58static int 59imx_gpio_irq_type(unsigned int _irq, unsigned int type) 60{ 61 unsigned int irq_type = 0, irq, reg, bit; 62 63 irq = _irq - IRQ_GPIOA(0); 64 reg = irq >> 5; 65 bit = 1 << (irq % 32); 66 67 if (type == IRQT_PROBE) { 68 /* Don't mess with enabled GPIOs using preconfigured edges or 69 GPIOs set to alternate function during probe */ 70 /* TODO: support probe */ 71// if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) & 72// GPIO_bit(gpio)) 73// return 0; 74// if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2))) 75// return 0; 76// type = __IRQT_RISEDGE | __IRQT_FALEDGE; 77 } 78 79 GIUS(reg) |= bit; 80 DDIR(reg) &= ~(bit); 81 82 DEBUG_IRQ("setting type of irq %d to ", _irq); 83 84 if (type & __IRQT_RISEDGE) { 85 DEBUG_IRQ("rising edges\n"); 86 irq_type = 0x0; 87 } 88 if (type & __IRQT_FALEDGE) { 89 DEBUG_IRQ("falling edges\n"); 90 irq_type = 0x1; 91 } 92 if (type & __IRQT_LOWLVL) { 93 DEBUG_IRQ("low level\n"); 94 irq_type = 0x3; 95 } 96 if (type & __IRQT_HIGHLVL) { 97 DEBUG_IRQ("high level\n"); 98 irq_type = 0x2; 99 } 100 101 if (irq % 32 < 16) { 102 ICR1(reg) = (ICR1(reg) & ~(0x3 << ((irq % 16) * 2))) | 103 (irq_type << ((irq % 16) * 2)); 104 } else { 105 ICR2(reg) = (ICR2(reg) & ~(0x3 << ((irq % 16) * 2))) | 106 (irq_type << ((irq % 16) * 2)); 107 } 108 109 return 0; 110 111} 112 113static void 114imx_gpio_ack_irq(unsigned int irq) 115{ 116 DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq); 117 ISR(IRQ_TO_REG(irq)) = 1 << ((irq - IRQ_GPIOA(0)) % 32); 118} 119 120static void 121imx_gpio_mask_irq(unsigned int irq) 122{ 123 DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq); 124 IMR(IRQ_TO_REG(irq)) &= ~( 1 << ((irq - IRQ_GPIOA(0)) % 32)); 125} 126 127static void 128imx_gpio_unmask_irq(unsigned int irq) 129{ 130 DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq); 131 IMR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32); 132} 133 134static void 135imx_gpio_handler(unsigned int mask, unsigned int irq, 136 struct irq_desc *desc) 137{ 138 desc = irq_desc + irq; 139 while (mask) { 140 if (mask & 1) { 141 DEBUG_IRQ("handling irq %d\n", irq); 142 desc_handle_irq(irq, desc); 143 } 144 irq++; 145 desc++; 146 mask >>= 1; 147 } 148} 149 150static void 151imx_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) 152{ 153 unsigned int mask, irq; 154 155 mask = ISR(0); 156 irq = IRQ_GPIOA(0); 157 imx_gpio_handler(mask, irq, desc); 158} 159 160static void 161imx_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) 162{ 163 unsigned int mask, irq; 164 165 mask = ISR(1); 166 irq = IRQ_GPIOB(0); 167 imx_gpio_handler(mask, irq, desc); 168} 169 170static void 171imx_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) 172{ 173 unsigned int mask, irq; 174 175 mask = ISR(2); 176 irq = IRQ_GPIOC(0); 177 imx_gpio_handler(mask, irq, desc); 178} 179 180static void 181imx_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) 182{ 183 unsigned int mask, irq; 184 185 mask = ISR(3); 186 irq = IRQ_GPIOD(0); 187 imx_gpio_handler(mask, irq, desc); 188} 189 190static struct irq_chip imx_internal_chip = { 191 .name = "MPU", 192 .ack = imx_mask_irq, 193 .mask = imx_mask_irq, 194 .unmask = imx_unmask_irq, 195}; 196 197static struct irq_chip imx_gpio_chip = { 198 .name = "GPIO", 199 .ack = imx_gpio_ack_irq, 200 .mask = imx_gpio_mask_irq, 201 .unmask = imx_gpio_unmask_irq, 202 .set_type = imx_gpio_irq_type, 203}; 204 205void __init 206imx_init_irq(void) 207{ 208 unsigned int irq; 209 210 DEBUG_IRQ("Initializing imx interrupts\n"); 211 212 /* Mask all interrupts initially */ 213 IMR(0) = 0; 214 IMR(1) = 0; 215 IMR(2) = 0; 216 IMR(3) = 0; 217 218 for (irq = 0; irq < IMX_IRQS; irq++) { 219 set_irq_chip(irq, &imx_internal_chip); 220 set_irq_handler(irq, handle_level_irq); 221 set_irq_flags(irq, IRQF_VALID); 222 } 223 224 for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) { 225 set_irq_chip(irq, &imx_gpio_chip); 226 set_irq_handler(irq, handle_edge_irq); 227 set_irq_flags(irq, IRQF_VALID); 228 } 229 230 set_irq_chained_handler(GPIO_INT_PORTA, imx_gpioa_demux_handler); 231 set_irq_chained_handler(GPIO_INT_PORTB, imx_gpiob_demux_handler); 232 set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler); 233 set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler); 234 235 /* Disable all interrupts initially. */ 236 /* In IMX this is done in the bootloader. */ 237} 238