diff options
-rw-r--r-- | arch/arm/plat-versatile/fpga-irq.c | 50 |
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 | ||
135 | static __init struct fpga_irq_data * | 135 | void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start, |
136 | fpga_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 | |||
155 | void __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 |