diff mbox series

[05/21] hw/dma/zynq: Notify devcfg on FPGA reset via SLCR control

Message ID 20250318130817.119636-6-corvin.koehne@gmail.com (mailing list archive)
State New
Headers show
Series Hi, | expand

Commit Message

Corvin Köhne March 18, 2025, 1:07 p.m. UTC
From: YannickV <Y.Vossen@beckhoff.com>

When the FPGA_RST_CTRL register in the SLCR (System Level Control
Register) is written to, the devcfg (Device Configuration) should
indicate the finished reset.

Problems occure when Loaders trigger a reset via SLCR and poll for
the done flag in devcfg. Since the flag will never be set, this can
result in an endless loop.

A callback function `slcr_reset_handler` is added to the
`XlnxZynqDevcfg` structure. The `slcr_reset` function sets the
`PCFG_DONE` flag when triggered by an FPGA reset in the SLCR.
The SLCR write handler calls the `slcr_reset` function when the
FPGA reset control register (`R_FPGA_RST_CTRL`) is written with
the reset value.

Signed-off-by: Yannick Voßen <y.vossen@beckhoff.com>
---
 hw/dma/xlnx-zynq-devcfg.c         |  7 +++++++
 hw/misc/zynq_slcr.c               | 16 ++++++++++++++++
 include/hw/dma/xlnx-zynq-devcfg.h |  1 +
 3 files changed, 24 insertions(+)
diff mbox series

Patch

diff --git a/hw/dma/xlnx-zynq-devcfg.c b/hw/dma/xlnx-zynq-devcfg.c
index 03b5280228..611a57b4d4 100644
--- a/hw/dma/xlnx-zynq-devcfg.c
+++ b/hw/dma/xlnx-zynq-devcfg.c
@@ -138,6 +138,11 @@  static void xlnx_zynq_devcfg_update_ixr(XlnxZynqDevcfg *s)
     qemu_set_irq(s->irq, ~s->regs[R_INT_MASK] & s->regs[R_INT_STS]);
 }
 
+static void slcr_reset (DeviceState *dev) {
+    XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(dev);
+    s->regs[R_INT_STS] |= R_INT_STS_PCFG_DONE_MASK;
+}
+
 static void xlnx_zynq_devcfg_reset(DeviceState *dev)
 {
     XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(dev);
@@ -374,6 +379,8 @@  static void xlnx_zynq_devcfg_init(Object *obj)
     XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(obj);
     RegisterInfoArray *reg_array;
 
+    s->slcr_reset_handler = slcr_reset;
+
     sysbus_init_irq(sbd, &s->irq);
 
     memory_region_init(&s->iomem, obj, "devcfg", XLNX_ZYNQ_DEVCFG_R_MAX * 4);
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index a766bab182..9b3220f354 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -26,6 +26,7 @@ 
 #include "qom/object.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
+#include "hw/dma/xlnx-zynq-devcfg.h"
 
 #ifndef ZYNQ_SLCR_ERR_DEBUG
 #define ZYNQ_SLCR_ERR_DEBUG 0
@@ -576,6 +577,21 @@  static void zynq_slcr_write(void *opaque, hwaddr offset,
         zynq_slcr_compute_clocks(s);
         zynq_slcr_propagate_clocks(s);
         break;
+    case R_FPGA_RST_CTRL:
+        if (val == 0) {
+            Object *devcfgObject =
+                    object_resolve_type_unambiguous("xlnx.ps7-dev-cfg", NULL);
+            if (!devcfgObject) {
+                break;
+            }
+            DeviceState *devcfg = OBJECT_CHECK(DeviceState, devcfgObject,
+                                               "xlnx.ps7-dev-cfg");
+            XlnxZynqDevcfg *zynqdevcfg = XLNX_ZYNQ_DEVCFG(devcfg);
+            if (zynqdevcfg) {
+                zynqdevcfg->slcr_reset_handler(devcfg);
+            }
+        }
+        break;
     }
 }
 
diff --git a/include/hw/dma/xlnx-zynq-devcfg.h b/include/hw/dma/xlnx-zynq-devcfg.h
index 2ab054e598..f48a630c5a 100644
--- a/include/hw/dma/xlnx-zynq-devcfg.h
+++ b/include/hw/dma/xlnx-zynq-devcfg.h
@@ -56,6 +56,7 @@  struct XlnxZynqDevcfg {
     uint8_t dma_cmd_fifo_num;
 
     bool is_initialized;
+    void (*slcr_reset_handler) (DeviceState *dev);
 
     uint32_t regs[XLNX_ZYNQ_DEVCFG_R_MAX];
     RegisterInfo regs_info[XLNX_ZYNQ_DEVCFG_R_MAX];