struct brcmstb_intc_init_params {
irq_flow_handler_t handler; int cpu_status; int cpu_clear; int cpu_mask_status; int cpu_mask_set; int cpu_mask_clear;
};
do {
irq = ffs(status) - 1;
status &= ~(1 << irq);
generic_handle_domain_irq(b->domain, irq);
} while (status);
out: /* Don't ack parent before all device writes are done */
wmb();
data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
base = of_iomap(np, 0); if (!base) {
pr_err("failed to remap intc L2 registers\n");
ret = -ENOMEM; goto out_free;
}
/* Disable all interrupts by default */
writel(0xffffffff, base + init_params->cpu_mask_set);
/* Wakeup interrupts may be retained from S5 (cold boot) */
data->can_wake = of_property_read_bool(np, "brcm,irq-can-wake"); if (!data->can_wake && (init_params->cpu_clear >= 0))
writel(0xffffffff, base + init_params->cpu_clear);
parent_irq = irq_of_parse_and_map(np, 0); if (!parent_irq) {
pr_err("failed to find parent interrupt\n");
ret = -EINVAL; goto out_unmap;
}
data->domain = irq_domain_create_linear(of_fwnode_handle(np), 32,
&irq_generic_chip_ops, NULL); if (!data->domain) {
ret = -ENOMEM; goto out_unmap;
}
/* MIPS chips strapped for BE will automagically configure the * peripheral registers for CPU-native byte order.
*/
flags = 0; if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
flags |= IRQ_GC_BE_IO;
if (init_params->handler == handle_level_irq)
set |= IRQ_LEVEL;
/* Allocate a single Generic IRQ chip for this node */
ret = irq_alloc_domain_generic_chips(data->domain, 32, 1,
np->full_name, init_params->handler, clr, set, flags); if (ret) {
pr_err("failed to allocate generic irq chip\n"); goto out_free_domain;
}
/* Set the IRQ chaining logic */
irq_set_chained_handler_and_data(parent_irq,
brcmstb_l2_intc_irq_handle, data);
if (init_params->cpu_clear >= 0) {
ct->regs.ack = init_params->cpu_clear;
ct->chip.irq_ack = irq_gc_ack_set_bit;
ct->chip.irq_mask_ack = irq_gc_mask_disable_and_ack_set;
} else { /* No Ack - but still slightly more efficient to define this */
ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
}
if (data->can_wake) { /* This IRQ chip can wake the system, set all child interrupts * in wake_enabled mask
*/
data->gc->wake_enabled = 0xffffffff;
ct->chip.irq_set_wake = irq_gc_set_wake;
enable_irq_wake(parent_irq);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.