diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-10 20:45:30 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-10 20:45:30 -0800 |
| commit | bdbddf72a2ab1cfea699959795d70df3931eefe7 (patch) | |
| tree | e3f8018c6e8d0354bf2a2fbd99569790ef521805 /drivers/of | |
| parent | f7fae9b4d38f0c52489640c9688e529c4a58e1b6 (diff) | |
| parent | cfd00b7e26c8331e3bb0f03ca770888866c15ff4 (diff) | |
Merge tag 'soc-drivers-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull SoC driver updates from Arnd Bergmann:
"There are are a number of to firmware drivers, in particular the TEE
subsystem:
- a bus callback for TEE firmware that device drivers can register to
- sysfs support for tee firmware information
- minor updates to platform specific TEE drivers for AMD, NXP,
Qualcomm and the generic optee driver
- ARM SCMI firmware refactoring to improve the protocol discover
among other fixes and cleanups
- ARM FF-A firmware interoperability improvements
The reset controller and memory controller subsystems gain support for
additional hardware platforms from Mediatek, Renesas, NXP, Canaan and
SpacemiT.
Most of the other changes are for random drivers/soc code. Among a
number of cleanups and newly added hardware support, including:
- Mediatek MT8196 DVFS power management and mailbox support
- Qualcomm SCM firmware and MDT loader refactoring, as part of the
new Glymur platform support.
- NXP i.MX9 System Manager firmware support for accessing the syslog
- Minor updates for TI, Renesas, Samsung, Apple, Marvell and AMD
SoCs"
* tag 'soc-drivers-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (171 commits)
bus: fsl-mc: fix an error handling in fsl_mc_device_add()
reset: spacemit: Add SpacemiT K3 reset driver
reset: spacemit: Extract common K1 reset code
reset: Create subdirectory for SpacemiT drivers
dt-bindings: soc: spacemit: Add K3 reset support and IDs
reset: canaan: k230: drop OF dependency and enable by default
reset: rzg2l-usbphy-ctrl: Add suspend/resume support
reset: rzg2l-usbphy-ctrl: Propagate the return value of regmap_field_update_bits()
reset: gpio: check the return value of gpiod_set_value_cansleep()
reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV
reset: imx8mp-audiomix: Extend the driver usage
reset: imx8mp-audiomix: Switch to using regmap API
reset: imx8mp-audiomix: Drop unneeded macros
soc: fsl: qe: qe_ports_ic: Consolidate chained IRQ handler install/remove
soc: mediatek: mtk-cmdq: Add mminfra_offset adjustment for DRAM addresses
soc: mediatek: mtk-cmdq: Extend cmdq_pkt_write API for SoCs without subsys ID
soc: mediatek: mtk-cmdq: Add pa_base parsing for hardware without subsys ID support
soc: mediatek: mtk-cmdq: Add cmdq_get_mbox_priv() in cmdq_pkt_create()
mailbox: mtk-cmdq: Add driver data to support for MT8196
mailbox: mtk-cmdq: Add mminfra_offset configuration for DRAM transaction
...
Diffstat (limited to 'drivers/of')
| -rw-r--r-- | drivers/of/irq.c | 70 | ||||
| -rw-r--r-- | drivers/of/unittest-data/tests-interrupts.dtsi | 9 | ||||
| -rw-r--r-- | drivers/of/unittest.c | 116 |
3 files changed, 195 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 diff --git a/drivers/of/unittest-data/tests-interrupts.dtsi b/drivers/of/unittest-data/tests-interrupts.dtsi index 4ccb54f91c30..974f888c9b15 100644 --- a/drivers/of/unittest-data/tests-interrupts.dtsi +++ b/drivers/of/unittest-data/tests-interrupts.dtsi @@ -50,6 +50,15 @@ interrupt-map = <0x5000 1 2 &test_intc0 15>; }; + intmap2 { + #interrupt-cells = <2>; + #address-cells = <0>; + interrupt-map = <1 11 &test_intc0 100>, + <2 22 &test_intc1 200 201 202>, + <3 33 &test_intc2 300 301>, + <4 44 &test_intc2 400 401>; + }; + test_intc_intmap0: intc-intmap0 { #interrupt-cells = <1>; #address-cells = <1>; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 3b773aaf9d05..7eccb5d9135f 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1654,6 +1654,121 @@ static void __init of_unittest_parse_interrupts_extended(void) of_node_put(np); } +struct of_unittest_expected_imap_item { + u32 child_imap_count; + u32 child_imap[2]; + const char *parent_path; + int parent_args_count; + u32 parent_args[3]; +}; + +static const struct of_unittest_expected_imap_item of_unittest_expected_imap_items[] = { + { + .child_imap_count = 2, + .child_imap = {1, 11}, + .parent_path = "/testcase-data/interrupts/intc0", + .parent_args_count = 1, + .parent_args = {100}, + }, { + .child_imap_count = 2, + .child_imap = {2, 22}, + .parent_path = "/testcase-data/interrupts/intc1", + .parent_args_count = 3, + .parent_args = {200, 201, 202}, + }, { + .child_imap_count = 2, + .child_imap = {3, 33}, + .parent_path = "/testcase-data/interrupts/intc2", + .parent_args_count = 2, + .parent_args = {300, 301}, + }, { + .child_imap_count = 2, + .child_imap = {4, 44}, + .parent_path = "/testcase-data/interrupts/intc2", + .parent_args_count = 2, + .parent_args = {400, 401}, + } +}; + +static void __init of_unittest_parse_interrupt_map(void) +{ + const struct of_unittest_expected_imap_item *expected_item; + struct device_node *imap_np, *expected_parent_np; + struct of_imap_parser imap_parser; + struct of_imap_item imap_item; + int count, ret, i; + + if (of_irq_workarounds & (OF_IMAP_NO_PHANDLE | OF_IMAP_OLDWORLD_MAC)) + return; + + imap_np = of_find_node_by_path("/testcase-data/interrupts/intmap2"); + if (!imap_np) { + pr_err("missing testcase data\n"); + return; + } + + ret = of_imap_parser_init(&imap_parser, imap_np, &imap_item); + if (unittest(!ret, "of_imap_parser_init(%pOF) returned error %d\n", + imap_np, ret)) + goto end; + + expected_item = of_unittest_expected_imap_items; + count = 0; + + for_each_of_imap_item(&imap_parser, &imap_item) { + if (unittest(count < ARRAY_SIZE(of_unittest_expected_imap_items), + "imap item number %d not expected. Max number %zu\n", + count, ARRAY_SIZE(of_unittest_expected_imap_items) - 1)) { + of_node_put(imap_item.parent_args.np); + goto end; + } + + expected_parent_np = of_find_node_by_path(expected_item->parent_path); + if (unittest(expected_parent_np, + "missing dependent testcase data (%s)\n", + expected_item->parent_path)) { + of_node_put(imap_item.parent_args.np); + goto end; + } + + unittest(imap_item.child_imap_count == expected_item->child_imap_count, + "imap[%d] child_imap_count = %u, expected %u\n", + count, imap_item.child_imap_count, + expected_item->child_imap_count); + + for (i = 0; i < expected_item->child_imap_count; i++) + unittest(imap_item.child_imap[i] == expected_item->child_imap[i], + "imap[%d] child_imap[%d] = %u, expected %u\n", + count, i, imap_item.child_imap[i], + expected_item->child_imap[i]); + + unittest(imap_item.parent_args.np == expected_parent_np, + "imap[%d] parent np = %pOF, expected %pOF\n", + count, imap_item.parent_args.np, expected_parent_np); + + unittest(imap_item.parent_args.args_count == expected_item->parent_args_count, + "imap[%d] parent param_count = %d, expected %d\n", + count, imap_item.parent_args.args_count, + expected_item->parent_args_count); + + for (i = 0; i < expected_item->parent_args_count; i++) + unittest(imap_item.parent_args.args[i] == expected_item->parent_args[i], + "imap[%d] parent param[%d] = %u, expected %u\n", + count, i, imap_item.parent_args.args[i], + expected_item->parent_args[i]); + + of_node_put(expected_parent_np); + count++; + expected_item++; + } + + unittest(count == ARRAY_SIZE(of_unittest_expected_imap_items), + "Missing items. %d parsed, expected %zu\n", + count, ARRAY_SIZE(of_unittest_expected_imap_items)); +end: + of_node_put(imap_np); +} + #if IS_ENABLED(CONFIG_OF_DYNAMIC) static void __init of_unittest_irq_refcount(void) { @@ -4393,6 +4508,7 @@ static int __init of_unittest(void) of_unittest_changeset_prop(); of_unittest_parse_interrupts(); of_unittest_parse_interrupts_extended(); + of_unittest_parse_interrupt_map(); of_unittest_irq_refcount(); of_unittest_dma_get_max_cpu_address(); of_unittest_parse_dma_ranges(); |
