aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/jz4740/irq.c
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/jz4740/irq.c
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/jz4740/irq.c')
-rw-r--r--arch/mips/jz4740/irq.c92
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
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,