| /* |
| * Copyright (c) 2021 BayLibre, SAS |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/ztest.h> |
| #include <zephyr/device.h> |
| #include <zephyr/drivers/interrupt_controller/gicv3_its.h> |
| |
| #define DT_DRV_COMPAT arm_gic_v3_its |
| |
| static volatile unsigned int last_lpi_irq_num; |
| |
| static void lpi_irq_handle(const void *parameter) |
| { |
| uintptr_t i = (uintptr_t)parameter; |
| |
| last_lpi_irq_num = i; |
| } |
| |
| /* Generate a DeviceID over the whole 16bits */ |
| #define ITS_TEST_DEV(id) ((((id + 256) % 16) << 12) | (((id + 256) % 24) << 8) | (id & 0xff)) |
| |
| /* Cover up to 8192 LPIs over 256 DevicesIDs and 32 EventIDs per DeviceID */ |
| #define ITS_TEST_NUM_DEVS 256 |
| #define ITS_TEST_NUM_ITES 32 |
| |
| /* Do not test all 8192 irqs, iterate with a prime offset to cover most of the possible event_ids */ |
| #define ITS_TEST_NEXT 13 |
| |
| /* Active-wait loops waiting for an interrupt */ |
| #define ITS_TEST_LOOPS 10 |
| |
| unsigned int vectors[ITS_TEST_NUM_DEVS][ITS_TEST_NUM_ITES]; |
| |
| ZTEST(arm64_gicv3_its, test_gicv3_its_alloc) |
| { |
| int devn, event_id; |
| const struct device *const dev = DEVICE_DT_INST_GET(0); |
| |
| zassert_false(dev == NULL, ""); |
| |
| for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) { |
| int device_id = ITS_TEST_DEV(devn); |
| |
| zassert_true(its_setup_deviceid(dev, device_id, ITS_TEST_NUM_ITES) == 0, ""); |
| |
| for (event_id = 0; event_id < ITS_TEST_NUM_ITES; ++event_id) { |
| vectors[devn][event_id] = its_alloc_intid(dev); |
| zassert_true(vectors[devn][event_id] >= 8192, ""); |
| zassert_true(vectors[devn][event_id] < CONFIG_NUM_IRQS, ""); |
| |
| zassert_true(its_map_intid(dev, device_id, event_id, |
| vectors[devn][event_id]) == 0, ""); |
| } |
| } |
| } |
| |
| ZTEST(arm64_gicv3_its, test_gicv3_its_connect) |
| { |
| int devn, event_id; |
| const struct device *const dev = DEVICE_DT_INST_GET(0); |
| unsigned int remain = 0; |
| |
| zassert_false(dev == NULL, ""); |
| |
| for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) { |
| for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) { |
| unsigned int irqn = vectors[devn][event_id]; |
| |
| zassert_true(irq_connect_dynamic(irqn, 0, lpi_irq_handle, |
| (void *)(uintptr_t)(irqn), 0) == irqn, ""); |
| |
| irq_enable(irqn); |
| } |
| remain = event_id - ITS_TEST_NUM_ITES; |
| } |
| } |
| |
| ZTEST(arm64_gicv3_its, test_gicv3_its_irq_simple) |
| { |
| const struct device *const dev = DEVICE_DT_INST_GET(0); |
| unsigned int irqn = vectors[0][0]; |
| unsigned int timeout; |
| int device_id = ITS_TEST_DEV(0); |
| int event_id = 0; |
| |
| zassert_false(dev == NULL, ""); |
| |
| last_lpi_irq_num = 0; |
| zassert_true(its_send_int(dev, device_id, event_id) == 0, ""); |
| |
| timeout = ITS_TEST_LOOPS; |
| while (!last_lpi_irq_num && timeout) { |
| timeout--; |
| } |
| |
| zassert_true(last_lpi_irq_num == irqn, |
| "IRQ %d of DeviceID %x EventID %d failed", |
| irqn, device_id, event_id); |
| } |
| |
| ZTEST(arm64_gicv3_its, test_gicv3_its_irq_disable) |
| { |
| const struct device *const dev = DEVICE_DT_INST_GET(0); |
| unsigned int irqn = vectors[0][0]; |
| unsigned int timeout; |
| int device_id = ITS_TEST_DEV(0); |
| int event_id = 0; |
| |
| zassert_false(dev == NULL, ""); |
| |
| irq_disable(irqn); |
| |
| last_lpi_irq_num = 0; |
| zassert_true(its_send_int(dev, device_id, event_id) == 0, ""); |
| |
| timeout = ITS_TEST_LOOPS; |
| while (!last_lpi_irq_num && timeout) { |
| timeout--; |
| } |
| |
| zassert_true(last_lpi_irq_num == 0, |
| "IRQ %d of DeviceID %x EventID %d disable failed", |
| irqn, device_id, event_id); |
| |
| irq_enable(irqn); |
| |
| last_lpi_irq_num = 0; |
| zassert_true(its_send_int(dev, device_id, event_id) == 0, ""); |
| |
| timeout = ITS_TEST_LOOPS; |
| while (!last_lpi_irq_num && timeout) { |
| timeout--; |
| } |
| |
| zassert_true(last_lpi_irq_num == irqn, |
| "IRQ %d of DeviceID %x EventID %d re-enable failed", |
| irqn, device_id, event_id); |
| } |
| |
| ZTEST(arm64_gicv3_its, test_gicv3_its_irq) |
| { |
| int devn, event_id; |
| const struct device *const dev = DEVICE_DT_INST_GET(0); |
| unsigned int timeout; |
| unsigned int remain = 0; |
| |
| zassert_false(dev == NULL, ""); |
| |
| for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) { |
| int device_id = ITS_TEST_DEV(devn); |
| |
| for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) { |
| unsigned int irqn = vectors[devn][event_id]; |
| |
| last_lpi_irq_num = 0; |
| zassert_true(its_send_int(dev, device_id, event_id) == 0, ""); |
| |
| timeout = ITS_TEST_LOOPS; |
| while (!last_lpi_irq_num && timeout) { |
| timeout--; |
| } |
| |
| zassert_true(last_lpi_irq_num == irqn, |
| "IRQ %d of DeviceID %x EventID %d failed", |
| irqn, device_id, event_id); |
| } |
| |
| remain = event_id - ITS_TEST_NUM_ITES; |
| } |
| } |
| |
| ZTEST_SUITE(arm64_gicv3_its, NULL, NULL, NULL, NULL, NULL); |