diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2011-09-23 20:29:46 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-10-24 18:34:25 -0400 |
commit | 83bc769200802c9ce8fd1c7315fd14198d385b12 (patch) | |
tree | 5ad1e1704460f1bb03a6bfb13fdb2fa81ebc3279 /arch/mips/jz4740/irq.c | |
parent | 3766386037827fe7064f57f9aec27b3b5e9417aa (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/jz4740/irq.c')
-rw-r--r-- | arch/mips/jz4740/irq.c | 92 |
1 files changed, 38 insertions, 54 deletions
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 | ||
34 | static void __iomem *jz_intc_base; | 34 | static void __iomem *jz_intc_base; |
35 | static uint32_t jz_intc_wakeup; | ||
36 | static 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) | 42 | static irqreturn_t jz4740_cascade(int irq, void *data) |
45 | |||
46 | static 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 | ||
51 | static 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 | ||
56 | static 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 | ||
61 | static int intc_irq_set_wake(struct irq_data *data, unsigned int on) | 54 | static 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 | ||
71 | static struct irq_chip intc_irq_type = { | 62 | void 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 | |||
79 | static 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; | 68 | void 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 | ||
91 | static struct irqaction jz4740_cascade_action = { | 74 | static struct irqaction jz4740_cascade_action = { |
@@ -95,7 +78,9 @@ static struct irqaction jz4740_cascade_action = { | |||
95 | 78 | ||
96 | void __init arch_init_irq(void) | 79 | void __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 | ||
125 | void 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 | |||
132 | void 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 | ||
140 | static inline void intc_seq_reg(struct seq_file *s, const char *name, | 124 | static inline void intc_seq_reg(struct seq_file *s, const char *name, |