aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/netduinoplus2.c12
-rw-r--r--hw/arm/stm32f405_soc.c30
2 files changed, 37 insertions, 5 deletions
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
index d3ad7a2..a5a8999 100644
--- a/hw/arm/netduinoplus2.c
+++ b/hw/arm/netduinoplus2.c
@@ -26,6 +26,7 @@
#include "qapi/error.h"
#include "hw/boards.h"
#include "hw/qdev-properties.h"
+#include "hw/qdev-clock.h"
#include "qemu/error-report.h"
#include "hw/arm/stm32f405_soc.h"
#include "hw/arm/boot.h"
@@ -36,16 +37,17 @@
static void netduinoplus2_init(MachineState *machine)
{
DeviceState *dev;
+ Clock *sysclk;
- /*
- * TODO: ideally we would model the SoC RCC and let it handle
- * system_clock_scale, including its ability to define different
- * possible SYSCLK sources.
- */
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
+ /* This clock doesn't need migration because it is fixed-frequency */
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
+ clock_set_hz(sysclk, SYSCLK_FRQ);
+
dev = qdev_new(TYPE_STM32F405_SOC);
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
armv7m_load_kernel(ARM_CPU(first_cpu),
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
index cb04c11..0019b7f 100644
--- a/hw/arm/stm32f405_soc.c
+++ b/hw/arm/stm32f405_soc.c
@@ -28,6 +28,7 @@
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
#include "hw/arm/stm32f405_soc.h"
+#include "hw/qdev-clock.h"
#include "hw/misc/unimp.h"
#define SYSCFG_ADD 0x40013800
@@ -80,6 +81,9 @@ static void stm32f405_soc_initfn(Object *obj)
}
object_initialize_child(obj, "exti", &s->exti, TYPE_STM32F4XX_EXTI);
+
+ s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
+ s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
}
static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
@@ -91,6 +95,30 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
Error *err = NULL;
int i;
+ /*
+ * 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 clock must not be wired up by the board code");
+ return;
+ }
+
+ if (!clock_has_source(s->sysclk)) {
+ error_setg(errp, "sysclk clock must be wired up by the board code");
+ return;
+ }
+
+ /*
+ * TODO: ideally we should model the SoC RCC and its ability to
+ * change the sysclk frequency and define different sysclk sources.
+ */
+
+ /* The refclk always runs at frequency HCLK / 8 */
+ clock_set_mul_div(s->refclk, 8, 1);
+ clock_set_source(s->refclk, s->sysclk);
+
memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F405.flash",
FLASH_SIZE, &err);
if (err != NULL) {
@@ -116,6 +144,8 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
qdev_prop_set_uint32(armv7m, "num-irq", 96);
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->sysclk);
+ qdev_connect_clock_in(armv7m, "refclk", s->refclk);
object_property_set_link(OBJECT(&s->armv7m), "memory",
OBJECT(system_memory), &error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {