Blame view
arch/arm/plat-orion/gpio.c
11.7 KB
9569dae75 [ARM] Orion: shar... |
1 2 3 4 5 6 7 8 9 10 11 12 |
/* * arch/arm/plat-orion/gpio.c * * Marvell Orion SoC GPIO handling. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ #include <linux/kernel.h> #include <linux/init.h> |
07332318f [ARM] Orion: shar... |
13 |
#include <linux/irq.h> |
9569dae75 [ARM] Orion: shar... |
14 15 16 17 |
#include <linux/module.h> #include <linux/spinlock.h> #include <linux/bitops.h> #include <linux/io.h> |
a88656553 [ARM] orion: conv... |
18 |
#include <linux/gpio.h> |
9569dae75 [ARM] Orion: shar... |
19 |
|
9eac6d0a4 ARM: Remove depen... |
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
/* * GPIO unit register offsets. */ #define GPIO_OUT_OFF 0x0000 #define GPIO_IO_CONF_OFF 0x0004 #define GPIO_BLINK_EN_OFF 0x0008 #define GPIO_IN_POL_OFF 0x000c #define GPIO_DATA_IN_OFF 0x0010 #define GPIO_EDGE_CAUSE_OFF 0x0014 #define GPIO_EDGE_MASK_OFF 0x0018 #define GPIO_LEVEL_MASK_OFF 0x001c struct orion_gpio_chip { struct gpio_chip chip; spinlock_t lock; void __iomem *base; unsigned long valid_input; unsigned long valid_output; int mask_offset; int secondary_irq_base; }; static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip) { return ochip->base + GPIO_OUT_OFF; } static void __iomem *GPIO_IO_CONF(struct orion_gpio_chip *ochip) { return ochip->base + GPIO_IO_CONF_OFF; } static void __iomem *GPIO_BLINK_EN(struct orion_gpio_chip *ochip) { return ochip->base + GPIO_BLINK_EN_OFF; } static void __iomem *GPIO_IN_POL(struct orion_gpio_chip *ochip) { return ochip->base + GPIO_IN_POL_OFF; } static void __iomem *GPIO_DATA_IN(struct orion_gpio_chip *ochip) { return ochip->base + GPIO_DATA_IN_OFF; } static void __iomem *GPIO_EDGE_CAUSE(struct orion_gpio_chip *ochip) { return ochip->base + GPIO_EDGE_CAUSE_OFF; } static void __iomem *GPIO_EDGE_MASK(struct orion_gpio_chip *ochip) { return ochip->base + ochip->mask_offset + GPIO_EDGE_MASK_OFF; } static void __iomem *GPIO_LEVEL_MASK(struct orion_gpio_chip *ochip) { return ochip->base + ochip->mask_offset + GPIO_LEVEL_MASK_OFF; } |
9569dae75 [ARM] Orion: shar... |
81 |
|
9eac6d0a4 ARM: Remove depen... |
82 83 84 85 86 |
static struct orion_gpio_chip orion_gpio_chips[2]; static int orion_gpio_chip_count; static inline void __set_direction(struct orion_gpio_chip *ochip, unsigned pin, int input) |
9569dae75 [ARM] Orion: shar... |
87 88 |
{ u32 u; |
9eac6d0a4 ARM: Remove depen... |
89 |
u = readl(GPIO_IO_CONF(ochip)); |
9569dae75 [ARM] Orion: shar... |
90 |
if (input) |
9eac6d0a4 ARM: Remove depen... |
91 |
u |= 1 << pin; |
9569dae75 [ARM] Orion: shar... |
92 |
else |
9eac6d0a4 ARM: Remove depen... |
93 94 |
u &= ~(1 << pin); writel(u, GPIO_IO_CONF(ochip)); |
9569dae75 [ARM] Orion: shar... |
95 |
} |
9eac6d0a4 ARM: Remove depen... |
96 |
static void __set_level(struct orion_gpio_chip *ochip, unsigned pin, int high) |
9569dae75 [ARM] Orion: shar... |
97 98 |
{ u32 u; |
9eac6d0a4 ARM: Remove depen... |
99 |
u = readl(GPIO_OUT(ochip)); |
9569dae75 [ARM] Orion: shar... |
100 |
if (high) |
9eac6d0a4 ARM: Remove depen... |
101 |
u |= 1 << pin; |
9569dae75 [ARM] Orion: shar... |
102 |
else |
9eac6d0a4 ARM: Remove depen... |
103 104 |
u &= ~(1 << pin); writel(u, GPIO_OUT(ochip)); |
9569dae75 [ARM] Orion: shar... |
105 |
} |
9eac6d0a4 ARM: Remove depen... |
106 107 |
static inline void __set_blinking(struct orion_gpio_chip *ochip, unsigned pin, int blink) |
9569dae75 [ARM] Orion: shar... |
108 |
{ |
a88656553 [ARM] orion: conv... |
109 |
u32 u; |
9569dae75 [ARM] Orion: shar... |
110 |
|
9eac6d0a4 ARM: Remove depen... |
111 |
u = readl(GPIO_BLINK_EN(ochip)); |
a88656553 [ARM] orion: conv... |
112 |
if (blink) |
9eac6d0a4 ARM: Remove depen... |
113 |
u |= 1 << pin; |
a88656553 [ARM] orion: conv... |
114 |
else |
9eac6d0a4 ARM: Remove depen... |
115 116 |
u &= ~(1 << pin); writel(u, GPIO_BLINK_EN(ochip)); |
a88656553 [ARM] orion: conv... |
117 |
} |
9569dae75 [ARM] Orion: shar... |
118 |
|
9eac6d0a4 ARM: Remove depen... |
119 120 |
static inline int orion_gpio_is_valid(struct orion_gpio_chip *ochip, unsigned pin, int mode) |
a88656553 [ARM] orion: conv... |
121 |
{ |
9eac6d0a4 ARM: Remove depen... |
122 123 124 125 126 127 128 129 130 131 |
if (pin >= ochip->chip.ngpio) goto err_out; if ((mode & GPIO_INPUT_OK) && !test_bit(pin, &ochip->valid_input)) goto err_out; if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, &ochip->valid_output)) goto err_out; return 1; |
9569dae75 [ARM] Orion: shar... |
132 |
|
a88656553 [ARM] orion: conv... |
133 134 135 136 |
err_out: pr_debug("%s: invalid GPIO %d ", __func__, pin); return false; |
9569dae75 [ARM] Orion: shar... |
137 |
} |
9569dae75 [ARM] Orion: shar... |
138 |
|
a88656553 [ARM] orion: conv... |
139 140 141 |
/* * GENERIC_GPIO primitives. */ |
9eac6d0a4 ARM: Remove depen... |
142 143 144 145 146 147 148 149 150 151 152 |
static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) { struct orion_gpio_chip *ochip = container_of(chip, struct orion_gpio_chip, chip); if (orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK) || orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK)) return 0; return -EINVAL; } |
a88656553 [ARM] orion: conv... |
153 |
static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin) |
9569dae75 [ARM] Orion: shar... |
154 |
{ |
9eac6d0a4 ARM: Remove depen... |
155 156 |
struct orion_gpio_chip *ochip = container_of(chip, struct orion_gpio_chip, chip); |
9569dae75 [ARM] Orion: shar... |
157 |
unsigned long flags; |
9569dae75 [ARM] Orion: shar... |
158 |
|
9eac6d0a4 ARM: Remove depen... |
159 |
if (!orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK)) |
9569dae75 [ARM] Orion: shar... |
160 |
return -EINVAL; |
9569dae75 [ARM] Orion: shar... |
161 |
|
9eac6d0a4 ARM: Remove depen... |
162 163 164 |
spin_lock_irqsave(&ochip->lock, flags); __set_direction(ochip, pin, 1); spin_unlock_irqrestore(&ochip->lock, flags); |
9569dae75 [ARM] Orion: shar... |
165 166 167 |
return 0; } |
9569dae75 [ARM] Orion: shar... |
168 |
|
9eac6d0a4 ARM: Remove depen... |
169 |
static int orion_gpio_get(struct gpio_chip *chip, unsigned pin) |
9569dae75 [ARM] Orion: shar... |
170 |
{ |
9eac6d0a4 ARM: Remove depen... |
171 172 |
struct orion_gpio_chip *ochip = container_of(chip, struct orion_gpio_chip, chip); |
9569dae75 [ARM] Orion: shar... |
173 |
int val; |
9eac6d0a4 ARM: Remove depen... |
174 175 176 177 178 |
if (readl(GPIO_IO_CONF(ochip)) & (1 << pin)) { val = readl(GPIO_DATA_IN(ochip)) ^ readl(GPIO_IN_POL(ochip)); } else { val = readl(GPIO_OUT(ochip)); } |
9569dae75 [ARM] Orion: shar... |
179 |
|
9eac6d0a4 ARM: Remove depen... |
180 |
return (val >> pin) & 1; |
9569dae75 [ARM] Orion: shar... |
181 |
} |
9569dae75 [ARM] Orion: shar... |
182 |
|
9eac6d0a4 ARM: Remove depen... |
183 184 |
static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value) |
9569dae75 [ARM] Orion: shar... |
185 |
{ |
9eac6d0a4 ARM: Remove depen... |
186 187 |
struct orion_gpio_chip *ochip = container_of(chip, struct orion_gpio_chip, chip); |
9569dae75 [ARM] Orion: shar... |
188 |
unsigned long flags; |
a88656553 [ARM] orion: conv... |
189 |
|
9eac6d0a4 ARM: Remove depen... |
190 |
if (!orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK)) |
a88656553 [ARM] orion: conv... |
191 |
return -EINVAL; |
9569dae75 [ARM] Orion: shar... |
192 |
|
9eac6d0a4 ARM: Remove depen... |
193 194 195 196 197 |
spin_lock_irqsave(&ochip->lock, flags); __set_blinking(ochip, pin, 0); __set_level(ochip, pin, value); __set_direction(ochip, pin, 0); spin_unlock_irqrestore(&ochip->lock, flags); |
a88656553 [ARM] orion: conv... |
198 199 |
return 0; |
9569dae75 [ARM] Orion: shar... |
200 |
} |
9569dae75 [ARM] Orion: shar... |
201 |
|
9eac6d0a4 ARM: Remove depen... |
202 |
static void orion_gpio_set(struct gpio_chip *chip, unsigned pin, int value) |
9569dae75 [ARM] Orion: shar... |
203 |
{ |
9eac6d0a4 ARM: Remove depen... |
204 205 |
struct orion_gpio_chip *ochip = container_of(chip, struct orion_gpio_chip, chip); |
9569dae75 [ARM] Orion: shar... |
206 |
unsigned long flags; |
9569dae75 [ARM] Orion: shar... |
207 |
|
9eac6d0a4 ARM: Remove depen... |
208 209 210 |
spin_lock_irqsave(&ochip->lock, flags); __set_level(ochip, pin, value); spin_unlock_irqrestore(&ochip->lock, flags); |
9569dae75 [ARM] Orion: shar... |
211 |
} |
9569dae75 [ARM] Orion: shar... |
212 |
|
9eac6d0a4 ARM: Remove depen... |
213 |
static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin) |
9569dae75 [ARM] Orion: shar... |
214 |
{ |
9eac6d0a4 ARM: Remove depen... |
215 216 |
struct orion_gpio_chip *ochip = container_of(chip, struct orion_gpio_chip, chip); |
9569dae75 [ARM] Orion: shar... |
217 |
|
9eac6d0a4 ARM: Remove depen... |
218 |
return ochip->secondary_irq_base + pin; |
a88656553 [ARM] orion: conv... |
219 |
} |
9569dae75 [ARM] Orion: shar... |
220 |
|
9eac6d0a4 ARM: Remove depen... |
221 |
|
9569dae75 [ARM] Orion: shar... |
222 223 224 |
/* * Orion-specific GPIO API extensions. */ |
9eac6d0a4 ARM: Remove depen... |
225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
static struct orion_gpio_chip *orion_gpio_chip_find(int pin) { int i; for (i = 0; i < orion_gpio_chip_count; i++) { struct orion_gpio_chip *ochip = orion_gpio_chips + i; struct gpio_chip *chip = &ochip->chip; if (pin >= chip->base && pin < chip->base + chip->ngpio) return ochip; } return NULL; } |
9569dae75 [ARM] Orion: shar... |
239 240 |
void __init orion_gpio_set_unused(unsigned pin) { |
9eac6d0a4 ARM: Remove depen... |
241 242 243 244 245 246 |
struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); if (ochip == NULL) return; pin -= ochip->chip.base; |
a88656553 [ARM] orion: conv... |
247 |
/* Configure as output, drive low. */ |
9eac6d0a4 ARM: Remove depen... |
248 249 |
__set_level(ochip, pin, 0); __set_direction(ochip, pin, 0); |
9569dae75 [ARM] Orion: shar... |
250 |
} |
28d27cf4c [ARM] Orion: make... |
251 |
void __init orion_gpio_set_valid(unsigned pin, int mode) |
9569dae75 [ARM] Orion: shar... |
252 |
{ |
9eac6d0a4 ARM: Remove depen... |
253 254 255 256 257 258 |
struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); if (ochip == NULL) return; pin -= ochip->chip.base; |
28d27cf4c [ARM] Orion: make... |
259 260 |
if (mode == 1) mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; |
9eac6d0a4 ARM: Remove depen... |
261 |
|
28d27cf4c [ARM] Orion: make... |
262 |
if (mode & GPIO_INPUT_OK) |
9eac6d0a4 ARM: Remove depen... |
263 |
__set_bit(pin, &ochip->valid_input); |
9569dae75 [ARM] Orion: shar... |
264 |
else |
9eac6d0a4 ARM: Remove depen... |
265 |
__clear_bit(pin, &ochip->valid_input); |
28d27cf4c [ARM] Orion: make... |
266 |
if (mode & GPIO_OUTPUT_OK) |
9eac6d0a4 ARM: Remove depen... |
267 |
__set_bit(pin, &ochip->valid_output); |
28d27cf4c [ARM] Orion: make... |
268 |
else |
9eac6d0a4 ARM: Remove depen... |
269 |
__clear_bit(pin, &ochip->valid_output); |
9569dae75 [ARM] Orion: shar... |
270 271 272 273 |
} void orion_gpio_set_blink(unsigned pin, int blink) { |
9eac6d0a4 ARM: Remove depen... |
274 |
struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); |
9569dae75 [ARM] Orion: shar... |
275 |
unsigned long flags; |
9569dae75 [ARM] Orion: shar... |
276 |
|
9eac6d0a4 ARM: Remove depen... |
277 278 |
if (ochip == NULL) return; |
9569dae75 [ARM] Orion: shar... |
279 |
|
9eac6d0a4 ARM: Remove depen... |
280 281 282 283 |
spin_lock_irqsave(&ochip->lock, flags); __set_level(ochip, pin, 0); __set_blinking(ochip, pin, blink); spin_unlock_irqrestore(&ochip->lock, flags); |
9569dae75 [ARM] Orion: shar... |
284 285 |
} EXPORT_SYMBOL(orion_gpio_set_blink); |
07332318f [ARM] Orion: shar... |
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
/***************************************************************************** * Orion GPIO IRQ * * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same * value of the line or the opposite value. * * Level IRQ handlers: DATA_IN is used directly as cause register. * Interrupt are masked by LEVEL_MASK registers. * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. * Interrupt are masked by EDGE_MASK registers. * Both-edge handlers: Similar to regular Edge handlers, but also swaps * the polarity to catch the next line transaction. * This is a race condition that might not perfectly * work on some use cases. * * Every eight GPIO lines are grouped (OR'ed) before going up to main * cause register. * * EDGE cause mask * data-in /--------| |-----| |----\ * -----| |----- ---- to main cause reg * X \----------------| |----/ * polarity LEVEL mask * ****************************************************************************/ |
07332318f [ARM] Orion: shar... |
313 |
|
3b0c8d403 ARM: plat-orion: ... |
314 |
static int gpio_irq_set_type(struct irq_data *d, u32 type) |
07332318f [ARM] Orion: shar... |
315 |
{ |
e59347a1d arm: orion: Use g... |
316 317 318 |
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct irq_chip_type *ct = irq_data_get_chip_type(d); struct orion_gpio_chip *ochip = gc->private; |
9eac6d0a4 ARM: Remove depen... |
319 |
int pin; |
07332318f [ARM] Orion: shar... |
320 |
u32 u; |
e59347a1d arm: orion: Use g... |
321 |
pin = d->irq - gc->irq_base; |
9eac6d0a4 ARM: Remove depen... |
322 323 |
u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); |
07332318f [ARM] Orion: shar... |
324 325 |
if (!u) { printk(KERN_ERR "orion gpio_irq_set_type failed " |
3b0c8d403 ARM: plat-orion: ... |
326 327 |
"(irq %d, pin %d). ", d->irq, pin); |
07332318f [ARM] Orion: shar... |
328 329 |
return -EINVAL; } |
e59347a1d arm: orion: Use g... |
330 331 |
type &= IRQ_TYPE_SENSE_MASK; if (type == IRQ_TYPE_NONE) |
07332318f [ARM] Orion: shar... |
332 |
return -EINVAL; |
e59347a1d arm: orion: Use g... |
333 334 335 336 337 |
/* Check if we need to change chip and handler */ if (!(ct->type & type)) if (irq_setup_alt_chip(d, type)) return -EINVAL; |
07332318f [ARM] Orion: shar... |
338 339 340 341 342 |
/* * Configure interrupt polarity. */ if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) { |
9eac6d0a4 ARM: Remove depen... |
343 344 345 |
u = readl(GPIO_IN_POL(ochip)); u &= ~(1 << pin); writel(u, GPIO_IN_POL(ochip)); |
07332318f [ARM] Orion: shar... |
346 |
} else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) { |
9eac6d0a4 ARM: Remove depen... |
347 348 349 |
u = readl(GPIO_IN_POL(ochip)); u |= 1 << pin; writel(u, GPIO_IN_POL(ochip)); |
07332318f [ARM] Orion: shar... |
350 351 |
} else if (type == IRQ_TYPE_EDGE_BOTH) { u32 v; |
9eac6d0a4 ARM: Remove depen... |
352 |
v = readl(GPIO_IN_POL(ochip)) ^ readl(GPIO_DATA_IN(ochip)); |
07332318f [ARM] Orion: shar... |
353 354 355 356 |
/* * set initial polarity based on current input level */ |
9eac6d0a4 ARM: Remove depen... |
357 358 359 |
u = readl(GPIO_IN_POL(ochip)); if (v & (1 << pin)) u |= 1 << pin; /* falling */ |
07332318f [ARM] Orion: shar... |
360 |
else |
9eac6d0a4 ARM: Remove depen... |
361 362 |
u &= ~(1 << pin); /* rising */ writel(u, GPIO_IN_POL(ochip)); |
07332318f [ARM] Orion: shar... |
363 |
} |
07332318f [ARM] Orion: shar... |
364 365 |
return 0; } |
9eac6d0a4 ARM: Remove depen... |
366 367 368 369 |
void __init orion_gpio_init(int gpio_base, int ngpio, u32 base, int mask_offset, int secondary_irq_base) { struct orion_gpio_chip *ochip; |
e59347a1d arm: orion: Use g... |
370 371 |
struct irq_chip_generic *gc; struct irq_chip_type *ct; |
0b35a45bd ARM: plat-orion: ... |
372 |
char gc_label[16]; |
9eac6d0a4 ARM: Remove depen... |
373 374 375 |
if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) return; |
0b35a45bd ARM: plat-orion: ... |
376 377 |
snprintf(gc_label, sizeof(gc_label), "orion_gpio%d", orion_gpio_chip_count); |
9eac6d0a4 ARM: Remove depen... |
378 |
ochip = orion_gpio_chips + orion_gpio_chip_count; |
0b35a45bd ARM: plat-orion: ... |
379 |
ochip->chip.label = kstrdup(gc_label, GFP_KERNEL); |
9eac6d0a4 ARM: Remove depen... |
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
ochip->chip.request = orion_gpio_request; ochip->chip.direction_input = orion_gpio_direction_input; ochip->chip.get = orion_gpio_get; ochip->chip.direction_output = orion_gpio_direction_output; ochip->chip.set = orion_gpio_set; ochip->chip.to_irq = orion_gpio_to_irq; ochip->chip.base = gpio_base; ochip->chip.ngpio = ngpio; ochip->chip.can_sleep = 0; spin_lock_init(&ochip->lock); ochip->base = (void __iomem *)base; ochip->valid_input = 0; ochip->valid_output = 0; ochip->mask_offset = mask_offset; ochip->secondary_irq_base = secondary_irq_base; gpiochip_add(&ochip->chip); orion_gpio_chip_count++; /* * Mask and clear GPIO interrupts. */ writel(0, GPIO_EDGE_CAUSE(ochip)); writel(0, GPIO_EDGE_MASK(ochip)); writel(0, GPIO_LEVEL_MASK(ochip)); |
e59347a1d arm: orion: Use g... |
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
gc = irq_alloc_generic_chip("orion_gpio_irq", 2, secondary_irq_base, ochip->base, handle_level_irq); gc->private = ochip; ct = gc->chip_types; ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF; ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; ct->chip.irq_mask = irq_gc_mask_clr_bit; ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = gpio_irq_set_type; ct++; ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF; ct->regs.ack = GPIO_EDGE_CAUSE_OFF; ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; |
659fb32d1 genirq: replace i... |
421 |
ct->chip.irq_ack = irq_gc_ack_clr_bit; |
e59347a1d arm: orion: Use g... |
422 423 424 425 426 427 428 |
ct->chip.irq_mask = irq_gc_mask_clr_bit; ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = gpio_irq_set_type; ct->handler = handle_edge_irq; irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); |
9eac6d0a4 ARM: Remove depen... |
429 |
} |
07332318f [ARM] Orion: shar... |
430 431 |
void orion_gpio_irq_handler(int pinoff) { |
9eac6d0a4 ARM: Remove depen... |
432 |
struct orion_gpio_chip *ochip; |
e83bbb115 arm: Cleanup irq_... |
433 |
u32 cause, type; |
9eac6d0a4 ARM: Remove depen... |
434 |
int i; |
07332318f [ARM] Orion: shar... |
435 |
|
9eac6d0a4 ARM: Remove depen... |
436 437 438 |
ochip = orion_gpio_chip_find(pinoff); if (ochip == NULL) return; |
07332318f [ARM] Orion: shar... |
439 |
|
9eac6d0a4 ARM: Remove depen... |
440 441 |
cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip)); cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip)); |
07332318f [ARM] Orion: shar... |
442 |
|
9eac6d0a4 ARM: Remove depen... |
443 444 |
for (i = 0; i < ochip->chip.ngpio; i++) { int irq; |
9eac6d0a4 ARM: Remove depen... |
445 446 447 448 |
irq = ochip->secondary_irq_base + i; if (!(cause & (1 << i))) |
07332318f [ARM] Orion: shar... |
449 |
continue; |
e83bbb115 arm: Cleanup irq_... |
450 451 |
type = irqd_get_trigger_type(irq_get_irq_data(irq)); if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { |
07332318f [ARM] Orion: shar... |
452 453 |
/* Swap polarity (race with GPIO line) */ u32 polarity; |
9eac6d0a4 ARM: Remove depen... |
454 455 456 |
polarity = readl(GPIO_IN_POL(ochip)); polarity ^= 1 << i; writel(polarity, GPIO_IN_POL(ochip)); |
07332318f [ARM] Orion: shar... |
457 |
} |
e83bbb115 arm: Cleanup irq_... |
458 |
generic_handle_irq(irq); |
07332318f [ARM] Orion: shar... |
459 460 |
} } |