aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2012-10-26 19:05:06 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-10-26 19:05:06 -0400
commit3a6ca8c5c9e310d26fe090ac7c777c269661f0e6 (patch)
tree0e61e6fa28b7a22e1fdc47100bc5a8207cbeb5ca /arch/arm
parent6f0c0580b70c89094b3422ba81118c7b959c7556 (diff)
ARM: plat-versatile: use simple irqdomain for FPGA IRQ
This switches the FPGA IRQ driver over to using the simple IRQ domain. We can then use the same codepath for this in the DT and non-DT cases. To be able to use quicker irq_find_mapping() in the handlers we first call irq_create_mapping() on all the valid HW IRQ numbers so that descriptors will be created for them in the DT case where a linear domain will be the outcome of the call. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/plat-versatile/fpga-irq.c50
1 files changed, 22 insertions, 28 deletions
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c
index 091ae1030045..dfe317c20354 100644
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ b/arch/arm/plat-versatile/fpga-irq.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Support for Versatile FPGA-based IRQ controllers 2 * Support for Versatile FPGA-based IRQ controllers
3 */ 3 */
4#include <linux/bitops.h>
4#include <linux/irq.h> 5#include <linux/irq.h>
5#include <linux/io.h> 6#include <linux/io.h>
6#include <linux/irqdomain.h> 7#include <linux/irqdomain.h>
@@ -117,13 +118,12 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
117 struct fpga_irq_data *f = d->host_data; 118 struct fpga_irq_data *f = d->host_data;
118 119
119 /* Skip invalid IRQs, only register handlers for the real ones */ 120 /* Skip invalid IRQs, only register handlers for the real ones */
120 if (!(f->valid & (1 << hwirq))) 121 if (!(f->valid & BIT(hwirq)))
121 return -ENOTSUPP; 122 return -ENOTSUPP;
122 irq_set_chip_data(irq, f); 123 irq_set_chip_data(irq, f);
123 irq_set_chip_and_handler(irq, &f->chip, 124 irq_set_chip_and_handler(irq, &f->chip,
124 handle_level_irq); 125 handle_level_irq);
125 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 126 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
126 f->used_irqs++;
127 return 0; 127 return 0;
128} 128}
129 129
@@ -132,13 +132,15 @@ static struct irq_domain_ops fpga_irqdomain_ops = {
132 .xlate = irq_domain_xlate_onetwocell, 132 .xlate = irq_domain_xlate_onetwocell,
133}; 133};
134 134
135static __init struct fpga_irq_data * 135void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
136fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) { 136 int parent_irq, u32 valid, struct device_node *node)
137{
137 struct fpga_irq_data *f; 138 struct fpga_irq_data *f;
139 int i;
138 140
139 if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) { 141 if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
140 printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__); 142 pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
141 return NULL; 143 return;
142 } 144 }
143 f = &fpga_irq_devices[fpga_irq_id]; 145 f = &fpga_irq_devices[fpga_irq_id];
144 f->base = base; 146 f->base = base;
@@ -147,29 +149,28 @@ fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
147 f->chip.irq_mask = fpga_irq_mask; 149 f->chip.irq_mask = fpga_irq_mask;
148 f->chip.irq_unmask = fpga_irq_unmask; 150 f->chip.irq_unmask = fpga_irq_unmask;
149 f->valid = valid; 151 f->valid = valid;
150 fpga_irq_id++;
151
152 return f;
153}
154
155void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
156 int parent_irq, u32 valid, struct device_node *node)
157{
158 struct fpga_irq_data *f;
159
160 f = fpga_irq_prep_struct(base, name, valid);
161 if (!f)
162 return;
163 152
164 if (parent_irq != -1) { 153 if (parent_irq != -1) {
165 irq_set_handler_data(parent_irq, f); 154 irq_set_handler_data(parent_irq, f);
166 irq_set_chained_handler(parent_irq, fpga_irq_handle); 155 irq_set_chained_handler(parent_irq, fpga_irq_handle);
167 } 156 }
168 157
169 f->domain = irq_domain_add_legacy(node, fls(valid), irq_start, 0, 158 /* This will also allocate irq descriptors */
159 f->domain = irq_domain_add_simple(node, fls(valid), irq_start,
170 &fpga_irqdomain_ops, f); 160 &fpga_irqdomain_ops, f);
161
162 /* This will allocate all valid descriptors in the linear case */
163 for (i = 0; i < fls(valid); i++)
164 if (valid & BIT(i)) {
165 if (!irq_start)
166 irq_create_mapping(f->domain, i);
167 f->used_irqs++;
168 }
169
171 pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n", 170 pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
172 fpga_irq_id, name, base, f->used_irqs); 171 fpga_irq_id, name, base, f->used_irqs);
172
173 fpga_irq_id++;
173} 174}
174 175
175#ifdef CONFIG_OF 176#ifdef CONFIG_OF
@@ -193,18 +194,11 @@ int __init fpga_irq_of_init(struct device_node *node,
193 if (of_property_read_u32(node, "valid-mask", &valid_mask)) 194 if (of_property_read_u32(node, "valid-mask", &valid_mask))
194 valid_mask = 0; 195 valid_mask = 0;
195 196
196 f = fpga_irq_prep_struct(base, node->name, valid_mask); 197 fpga_irq_init(base, node->name, 0, -1, valid_mask, node);
197 if (!f)
198 return -ENOMEM;
199 198
200 writel(clear_mask, base + IRQ_ENABLE_CLEAR); 199 writel(clear_mask, base + IRQ_ENABLE_CLEAR);
201 writel(clear_mask, base + FIQ_ENABLE_CLEAR); 200 writel(clear_mask, base + FIQ_ENABLE_CLEAR);
202 201
203 f->domain = irq_domain_add_linear(node, fls(valid_mask), &fpga_irqdomain_ops, f);
204 f->used_irqs = hweight32(valid_mask);
205
206 pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
207 fpga_irq_id, node->name, base, f->used_irqs);
208 return 0; 202 return 0;
209} 203}
210#endif 204#endif