[PATCH v2 4/5] hw/riscv/k230: Route SSI interrupts to the PLIC
Kangjie Huang <[email protected]> Sun, 2 Aug 2026 03:28:47 +0800
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Connect the nine interrupt outputs of each K230 SSI controller to the documented PLIC source range. The TXU, DONE, and AXIE lines are wired to preserve the physical K230 interrupt topology, but remain inactive until their transfer engines are modeled. Extend qtests to cover TXE routing for all instances and RXU routing and instance isolation. Signed-off-by: Kangjie Huang <[email protected]> --- hw/riscv/k230.c | 36 +++++++++++++++++++++++++++ include/hw/riscv/k230.h | 3 +++ tests/qtest/k230-dw-ssi-test.c | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c index 4c321002cd..d856864839 100644 --- a/hw/riscv/k230.c +++ b/hw/riscv/k230.c @@ -104,6 +104,21 @@ static const MemMapEntry memmap[] = { [K230_DEV_CLINT] = { 0xF04000000, 0x00400000 }, }; +typedef struct K230SsiRoute { + unsigned int ssi_index; + unsigned int irq_base; +} K230SsiRoute; + +/* + * SDK numbering follows the address map: spi0 is the SPI-OPI instance, + * while spi1 and spi2 are QSPI0 and QSPI1. + */ +static const K230SsiRoute k230_ssi_routes[] = { + { .ssi_index = 2, .irq_base = K230_SPI0_IRQ_BASE }, + { .ssi_index = 0, .irq_base = K230_SPI1_IRQ_BASE }, + { .ssi_index = 1, .irq_base = K230_SPI2_IRQ_BASE }, +}; + typedef struct K230DwSsiProfile { uint32_t num_cs; uint32_t fifo_depth; @@ -193,6 +208,25 @@ static void k230_create_uart(MemoryRegion *sys_mem, DeviceState *plic, 399193, serial_hd(index), DEVICE_LITTLE_ENDIAN); } +static void k230_connect_ssi_irqs(K230SoCState *s) +{ + for (size_t route_idx = 0; + route_idx < ARRAY_SIZE(k230_ssi_routes); route_idx++) { + const K230SsiRoute *route = &k230_ssi_routes[route_idx]; + SysBusDevice *ssi; + + g_assert(route->ssi_index < ARRAY_SIZE(s->dw_ssi)); + g_assert(route->irq_base + DW_SSI_IRQ_COUNT <= + K230_PLIC_NUM_SOURCES); + + ssi = SYS_BUS_DEVICE(&s->dw_ssi[route->ssi_index]); + for (unsigned int i = 0; i < DW_SSI_IRQ_COUNT; i++) { + sysbus_connect_irq(ssi, i, + qdev_get_gpio_in(DEVICE(s->c908_plic), route->irq_base + i)); + } + } +} + static void k230_soc_realize(DeviceState *dev, Error **errp) { K230SoCState *s = RISCV_K230_SOC(dev); @@ -247,6 +281,8 @@ static void k230_soc_realize(DeviceState *dev, Error **errp) } } + k230_connect_ssi_irqs(s); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[0]), 0, memmap[K230_DEV_WDT0].base); sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[0]), 0, qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT0_IRQ)); diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h index 99996a93b1..275b6b62c3 100644 --- a/include/hw/riscv/k230.h +++ b/include/hw/riscv/k230.h @@ -131,6 +131,9 @@ enum { K230_UART4_IRQ = 20, K230_WDT0_IRQ = 107, K230_WDT1_IRQ = 108, + K230_SPI0_IRQ_BASE = 146, + K230_SPI1_IRQ_BASE = 155, + K230_SPI2_IRQ_BASE = 164, }; #define K230_UART_COUNT 5 diff --git a/tests/qtest/k230-dw-ssi-test.c b/tests/qtest/k230-dw-ssi-test.c index 6361c2b5ee..7252302c0e 100644 --- a/tests/qtest/k230-dw-ssi-test.c +++ b/tests/qtest/k230-dw-ssi-test.c @@ -14,6 +14,8 @@ #define K230_SPI0_BASE 0x91584000ULL #define K230_SPI1_BASE 0x91582000ULL #define K230_SPI2_BASE 0x91583000ULL +#define K230_PLIC_BASE 0xf00000000ULL +#define K230_PLIC_PENDING_BASE 0x1000 #define K230_SSI_CTRLR0 0x000 #define K230_SSI_CTRLR1 0x004 #define K230_SSI_SSIENR 0x008 @@ -57,6 +59,8 @@ #define K230_SSI_INT_TXO BIT(1) #define K230_SSI_INT_RXO BIT(3) #define K230_SSI_INT_RXU BIT(2) +#define K230_SSI_IRQ_TXE 0 +#define K230_SSI_IRQ_RXU 5 #define K230_SSI_RXFTLR 0x01c #define K230_SSI_RXOICR 0x03c @@ -71,6 +75,7 @@ typedef struct K230SsiInstance { uint64_t base; uint32_t num_cs; uint32_t imr_reset; + uint32_t first_irq; } K230SsiInstance; static const K230SsiInstance k230_ssi_instances[3] = { @@ -78,14 +83,17 @@ static const K230SsiInstance k230_ssi_instances[3] = { .base = K230_SPI0_BASE, .num_cs = 1, .imr_reset = 0x0000003fU, + .first_irq = 146, }, { .base = K230_SPI1_BASE, .num_cs = 5, .imr_reset = 0x0000001fU, + .first_irq = 155, }, { .base = K230_SPI2_BASE, .num_cs = 5, .imr_reset = 0x0000001fU, + .first_irq = 164, }, }; @@ -106,6 +114,14 @@ static void k230_ssi_writel(QTestState *qts, uint64_t base, qtest_writel(qts, base + offset, value); } +static bool k230_ssi_plic_pending(QTestState *qts, uint32_t irq) +{ + uint64_t addr = K230_PLIC_BASE + K230_PLIC_PENDING_BASE + + (irq / 32) * sizeof(uint32_t); + + return qtest_readl(qts, addr) & BIT(irq % 32); +} + static void k230_ssi_disable(QTestState *qts, uint64_t base) { k230_ssi_writel(qts, base, K230_SSI_SSIENR, 0); @@ -281,6 +297,34 @@ static void test_interrupt_controller(void) } +static void test_plic_routing(void) +{ + QTestState *qts = k230_ssi_start(); + const K230SsiInstance *target = &k230_ssi_instances[1]; + + for (int i = 0; i < ARRAY_SIZE(k230_ssi_instances); i++) { + const K230SsiInstance *inst = &k230_ssi_instances[i]; + + g_assert_true(k230_ssi_plic_pending(qts, + inst->first_irq + + K230_SSI_IRQ_TXE)); + k230_ssi_writel(qts, inst->base, K230_SSI_IMR, 0); + } + + k230_ssi_writel(qts, target->base, K230_SSI_IMR, K230_SSI_INT_RXU); + (void)k230_ssi_read_frame(qts, target->base); + g_assert_true(k230_ssi_plic_pending(qts, + target->first_irq + + K230_SSI_IRQ_RXU)); + for (int i = 0; i < ARRAY_SIZE(k230_ssi_instances); i++) { + if (&k230_ssi_instances[i] != target) { + g_assert_false(k230_ssi_plic_pending( + qts, k230_ssi_instances[i].first_irq + K230_SSI_IRQ_RXU)); + } + } + qtest_quit(qts); +} + static void test_tx_only_mode(void) { QTestState *qts = k230_ssi_start(); @@ -455,6 +499,7 @@ int main(int argc, char **argv) qtest_add_func("/k230-dw-ssi/pio-data-path", test_pio_data_path); qtest_add_func("/k230-dw-ssi/interrupt-controller", test_interrupt_controller); + qtest_add_func("/k230-dw-ssi/plic-routing", test_plic_routing); qtest_add_func("/k230-dw-ssi/tx-only-mode", test_tx_only_mode); qtest_add_func("/k230-dw-ssi/eeprom-read-contract", test_eeprom_read_contract); -- 2.43.0