From: Nicolin Chen <[email protected]> This is the write side counterpart of the VCMDQ read emulation.
Add write handling for global VCMDQ and VI_VCMDQ register windows. Per-VCMDQ accesses are decoded into a VCMDQ index and normalized to VCMDQ0_* offsets, reusing the same layout assumptions as the read path. VI_VCMDQ registers are treated as a logical alias of the global VCMDQ registers and share the same decoding logic. Writes are backed by cached register state only; no hardware queue mapping is performed yet. Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Shameer Kolothum <[email protected]> --- hw/arm/tegra241-cmdqv.c | 83 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c index d2e6938e44..e1f1562c44 100644 --- a/hw/arm/tegra241-cmdqv.c +++ b/hw/arm/tegra241-cmdqv.c @@ -151,6 +151,70 @@ static uint64_t tegra241_cmdqv_read(void *opaque, hwaddr offset, unsigned size) } } +/* + * Write a VCMDQ register using VCMDQ0_* offsets. + * + * The caller normalizes the MMIO offset such that @offset0 always refers + * to a VCMDQ0_* register, while @index selects the VCMDQ instance. + */ +static void +tegra241_cmdqv_write_vcmdq(Tegra241CMDQV *cmdqv, hwaddr offset0, int index, + uint64_t value, unsigned size) +{ + switch (offset0) { + case A_VCMDQ0_CONS_INDX: + cmdqv->vcmdq_cons_indx[index] = value; + return; + case A_VCMDQ0_PROD_INDX: + cmdqv->vcmdq_prod_indx[index] = (uint32_t)value; + return; + case A_VCMDQ0_CONFIG: + if (value & R_VCMDQ0_CONFIG_CMDQ_EN_MASK) { + cmdqv->vcmdq_status[index] |= R_VCMDQ0_STATUS_CMDQ_EN_OK_MASK; + } else { + cmdqv->vcmdq_status[index] &= ~R_VCMDQ0_STATUS_CMDQ_EN_OK_MASK; + } + cmdqv->vcmdq_config[index] = (uint32_t)value; + return; + case A_VCMDQ0_GERRORN: + cmdqv->vcmdq_gerrorn[index] = (uint32_t)value; + return; + case A_VCMDQ0_BASE_L: + if (size == 8) { + cmdqv->vcmdq_base[index] = value; + } else if (size == 4) { + cmdqv->vcmdq_base[index] = + (cmdqv->vcmdq_base[index] & 0xffffffff00000000ULL) | + (value & 0xffffffffULL); + } + return; + case A_VCMDQ0_BASE_H: + cmdqv->vcmdq_base[index] = + (cmdqv->vcmdq_base[index] & 0xffffffffULL) | + ((uint64_t)value << 32); + return; + case A_VCMDQ0_CONS_INDX_BASE_DRAM_L: + if (size == 8) { + cmdqv->vcmdq_cons_indx_base[index] = value; + } else if (size == 4) { + cmdqv->vcmdq_cons_indx_base[index] = + (cmdqv->vcmdq_cons_indx_base[index] & 0xffffffff00000000ULL) | + (value & 0xffffffffULL); + } + return; + case A_VCMDQ0_CONS_INDX_BASE_DRAM_H: + cmdqv->vcmdq_cons_indx_base[index] = + (cmdqv->vcmdq_cons_indx_base[index] & 0xffffffffULL) | + ((uint64_t)value << 32); + return; + default: + qemu_log_mask(LOG_UNIMP, + "%s unhandled write access at 0x%" PRIx64 "\n", + __func__, offset0); + return; + } +} + static void tegra241_cmdqv_write_vintf(Tegra241CMDQV *cmdqv, hwaddr offset, uint64_t value) { @@ -187,6 +251,7 @@ static void tegra241_cmdqv_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { Tegra241CMDQV *cmdqv = (Tegra241CMDQV *)opaque; + int index; if (offset >= TEGRA241_CMDQV_IO_LEN) { qemu_log_mask(LOG_UNIMP, @@ -213,6 +278,24 @@ static void tegra241_cmdqv_write(void *opaque, hwaddr offset, uint64_t value, case A_VINTF0_CONFIG ... A_VINTF0_LVCMDQ_ERR_MAP_3: tegra241_cmdqv_write_vintf(cmdqv, offset, value); break; + case A_VI_VCMDQ0_CONS_INDX ... A_VI_VCMDQ1_GERRORN: + /* Same decoding as read() case: See comments above */ + offset -= 0x20000; + QEMU_FALLTHROUGH; + case A_VCMDQ0_CONS_INDX ... A_VCMDQ1_GERRORN: + index = (offset - 0x10000) / 0x80; + tegra241_cmdqv_write_vcmdq(cmdqv, offset - 0x80 * index, index, value, + size); + break; + case A_VI_VCMDQ0_BASE_L ... A_VI_VCMDQ1_CONS_INDX_BASE_DRAM_H: + /* Same decoding as read() case: See comments above */ + offset -= 0x20000; + QEMU_FALLTHROUGH; + case A_VCMDQ0_BASE_L ... A_VCMDQ1_CONS_INDX_BASE_DRAM_H: + index = (offset - 0x20000) / 0x80; + tegra241_cmdqv_write_vcmdq(cmdqv, offset - 0x80 * index, index, value, + size); + break; default: qemu_log_mask(LOG_UNIMP, "%s unhandled write access at 0x%" PRIx64 "\n", __func__, offset); -- 2.43.0
