Lines Matching +full:irqs +full:- +full:reserved

1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/irqchip/irq-crossbar.c
5 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
16 #define IRQ_FREE -1
17 #define IRQ_RESERVED -2
18 #define IRQ_SKIP -3
22 * struct crossbar_device - crossbar device description
47 writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); in crossbar_writel()
52 writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); in crossbar_writew()
57 writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); in crossbar_writeb()
81 if (!irq_domain_get_of_node(domain->parent)) in allocate_gic_irq()
82 return -EINVAL; in allocate_gic_irq()
84 raw_spin_lock(&cb->lock); in allocate_gic_irq()
85 for (i = cb->int_max - 1; i >= 0; i--) { in allocate_gic_irq()
86 if (cb->irq_map[i] == IRQ_FREE) { in allocate_gic_irq()
87 cb->irq_map[i] = hwirq; in allocate_gic_irq()
91 raw_spin_unlock(&cb->lock); in allocate_gic_irq()
94 return -ENODEV; in allocate_gic_irq()
96 fwspec.fwnode = domain->parent->fwnode; in allocate_gic_irq()
104 cb->irq_map[i] = IRQ_FREE; in allocate_gic_irq()
106 cb->write(i, hwirq); in allocate_gic_irq()
118 if (fwspec->param_count != 3) in crossbar_domain_alloc()
119 return -EINVAL; /* Not GIC compliant */ in crossbar_domain_alloc()
120 if (fwspec->param[0] != 0) in crossbar_domain_alloc()
121 return -EINVAL; /* No PPI should point to this domain */ in crossbar_domain_alloc()
123 hwirq = fwspec->param[1]; in crossbar_domain_alloc()
124 if ((hwirq + nr_irqs) > cb->max_crossbar_sources) in crossbar_domain_alloc()
125 return -EINVAL; /* Can't deal with this */ in crossbar_domain_alloc()
141 * crossbar_domain_free - unmap/free a crossbar<->irq connection
144 * @nr_irqs: number of irqs to free
157 raw_spin_lock(&cb->lock); in crossbar_domain_free()
162 cb->irq_map[d->hwirq] = IRQ_FREE; in crossbar_domain_free()
163 cb->write(d->hwirq, cb->safe_map); in crossbar_domain_free()
165 raw_spin_unlock(&cb->lock); in crossbar_domain_free()
173 if (is_of_node(fwspec->fwnode)) { in crossbar_domain_translate()
174 if (fwspec->param_count != 3) in crossbar_domain_translate()
175 return -EINVAL; in crossbar_domain_translate()
178 if (fwspec->param[0] != 0) in crossbar_domain_translate()
179 return -EINVAL; in crossbar_domain_translate()
181 *hwirq = fwspec->param[1]; in crossbar_domain_translate()
182 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; in crossbar_domain_translate()
186 return -EINVAL; in crossbar_domain_translate()
198 int i, size, reserved = 0; in crossbar_of_init() local
200 int ret = -ENOMEM; in crossbar_of_init()
207 cb->crossbar_base = of_iomap(node, 0); in crossbar_of_init()
208 if (!cb->crossbar_base) in crossbar_of_init()
211 of_property_read_u32(node, "ti,max-crossbar-sources", in crossbar_of_init()
212 &cb->max_crossbar_sources); in crossbar_of_init()
213 if (!cb->max_crossbar_sources) { in crossbar_of_init()
214 pr_err("missing 'ti,max-crossbar-sources' property\n"); in crossbar_of_init()
215 ret = -EINVAL; in crossbar_of_init()
219 of_property_read_u32(node, "ti,max-irqs", &max); in crossbar_of_init()
221 pr_err("missing 'ti,max-irqs' property\n"); in crossbar_of_init()
222 ret = -EINVAL; in crossbar_of_init()
225 cb->irq_map = kcalloc(max, sizeof(int), GFP_KERNEL); in crossbar_of_init()
226 if (!cb->irq_map) in crossbar_of_init()
229 cb->int_max = max; in crossbar_of_init()
232 cb->irq_map[i] = IRQ_FREE; in crossbar_of_init()
234 /* Get and mark reserved irqs */ in crossbar_of_init()
235 irqsr = of_get_property(node, "ti,irqs-reserved", &size); in crossbar_of_init()
241 "ti,irqs-reserved", in crossbar_of_init()
244 pr_err("Invalid reserved entry\n"); in crossbar_of_init()
245 ret = -EINVAL; in crossbar_of_init()
248 cb->irq_map[entry] = IRQ_RESERVED; in crossbar_of_init()
252 /* Skip irqs hardwired to bypass the crossbar */ in crossbar_of_init()
253 irqsr = of_get_property(node, "ti,irqs-skip", &size); in crossbar_of_init()
259 "ti,irqs-skip", in crossbar_of_init()
263 ret = -EINVAL; in crossbar_of_init()
266 cb->irq_map[entry] = IRQ_SKIP; in crossbar_of_init()
271 cb->register_offsets = kcalloc(max, sizeof(int), GFP_KERNEL); in crossbar_of_init()
272 if (!cb->register_offsets) in crossbar_of_init()
275 of_property_read_u32(node, "ti,reg-size", &reg_size); in crossbar_of_init()
279 cb->write = crossbar_writeb; in crossbar_of_init()
282 cb->write = crossbar_writew; in crossbar_of_init()
285 cb->write = crossbar_writel; in crossbar_of_init()
288 pr_err("Invalid reg-size property\n"); in crossbar_of_init()
289 ret = -EINVAL; in crossbar_of_init()
296 * reserved irqs. so find and store the offsets once. in crossbar_of_init()
299 if (cb->irq_map[i] == IRQ_RESERVED) in crossbar_of_init()
302 cb->register_offsets[i] = reserved; in crossbar_of_init()
303 reserved += reg_size; in crossbar_of_init()
306 of_property_read_u32(node, "ti,irqs-safe-map", &cb->safe_map); in crossbar_of_init()
309 if (cb->irq_map[i] == IRQ_RESERVED || in crossbar_of_init()
310 cb->irq_map[i] == IRQ_SKIP) in crossbar_of_init()
313 cb->write(i, cb->safe_map); in crossbar_of_init()
316 raw_spin_lock_init(&cb->lock); in crossbar_of_init()
321 kfree(cb->register_offsets); in crossbar_of_init()
323 kfree(cb->irq_map); in crossbar_of_init()
325 iounmap(cb->crossbar_base); in crossbar_of_init()
341 return -ENODEV; in irqcrossbar_init()
347 return -ENXIO; in irqcrossbar_init()
355 cb->max_crossbar_sources, in irqcrossbar_init()
360 return -ENOMEM; in irqcrossbar_init()
366 IRQCHIP_DECLARE(ti_irqcrossbar, "ti,irq-crossbar", irqcrossbar_init);