drivers: misc: irq-uclass: Update irq_get_by_index
Support reading the "interrupts" property from the devicetree in case the "interrupts-extended" property isn't found. As the "interrupts" property is commonly used, this allows to parse all existing FDT and makes irq_get_by_index() more useful. The "interrupts" property doesn't contain a phandle as "interrupts-extended" does, so implement a new method to locate the interrupt-parent called irq_get_interrupt_parent(). TEST: Read the interrupts from the GIC node for ACPI MADT generation. Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-by: Moritz Fischer <moritzf@google.com>
This commit is contained in:
committed by
Tom Rini
parent
df8d759d9d
commit
f116feadea
@@ -62,6 +62,40 @@ int irq_read_and_clear(struct irq *irq)
|
||||
return ops->read_and_clear(irq);
|
||||
}
|
||||
|
||||
int irq_get_interrupt_parent(const struct udevice *dev,
|
||||
struct udevice **interrupt_parent)
|
||||
{
|
||||
struct ofnode_phandle_args phandle_args;
|
||||
struct udevice *irq = NULL;
|
||||
ofnode node;
|
||||
int ret;
|
||||
|
||||
if (!dev || !interrupt_parent)
|
||||
return -EINVAL;
|
||||
|
||||
*interrupt_parent = NULL;
|
||||
|
||||
node = dev_ofnode(dev);
|
||||
if (!ofnode_valid(node))
|
||||
return -EINVAL;
|
||||
|
||||
while (ofnode_valid(node)) {
|
||||
ret = ofnode_parse_phandle_with_args(node, "interrupt-parent",
|
||||
NULL, 0, 0, &phandle_args);
|
||||
if (!ret && !device_get_global_by_ofnode(phandle_args.node, &irq))
|
||||
break;
|
||||
node = ofnode_get_parent(node);
|
||||
}
|
||||
|
||||
if (!irq) {
|
||||
log_err("Cannot find an interrupt parent for device %s\n", dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
*interrupt_parent = irq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||
int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
|
||||
struct irq *irq)
|
||||
@@ -142,10 +176,40 @@ err:
|
||||
int irq_get_by_index(struct udevice *dev, int index, struct irq *irq)
|
||||
{
|
||||
struct ofnode_phandle_args args;
|
||||
int ret;
|
||||
struct udevice *interrupt_parent;
|
||||
int ret, size, i;
|
||||
const __be32 *list;
|
||||
u32 count;
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, "interrupts-extended",
|
||||
"#interrupt-cells", 0, index, &args);
|
||||
if (ret) {
|
||||
list = dev_read_prop(dev, "interrupts", &size);
|
||||
if (!list)
|
||||
return -ENOENT;
|
||||
|
||||
ret = irq_get_interrupt_parent(dev, &interrupt_parent);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
args.node = dev_ofnode(interrupt_parent);
|
||||
|
||||
if (dev_read_u32(interrupt_parent, "#interrupt-cells", &count)) {
|
||||
log_err("%s: could not get #interrupt-cells for %s\n",
|
||||
__func__, dev->name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (index * count >= size / sizeof(*list))
|
||||
return -ENOENT;
|
||||
if (count > OF_MAX_PHANDLE_ARGS)
|
||||
count = OF_MAX_PHANDLE_ARGS;
|
||||
args.args_count = count;
|
||||
for (i = 0; i < count; i++)
|
||||
args.args[i] = be32_to_cpup(&list[index * count + i]);
|
||||
|
||||
return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
|
||||
"interrupts", index, irq);
|
||||
}
|
||||
|
||||
return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
|
||||
"interrupts-extended", index > 0, irq);
|
||||
|
||||
Reference in New Issue
Block a user