summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHerve Codina (Schneider Electric) <herve.codina@bootlin.com>2026-01-14 10:39:30 +0100
committerGeert Uytterhoeven <geert+renesas@glider.be>2026-01-15 12:03:27 +0100
commit49d2cda7ca2e8e287617e7a5b7fae523eaece955 (patch)
treed922e05e9f12afd350d84b5f943ff64436880f05 /drivers
parent1bea7e94bf09ee6d46051076866a9369f64d302a (diff)
of/irq: Introduce for_each_of_imap_item
for_each_of_imap_item is an iterator designed to help a driver to parse an interrupt-map property. Indeed some drivers need to know details about the interrupt mapping described in the device-tree in order to set internal registers accordingly. Signed-off-by: Herve Codina (Schneider Electric) <herve.codina@bootlin.com> Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Reviewed-by: Rob Herring (Arm) <robh@kernel.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patch.msgid.link/20260114093938.1089936-2-herve.codina@bootlin.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/of/irq.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index e3816819dbfe..f374d8b212b8 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -157,6 +157,76 @@ const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_ph
return imap;
}
+int of_imap_parser_init(struct of_imap_parser *parser, struct device_node *node,
+ struct of_imap_item *item)
+{
+ int imaplen;
+ u32 tmp;
+ int ret;
+
+ /*
+ * parent_offset is the offset where the parent part is starting.
+ * In other words, the offset where the parent interrupt controller
+ * phandle is present.
+ *
+ * Compute this offset (child #interrupt-cells + child #address-cells)
+ */
+ parser->parent_offset = of_bus_n_addr_cells(node);
+
+ ret = of_property_read_u32(node, "#interrupt-cells", &tmp);
+ if (ret)
+ return ret;
+
+ parser->parent_offset += tmp;
+
+ if (WARN(parser->parent_offset > ARRAY_SIZE(item->child_imap),
+ "child part size = %u, cannot fit in array of %zu items",
+ parser->parent_offset, ARRAY_SIZE(item->child_imap)))
+ return -EINVAL;
+
+ parser->imap = of_get_property(node, "interrupt-map", &imaplen);
+ if (!parser->imap)
+ return -ENOENT;
+
+ imaplen /= sizeof(*parser->imap);
+ parser->imap_end = parser->imap + imaplen;
+
+ memset(item, 0, sizeof(*item));
+ item->child_imap_count = parser->parent_offset;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_imap_parser_init);
+
+struct of_imap_item *of_imap_parser_one(struct of_imap_parser *parser,
+ struct of_imap_item *item)
+{
+ const __be32 *imap_parent, *imap_next;
+ int i;
+
+ /* Release previously get parent node */
+ of_node_put(item->parent_args.np);
+
+ if (parser->imap + parser->parent_offset + 1 >= parser->imap_end)
+ return NULL;
+
+ imap_parent = parser->imap + parser->parent_offset;
+
+ imap_next = of_irq_parse_imap_parent(imap_parent,
+ parser->imap_end - imap_parent,
+ &item->parent_args);
+ if (!imap_next)
+ return NULL;
+
+ for (i = 0; i < parser->parent_offset; i++)
+ item->child_imap[i] = be32_to_cpu(*(parser->imap + i));
+
+ parser->imap = imap_next;
+
+ return item;
+}
+EXPORT_SYMBOL_GPL(of_imap_parser_one);
+
/**
* of_irq_parse_raw - Low level interrupt tree parsing
* @addr: address specifier (start of "reg" property of the device) in be32 format