Lines Matching +full:shadow +full:- +full:interrupts

1 // SPDX-License-Identifier: GPL-2.0-only
7 * be routed to either VPE but not both, so to support per-CPU interrupts, a
9 * this driver, these are called "shadow interrupts". The assignment of shadow
10 * interrupts is defined by the SoC integrator when wiring the interrupt lines,
13 * If an interrupt (say 30) needs per-CPU capability, the SoC integrator
14 * allocates another IRQ number (say 29) to be its shadow. The device tree
15 * reflects this by adding the pair <30 29> to the "econet,shadow-interrupts"
45 * @interrupt_shadows: Array of all interrupts, for each value,
46 * - NOT_PERCPU: This interrupt is not per-cpu, so it has no shadow
47 * - IS_SHADOW: This interrupt is a shadow of another per-cpu interrupt
48 * - else: This is a per-cpu interrupt whose shadow is the value
74 u8 shadow; in econet_chmask() local
77 * If the IRQ is a shadow, it should never be manipulated directly. in econet_chmask()
78 * It should only be masked/unmasked as a result of the "real" per-cpu in econet_chmask()
80 * If it is per-cpu (has a shadow), and we're on VPE#1, the shadow is what we mask. in econet_chmask()
83 shadow = econet_intc.interrupt_shadows[hwirq]; in econet_chmask()
84 if (WARN_ON_ONCE(shadow == IS_SHADOW)) in econet_chmask()
86 else if (shadow != NOT_PERCPU && smp_processor_id() == 1) in econet_chmask()
87 hwirq = shadow; in econet_chmask()
91 mask = BIT(hwirq - 32); in econet_chmask()
103 econet_chmask(d->hwirq, false); in econet_intc_mask()
109 econet_chmask(d->hwirq, true); in econet_intc_unmask()
114 /* IRQs are generally disabled during init, but guarding here makes it non-obligatory. */ in econet_mask_all()
125 hwirq = fls(pending) - 1; in econet_intc_handle_pending()
161 return -EINVAL; in econet_intc_map()
163 pr_err("%s: can't map hwirq %lu, it is a shadow interrupt\n", __func__, hwirq); in econet_intc_map()
164 return -EINVAL; in econet_intc_map()
173 pr_warn("%s: Failed irq_set_percpu_devid for %u: %d\n", d->name, irq, ret); in econet_intc_map()
181 .name = "en751221-intc",
194 const char *field = "econet,shadow-interrupts"; in get_shadow_interrupts()
211 return -ENOMEM; in get_shadow_interrupts()
215 return -EINVAL; in get_shadow_interrupts()
219 u32 shadow = shadows[i + 1]; in get_shadow_interrupts() local
222 if (shadow > IRQ_COUNT) { in get_shadow_interrupts()
223 pr_err("%pOF: %s[%d] shadow(%d) out of range\n", in get_shadow_interrupts()
224 node, field, i + 1, shadow); in get_shadow_interrupts()
234 pr_err("%pOF: %s[%d] target(%d) already has a shadow\n", in get_shadow_interrupts()
239 if (econet_intc.interrupt_shadows[shadow] != NOT_PERCPU) { in get_shadow_interrupts()
240 pr_err("%pOF: %s[%d] shadow(%d) already has a target\n", in get_shadow_interrupts()
241 node, field, i + 1, shadow); in get_shadow_interrupts()
245 econet_intc.interrupt_shadows[target] = shadow; in get_shadow_interrupts()
246 econet_intc.interrupt_shadows[shadow] = IS_SHADOW; in get_shadow_interrupts()
264 pr_err("%pOF: DT: Failed to get IRQ from 'interrupts'\n", node); in econet_intc_of_init()
265 return -EINVAL; in econet_intc_of_init()
270 ret = -EINVAL; in econet_intc_of_init()
276 ret = -EBUSY; in econet_intc_of_init()
283 ret = -ENOMEM; in econet_intc_of_init()
293 ret = -ENOMEM; in econet_intc_of_init()
310 IRQCHIP_DECLARE(econet_en751221_intc, "econet,en751221-intc", econet_intc_of_init);