aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2011-09-23 20:29:46 -0400
committerRalf Baechle <ralf@linux-mips.org>2011-10-24 18:34:25 -0400
commit83bc769200802c9ce8fd1c7315fd14198d385b12 (patch)
tree5ad1e1704460f1bb03a6bfb13fdb2fa81ebc3279 /arch/mips
parent3766386037827fe7064f57f9aec27b3b5e9417aa (diff)
MIPS: JZ4740: Use generic irq chip
Use the generic irq chip framework to implement the jz4740 INTC and GPIO irq chips. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/2434/ Patchwork: https://patchwork.linux-mips.org/patch/2771/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/jz4740/gpio.c130
-rw-r--r--arch/mips/jz4740/irq.c92
-rw-r--r--arch/mips/jz4740/irq.h6
-rw-r--r--arch/mips/jz4740/pm.c3
5 files changed, 79 insertions, 153 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d4d569b158fd..0674b12841ee 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -215,6 +215,7 @@ config MACH_JZ4740
215 select SYS_HAS_EARLY_PRINTK 215 select SYS_HAS_EARLY_PRINTK
216 select HAVE_PWM 216 select HAVE_PWM
217 select HAVE_CLK 217 select HAVE_CLK
218 select GENERIC_IRQ_CHIP
218 219
219config LANTIQ 220config LANTIQ
220 bool "Lantiq based platforms" 221 bool "Lantiq based platforms"
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c
index 4397972949fa..415d7d7e3283 100644
--- a/arch/mips/jz4740/gpio.c
+++ b/arch/mips/jz4740/gpio.c
@@ -17,8 +17,6 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/init.h> 18#include <linux/init.h>
19 19
20#include <linux/spinlock.h>
21#include <linux/syscore_ops.h>
22#include <linux/io.h> 20#include <linux/io.h>
23#include <linux/gpio.h> 21#include <linux/gpio.h>
24#include <linux/delay.h> 22#include <linux/delay.h>
@@ -30,6 +28,8 @@
30 28
31#include <asm/mach-jz4740/base.h> 29#include <asm/mach-jz4740/base.h>
32 30
31#include "irq.h"
32
33#define JZ4740_GPIO_BASE_A (32*0) 33#define JZ4740_GPIO_BASE_A (32*0)
34#define JZ4740_GPIO_BASE_B (32*1) 34#define JZ4740_GPIO_BASE_B (32*1)
35#define JZ4740_GPIO_BASE_C (32*2) 35#define JZ4740_GPIO_BASE_C (32*2)
@@ -77,14 +77,10 @@
77struct jz_gpio_chip { 77struct jz_gpio_chip {
78 unsigned int irq; 78 unsigned int irq;
79 unsigned int irq_base; 79 unsigned int irq_base;
80 uint32_t wakeup;
81 uint32_t suspend_mask;
82 uint32_t edge_trigger_both; 80 uint32_t edge_trigger_both;
83 81
84 void __iomem *base; 82 void __iomem *base;
85 83
86 spinlock_t lock;
87
88 struct gpio_chip gpio_chip; 84 struct gpio_chip gpio_chip;
89}; 85};
90 86
@@ -102,7 +98,8 @@ static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *g
102 98
103static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data) 99static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data)
104{ 100{
105 return irq_data_get_irq_chip_data(data); 101 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
102 return gc->private;
106} 103}
107 104
108static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) 105static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg)
@@ -329,18 +326,12 @@ static inline void jz_gpio_set_irq_bit(struct irq_data *data, unsigned int reg)
329 writel(IRQ_TO_BIT(data->irq), chip->base + reg); 326 writel(IRQ_TO_BIT(data->irq), chip->base + reg);
330} 327}
331 328
332static void jz_gpio_irq_mask(struct irq_data *data)
333{
334 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET);
335};
336
337static void jz_gpio_irq_unmask(struct irq_data *data) 329static void jz_gpio_irq_unmask(struct irq_data *data)
338{ 330{
339 struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); 331 struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
340 332
341 jz_gpio_check_trigger_both(chip, data->irq); 333 jz_gpio_check_trigger_both(chip, data->irq);
342 334 irq_gc_unmask_enable_reg(data);
343 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR);
344}; 335};
345 336
346/* TODO: Check if function is gpio */ 337/* TODO: Check if function is gpio */
@@ -353,18 +344,13 @@ static unsigned int jz_gpio_irq_startup(struct irq_data *data)
353 344
354static void jz_gpio_irq_shutdown(struct irq_data *data) 345static void jz_gpio_irq_shutdown(struct irq_data *data)
355{ 346{
356 jz_gpio_irq_mask(data); 347 irq_gc_mask_disable_reg(data);
357 348
358 /* Set direction to input */ 349 /* Set direction to input */
359 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); 350 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR);
360 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR); 351 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR);
361} 352}
362 353
363static void jz_gpio_irq_ack(struct irq_data *data)
364{
365 jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR);
366};
367
368static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) 354static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
369{ 355{
370 struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); 356 struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
@@ -408,35 +394,13 @@ static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
408static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) 394static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
409{ 395{
410 struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); 396 struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
411 spin_lock(&chip->lock);
412 if (on)
413 chip->wakeup |= IRQ_TO_BIT(data->irq);
414 else
415 chip->wakeup &= ~IRQ_TO_BIT(data->irq);
416 spin_unlock(&chip->lock);
417 397
398 irq_gc_set_wake(data, on);
418 irq_set_irq_wake(chip->irq, on); 399 irq_set_irq_wake(chip->irq, on);
400
419 return 0; 401 return 0;
420} 402}
421 403
422static struct irq_chip jz_gpio_irq_chip = {
423 .name = "GPIO",
424 .irq_mask = jz_gpio_irq_mask,
425 .irq_unmask = jz_gpio_irq_unmask,
426 .irq_ack = jz_gpio_irq_ack,
427 .irq_startup = jz_gpio_irq_startup,
428 .irq_shutdown = jz_gpio_irq_shutdown,
429 .irq_set_type = jz_gpio_irq_set_type,
430 .irq_set_wake = jz_gpio_irq_set_wake,
431 .flags = IRQCHIP_SET_TYPE_MASKED,
432};
433
434/*
435 * This lock class tells lockdep that GPIO irqs are in a different
436 * category than their parents, so it won't report false recursion.
437 */
438static struct lock_class_key gpio_lock_class;
439
440#define JZ4740_GPIO_CHIP(_bank) { \ 404#define JZ4740_GPIO_CHIP(_bank) { \
441 .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ 405 .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \
442 .gpio_chip = { \ 406 .gpio_chip = { \
@@ -458,64 +422,44 @@ static struct jz_gpio_chip jz4740_gpio_chips[] = {
458 JZ4740_GPIO_CHIP(D), 422 JZ4740_GPIO_CHIP(D),
459}; 423};
460 424
461static void jz4740_gpio_suspend_chip(struct jz_gpio_chip *chip) 425static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
462{
463 chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK);
464 writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET);
465 writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR);
466}
467
468static int jz4740_gpio_suspend(void)
469{
470 int i;
471
472 for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); i++)
473 jz4740_gpio_suspend_chip(&jz4740_gpio_chips[i]);
474
475 return 0;
476}
477
478static void jz4740_gpio_resume_chip(struct jz_gpio_chip *chip)
479{ 426{
480 uint32_t mask = chip->suspend_mask; 427 struct irq_chip_generic *gc;
428 struct irq_chip_type *ct;
481 429
482 writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); 430 chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
483 writel(mask, chip->base + JZ_REG_GPIO_MASK_SET);
484}
485 431
486static void jz4740_gpio_resume(void) 432 chip->irq = JZ4740_IRQ_INTC_GPIO(id);
487{ 433 irq_set_handler_data(chip->irq, chip);
488 int i; 434 irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
489 435
490 for (i = ARRAY_SIZE(jz4740_gpio_chips) - 1; i >= 0 ; i--) 436 gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base,
491 jz4740_gpio_resume_chip(&jz4740_gpio_chips[i]); 437 chip->base, handle_level_irq);
492}
493 438
494static struct syscore_ops jz4740_gpio_syscore_ops = { 439 gc->wake_enabled = IRQ_MSK(chip->gpio_chip.ngpio);
495 .suspend = jz4740_gpio_suspend, 440 gc->private = chip;
496 .resume = jz4740_gpio_resume,
497};
498 441
499static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) 442 ct = gc->chip_types;
500{ 443 ct->regs.enable = JZ_REG_GPIO_MASK_CLEAR;
501 int irq; 444 ct->regs.disable = JZ_REG_GPIO_MASK_SET;
445 ct->regs.ack = JZ_REG_GPIO_FLAG_CLEAR;
502 446
503 spin_lock_init(&chip->lock); 447 ct->chip.name = "GPIO";
448 ct->chip.irq_mask = irq_gc_mask_disable_reg;
449 ct->chip.irq_unmask = jz_gpio_irq_unmask;
450 ct->chip.irq_ack = irq_gc_ack_set_bit;
451 ct->chip.irq_suspend = jz4740_irq_suspend;
452 ct->chip.irq_resume = jz4740_irq_resume;
453 ct->chip.irq_startup = jz_gpio_irq_startup;
454 ct->chip.irq_shutdown = jz_gpio_irq_shutdown;
455 ct->chip.irq_set_type = jz_gpio_irq_set_type;
456 ct->chip.irq_set_wake = jz_gpio_irq_set_wake;
457 ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
504 458
505 chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); 459 irq_setup_generic_chip(gc, IRQ_MSK(chip->gpio_chip.ngpio),
460 IRQ_GC_INIT_NESTED_LOCK, 0, IRQ_NOPROBE | IRQ_LEVEL);
506 461
507 gpiochip_add(&chip->gpio_chip); 462 gpiochip_add(&chip->gpio_chip);
508
509 chip->irq = JZ4740_IRQ_INTC_GPIO(id);
510 irq_set_handler_data(chip->irq, chip);
511 irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
512
513 for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) {
514 irq_set_lockdep_class(irq, &gpio_lock_class);
515 irq_set_chip_data(irq, chip);
516 irq_set_chip_and_handler(irq, &jz_gpio_irq_chip,
517 handle_level_irq);
518 }
519} 463}
520 464
521static int __init jz4740_gpio_init(void) 465static int __init jz4740_gpio_init(void)
@@ -525,8 +469,6 @@ static int __init jz4740_gpio_init(void)
525 for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) 469 for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i)
526 jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); 470 jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i);
527 471
528 register_syscore_ops(&jz4740_gpio_syscore_ops);
529
530 printk(KERN_INFO "JZ4740 GPIO initialized\n"); 472 printk(KERN_INFO "JZ4740 GPIO initialized\n");
531 473
532 return 0; 474 return 0;
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index d82c0c430e03..fc57ded326d8 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -32,8 +32,6 @@
32#include <asm/mach-jz4740/base.h> 32#include <asm/mach-jz4740/base.h>
33 33
34static void __iomem *jz_intc_base; 34static void __iomem *jz_intc_base;
35static uint32_t jz_intc_wakeup;
36static uint32_t jz_intc_saved;
37 35
38#define JZ_REG_INTC_STATUS 0x00 36#define JZ_REG_INTC_STATUS 0x00
39#define JZ_REG_INTC_MASK 0x04 37#define JZ_REG_INTC_MASK 0x04
@@ -41,51 +39,36 @@ static uint32_t jz_intc_saved;
41#define JZ_REG_INTC_CLEAR_MASK 0x0c 39#define JZ_REG_INTC_CLEAR_MASK 0x0c
42#define JZ_REG_INTC_PENDING 0x10 40#define JZ_REG_INTC_PENDING 0x10
43 41
44#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE) 42static irqreturn_t jz4740_cascade(int irq, void *data)
45
46static inline unsigned long intc_irq_bit(struct irq_data *data)
47{ 43{
48 return (unsigned long)irq_data_get_irq_chip_data(data); 44 uint32_t irq_reg;
49}
50 45
51static void intc_irq_unmask(struct irq_data *data) 46 irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
52{
53 writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
54}
55 47
56static void intc_irq_mask(struct irq_data *data) 48 if (irq_reg)
57{ 49 generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
58 writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_SET_MASK); 50
51 return IRQ_HANDLED;
59} 52}
60 53
61static int intc_irq_set_wake(struct irq_data *data, unsigned int on) 54static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
62{ 55{
63 if (on) 56 struct irq_chip_regs *regs = &gc->chip_types->regs;
64 jz_intc_wakeup |= intc_irq_bit(data);
65 else
66 jz_intc_wakeup &= ~intc_irq_bit(data);
67 57
68 return 0; 58 writel(mask, gc->reg_base + regs->enable);
59 writel(~mask, gc->reg_base + regs->disable);
69} 60}
70 61
71static struct irq_chip intc_irq_type = { 62void jz4740_irq_suspend(struct irq_data *data)
72 .name = "INTC",
73 .irq_mask = intc_irq_mask,
74 .irq_mask_ack = intc_irq_mask,
75 .irq_unmask = intc_irq_unmask,
76 .irq_set_wake = intc_irq_set_wake,
77};
78
79static irqreturn_t jz4740_cascade(int irq, void *data)
80{ 63{
81 uint32_t irq_reg; 64 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
82 65 jz4740_irq_set_mask(gc, gc->wake_active);
83 irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); 66}
84
85 if (irq_reg)
86 generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
87 67
88 return IRQ_HANDLED; 68void jz4740_irq_resume(struct irq_data *data)
69{
70 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
71 jz4740_irq_set_mask(gc, gc->mask_cache);
89} 72}
90 73
91static struct irqaction jz4740_cascade_action = { 74static struct irqaction jz4740_cascade_action = {
@@ -95,7 +78,9 @@ static struct irqaction jz4740_cascade_action = {
95 78
96void __init arch_init_irq(void) 79void __init arch_init_irq(void)
97{ 80{
98 int i; 81 struct irq_chip_generic *gc;
82 struct irq_chip_type *ct;
83
99 mips_cpu_irq_init(); 84 mips_cpu_irq_init();
100 85
101 jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14); 86 jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
@@ -103,10 +88,22 @@ void __init arch_init_irq(void)
103 /* Mask all irqs */ 88 /* Mask all irqs */
104 writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK); 89 writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
105 90
106 for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) { 91 gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
107 irq_set_chip_data(i, (void *)IRQ_BIT(i)); 92 handle_level_irq);
108 irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq); 93
109 } 94 gc->wake_enabled = IRQ_MSK(32);
95
96 ct = gc->chip_types;
97 ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
98 ct->regs.disable = JZ_REG_INTC_SET_MASK;
99 ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
100 ct->chip.irq_mask = irq_gc_mask_disable_reg;
101 ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
102 ct->chip.irq_set_wake = irq_gc_set_wake;
103 ct->chip.irq_suspend = jz4740_irq_suspend;
104 ct->chip.irq_resume = jz4740_irq_resume;
105
106 irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
110 107
111 setup_irq(2, &jz4740_cascade_action); 108 setup_irq(2, &jz4740_cascade_action);
112} 109}
@@ -122,19 +119,6 @@ asmlinkage void plat_irq_dispatch(void)
122 spurious_interrupt(); 119 spurious_interrupt();
123} 120}
124 121
125void jz4740_intc_suspend(void)
126{
127 jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
128 writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
129 writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
130}
131
132void jz4740_intc_resume(void)
133{
134 writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
135 writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
136}
137
138#ifdef CONFIG_DEBUG_FS 122#ifdef CONFIG_DEBUG_FS
139 123
140static inline void intc_seq_reg(struct seq_file *s, const char *name, 124static inline void intc_seq_reg(struct seq_file *s, const char *name,
diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h
index 56b5eadd1fa2..f75e39d62885 100644
--- a/arch/mips/jz4740/irq.h
+++ b/arch/mips/jz4740/irq.h
@@ -15,7 +15,9 @@
15#ifndef __MIPS_JZ4740_IRQ_H__ 15#ifndef __MIPS_JZ4740_IRQ_H__
16#define __MIPS_JZ4740_IRQ_H__ 16#define __MIPS_JZ4740_IRQ_H__
17 17
18extern void jz4740_intc_suspend(void); 18#include <linux/irq.h>
19extern void jz4740_intc_resume(void); 19
20extern void jz4740_irq_suspend(struct irq_data *data);
21extern void jz4740_irq_resume(struct irq_data *data);
20 22
21#endif 23#endif
diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c
index 902d5b50124c..6744fa723f72 100644
--- a/arch/mips/jz4740/pm.c
+++ b/arch/mips/jz4740/pm.c
@@ -21,11 +21,9 @@
21#include <asm/mach-jz4740/clock.h> 21#include <asm/mach-jz4740/clock.h>
22 22
23#include "clock.h" 23#include "clock.h"
24#include "irq.h"
25 24
26static int jz4740_pm_enter(suspend_state_t state) 25static int jz4740_pm_enter(suspend_state_t state)
27{ 26{
28 jz4740_intc_suspend();
29 jz4740_clock_suspend(); 27 jz4740_clock_suspend();
30 28
31 jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP); 29 jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP);
@@ -37,7 +35,6 @@ static int jz4740_pm_enter(suspend_state_t state)
37 jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE); 35 jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE);
38 36
39 jz4740_clock_resume(); 37 jz4740_clock_resume();
40 jz4740_intc_resume();
41 38
42 return 0; 39 return 0;
43} 40}