@samitouri / QOSamiQemu / commits / c8ba862dbf

hw/misc/zynq_slcr: Add logic for DCI configuration

The registers for the digitally controlled impedance (DCI) clock are part of the system level control registers (SLCR). The DONE bit in the status register indicates a successfull DCI calibration. An description of the calibration process can be found here: https://docs.amd.com/r/en-US/ug585-zynq-7000-SoC-TRM/DDR-IOB-Impedance-Calibration The DCI control register and status register have been added. As soon as the ENABLE and RESET bit are set, the RESET bit has also been toggled to 0 before and the UPDATE_CONTROL is not set, the DONE bit in the status register is set. If these bits change the DONE bit is reset. Note that the option bits are not taken into consideration. Signed-off-by: YannickV <Y.Vossen@beckhoff.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Message-id: 20260518073401.11279-8-corvin.koehne@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

YannickV committed May 18, 2026 at 09:33 UTC c8ba862dbfdc0f4006ba675d5568f36f568a05cd
1 file changed +31
hw/misc/zynq_slcr.c
+31
@@ -180,6 +180,12 @@ REG32(GPIOB_CFG_HSTL, 0xb14)
180 REG32(GPIOB_DRVR_BIAS_CTRL, 0xb18)
181
182 REG32(DDRIOB, 0xb40)
183 +REG32(DDRIOB_DCI_CTRL, 0xb70)
184 + FIELD(DDRIOB_DCI_CTRL, RESET, 0, 1)
185 + FIELD(DDRIOB_DCI_CTRL, ENABLE, 1, 1)
186 + FIELD(DDRIOB_DCI_CTRL, UPDATE_CONTROL, 20, 1)
187 +REG32(DDRIOB_DCI_STATUS, 0xb74)
188 + FIELD(DDRIOB_DCI_STATUS, DONE, 13, 1)
189 #define DDRIOB_LENGTH 14
190
191 #define ZYNQ_SLCR_MMIO_SIZE 0x1000
@@ -193,6 +199,8 @@ struct ZynqSLCRState {
199
200 MemoryRegion iomem;
201
202 + bool ddriob_dci_ctrl_reset_toggled;
203 +
204 uint32_t regs[ZYNQ_SLCR_NUM_REGS];
205
206 Clock *ps_clk;
@@ -331,6 +339,8 @@ static void zynq_slcr_reset_init(Object *obj, ResetType type)
339
340 DB_PRINT("RESET\n");
341
342 + s->ddriob_dci_ctrl_reset_toggled = false;
343 +
344 s->regs[R_LOCKSTA] = 1;
345 /* 0x100 - 0x11C */
346 s->regs[R_ARM_PLL_CTRL] = 0x0001A008;
@@ -418,6 +428,8 @@ static void zynq_slcr_reset_init(Object *obj, ResetType type)
428 s->regs[R_DDRIOB + 4] = s->regs[R_DDRIOB + 5] = s->regs[R_DDRIOB + 6]
429 = 0x00000e00;
430 s->regs[R_DDRIOB + 12] = 0x00000021;
431 +
432 + s->regs[R_DDRIOB_DCI_CTRL] = 0x00000020;
433 }
434
435 static void zynq_slcr_reset_hold(Object *obj, ResetType type)
@@ -554,6 +566,25 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
566 (int)offset, (unsigned)val & 0xFFFF);
567 }
568 return;
569 +
570 + case R_DDRIOB_DCI_CTRL:
571 + if (!FIELD_EX32(val, DDRIOB_DCI_CTRL, RESET) &&
572 + FIELD_EX32(s->regs[R_DDRIOB_DCI_CTRL], DDRIOB_DCI_CTRL, RESET)) {
573 +
574 + s->ddriob_dci_ctrl_reset_toggled = true;
575 + DB_PRINT("DDRIOB DCI CTRL RESET was toggled\n");
576 + }
577 +
578 + if (FIELD_EX32(val, DDRIOB_DCI_CTRL, ENABLE) &&
579 + FIELD_EX32(val, DDRIOB_DCI_CTRL, RESET) &&
580 + !FIELD_EX32(val, DDRIOB_DCI_CTRL, UPDATE_CONTROL) &&
581 + s->ddriob_dci_ctrl_reset_toggled) {
582 +
583 + s->regs[R_DDRIOB_DCI_STATUS] |= R_DDRIOB_DCI_STATUS_DONE_MASK;
584 + } else {
585 + s->regs[R_DDRIOB_DCI_STATUS] &= ~R_DDRIOB_DCI_STATUS_DONE_MASK;
586 + }
587 + break;
588 }
589
590 if (s->regs[R_LOCKSTA]) {