From: YannickV <Y.Vossen@beckhoff.com>
Introduce a new machine type 'beckhoff-cx7200' that inherits from the
xilinx-zynq-a9 machine. The CX7200 is an industrial PC based on the
Xilinx Zynq-7000 SoC.
The machine preserves all standard Zynq features (boot-mode selection,
SPI, UART, Ethernet, etc.) while adding CX7200-specific hardware
components.
Signed-off-by: YannickV <Y.Vossen@beckhoff.com>
---
hw/arm/Kconfig | 7 +++
hw/arm/beckhoff_CX7200.c | 104 +++++++++++++++++++++++++++++++++++++++
hw/arm/meson.build | 1 +
3 files changed, 112 insertions(+)
create mode 100644 hw/arm/beckhoff_CX7200.c
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7877506384..00810634d2 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -307,6 +307,13 @@ config ZYNQ
select XILINX_SPIPS
select ZYNQ_DEVCFG
+config BECKHOFF_CX7200
+ bool
+ default y
+ depends on TCG && ARM
+ select ZYNQ
+ select BECKHOFF_CCAT
+
config ARM_V7M
bool
# currently v7M must be included in a TCG build due to translate.c
diff --git a/hw/arm/beckhoff_CX7200.c b/hw/arm/beckhoff_CX7200.c
new file mode 100644
index 0000000000..85e2fd0fd6
--- /dev/null
+++ b/hw/arm/beckhoff_CX7200.c
@@ -0,0 +1,104 @@
+
+/*
+ * Modified Xilinx Zynq Baseboard System emulation for Beckhoff CX7200.
+ *
+ * Copyright (c) 2024 Beckhoff Automation GmbH & Co. KG
+ *
+ * Based on /hw/arm/xilinx_zynq.c:
+ * Copyright (c) 2010 Xilinx.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite@petalogix.com)
+ * Copyright (c) 2012 Petalogix Pty Ltd.
+ * Original code by Haibing Ma.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/block/block.h"
+#include "hw/loader.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xilinx_zynq.h" /* For ZynqMachineState */
+#include "hw/cpu/a9mpcore.h"
+#include "qom/object.h"
+
+#define TYPE_CX7200_MACHINE MACHINE_TYPE_NAME("beckhoff-cx7200")
+
+#define CX7200_PERIPHCLK_DIVIDER 2
+#define CX7200_PS7_CPU_CLK_FREQUENCY 720000000
+
+static void ccat_init(uint32_t base, BlockBackend *eeprom_blk)
+{
+ DeviceState *dev;
+ SysBusDevice *busdev;
+
+ dev = qdev_new("beckhoff-ccat");
+ if (eeprom_blk) {
+ qdev_prop_set_drive_err(dev, "eeprom", eeprom_blk, &error_fatal);
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_realize_and_unref(busdev, &error_fatal);
+ sysbus_mmio_map(busdev, 0, base);
+}
+
+static void beckhoff_cx7200_init(MachineState *machine)
+{
+ DriveInfo *di;
+ BlockBackend *blk;
+ MachineClass *parent_mc;
+ DeviceState *a9mpcore_dev;
+ A9MPPrivState *a9mp_priv_state;
+
+ object_property_set_str(OBJECT(machine), "flash-type", "is25lp016d",
+ &error_fatal);
+
+ parent_mc = MACHINE_CLASS(object_class_get_parent(
+ object_get_class(OBJECT(machine))));
+ parent_mc->init(machine);
+
+ /* Find A9MPCore and set timer frequencies directly */
+ a9mpcore_dev = DEVICE(object_resolve_path_type("", TYPE_A9MPCORE_PRIV,
+ NULL));
+ if (a9mpcore_dev) {
+ a9mp_priv_state = A9MPCORE_PRIV(a9mpcore_dev);
+
+ /* Direct struct access - devices are already realized */
+ a9mp_priv_state->gtimer.freq_hz = CX7200_PS7_CPU_CLK_FREQUENCY;
+ a9mp_priv_state->gtimer.periphclk_divider = CX7200_PERIPHCLK_DIVIDER;
+ a9mp_priv_state->mptimer.freq_hz = CX7200_PS7_CPU_CLK_FREQUENCY;
+ a9mp_priv_state->mptimer.periphclk_divider = CX7200_PERIPHCLK_DIVIDER;
+ a9mp_priv_state->wdt.freq_hz = CX7200_PS7_CPU_CLK_FREQUENCY;
+ a9mp_priv_state->wdt.periphclk_divider = CX7200_PERIPHCLK_DIVIDER;
+ } else {
+ error_setg(&error_fatal, "Could not find A9MPCore device "
+ "for CX7200 timer configuration");
+ }
+
+ di = drive_get(IF_NONE, 0, 0);
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
+ ccat_init(0x40000000, blk);
+}
+
+static void beckhoff_cx7200_machine_class_init(ObjectClass *oc,
+ const void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Beckhoff CX7200 Industrial PC (Zynq-based)";
+ mc->init = beckhoff_cx7200_init;
+}
+
+static const TypeInfo beckhoff_cx7200_machine_type = {
+ .name = TYPE_CX7200_MACHINE,
+ .parent = TYPE_ZYNQ_MACHINE,
+ .class_init = beckhoff_cx7200_machine_class_init,
+ .instance_size = sizeof(ZynqMachineState),
+};
+
+static void beckhoff_cx7200_machine_register_types(void)
+{
+ type_register_static(&beckhoff_cx7200_machine_type);
+}
+
+type_init(beckhoff_cx7200_machine_register_types)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index aeaf654790..4ea5d2648c 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -2,6 +2,7 @@ arm_ss = ss.source_set()
arm_common_ss = ss.source_set()
arm_common_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c'))
arm_common_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
+arm_common_ss.add(when: 'CONFIG_BECKHOFF_CX7200', if_true: files('beckhoff_CX7200.c'))
arm_common_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c'))
arm_common_ss.add(when: 'CONFIG_EMCRAFT_SF2', if_true: files('msf2-som.c'))
arm_common_ss.add(when: 'CONFIG_HIGHBANK', if_true: files('highbank.c'))
--
2.47.3