[PATCH 11/11] hw/ssi: Add trace events for K230 DesignWare SSI
Kangjie Huang <[email protected]> Sun, 26 Jul 2026 20:28:29 +0800
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <1342f13a6ea463424245534989fab7840c13eb3f.1785064313.git.flamboyant.h.01@gmail.com> |
Add trace events for the K230 DesignWare SSI model covering: - register accesses using the effective masked or returned value; - transaction boundaries for standard and enhanced PIO transfers; - interrupt output levels driven toward the PLIC; - IDMA start, completion, and AXI error paths; and - XIP reads with the final returned value. DR accesses are excluded from register tracing: every FIFO frame passes through DR, so logging it would drown out everything else during U-Boot and Linux SPI NOR traffic. The events avoid tracing individual FIFO data frames so that traces remain usable during U-Boot and Linux SPI NOR transfers. The events only observe model behaviour and do not change it. Signed-off-by: Kangjie Huang <[email protected]> --- hw/ssi/k230_dw_ssi.c | 26 ++++++++++++++++++++++++++ hw/ssi/trace-events | 11 +++++++++++ 2 files changed, 37 insertions(+) diff --git a/hw/ssi/k230_dw_ssi.c b/hw/ssi/k230_dw_ssi.c index d187e3345a..2bd84a4723 100644 --- a/hw/ssi/k230_dw_ssi.c +++ b/hw/ssi/k230_dw_ssi.c @@ -27,6 +27,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "system/dma.h" +#include "trace.h" #define K230_DW_SSI_FIFO_CAPACITY 256 @@ -285,6 +286,7 @@ static void k230_dw_ssi_write_masked(K230DwSsiState *s, unsigned int reg, uint32_t value, uint32_t mask) { s->regs[reg] = (s->regs[reg] & ~mask) | (value & mask); + trace_k230_dw_ssi_reg_write(s, reg * sizeof(uint32_t), s->regs[reg]); } static uint32_t k230_dw_ssi_irq_raw_status(K230DwSsiState *s) @@ -312,6 +314,8 @@ static void k230_dw_ssi_update_irq(K230DwSsiState *s) s->regs[R_IMR] & K230_DW_SSI_IRQ_VALID_MASK; for (int i = 0; i < K230_DW_SSI_IRQ_COUNT; i++) { + trace_k230_dw_ssi_irq_update( + s, i, !!(status & k230_dw_ssi_irq_status_mask[i])); qemu_set_irq(s->irqs[i], !!(status & k230_dw_ssi_irq_status_mask[i])); } } @@ -359,6 +363,11 @@ static void k230_dw_ssi_deselect(K230DwSsiState *s) return; } + trace_k230_dw_ssi_transaction_end( + s, s->active_cs, + FIELD_EX32(s->regs[R_CTRLR0], CTRLR0, TMOD), + FIELD_EX32(s->regs[R_CTRLR0], CTRLR0, SPI_FRF), + fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo)); qemu_irq_raise(s->cs_lines[s->active_cs]); s->active_cs = -1; } @@ -380,6 +389,10 @@ static void k230_dw_ssi_select(K230DwSsiState *s, unsigned cs) k230_dw_ssi_deselect(s); qemu_irq_lower(s->cs_lines[cs]); s->active_cs = cs; + trace_k230_dw_ssi_transaction_start( + s, cs, FIELD_EX32(s->regs[R_CTRLR0], CTRLR0, TMOD), + FIELD_EX32(s->regs[R_CTRLR0], CTRLR0, SPI_FRF), + fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo)); } static void k230_dw_ssi_update_cs(K230DwSsiState *s) @@ -776,6 +789,7 @@ static uint64_t k230_dw_ssi_xip_read(void *opaque, hwaddr address, value |= (uint64_t)(ssi_transfer(s->spi, 0) & 0xff) << (8 * i); } + trace_k230_dw_ssi_xip_read(s, address, size, value); k230_dw_ssi_deselect(s); return value; } @@ -907,15 +921,19 @@ static void k230_dw_ssi_try_idma(K230DwSsiState *s) s->idma_completed_frames = 0; if (address > UINT64_MAX - (length - 1)) { + trace_k230_dw_ssi_idma_error(s, 0, address); k230_dw_ssi_idma_fail(s, "address range"); return; } + trace_k230_dw_ssi_idma_start( + s, command.tmod, command.spi_frf, length, address, command.address); buffer = g_malloc(length); if (command.tmod == K230_DW_SSI_TMOD_TO) { result = dma_memory_read(&address_space_memory, address, buffer, length, MEMTXATTRS_UNSPECIFIED); if (result != MEMTX_OK) { + trace_k230_dw_ssi_idma_error(s, 1, address); k230_dw_ssi_idma_fail(s, "source"); return; } @@ -960,6 +978,7 @@ static void k230_dw_ssi_try_idma(K230DwSsiState *s) result = dma_memory_write(&address_space_memory, address, buffer, length, MEMTXATTRS_UNSPECIFIED); if (result != MEMTX_OK) { + trace_k230_dw_ssi_idma_error(s, 2, address); k230_dw_ssi_idma_fail(s, "destination"); return; } @@ -970,6 +989,7 @@ static void k230_dw_ssi_try_idma(K230DwSsiState *s) } s->idma_completed_frames = length; + trace_k230_dw_ssi_idma_done(s, address, length); k230_dw_ssi_idma_end(s, R_RISR_DONER_MASK); } @@ -1245,6 +1265,7 @@ static uint64_t k230_dw_ssi_read(void *opaque, hwaddr addr, unsigned int size) } if (k230_dw_ssi_is_razwi(addr)) { + trace_k230_dw_ssi_reg_read(s, addr, 0); return 0; } @@ -1334,6 +1355,7 @@ static uint64_t k230_dw_ssi_read(void *opaque, hwaddr addr, unsigned int size) break; } + trace_k230_dw_ssi_reg_read(s, addr, value); return value; } @@ -1352,6 +1374,7 @@ static void k230_dw_ssi_write(void *opaque, hwaddr addr, } if (k230_dw_ssi_is_razwi(addr)) { + trace_k230_dw_ssi_reg_write(s, addr, 0); return; } @@ -1378,10 +1401,12 @@ static void k230_dw_ssi_write(void *opaque, hwaddr addr, bool new_enabled = value & R_SSIENR_SSIC_EN_MASK; if (old_enabled == new_enabled) { + trace_k230_dw_ssi_reg_write(s, addr, s->regs[R_SSIENR]); return; } s->regs[R_SSIENR] = FIELD_DP32(0, SSIENR, SSIC_EN, new_enabled); + trace_k230_dw_ssi_reg_write(s, addr, s->regs[R_SSIENR]); if (!new_enabled) { k230_dw_ssi_abort_transfer(s); s->sleep_status = true; @@ -1406,6 +1431,7 @@ static void k230_dw_ssi_write(void *opaque, hwaddr addr, uint32_t old_ser = s->regs[R_SER]; s->regs[R_SER] = value & MAKE_64BIT_MASK(0, s->num_cs); + trace_k230_dw_ssi_reg_write(s, addr, s->regs[R_SER]); if (old_ser && !s->regs[R_SER]) { k230_dw_ssi_abort_transfer(s); break; diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events index b9d8648297..873ca3ba51 100644 --- a/hw/ssi/trace-events +++ b/hw/ssi/trace-events @@ -62,3 +62,14 @@ allwinner_a10_spi_tx(uint8_t byte) "write 0x%02x" allwinner_a10_spi_rx(uint8_t byte) "read 0x%02x" allwinner_a10_spi_read(const char* regname, uint32_t value) "reg[%s] => 0x%08x" allwinner_a10_spi_write(const char* regname, uint32_t value) "reg[%s] <= 0x%08x" + +# k230_dw_ssi.c +k230_dw_ssi_reg_read(void *dev, uint64_t addr, uint32_t value) "dev=%p addr=0x%" PRIx64 " value=0x%" PRIx32 +k230_dw_ssi_reg_write(void *dev, uint64_t addr, uint32_t value) "dev=%p addr=0x%" PRIx64 " value=0x%" PRIx32 +k230_dw_ssi_irq_update(void *dev, uint32_t irq, uint32_t level) "dev=%p irq=%" PRIu32 " level=%" PRIu32 +k230_dw_ssi_transaction_start(void *dev, uint32_t cs, uint32_t tmod, uint32_t frf, uint32_t tx, uint32_t rx) "dev=%p cs=%" PRIu32 " tmod=%" PRIu32 " frf=%" PRIu32 " tx=%" PRIu32 " rx=%" PRIu32 +k230_dw_ssi_transaction_end(void *dev, uint32_t cs, uint32_t tmod, uint32_t frf, uint32_t tx, uint32_t rx) "dev=%p cs=%" PRIu32 " tmod=%" PRIu32 " frf=%" PRIu32 " tx=%" PRIu32 " rx=%" PRIu32 +k230_dw_ssi_idma_start(void *dev, uint32_t tmod, uint32_t frf, uint32_t frames, uint64_t guest_addr, uint32_t flash_addr) "dev=%p tmod=%" PRIu32 " frf=%" PRIu32 " frames=%" PRIu32 " guest=0x%" PRIx64 " flash=0x%" PRIx32 +k230_dw_ssi_idma_done(void *dev, uint64_t guest_addr, uint32_t frames) "dev=%p guest=0x%" PRIx64 " frames=%" PRIu32 +k230_dw_ssi_idma_error(void *dev, uint32_t stage, uint64_t guest_addr) "dev=%p stage=%" PRIu32 " guest=0x%" PRIx64 +k230_dw_ssi_xip_read(void *dev, uint64_t addr, uint32_t size, uint64_t value) "dev=%p addr=0x%" PRIx64 " size=%" PRIu32 " value=0x%" PRIx64 -- 2.43.0