From: Nicolin Chen <nicolinc@nvidia.com>
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 <nicolinc@nvidia.com>
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
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