aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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