diff options
Diffstat (limited to 'arch/arm/plat-nomadik')
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 487 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio.h | 6 |
2 files changed, 423 insertions, 70 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 1e88ecb846d1..70620426ee55 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c | |||
@@ -30,23 +30,39 @@ | |||
30 | /* | 30 | /* |
31 | * The GPIO module in the Nomadik family of Systems-on-Chip is an | 31 | * The GPIO module in the Nomadik family of Systems-on-Chip is an |
32 | * AMBA device, managing 32 pins and alternate functions. The logic block | 32 | * AMBA device, managing 32 pins and alternate functions. The logic block |
33 | * is currently only used in the Nomadik. | 33 | * is currently used in the Nomadik and ux500. |
34 | * | 34 | * |
35 | * Symbols in this file are called "nmk_gpio" for "nomadik gpio" | 35 | * Symbols in this file are called "nmk_gpio" for "nomadik gpio" |
36 | */ | 36 | */ |
37 | 37 | ||
38 | #define NMK_GPIO_PER_CHIP 32 | 38 | #define NMK_GPIO_PER_CHIP 32 |
39 | |||
39 | struct nmk_gpio_chip { | 40 | struct nmk_gpio_chip { |
40 | struct gpio_chip chip; | 41 | struct gpio_chip chip; |
41 | void __iomem *addr; | 42 | void __iomem *addr; |
42 | struct clk *clk; | 43 | struct clk *clk; |
44 | unsigned int bank; | ||
43 | unsigned int parent_irq; | 45 | unsigned int parent_irq; |
46 | int secondary_parent_irq; | ||
47 | u32 (*get_secondary_status)(unsigned int bank); | ||
48 | void (*set_ioforce)(bool enable); | ||
44 | spinlock_t lock; | 49 | spinlock_t lock; |
45 | /* Keep track of configured edges */ | 50 | /* Keep track of configured edges */ |
46 | u32 edge_rising; | 51 | u32 edge_rising; |
47 | u32 edge_falling; | 52 | u32 edge_falling; |
53 | u32 real_wake; | ||
54 | u32 rwimsc; | ||
55 | u32 fwimsc; | ||
56 | u32 slpm; | ||
48 | }; | 57 | }; |
49 | 58 | ||
59 | static struct nmk_gpio_chip * | ||
60 | nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)]; | ||
61 | |||
62 | static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); | ||
63 | |||
64 | #define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips) | ||
65 | |||
50 | static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, | 66 | static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, |
51 | unsigned offset, int gpio_mode) | 67 | unsigned offset, int gpio_mode) |
52 | { | 68 | { |
@@ -118,8 +134,35 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, | |||
118 | __nmk_gpio_set_output(nmk_chip, offset, val); | 134 | __nmk_gpio_set_output(nmk_chip, offset, val); |
119 | } | 135 | } |
120 | 136 | ||
137 | static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, | ||
138 | unsigned offset, int gpio_mode, | ||
139 | bool glitch) | ||
140 | { | ||
141 | u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); | ||
142 | u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); | ||
143 | |||
144 | if (glitch && nmk_chip->set_ioforce) { | ||
145 | u32 bit = BIT(offset); | ||
146 | |||
147 | /* Prevent spurious wakeups */ | ||
148 | writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC); | ||
149 | writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC); | ||
150 | |||
151 | nmk_chip->set_ioforce(true); | ||
152 | } | ||
153 | |||
154 | __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode); | ||
155 | |||
156 | if (glitch && nmk_chip->set_ioforce) { | ||
157 | nmk_chip->set_ioforce(false); | ||
158 | |||
159 | writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC); | ||
160 | writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC); | ||
161 | } | ||
162 | } | ||
163 | |||
121 | static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | 164 | static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, |
122 | pin_cfg_t cfg, bool sleep) | 165 | pin_cfg_t cfg, bool sleep, unsigned int *slpmregs) |
123 | { | 166 | { |
124 | static const char *afnames[] = { | 167 | static const char *afnames[] = { |
125 | [NMK_GPIO_ALT_GPIO] = "GPIO", | 168 | [NMK_GPIO_ALT_GPIO] = "GPIO", |
@@ -144,6 +187,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | |||
144 | int slpm = PIN_SLPM(cfg); | 187 | int slpm = PIN_SLPM(cfg); |
145 | int output = PIN_DIR(cfg); | 188 | int output = PIN_DIR(cfg); |
146 | int val = PIN_VAL(cfg); | 189 | int val = PIN_VAL(cfg); |
190 | bool glitch = af == NMK_GPIO_ALT_C; | ||
147 | 191 | ||
148 | dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", | 192 | dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", |
149 | pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], | 193 | pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], |
@@ -155,6 +199,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | |||
155 | int slpm_output = PIN_SLPM_DIR(cfg); | 199 | int slpm_output = PIN_SLPM_DIR(cfg); |
156 | int slpm_val = PIN_SLPM_VAL(cfg); | 200 | int slpm_val = PIN_SLPM_VAL(cfg); |
157 | 201 | ||
202 | af = NMK_GPIO_ALT_GPIO; | ||
203 | |||
158 | /* | 204 | /* |
159 | * The SLPM_* values are normal values + 1 to allow zero to | 205 | * The SLPM_* values are normal values + 1 to allow zero to |
160 | * mean "same as normal". | 206 | * mean "same as normal". |
@@ -180,8 +226,116 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | |||
180 | __nmk_gpio_set_pull(nmk_chip, offset, pull); | 226 | __nmk_gpio_set_pull(nmk_chip, offset, pull); |
181 | } | 227 | } |
182 | 228 | ||
183 | __nmk_gpio_set_slpm(nmk_chip, offset, slpm); | 229 | /* |
184 | __nmk_gpio_set_mode(nmk_chip, offset, af); | 230 | * If we've backed up the SLPM registers (glitch workaround), modify |
231 | * the backups since they will be restored. | ||
232 | */ | ||
233 | if (slpmregs) { | ||
234 | if (slpm == NMK_GPIO_SLPM_NOCHANGE) | ||
235 | slpmregs[nmk_chip->bank] |= BIT(offset); | ||
236 | else | ||
237 | slpmregs[nmk_chip->bank] &= ~BIT(offset); | ||
238 | } else | ||
239 | __nmk_gpio_set_slpm(nmk_chip, offset, slpm); | ||
240 | |||
241 | __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch); | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Safe sequence used to switch IOs between GPIO and Alternate-C mode: | ||
246 | * - Save SLPM registers | ||
247 | * - Set SLPM=0 for the IOs you want to switch and others to 1 | ||
248 | * - Configure the GPIO registers for the IOs that are being switched | ||
249 | * - Set IOFORCE=1 | ||
250 | * - Modify the AFLSA/B registers for the IOs that are being switched | ||
251 | * - Set IOFORCE=0 | ||
252 | * - Restore SLPM registers | ||
253 | * - Any spurious wake up event during switch sequence to be ignored and | ||
254 | * cleared | ||
255 | */ | ||
256 | static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) | ||
257 | { | ||
258 | int i; | ||
259 | |||
260 | for (i = 0; i < NUM_BANKS; i++) { | ||
261 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; | ||
262 | unsigned int temp = slpm[i]; | ||
263 | |||
264 | if (!chip) | ||
265 | break; | ||
266 | |||
267 | slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); | ||
268 | writel(temp, chip->addr + NMK_GPIO_SLPC); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) | ||
273 | { | ||
274 | int i; | ||
275 | |||
276 | for (i = 0; i < NUM_BANKS; i++) { | ||
277 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; | ||
278 | |||
279 | if (!chip) | ||
280 | break; | ||
281 | |||
282 | writel(slpm[i], chip->addr + NMK_GPIO_SLPC); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) | ||
287 | { | ||
288 | static unsigned int slpm[NUM_BANKS]; | ||
289 | unsigned long flags; | ||
290 | bool glitch = false; | ||
291 | int ret = 0; | ||
292 | int i; | ||
293 | |||
294 | for (i = 0; i < num; i++) { | ||
295 | if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) { | ||
296 | glitch = true; | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); | ||
302 | |||
303 | if (glitch) { | ||
304 | memset(slpm, 0xff, sizeof(slpm)); | ||
305 | |||
306 | for (i = 0; i < num; i++) { | ||
307 | int pin = PIN_NUM(cfgs[i]); | ||
308 | int offset = pin % NMK_GPIO_PER_CHIP; | ||
309 | |||
310 | if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) | ||
311 | slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset); | ||
312 | } | ||
313 | |||
314 | nmk_gpio_glitch_slpm_init(slpm); | ||
315 | } | ||
316 | |||
317 | for (i = 0; i < num; i++) { | ||
318 | struct nmk_gpio_chip *nmk_chip; | ||
319 | int pin = PIN_NUM(cfgs[i]); | ||
320 | |||
321 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(pin)); | ||
322 | if (!nmk_chip) { | ||
323 | ret = -EINVAL; | ||
324 | break; | ||
325 | } | ||
326 | |||
327 | spin_lock(&nmk_chip->lock); | ||
328 | __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, | ||
329 | cfgs[i], sleep, glitch ? slpm : NULL); | ||
330 | spin_unlock(&nmk_chip->lock); | ||
331 | } | ||
332 | |||
333 | if (glitch) | ||
334 | nmk_gpio_glitch_slpm_restore(slpm); | ||
335 | |||
336 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | ||
337 | |||
338 | return ret; | ||
185 | } | 339 | } |
186 | 340 | ||
187 | /** | 341 | /** |
@@ -200,19 +354,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | |||
200 | */ | 354 | */ |
201 | int nmk_config_pin(pin_cfg_t cfg, bool sleep) | 355 | int nmk_config_pin(pin_cfg_t cfg, bool sleep) |
202 | { | 356 | { |
203 | struct nmk_gpio_chip *nmk_chip; | 357 | return __nmk_config_pins(&cfg, 1, sleep); |
204 | int gpio = PIN_NUM(cfg); | ||
205 | unsigned long flags; | ||
206 | |||
207 | nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); | ||
208 | if (!nmk_chip) | ||
209 | return -EINVAL; | ||
210 | |||
211 | spin_lock_irqsave(&nmk_chip->lock, flags); | ||
212 | __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep); | ||
213 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | ||
214 | |||
215 | return 0; | ||
216 | } | 358 | } |
217 | EXPORT_SYMBOL(nmk_config_pin); | 359 | EXPORT_SYMBOL(nmk_config_pin); |
218 | 360 | ||
@@ -226,31 +368,13 @@ EXPORT_SYMBOL(nmk_config_pin); | |||
226 | */ | 368 | */ |
227 | int nmk_config_pins(pin_cfg_t *cfgs, int num) | 369 | int nmk_config_pins(pin_cfg_t *cfgs, int num) |
228 | { | 370 | { |
229 | int ret = 0; | 371 | return __nmk_config_pins(cfgs, num, false); |
230 | int i; | ||
231 | |||
232 | for (i = 0; i < num; i++) { | ||
233 | ret = nmk_config_pin(cfgs[i], false); | ||
234 | if (ret) | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | return ret; | ||
239 | } | 372 | } |
240 | EXPORT_SYMBOL(nmk_config_pins); | 373 | EXPORT_SYMBOL(nmk_config_pins); |
241 | 374 | ||
242 | int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num) | 375 | int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num) |
243 | { | 376 | { |
244 | int ret = 0; | 377 | return __nmk_config_pins(cfgs, num, true); |
245 | int i; | ||
246 | |||
247 | for (i = 0; i < num; i++) { | ||
248 | ret = nmk_config_pin(cfgs[i], true); | ||
249 | if (ret) | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | 378 | } |
255 | EXPORT_SYMBOL(nmk_config_pins_sleep); | 379 | EXPORT_SYMBOL(nmk_config_pins_sleep); |
256 | 380 | ||
@@ -277,9 +401,13 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) | |||
277 | if (!nmk_chip) | 401 | if (!nmk_chip) |
278 | return -EINVAL; | 402 | return -EINVAL; |
279 | 403 | ||
280 | spin_lock_irqsave(&nmk_chip->lock, flags); | 404 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
405 | spin_lock(&nmk_chip->lock); | ||
406 | |||
281 | __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); | 407 | __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); |
282 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 408 | |
409 | spin_unlock(&nmk_chip->lock); | ||
410 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | ||
283 | 411 | ||
284 | return 0; | 412 | return 0; |
285 | } | 413 | } |
@@ -314,6 +442,15 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) | |||
314 | } | 442 | } |
315 | 443 | ||
316 | /* Mode functions */ | 444 | /* Mode functions */ |
445 | /** | ||
446 | * nmk_gpio_set_mode() - set the mux mode of a gpio pin | ||
447 | * @gpio: pin number | ||
448 | * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A, | ||
449 | * NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C | ||
450 | * | ||
451 | * Sets the mode of the specified pin to one of the alternate functions or | ||
452 | * plain GPIO. | ||
453 | */ | ||
317 | int nmk_gpio_set_mode(int gpio, int gpio_mode) | 454 | int nmk_gpio_set_mode(int gpio, int gpio_mode) |
318 | { | 455 | { |
319 | struct nmk_gpio_chip *nmk_chip; | 456 | struct nmk_gpio_chip *nmk_chip; |
@@ -401,8 +538,20 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, | |||
401 | } | 538 | } |
402 | } | 539 | } |
403 | 540 | ||
404 | static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which, | 541 | static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, |
405 | bool enable) | 542 | int gpio, bool on) |
543 | { | ||
544 | #ifdef CONFIG_ARCH_U8500 | ||
545 | if (cpu_is_u8500v2()) { | ||
546 | __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, | ||
547 | on ? NMK_GPIO_SLPM_WAKEUP_ENABLE | ||
548 | : NMK_GPIO_SLPM_WAKEUP_DISABLE); | ||
549 | } | ||
550 | #endif | ||
551 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); | ||
552 | } | ||
553 | |||
554 | static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) | ||
406 | { | 555 | { |
407 | int gpio; | 556 | int gpio; |
408 | struct nmk_gpio_chip *nmk_chip; | 557 | struct nmk_gpio_chip *nmk_chip; |
@@ -415,44 +564,58 @@ static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which, | |||
415 | if (!nmk_chip) | 564 | if (!nmk_chip) |
416 | return -EINVAL; | 565 | return -EINVAL; |
417 | 566 | ||
418 | spin_lock_irqsave(&nmk_chip->lock, flags); | 567 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
419 | __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); | 568 | spin_lock(&nmk_chip->lock); |
420 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 569 | |
570 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable); | ||
571 | |||
572 | if (!(nmk_chip->real_wake & bitmask)) | ||
573 | __nmk_gpio_set_wake(nmk_chip, gpio, enable); | ||
574 | |||
575 | spin_unlock(&nmk_chip->lock); | ||
576 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | ||
421 | 577 | ||
422 | return 0; | 578 | return 0; |
423 | } | 579 | } |
424 | 580 | ||
425 | static void nmk_gpio_irq_mask(struct irq_data *d) | 581 | static void nmk_gpio_irq_mask(struct irq_data *d) |
426 | { | 582 | { |
427 | nmk_gpio_irq_modify(d, NORMAL, false); | 583 | nmk_gpio_irq_maskunmask(d, false); |
428 | } | 584 | } |
429 | 585 | ||
430 | static void nmk_gpio_irq_unmask(struct irq_data *d) | 586 | static void nmk_gpio_irq_unmask(struct irq_data *d) |
431 | { | 587 | { |
432 | nmk_gpio_irq_modify(d, NORMAL, true); | 588 | nmk_gpio_irq_maskunmask(d, true); |
433 | } | 589 | } |
434 | 590 | ||
435 | static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) | 591 | static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) |
436 | { | 592 | { |
593 | struct irq_desc *desc = irq_to_desc(d->irq); | ||
594 | bool enabled = !(desc->status & IRQ_DISABLED); | ||
437 | struct nmk_gpio_chip *nmk_chip; | 595 | struct nmk_gpio_chip *nmk_chip; |
438 | unsigned long flags; | 596 | unsigned long flags; |
597 | u32 bitmask; | ||
439 | int gpio; | 598 | int gpio; |
440 | 599 | ||
441 | gpio = NOMADIK_IRQ_TO_GPIO(d->irq); | 600 | gpio = NOMADIK_IRQ_TO_GPIO(d->irq); |
442 | nmk_chip = irq_data_get_irq_chip_data(d); | 601 | nmk_chip = irq_data_get_irq_chip_data(d); |
443 | if (!nmk_chip) | 602 | if (!nmk_chip) |
444 | return -EINVAL; | 603 | return -EINVAL; |
604 | bitmask = nmk_gpio_get_bitmask(gpio); | ||
445 | 605 | ||
446 | spin_lock_irqsave(&nmk_chip->lock, flags); | 606 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
447 | #ifdef CONFIG_ARCH_U8500 | 607 | spin_lock(&nmk_chip->lock); |
448 | if (cpu_is_u8500v2()) { | 608 | |
449 | __nmk_gpio_set_slpm(nmk_chip, gpio, | 609 | if (!enabled) |
450 | on ? NMK_GPIO_SLPM_WAKEUP_ENABLE | 610 | __nmk_gpio_set_wake(nmk_chip, gpio, on); |
451 | : NMK_GPIO_SLPM_WAKEUP_DISABLE); | 611 | |
452 | } | 612 | if (on) |
453 | #endif | 613 | nmk_chip->real_wake |= bitmask; |
454 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); | 614 | else |
455 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 615 | nmk_chip->real_wake &= ~bitmask; |
616 | |||
617 | spin_unlock(&nmk_chip->lock); | ||
618 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | ||
456 | 619 | ||
457 | return 0; | 620 | return 0; |
458 | } | 621 | } |
@@ -483,7 +646,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
483 | if (enabled) | 646 | if (enabled) |
484 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); | 647 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); |
485 | 648 | ||
486 | if (wake) | 649 | if (enabled || wake) |
487 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); | 650 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); |
488 | 651 | ||
489 | nmk_chip->edge_rising &= ~bitmask; | 652 | nmk_chip->edge_rising &= ~bitmask; |
@@ -497,7 +660,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
497 | if (enabled) | 660 | if (enabled) |
498 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); | 661 | __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); |
499 | 662 | ||
500 | if (wake) | 663 | if (enabled || wake) |
501 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); | 664 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); |
502 | 665 | ||
503 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 666 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
@@ -514,12 +677,11 @@ static struct irq_chip nmk_gpio_irq_chip = { | |||
514 | .irq_set_wake = nmk_gpio_irq_set_wake, | 677 | .irq_set_wake = nmk_gpio_irq_set_wake, |
515 | }; | 678 | }; |
516 | 679 | ||
517 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 680 | static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, |
681 | u32 status) | ||
518 | { | 682 | { |
519 | struct nmk_gpio_chip *nmk_chip; | 683 | struct nmk_gpio_chip *nmk_chip; |
520 | struct irq_chip *host_chip = get_irq_chip(irq); | 684 | struct irq_chip *host_chip = get_irq_chip(irq); |
521 | unsigned int gpio_irq; | ||
522 | u32 pending; | ||
523 | unsigned int first_irq; | 685 | unsigned int first_irq; |
524 | 686 | ||
525 | if (host_chip->irq_mask_ack) | 687 | if (host_chip->irq_mask_ack) |
@@ -532,29 +694,56 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
532 | 694 | ||
533 | nmk_chip = get_irq_data(irq); | 695 | nmk_chip = get_irq_data(irq); |
534 | first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); | 696 | first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); |
535 | while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { | 697 | while (status) { |
536 | gpio_irq = first_irq + __ffs(pending); | 698 | int bit = __ffs(status); |
537 | generic_handle_irq(gpio_irq); | 699 | |
700 | generic_handle_irq(first_irq + bit); | ||
701 | status &= ~BIT(bit); | ||
538 | } | 702 | } |
539 | 703 | ||
540 | host_chip->irq_unmask(&desc->irq_data); | 704 | host_chip->irq_unmask(&desc->irq_data); |
541 | } | 705 | } |
542 | 706 | ||
707 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
708 | { | ||
709 | struct nmk_gpio_chip *nmk_chip = get_irq_data(irq); | ||
710 | u32 status = readl(nmk_chip->addr + NMK_GPIO_IS); | ||
711 | |||
712 | __nmk_gpio_irq_handler(irq, desc, status); | ||
713 | } | ||
714 | |||
715 | static void nmk_gpio_secondary_irq_handler(unsigned int irq, | ||
716 | struct irq_desc *desc) | ||
717 | { | ||
718 | struct nmk_gpio_chip *nmk_chip = get_irq_data(irq); | ||
719 | u32 status = nmk_chip->get_secondary_status(nmk_chip->bank); | ||
720 | |||
721 | __nmk_gpio_irq_handler(irq, desc, status); | ||
722 | } | ||
723 | |||
543 | static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) | 724 | static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) |
544 | { | 725 | { |
545 | unsigned int first_irq; | 726 | unsigned int first_irq; |
546 | int i; | 727 | int i; |
547 | 728 | ||
548 | first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); | 729 | first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); |
549 | for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { | 730 | for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) { |
550 | set_irq_chip(i, &nmk_gpio_irq_chip); | 731 | set_irq_chip(i, &nmk_gpio_irq_chip); |
551 | set_irq_handler(i, handle_edge_irq); | 732 | set_irq_handler(i, handle_edge_irq); |
552 | set_irq_flags(i, IRQF_VALID); | 733 | set_irq_flags(i, IRQF_VALID); |
553 | set_irq_chip_data(i, nmk_chip); | 734 | set_irq_chip_data(i, nmk_chip); |
554 | set_irq_type(i, IRQ_TYPE_EDGE_FALLING); | 735 | set_irq_type(i, IRQ_TYPE_EDGE_FALLING); |
555 | } | 736 | } |
737 | |||
556 | set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); | 738 | set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); |
557 | set_irq_data(nmk_chip->parent_irq, nmk_chip); | 739 | set_irq_data(nmk_chip->parent_irq, nmk_chip); |
740 | |||
741 | if (nmk_chip->secondary_parent_irq >= 0) { | ||
742 | set_irq_chained_handler(nmk_chip->secondary_parent_irq, | ||
743 | nmk_gpio_secondary_irq_handler); | ||
744 | set_irq_data(nmk_chip->secondary_parent_irq, nmk_chip); | ||
745 | } | ||
746 | |||
558 | return 0; | 747 | return 0; |
559 | } | 748 | } |
560 | 749 | ||
@@ -605,6 +794,97 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
605 | return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset; | 794 | return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset; |
606 | } | 795 | } |
607 | 796 | ||
797 | #ifdef CONFIG_DEBUG_FS | ||
798 | |||
799 | #include <linux/seq_file.h> | ||
800 | |||
801 | static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | ||
802 | { | ||
803 | int mode; | ||
804 | unsigned i; | ||
805 | unsigned gpio = chip->base; | ||
806 | int is_out; | ||
807 | struct nmk_gpio_chip *nmk_chip = | ||
808 | container_of(chip, struct nmk_gpio_chip, chip); | ||
809 | const char *modes[] = { | ||
810 | [NMK_GPIO_ALT_GPIO] = "gpio", | ||
811 | [NMK_GPIO_ALT_A] = "altA", | ||
812 | [NMK_GPIO_ALT_B] = "altB", | ||
813 | [NMK_GPIO_ALT_C] = "altC", | ||
814 | }; | ||
815 | |||
816 | for (i = 0; i < chip->ngpio; i++, gpio++) { | ||
817 | const char *label = gpiochip_is_requested(chip, i); | ||
818 | bool pull; | ||
819 | u32 bit = 1 << i; | ||
820 | |||
821 | if (!label) | ||
822 | continue; | ||
823 | |||
824 | is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit; | ||
825 | pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); | ||
826 | mode = nmk_gpio_get_mode(gpio); | ||
827 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", | ||
828 | gpio, label, | ||
829 | is_out ? "out" : "in ", | ||
830 | chip->get | ||
831 | ? (chip->get(chip, i) ? "hi" : "lo") | ||
832 | : "? ", | ||
833 | (mode < 0) ? "unknown" : modes[mode], | ||
834 | pull ? "pull" : "none"); | ||
835 | |||
836 | if (!is_out) { | ||
837 | int irq = gpio_to_irq(gpio); | ||
838 | struct irq_desc *desc = irq_to_desc(irq); | ||
839 | |||
840 | /* This races with request_irq(), set_irq_type(), | ||
841 | * and set_irq_wake() ... but those are "rare". | ||
842 | * | ||
843 | * More significantly, trigger type flags aren't | ||
844 | * currently maintained by genirq. | ||
845 | */ | ||
846 | if (irq >= 0 && desc->action) { | ||
847 | char *trigger; | ||
848 | |||
849 | switch (desc->status & IRQ_TYPE_SENSE_MASK) { | ||
850 | case IRQ_TYPE_NONE: | ||
851 | trigger = "(default)"; | ||
852 | break; | ||
853 | case IRQ_TYPE_EDGE_FALLING: | ||
854 | trigger = "edge-falling"; | ||
855 | break; | ||
856 | case IRQ_TYPE_EDGE_RISING: | ||
857 | trigger = "edge-rising"; | ||
858 | break; | ||
859 | case IRQ_TYPE_EDGE_BOTH: | ||
860 | trigger = "edge-both"; | ||
861 | break; | ||
862 | case IRQ_TYPE_LEVEL_HIGH: | ||
863 | trigger = "level-high"; | ||
864 | break; | ||
865 | case IRQ_TYPE_LEVEL_LOW: | ||
866 | trigger = "level-low"; | ||
867 | break; | ||
868 | default: | ||
869 | trigger = "?trigger?"; | ||
870 | break; | ||
871 | } | ||
872 | |||
873 | seq_printf(s, " irq-%d %s%s", | ||
874 | irq, trigger, | ||
875 | (desc->status & IRQ_WAKEUP) | ||
876 | ? " wakeup" : ""); | ||
877 | } | ||
878 | } | ||
879 | |||
880 | seq_printf(s, "\n"); | ||
881 | } | ||
882 | } | ||
883 | |||
884 | #else | ||
885 | #define nmk_gpio_dbg_show NULL | ||
886 | #endif | ||
887 | |||
608 | /* This structure is replicated for each GPIO block allocated at probe time */ | 888 | /* This structure is replicated for each GPIO block allocated at probe time */ |
609 | static struct gpio_chip nmk_gpio_template = { | 889 | static struct gpio_chip nmk_gpio_template = { |
610 | .direction_input = nmk_gpio_make_input, | 890 | .direction_input = nmk_gpio_make_input, |
@@ -612,10 +892,64 @@ static struct gpio_chip nmk_gpio_template = { | |||
612 | .direction_output = nmk_gpio_make_output, | 892 | .direction_output = nmk_gpio_make_output, |
613 | .set = nmk_gpio_set_output, | 893 | .set = nmk_gpio_set_output, |
614 | .to_irq = nmk_gpio_to_irq, | 894 | .to_irq = nmk_gpio_to_irq, |
615 | .ngpio = NMK_GPIO_PER_CHIP, | 895 | .dbg_show = nmk_gpio_dbg_show, |
616 | .can_sleep = 0, | 896 | .can_sleep = 0, |
617 | }; | 897 | }; |
618 | 898 | ||
899 | /* | ||
900 | * Called from the suspend/resume path to only keep the real wakeup interrupts | ||
901 | * (those that have had set_irq_wake() called on them) as wakeup interrupts, | ||
902 | * and not the rest of the interrupts which we needed to have as wakeups for | ||
903 | * cpuidle. | ||
904 | * | ||
905 | * PM ops are not used since this needs to be done at the end, after all the | ||
906 | * other drivers are done with their suspend callbacks. | ||
907 | */ | ||
908 | void nmk_gpio_wakeups_suspend(void) | ||
909 | { | ||
910 | int i; | ||
911 | |||
912 | for (i = 0; i < NUM_BANKS; i++) { | ||
913 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; | ||
914 | |||
915 | if (!chip) | ||
916 | break; | ||
917 | |||
918 | chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); | ||
919 | chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); | ||
920 | |||
921 | writel(chip->rwimsc & chip->real_wake, | ||
922 | chip->addr + NMK_GPIO_RWIMSC); | ||
923 | writel(chip->fwimsc & chip->real_wake, | ||
924 | chip->addr + NMK_GPIO_FWIMSC); | ||
925 | |||
926 | if (cpu_is_u8500v2()) { | ||
927 | chip->slpm = readl(chip->addr + NMK_GPIO_SLPC); | ||
928 | |||
929 | /* 0 -> wakeup enable */ | ||
930 | writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); | ||
931 | } | ||
932 | } | ||
933 | } | ||
934 | |||
935 | void nmk_gpio_wakeups_resume(void) | ||
936 | { | ||
937 | int i; | ||
938 | |||
939 | for (i = 0; i < NUM_BANKS; i++) { | ||
940 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; | ||
941 | |||
942 | if (!chip) | ||
943 | break; | ||
944 | |||
945 | writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); | ||
946 | writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); | ||
947 | |||
948 | if (cpu_is_u8500v2()) | ||
949 | writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); | ||
950 | } | ||
951 | } | ||
952 | |||
619 | static int __devinit nmk_gpio_probe(struct platform_device *dev) | 953 | static int __devinit nmk_gpio_probe(struct platform_device *dev) |
620 | { | 954 | { |
621 | struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; | 955 | struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; |
@@ -623,6 +957,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
623 | struct gpio_chip *chip; | 957 | struct gpio_chip *chip; |
624 | struct resource *res; | 958 | struct resource *res; |
625 | struct clk *clk; | 959 | struct clk *clk; |
960 | int secondary_irq; | ||
626 | int irq; | 961 | int irq; |
627 | int ret; | 962 | int ret; |
628 | 963 | ||
@@ -641,6 +976,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
641 | goto out; | 976 | goto out; |
642 | } | 977 | } |
643 | 978 | ||
979 | secondary_irq = platform_get_irq(dev, 1); | ||
980 | if (secondary_irq >= 0 && !pdata->get_secondary_status) { | ||
981 | ret = -EINVAL; | ||
982 | goto out; | ||
983 | } | ||
984 | |||
644 | if (request_mem_region(res->start, resource_size(res), | 985 | if (request_mem_region(res->start, resource_size(res), |
645 | dev_name(&dev->dev)) == NULL) { | 986 | dev_name(&dev->dev)) == NULL) { |
646 | ret = -EBUSY; | 987 | ret = -EBUSY; |
@@ -664,14 +1005,19 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
664 | * The virt address in nmk_chip->addr is in the nomadik register space, | 1005 | * The virt address in nmk_chip->addr is in the nomadik register space, |
665 | * so we can simply convert the resource address, without remapping | 1006 | * so we can simply convert the resource address, without remapping |
666 | */ | 1007 | */ |
1008 | nmk_chip->bank = dev->id; | ||
667 | nmk_chip->clk = clk; | 1009 | nmk_chip->clk = clk; |
668 | nmk_chip->addr = io_p2v(res->start); | 1010 | nmk_chip->addr = io_p2v(res->start); |
669 | nmk_chip->chip = nmk_gpio_template; | 1011 | nmk_chip->chip = nmk_gpio_template; |
670 | nmk_chip->parent_irq = irq; | 1012 | nmk_chip->parent_irq = irq; |
1013 | nmk_chip->secondary_parent_irq = secondary_irq; | ||
1014 | nmk_chip->get_secondary_status = pdata->get_secondary_status; | ||
1015 | nmk_chip->set_ioforce = pdata->set_ioforce; | ||
671 | spin_lock_init(&nmk_chip->lock); | 1016 | spin_lock_init(&nmk_chip->lock); |
672 | 1017 | ||
673 | chip = &nmk_chip->chip; | 1018 | chip = &nmk_chip->chip; |
674 | chip->base = pdata->first_gpio; | 1019 | chip->base = pdata->first_gpio; |
1020 | chip->ngpio = pdata->num_gpio; | ||
675 | chip->label = pdata->name ?: dev_name(&dev->dev); | 1021 | chip->label = pdata->name ?: dev_name(&dev->dev); |
676 | chip->dev = &dev->dev; | 1022 | chip->dev = &dev->dev; |
677 | chip->owner = THIS_MODULE; | 1023 | chip->owner = THIS_MODULE; |
@@ -680,6 +1026,9 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
680 | if (ret) | 1026 | if (ret) |
681 | goto out_free; | 1027 | goto out_free; |
682 | 1028 | ||
1029 | BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); | ||
1030 | |||
1031 | nmk_gpio_chips[nmk_chip->bank] = nmk_chip; | ||
683 | platform_set_drvdata(dev, nmk_chip); | 1032 | platform_set_drvdata(dev, nmk_chip); |
684 | 1033 | ||
685 | nmk_gpio_init_irq(nmk_chip); | 1034 | nmk_gpio_init_irq(nmk_chip); |
@@ -705,10 +1054,8 @@ static struct platform_driver nmk_gpio_driver = { | |||
705 | .driver = { | 1054 | .driver = { |
706 | .owner = THIS_MODULE, | 1055 | .owner = THIS_MODULE, |
707 | .name = "gpio", | 1056 | .name = "gpio", |
708 | }, | 1057 | }, |
709 | .probe = nmk_gpio_probe, | 1058 | .probe = nmk_gpio_probe, |
710 | .suspend = NULL, /* to be done */ | ||
711 | .resume = NULL, | ||
712 | }; | 1059 | }; |
713 | 1060 | ||
714 | static int __init nmk_gpio_init(void) | 1061 | static int __init nmk_gpio_init(void) |
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index 67b113d639d8..1b9f6f0843d1 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h | |||
@@ -75,6 +75,9 @@ extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); | |||
75 | extern int nmk_gpio_set_mode(int gpio, int gpio_mode); | 75 | extern int nmk_gpio_set_mode(int gpio, int gpio_mode); |
76 | extern int nmk_gpio_get_mode(int gpio); | 76 | extern int nmk_gpio_get_mode(int gpio); |
77 | 77 | ||
78 | extern void nmk_gpio_wakeups_suspend(void); | ||
79 | extern void nmk_gpio_wakeups_resume(void); | ||
80 | |||
78 | /* | 81 | /* |
79 | * Platform data to register a block: only the initial gpio/irq number. | 82 | * Platform data to register a block: only the initial gpio/irq number. |
80 | */ | 83 | */ |
@@ -82,6 +85,9 @@ struct nmk_gpio_platform_data { | |||
82 | char *name; | 85 | char *name; |
83 | int first_gpio; | 86 | int first_gpio; |
84 | int first_irq; | 87 | int first_irq; |
88 | int num_gpio; | ||
89 | u32 (*get_secondary_status)(unsigned int bank); | ||
90 | void (*set_ioforce)(bool enable); | ||
85 | }; | 91 | }; |
86 | 92 | ||
87 | #endif /* __ASM_PLAT_GPIO_H */ | 93 | #endif /* __ASM_PLAT_GPIO_H */ |