120
}
121
}
122
123
+/*
124
+ * Write a VCMDQ Page 0 register (control/status) using VCMDQ0_* offsets.
125
+ *
126
+ * The caller normalizes the MMIO offset such that @offset0 always refers
127
+ * to a VCMDQ0_* register, while @index selects the VCMDQ instance.
128
+ *
129
+ * Page 0 registers are all 32-bit; this helper is only called for 4-byte
130
+ * writes.
131
+ */
132
+static void tegra241_cmdqv_write_vcmdq_page0(Tegra241CMDQV *cmdqv,
133
+ hwaddr offset0, int index,
134
+ uint32_t value, bool direct)
135
+{
136
+ switch (offset0) {
137
+ case A_VCMDQ0_CONS_INDX:
138
+ cmdqv->vcmdq_cons_indx[index] = value;
139
+ break;
140
+ case A_VCMDQ0_PROD_INDX:
141
+ /* VCMDQ is functional only once allocated to a VINTF; cache only. */
142
+ cmdqv->vcmdq_prod_indx[index] = value;
143
+ break;
144
+ case A_VCMDQ0_CONFIG:
145
+ if (value & R_VCMDQ0_CONFIG_CMDQ_EN_MASK) {
146
+ cmdqv->vcmdq_status[index] |= R_VCMDQ0_STATUS_CMDQ_EN_OK_MASK;
147
+ } else {
148
+ cmdqv->vcmdq_status[index] &= ~R_VCMDQ0_STATUS_CMDQ_EN_OK_MASK;
149
+ }
150
+ cmdqv->vcmdq_config[index] = value;
151
+ break;
152
+ case A_VCMDQ0_GERRORN:
153
+ /* VCMDQ is functional only once allocated to a VINTF; cache only. */
154
+ cmdqv->vcmdq_gerrorn[index] = value;
155
+ break;
156
+ default:
157
+ qemu_log_mask(LOG_UNIMP,
158
+ "%s unhandled write access at 0x%" PRIx64 "\n",
159
+ __func__, offset0);
160
+ }
161
+ trace_tegra241_cmdqv_write_vcmdq_page0(index, direct ? "direct" : "vi",
162
+ offset0, value);
163
+}
164
+
165
+/*
166
+ * Write a VCMDQ Page 1 register (base / DRAM address) - 4-byte access.
167
+ */
168
+static void tegra241_cmdqv_write_vcmdq_page1(Tegra241CMDQV *cmdqv,
169
+ hwaddr offset0, int index,
170
+ uint32_t value, bool direct)
171
+{
172
+ switch (offset0) {
173
+ case A_VCMDQ0_BASE_L:
174
+ cmdqv->vcmdq_base[index] =
175
+ deposit64(cmdqv->vcmdq_base[index], 0, 32, value);
176
+ break;
177
+ case A_VCMDQ0_BASE_H:
178
+ cmdqv->vcmdq_base[index] =
179
+ deposit64(cmdqv->vcmdq_base[index], 32, 32, value);
180
+ break;
181
+ case A_VCMDQ0_CONS_INDX_BASE_DRAM_L:
182
+ cmdqv->vcmdq_cons_indx_base[index] =
183
+ deposit64(cmdqv->vcmdq_cons_indx_base[index], 0, 32, value);
184
+ break;
185
+ case A_VCMDQ0_CONS_INDX_BASE_DRAM_H:
186
+ cmdqv->vcmdq_cons_indx_base[index] =
187
+ deposit64(cmdqv->vcmdq_cons_indx_base[index], 32, 32, value);
188
+ break;
189
+ default:
190
+ qemu_log_mask(LOG_UNIMP,
191
+ "%s unhandled write access at 0x%" PRIx64 "\n",
192
+ __func__, offset0);
193
+ }
194
+ trace_tegra241_cmdqv_write_vcmdq_page1(index, direct ? "direct" : "vi",
195
+ offset0, value);
196
+}
197
+
198
+/*
199
+ * Write a VCMDQ Page 1 register - 8-byte access at BASE_L or DRAM_L.
200
+ */
201
+static void tegra241_cmdqv_write_vcmdq_page1_64(Tegra241CMDQV *cmdqv,
202
+ hwaddr offset0, int index,
203
+ uint64_t value, bool direct)
204
+{
205
+ switch (offset0) {
206
+ case A_VCMDQ0_BASE_L:
207
+ cmdqv->vcmdq_base[index] = value;
208
+ break;
209
+ case A_VCMDQ0_CONS_INDX_BASE_DRAM_L:
210
+ cmdqv->vcmdq_cons_indx_base[index] = value;
211
+ break;
212
+ default:
213
+ qemu_log_mask(LOG_UNIMP,
214
+ "%s unhandled 64-bit write at 0x%" PRIx64 "\n",
215
+ __func__, offset0);
216
+ }
217
+ trace_tegra241_cmdqv_write_vcmdq_page1(index, direct ? "direct" : "vi",
218
+ offset0, value);
219
+}
220
+
221
static void tegra241_cmdqv_config_vintf_write(Tegra241CMDQV *cmdqv,
222
hwaddr offset, uint64_t value)
223
{
341
static void tegra241_cmdqv_writel_mmio(Tegra241CMDQV *cmdqv, hwaddr offset,
342
uint32_t value)
343
{
344
+ int index;
345
+
346
switch (offset) {
347
case A_CONFIG:
348
cmdqv->config = value;
361
case A_VINTF0_CONFIG ... A_VINTF0_LVCMDQ_ERR_MAP_3:
362
tegra241_cmdqv_config_vintf_write(cmdqv, offset, value);
363
break;
364
+ case A_VI_VCMDQ0_CONS_INDX ... A_VI_VCMDQ1_GERRORN:
365
+ /*
366
+ * VINTF Page0 registers are hardware aliases of VCMDQ Page0 registers.
367
+ * Translate the VINTF aperture offset to its VCMDQ Page0 equivalent
368
+ * before dispatching to the Page 0 helper.
369
+ */
370
+ offset -= CMDQV_VINTF_PAGE0_BASE - CMDQV_VCMDQ_PAGE0_BASE;
371
+ index = (offset - CMDQV_VCMDQ_PAGE0_BASE) / CMDQV_VCMDQ_STRIDE;
372
+ tegra241_cmdqv_write_vcmdq_page0(cmdqv,
373
+ offset - index * CMDQV_VCMDQ_STRIDE, index, value, false);
374
+ break;
375
+ case A_VCMDQ0_CONS_INDX ... A_VCMDQ1_GERRORN:
376
+ /*
377
+ * Decode a per-VCMDQ Page 0 access. Each VCMDQ occupies a
378
+ * CMDQV_VCMDQ_STRIDE-byte window; extract the index and normalize
379
+ * to the VCMDQ0_* offset before calling the Page 0 helper.
380
+ */
381
+ index = (offset - CMDQV_VCMDQ_PAGE0_BASE) / CMDQV_VCMDQ_STRIDE;
382
+ tegra241_cmdqv_write_vcmdq_page0(cmdqv,
383
+ offset - index * CMDQV_VCMDQ_STRIDE, index, value, true);
384
+ break;
385
+ case A_VI_VCMDQ0_BASE_L ... A_VI_VCMDQ1_CONS_INDX_BASE_DRAM_H:
386
+ /* Same VINTF-to-VCMDQ translation as VINTF Page0 case above. */
387
+ offset -= CMDQV_VINTF_PAGE1_BASE - CMDQV_VCMDQ_PAGE1_BASE;
388
+ index = (offset - CMDQV_VCMDQ_PAGE1_BASE) / CMDQV_VCMDQ_STRIDE;
389
+ tegra241_cmdqv_write_vcmdq_page1(cmdqv,
390
+ offset - index * CMDQV_VCMDQ_STRIDE, index, value, false);
391
+ break;
392
+ case A_VCMDQ0_BASE_L ... A_VCMDQ1_CONS_INDX_BASE_DRAM_H:
393
+ index = (offset - CMDQV_VCMDQ_PAGE1_BASE) / CMDQV_VCMDQ_STRIDE;
394
+ tegra241_cmdqv_write_vcmdq_page1(cmdqv,
395
+ offset - index * CMDQV_VCMDQ_STRIDE, index, value, true);
396
+ break;
397
default:
398
qemu_log_mask(LOG_UNIMP, "%s unhandled write access at 0x%" PRIx64 "\n",
399
__func__, offset);
401
}
402
403
/*
271
- * 8-byte MMIO write handler.
404
+ * 8-byte MMIO write handler. Only Page 1 BASE / CONS_INDX_BASE_DRAM accept
405
+ * full 64-bit writes; other offsets are write-ignored.
406
*/
407
static void tegra241_cmdqv_writell_mmio(Tegra241CMDQV *cmdqv, hwaddr offset,
408
uint64_t value)
409
{
276
- qemu_log_mask(LOG_UNIMP,
410
+ int index;
411
+
412
+ switch (offset) {
413
+ case A_VI_VCMDQ0_BASE_L ... A_VI_VCMDQ1_CONS_INDX_BASE_DRAM_H:
414
+ /*
415
+ * VINTF Page1 registers are hardware aliases of VCMDQ Page1 registers.
416
+ * Translate the VINTF aperture offset to its VCMDQ Page1 equivalent
417
+ * before dispatching to the Page 1 helper.
418
+ */
419
+ offset -= CMDQV_VINTF_PAGE1_BASE - CMDQV_VCMDQ_PAGE1_BASE;
420
+ index = (offset - CMDQV_VCMDQ_PAGE1_BASE) / CMDQV_VCMDQ_STRIDE;
421
+ tegra241_cmdqv_write_vcmdq_page1_64(cmdqv,
422
+ offset - index * CMDQV_VCMDQ_STRIDE, index, value, false);
423
+ break;
424
+ case A_VCMDQ0_BASE_L ... A_VCMDQ1_CONS_INDX_BASE_DRAM_H:
425
+ index = (offset - CMDQV_VCMDQ_PAGE1_BASE) / CMDQV_VCMDQ_STRIDE;
426
+ tegra241_cmdqv_write_vcmdq_page1_64(cmdqv,
427
+ offset - index * CMDQV_VCMDQ_STRIDE, index, value, true);
428
+ break;
429
+ default:
430
+ qemu_log_mask(LOG_UNIMP,
431
"%s unhandled 64-bit write at 0x%" PRIx64 " (WI)\n",
432
__func__, offset);
433
+ }
434
}
435
436
static void tegra241_cmdqv_write_mmio(void *opaque, hwaddr offset,