From: YannickV <y.vos...@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.vos...@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 --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]; -- 2.49.0