[PULL 46/51] hw/arm/msf2-soc: Wire up refclk

Maintainers: "Alex Bennée" <alex.bennee@linaro.org>, David Gibson <david@gibson.dropbear.id.au>, Paolo Bonzini <pbonzini@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Michael S. Tsirkin" <mst@redhat.com>, Thomas Huth <thuth@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Christian Borntraeger <borntraeger@de.ibm.com>, Alexandre Iooss <erdnaxe@crans.org>, Laurent Vivier <lvivier@redhat.com>, Alistair Francis <alistair@alistair23.me>, Joel Stanley <joel@jms.id.au>, Greg Kurz <groug@kaod.org>, Cornelia Huck <cohuck@redhat.com>, Aurelien Jarno <aurelien@aurel32.net>, Subbaraya Sundeep <sundeep.lkml@gmail.com>, Eduardo Habkost <ehabkost@redhat.com>, David Hildenbrand <david@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, Halil Pasic <pasic@linux.ibm.com>
There is a newer version of this series
[PULL 46/51] hw/arm/msf2-soc: Wire up refclk
Posted by Peter Maydell 3 years, 7 months ago
Wire up the refclk for the msf2 SoC.  This SoC runs the refclk at a
frequency which is programmably either /4, /8, /16 or /32 of the main
CPU clock.  We don't currently model the register which allows the
guest to set the divisor, so implement the refclk as a fixed /32 of
the CPU clock (which is the value of the divisor at reset).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
Message-id: 20210812093356.1946-21-peter.maydell@linaro.org
---
 include/hw/arm/msf2-soc.h |  1 +
 hw/arm/msf2-soc.c         | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
index 01f904cec47..ce417a6266a 100644
--- a/include/hw/arm/msf2-soc.h
+++ b/include/hw/arm/msf2-soc.h
@@ -59,6 +59,7 @@ struct MSF2State {
     uint64_t esram_size;
 
     Clock *m3clk;
+    Clock *refclk;
     uint8_t apb0div;
     uint8_t apb1div;
 
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
index 0a1e594aee6..dbc6d936a76 100644
--- a/hw/arm/msf2-soc.c
+++ b/hw/arm/msf2-soc.c
@@ -76,6 +76,7 @@ static void m2sxxx_soc_initfn(Object *obj)
     object_initialize_child(obj, "emac", &s->emac, TYPE_MSS_EMAC);
 
     s->m3clk = qdev_init_clock_in(DEVICE(obj), "m3clk", NULL, NULL, 0);
+    s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
 }
 
 static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
@@ -92,6 +93,27 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
         return;
     }
 
+    /*
+     * We use s->refclk internally and only define it with qdev_init_clock_in()
+     * so it is correctly parented and not leaked on an init/deinit; it is not
+     * intended as an externally exposed clock.
+     */
+    if (clock_has_source(s->refclk)) {
+        error_setg(errp, "refclk must not be wired up by the board code");
+        return;
+    }
+
+    /*
+     * TODO: ideally we should model the SoC SYSTICK_CR register at 0xe0042038,
+     * which allows the guest to program the divisor between the m3clk and
+     * the systick refclk to either /4, /8, /16 or /32, as well as setting
+     * the value the guest can read in the STCALIB register. Currently we
+     * implement the divisor as a fixed /32, which matches the reset value
+     * of SYSTICK_CR.
+     */
+    clock_set_mul_div(s->refclk, 32, 1);
+    clock_set_source(s->refclk, s->m3clk);
+
     memory_region_init_rom(&s->nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size,
                            &error_fatal);
     /*
@@ -115,6 +137,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
     qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
     qdev_prop_set_bit(armv7m, "enable-bitband", true);
     qdev_connect_clock_in(armv7m, "cpuclk", s->m3clk);
+    qdev_connect_clock_in(armv7m, "refclk", s->refclk);
     object_property_set_link(OBJECT(&s->armv7m), "memory",
                              OBJECT(get_system_memory()), &error_abort);
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
-- 
2.20.1