When wiring struct IMXGPTState to the clock control module, it is currently necessary to reach into its private data. Moreover, when forgetting to wire the clock control module, QEMU will crash after the guest has already started. Fix both by letting struct IMXGPTState expose a link property which is checked at realize time.
Inspired-by: Philippe Mathieu-Daudé <[email protected]> Signed-off-by: Bernhard Beschow <[email protected]> --- hw/arm/fsl-imx25.c | 3 ++- hw/arm/fsl-imx31.c | 3 ++- hw/arm/fsl-imx6.c | 3 ++- hw/arm/fsl-imx6ul.c | 3 ++- hw/arm/fsl-imx7.c | 3 ++- hw/arm/fsl-imx8mm.c | 3 ++- hw/arm/fsl-imx8mp.c | 3 ++- hw/timer/imx_gpt.c | 14 ++++++++++++++ 8 files changed, 28 insertions(+), 7 deletions(-) diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index efb22359c5..0840c2d86a 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -138,7 +138,8 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ } }; - s->gpt[i].ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt[i]), "clock-control-module", + OBJECT(&s->ccm), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) { return; diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index dd929c1085..b440ad6e28 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -105,7 +105,8 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) serial_table[i].irq)); } - s->gpt.ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt), "clock-control-module", + OBJECT(&s->ccm), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt), errp)) { return; diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index 7ba9b85a2e..22deb72496 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -204,7 +204,8 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(gic, serial_table[i].irq)); } - s->gpt.ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt), "clock-control-module", + OBJECT(&s->ccm), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt), errp)) { return; diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c index 84451c9909..2786889bda 100644 --- a/hw/arm/fsl-imx6ul.c +++ b/hw/arm/fsl-imx6ul.c @@ -245,7 +245,8 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_GPT2_IRQ, }; - s->gpt[i].ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt[i]), "clock-control-module", + OBJECT(&s->ccm), &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c index fc5d0efe06..9e206c59a1 100644 --- a/hw/arm/fsl-imx7.c +++ b/hw/arm/fsl-imx7.c @@ -250,7 +250,8 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_GPT4_IRQ, }; - s->gpt[i].ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt[i]), "clock-control-module", + OBJECT(&s->ccm), &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0, diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c index 875e92bb34..37934d2951 100644 --- a/hw/arm/fsl-imx8mm.c +++ b/hw/arm/fsl-imx8mm.c @@ -420,7 +420,8 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp) fsl_imx8mm_memmap[FSL_IMX8MM_GPT6].addr, }; - s->gpt[i].ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt[i]), "clock-control-module", + OBJECT(&s->ccm), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) { return; diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index bcd91739d9..f855378dff 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -447,7 +447,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp) fsl_imx8mp_memmap[FSL_IMX8MP_GPT6].addr, }; - s->gpt[i].ccm = IMX_CCM(&s->ccm); + object_property_set_link(OBJECT(&s->gpt[i]), "clock-control-module", + OBJECT(&s->ccm), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) { return; diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index cdc0257126..22fc8203bf 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -15,8 +15,10 @@ #include "qemu/osdep.h" #include "hw/core/irq.h" +#include "hw/core/qdev-properties.h" #include "hw/timer/imx_gpt.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/module.h" #include "qemu/log.h" #include "trace.h" @@ -522,6 +524,12 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp) IMXGPTState *s = IMX_GPT(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + if (!s->ccm) { + error_setg(errp, "%s 'clock-control-module' link property not set", + dev->canonical_path); + return; + } + sysbus_init_irq(sbd, &s->irq); memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT, 0x00001000); @@ -530,12 +538,18 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp) s->timer = ptimer_init(imx_gpt_timeout, s, PTIMER_POLICY_LEGACY); } +static const Property imx_timer_gpt_properties[] = { + DEFINE_PROP_LINK("clock-control-module", IMXGPTState, ccm, TYPE_IMX_CCM, + IMXCCMState *), +}; + static void imx_gpt_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = imx_gpt_realize; device_class_set_legacy_reset(dc, imx_gpt_reset); + device_class_set_props(dc, imx_timer_gpt_properties); dc->vmsd = &vmstate_imx_timer_gpt; dc->desc = "i.MX general timer"; } -- 2.55.0
