diff --git a/tests/kernel/interrupt/CMakeLists.txt b/tests/kernel/interrupt/CMakeLists.txt index b464719f89a..dac54fb4ce4 100644 --- a/tests/kernel/interrupt/CMakeLists.txt +++ b/tests/kernel/interrupt/CMakeLists.txt @@ -26,4 +26,5 @@ endif() if(CONFIG_MULTI_LEVEL_INTERRUPTS) target_sources_ifdef(CONFIG_DYNAMIC_INTERRUPTS app PRIVATE src/sw_isr_table.c) + target_sources_ifdef(CONFIG_TEST_MULTILEVEL_IRQ app PRIVATE src/multilevel_irq.c) endif() diff --git a/tests/kernel/interrupt/Kconfig b/tests/kernel/interrupt/Kconfig new file mode 100644 index 00000000000..daa87b5c30f --- /dev/null +++ b/tests/kernel/interrupt/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Meta Platforms + +config TEST_MULTILEVEL_IRQ + bool "Build the tests in multilevel_irq.c" + depends on MULTI_LEVEL_INTERRUPTS + +source "Kconfig.zephyr" diff --git a/tests/kernel/interrupt/multilevel_irq.overlay b/tests/kernel/interrupt/multilevel_irq.overlay new file mode 100644 index 00000000000..69878bd3f49 --- /dev/null +++ b/tests/kernel/interrupt/multilevel_irq.overlay @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Meta Platforms + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + test { + #address-cells = < 0x1 >; + #size-cells = < 0x1 >; + + test_cpu_intc: interrupt-controller { + compatible = "vnd,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + + test_l1_irq: interrupt-controller@bbbbcccc { + compatible = "vnd,intc"; + reg = <0xbbbbcccc 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <11 0>; + interrupt-parent = <&test_cpu_intc>; + }; + + test_l2_irq: interrupt-controller@bbbccccc { + compatible = "vnd,intc"; + reg = <0xbbbccccc 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <12 0>; + interrupt-parent = <&test_l1_irq>; + }; + + test_l3_irq: interrupt-holder { + compatible = "vnd,interrupt-holder"; + status = "okay"; + interrupts = <13 3>; + interrupt-parent = <&test_l2_irq>; + interrupt-names = "test"; + }; + }; +}; diff --git a/tests/kernel/interrupt/src/multilevel_irq.c b/tests/kernel/interrupt/src/multilevel_irq.c new file mode 100644 index 00000000000..d74a2283a5f --- /dev/null +++ b/tests/kernel/interrupt/src/multilevel_irq.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +ZTEST(interrupt_feature, test_multi_level_api) +{ + /* Zephyr multilevel-encoded IRQ */ + const uint32_t irqn_l3 = DT_IRQN(DT_NODELABEL(test_l3_irq)); + const uint32_t irqn_l2 = DT_IRQN(DT_NODELABEL(test_l2_irq)); + const uint32_t irqn_l1 = DT_IRQN(DT_NODELABEL(test_l1_irq)); + /* Raw IRQ specified in the devicetree */ + const uint32_t raw_l3 = DT_IRQ(DT_NODELABEL(test_l3_irq), irq); + const uint32_t raw_l2 = DT_IRQ(DT_NODELABEL(test_l2_irq), irq); + const uint32_t raw_l1 = DT_IRQ(DT_NODELABEL(test_l1_irq), irq); + + /** + * - irq_get_level() + */ + zassert_equal(3, irq_get_level(irqn_l3)); + zassert_equal(2, irq_get_level(irqn_l2)); + zassert_equal(1, irq_get_level(irqn_l1)); + + /** + * - irq_from_level_2() + * - irq_to_level_2() + * - irq_parent_level_2() + */ + zassert_equal(irq_from_level_2(irqn_l3), raw_l2); + zassert_equal(irq_from_level_2(irqn_l2), raw_l2); + + zassert_equal(irq_to_level_2(raw_l2) & irqn_l2, irq_to_level_2(raw_l2)); + + zassert_equal(irq_parent_level_2(irqn_l2), raw_l1); + + /** + * - irq_from_level_3() + * - irq_to_level_3() + * - irq_parent_level_3() + */ + zassert_equal(irq_from_level_3(irqn_l3), raw_l3); + + zassert_equal(irq_to_level_3(raw_l3) & irqn_l3, irq_to_level_3(raw_l3)); + + zassert_equal(irq_parent_level_3(irqn_l3), raw_l2); + + /** + * - irq_from_level() + * - irq_to_level() + * - irq_parent_level() + */ + zassert_equal(irq_from_level(irqn_l3, 2), raw_l2); + zassert_equal(irq_from_level(irqn_l2, 2), raw_l2); + zassert_equal(irq_from_level(irqn_l3, 3), raw_l3); + + zassert_equal(irq_to_level(raw_l2, 2) & irqn_l2, irq_to_level(raw_l2, 2)); + zassert_equal(irq_to_level(raw_l3, 3) & irqn_l3, irq_to_level(raw_l3, 3)); + + zassert_equal(irq_parent_level(irqn_l2, 2), raw_l1); + zassert_equal(irq_parent_level(irqn_l3, 3), raw_l2); + + /** + * - irq_get_intc_irq() + */ + zassert_equal(irq_get_intc_irq(irqn_l3), irqn_l2); + zassert_equal(irq_get_intc_irq(irqn_l2), irqn_l1); + zassert_equal(irq_get_intc_irq(irqn_l1), irqn_l1); +} + +ZTEST_SUITE(gen_isr_table_multilevel, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/kernel/interrupt/testcase.yaml b/tests/kernel/interrupt/testcase.yaml index 78d81a579d0..1ed995c0baa 100644 --- a/tests/kernel/interrupt/testcase.yaml +++ b/tests/kernel/interrupt/testcase.yaml @@ -79,3 +79,9 @@ tests: filter: > not CONFIG_TRUSTED_EXECUTION_NONSECURE and CONFIG_ISR_TABLES_LOCAL_DECLARATION_SUPPORTED and not CONFIG_CODE_DATA_RELOCATION + arch.interrupt.multilevel: + filter: CONFIG_MULTI_LEVEL_INTERRUPTS + extra_args: + - EXTRA_DTC_OVERLAY_FILE="multilevel_irq.overlay" + extra_configs: + - CONFIG_TEST_MULTILEVEL_IRQ=y