Blame view
arch/arm/mach-sa1100/irq.c
7.06 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * 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 <linux/init.h> #include <linux/module.h> |
119c641c9 [ARM] 3698/1: ARM... |
14 15 |
#include <linux/interrupt.h> #include <linux/irq.h> |
1da177e4c Linux-2.6.12-rc2 |
16 |
#include <linux/ioport.h> |
905339807 ARM / SA1100: Use... |
17 |
#include <linux/syscore_ops.h> |
1da177e4c Linux-2.6.12-rc2 |
18 |
|
a09e64fbc [ARM] Move includ... |
19 |
#include <mach/hardware.h> |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <asm/mach/irq.h> #include "generic.h" /* * SA1100 GPIO edge detection for IRQs: * IRQs are generated on Falling-Edge, Rising-Edge, or both. * Use this instead of directly setting GRER/GFER. */ static int GPIO_IRQ_rising_edge; static int GPIO_IRQ_falling_edge; static int GPIO_IRQ_mask = (1 << 11) - 1; /* * To get the GPIO number from an IRQ number */ #define GPIO_11_27_IRQ(i) ((i) - 21) #define GPIO11_27_MASK(irq) (1 << GPIO_11_27_IRQ(irq)) |
c4e8964e4 ARM: sa1100: irq_... |
39 |
static int sa1100_gpio_type(struct irq_data *d, unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
40 41 |
{ unsigned int mask; |
c4e8964e4 ARM: sa1100: irq_... |
42 43 |
if (d->irq <= 10) mask = 1 << d->irq; |
1da177e4c Linux-2.6.12-rc2 |
44 |
else |
c4e8964e4 ARM: sa1100: irq_... |
45 |
mask = GPIO11_27_MASK(d->irq); |
1da177e4c Linux-2.6.12-rc2 |
46 |
|
6cab48602 [ARM] 5179/1: Rep... |
47 |
if (type == IRQ_TYPE_PROBE) { |
1da177e4c Linux-2.6.12-rc2 |
48 49 |
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) return 0; |
6cab48602 [ARM] 5179/1: Rep... |
50 |
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; |
1da177e4c Linux-2.6.12-rc2 |
51 |
} |
6cab48602 [ARM] 5179/1: Rep... |
52 |
if (type & IRQ_TYPE_EDGE_RISING) { |
1da177e4c Linux-2.6.12-rc2 |
53 54 55 |
GPIO_IRQ_rising_edge |= mask; } else GPIO_IRQ_rising_edge &= ~mask; |
6cab48602 [ARM] 5179/1: Rep... |
56 |
if (type & IRQ_TYPE_EDGE_FALLING) { |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 60 61 62 63 64 65 66 67 68 69 |
GPIO_IRQ_falling_edge |= mask; } else GPIO_IRQ_falling_edge &= ~mask; GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; return 0; } /* * GPIO IRQs must be acknowledged. This is for IRQs from 0 to 10. */ |
c4e8964e4 ARM: sa1100: irq_... |
70 |
static void sa1100_low_gpio_ack(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
71 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
72 |
GEDR = (1 << d->irq); |
1da177e4c Linux-2.6.12-rc2 |
73 |
} |
c4e8964e4 ARM: sa1100: irq_... |
74 |
static void sa1100_low_gpio_mask(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
75 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
76 |
ICMR &= ~(1 << d->irq); |
1da177e4c Linux-2.6.12-rc2 |
77 |
} |
c4e8964e4 ARM: sa1100: irq_... |
78 |
static void sa1100_low_gpio_unmask(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
79 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
80 |
ICMR |= 1 << d->irq; |
1da177e4c Linux-2.6.12-rc2 |
81 |
} |
c4e8964e4 ARM: sa1100: irq_... |
82 |
static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on) |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
{ if (on) |
c4e8964e4 ARM: sa1100: irq_... |
85 |
PWER |= 1 << d->irq; |
1da177e4c Linux-2.6.12-rc2 |
86 |
else |
c4e8964e4 ARM: sa1100: irq_... |
87 |
PWER &= ~(1 << d->irq); |
1da177e4c Linux-2.6.12-rc2 |
88 89 |
return 0; } |
38c677cb9 [ARM] 3739/1: gen... |
90 91 |
static struct irq_chip sa1100_low_gpio_chip = { .name = "GPIO-l", |
c4e8964e4 ARM: sa1100: irq_... |
92 93 94 95 96 |
.irq_ack = sa1100_low_gpio_ack, .irq_mask = sa1100_low_gpio_mask, .irq_unmask = sa1100_low_gpio_unmask, .irq_set_type = sa1100_gpio_type, .irq_set_wake = sa1100_low_gpio_wake, |
1da177e4c Linux-2.6.12-rc2 |
97 98 99 100 101 102 103 104 |
}; /* * IRQ11 (GPIO11 through 27) handler. We enter here with the * irq_controller_lock held, and IRQs disabled. Decode the IRQ * and call the handler. */ static void |
10dd5ce28 [ARM] Remove comp... |
105 |
sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc) |
1da177e4c Linux-2.6.12-rc2 |
106 107 108 109 110 111 112 113 114 115 116 117 |
{ unsigned int mask; mask = GEDR & 0xfffff800; do { /* * clear down all currently active IRQ sources. * We will be processing them all. */ GEDR = mask; irq = IRQ_GPIO11; |
1da177e4c Linux-2.6.12-rc2 |
118 119 120 |
mask >>= 11; do { if (mask & 1) |
d8aa0251f [ARM] 5298/1: Dro... |
121 |
generic_handle_irq(irq); |
1da177e4c Linux-2.6.12-rc2 |
122 123 |
mask >>= 1; irq++; |
1da177e4c Linux-2.6.12-rc2 |
124 125 126 127 128 129 130 131 132 133 134 |
} while (mask); mask = GEDR & 0xfffff800; } while (mask); } /* * Like GPIO0 to 10, GPIO11-27 IRQs need to be handled specially. * In addition, the IRQs are all collected up into one bit in the * interrupt controller registers. */ |
c4e8964e4 ARM: sa1100: irq_... |
135 |
static void sa1100_high_gpio_ack(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
136 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
137 |
unsigned int mask = GPIO11_27_MASK(d->irq); |
1da177e4c Linux-2.6.12-rc2 |
138 139 140 |
GEDR = mask; } |
c4e8964e4 ARM: sa1100: irq_... |
141 |
static void sa1100_high_gpio_mask(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
142 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
143 |
unsigned int mask = GPIO11_27_MASK(d->irq); |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 147 148 149 |
GPIO_IRQ_mask &= ~mask; GRER &= ~mask; GFER &= ~mask; } |
c4e8964e4 ARM: sa1100: irq_... |
150 |
static void sa1100_high_gpio_unmask(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
151 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
152 |
unsigned int mask = GPIO11_27_MASK(d->irq); |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 156 157 158 |
GPIO_IRQ_mask |= mask; GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; } |
c4e8964e4 ARM: sa1100: irq_... |
159 |
static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on) |
1da177e4c Linux-2.6.12-rc2 |
160 161 |
{ if (on) |
c4e8964e4 ARM: sa1100: irq_... |
162 |
PWER |= GPIO11_27_MASK(d->irq); |
1da177e4c Linux-2.6.12-rc2 |
163 |
else |
c4e8964e4 ARM: sa1100: irq_... |
164 |
PWER &= ~GPIO11_27_MASK(d->irq); |
1da177e4c Linux-2.6.12-rc2 |
165 166 |
return 0; } |
38c677cb9 [ARM] 3739/1: gen... |
167 168 |
static struct irq_chip sa1100_high_gpio_chip = { .name = "GPIO-h", |
c4e8964e4 ARM: sa1100: irq_... |
169 170 171 172 173 |
.irq_ack = sa1100_high_gpio_ack, .irq_mask = sa1100_high_gpio_mask, .irq_unmask = sa1100_high_gpio_unmask, .irq_set_type = sa1100_gpio_type, .irq_set_wake = sa1100_high_gpio_wake, |
1da177e4c Linux-2.6.12-rc2 |
174 175 176 177 178 179 |
}; /* * 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. */ |
c4e8964e4 ARM: sa1100: irq_... |
180 |
static void sa1100_mask_irq(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
181 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
182 |
ICMR &= ~(1 << d->irq); |
1da177e4c Linux-2.6.12-rc2 |
183 |
} |
c4e8964e4 ARM: sa1100: irq_... |
184 |
static void sa1100_unmask_irq(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
185 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
186 |
ICMR |= (1 << d->irq); |
1da177e4c Linux-2.6.12-rc2 |
187 |
} |
19ca5d27e [ARM] Allow SA110... |
188 189 190 |
/* * Apart form GPIOs, only the RTC alarm can be a wakeup event. */ |
c4e8964e4 ARM: sa1100: irq_... |
191 |
static int sa1100_set_wake(struct irq_data *d, unsigned int on) |
19ca5d27e [ARM] Allow SA110... |
192 |
{ |
c4e8964e4 ARM: sa1100: irq_... |
193 |
if (d->irq == IRQ_RTCAlrm) { |
19ca5d27e [ARM] Allow SA110... |
194 195 196 197 198 199 200 201 |
if (on) PWER |= PWER_RTC; else PWER &= ~PWER_RTC; return 0; } return -EINVAL; } |
38c677cb9 [ARM] 3739/1: gen... |
202 203 |
static struct irq_chip sa1100_normal_chip = { .name = "SC", |
c4e8964e4 ARM: sa1100: irq_... |
204 205 206 207 |
.irq_ack = sa1100_mask_irq, .irq_mask = sa1100_mask_irq, .irq_unmask = sa1100_unmask_irq, .irq_set_wake = sa1100_set_wake, |
1da177e4c Linux-2.6.12-rc2 |
208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
}; static struct resource irq_resource = { .name = "irqs", .start = 0x90050000, .end = 0x9005ffff, }; static struct sa1100irq_state { unsigned int saved; unsigned int icmr; unsigned int iclr; unsigned int iccr; } sa1100irq_state; |
905339807 ARM / SA1100: Use... |
222 |
static int sa1100irq_suspend(void) |
1da177e4c Linux-2.6.12-rc2 |
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
{ struct sa1100irq_state *st = &sa1100irq_state; st->saved = 1; st->icmr = ICMR; st->iclr = ICLR; st->iccr = ICCR; /* * Disable all GPIO-based interrupts. */ ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| IC_GPIO1|IC_GPIO0); /* * Set the appropriate edges for wakeup. */ GRER = PWER & GPIO_IRQ_rising_edge; GFER = PWER & GPIO_IRQ_falling_edge; /* * Clear any pending GPIO interrupts. */ GEDR = GEDR; return 0; } |
905339807 ARM / SA1100: Use... |
251 |
static void sa1100irq_resume(void) |
1da177e4c Linux-2.6.12-rc2 |
252 253 254 255 256 257 258 259 260 261 262 263 |
{ struct sa1100irq_state *st = &sa1100irq_state; if (st->saved) { ICCR = st->iccr; ICLR = st->iclr; GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; ICMR = st->icmr; } |
1da177e4c Linux-2.6.12-rc2 |
264 |
} |
905339807 ARM / SA1100: Use... |
265 |
static struct syscore_ops sa1100irq_syscore_ops = { |
1da177e4c Linux-2.6.12-rc2 |
266 267 268 |
.suspend = sa1100irq_suspend, .resume = sa1100irq_resume, }; |
1da177e4c Linux-2.6.12-rc2 |
269 270 |
static int __init sa1100irq_init_devicefs(void) { |
905339807 ARM / SA1100: Use... |
271 272 |
register_syscore_ops(&sa1100irq_syscore_ops); return 0; |
1da177e4c Linux-2.6.12-rc2 |
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
} device_initcall(sa1100irq_init_devicefs); void __init sa1100_init_irq(void) { unsigned int irq; request_resource(&iomem_resource, &irq_resource); /* disable all IRQs */ ICMR = 0; /* all IRQs are IRQ, not FIQ */ ICLR = 0; /* clear all GPIO edge detects */ GFER = 0; GRER = 0; GEDR = -1; /* * Whatever the doc says, this has to be set for the wait-on-irq * instruction to work... on a SA1100 rev 9 at least. */ ICCR = 1; for (irq = 0; irq <= 10; irq++) { |
f38c02f3b arm: Fold irq_set... |
301 302 |
irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip, handle_edge_irq); |
1da177e4c Linux-2.6.12-rc2 |
303 304 305 306 |
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = 12; irq <= 31; irq++) { |
f38c02f3b arm: Fold irq_set... |
307 308 |
irq_set_chip_and_handler(irq, &sa1100_normal_chip, handle_level_irq); |
1da177e4c Linux-2.6.12-rc2 |
309 310 311 312 |
set_irq_flags(irq, IRQF_VALID); } for (irq = 32; irq <= 48; irq++) { |
f38c02f3b arm: Fold irq_set... |
313 314 |
irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip, handle_edge_irq); |
1da177e4c Linux-2.6.12-rc2 |
315 316 317 318 319 320 |
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } /* * Install handler for GPIO 11-27 edge detect interrupts */ |
6845664a6 arm: Cleanup the ... |
321 322 |
irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip); irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler); |
45528e381 [ARM] 4961/1: gpi... |
323 324 |
sa1100_init_gpio(); |
1da177e4c Linux-2.6.12-rc2 |
325 |
} |