qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/18] Add i.MX 8M Plus EVK machine
@ 2025-02-04  9:20 Bernhard Beschow
  2025-02-04  9:20 ` [PATCH v2 01/18] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
                   ` (17 more replies)
  0 siblings, 18 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

This series adds a new aarch64 machine to QEMU: i.MX 8M Plus EVK [1]. It allows
for running Linux distributions such as Buildroot
(freescale_imx8mpevk_defconfig) and Arch Linux [2] via direct kernel boot.
U-Boot does not work yet. I plan to use this machine myself and I also want to
make it available to a bigger audience, so I propose to add it to QEMU. My goal
would be to have it added for 10.0.

The series is structured as follows: The first three patches fix some issues in
device models reused by the new machine. Patches 4-17 add the machine step by
step which includes documentation. The last patch adds an I²C RTC which I'd like
to use along with the new machine.

I've based some code on existing one (see "Based on" in file headers) and I'm
unsure how to handle the licensing and attribution correctly -- advice welcome.

v2:
* Rebase onto master, eliminating some patches from the series
* Initialize ROM with memory_region_init_rom() (Zoltan)
* Mark the machine as "Maintained" (Peter)
* Do not select TEST_DEVICES (Peter)
* Have separate sources for the two clock tree modules (Peter)
* Make PCI devices attach to the correct bus (Peter)
* Avoid adding documentation that is removed later (Zoltan) Instead, document
  Buildroot process in the first place and change it slightly.
* Drop TCA6416 device model (Phil, Dmitrii)
* Add pca955* Kconfig cleanup patch

[1] https://www.nxp.com/design/design-center/development-boards-and-designs/8MPLUSLPD4-EVK
[2] https://archlinuxarm.org/platforms/armv8/generic

Bernhard Beschow (18):
  hw/usb/hcd-dwc3: Align global registers size with Linux
  hw/pci-host/designware: Prevent device attachment on internal PCIe
    root bus
  hw/gpio/pca955*: Move Kconfig switches next to implementations
  hw/arm: Add i.MX 8M Plus EVK board
  hw/arm/fsl-imx8mp: Implement clock tree
  hw/arm/fsl-imx8mp: Add SNVS
  hw/arm/fsl-imx8mp: Add USDHC storage controllers
  hw/arm/fsl-imx8mp: Add PCIe support
  hw/arm/fsl-imx8mp: Add GPIO controllers
  hw/arm/fsl-imx8mp: Add I2C controllers
  hw/arm/fsl-imx8mp: Add SPI controllers
  hw/arm/fsl-imx8mp: Add watchdog support
  hw/arm/fsl-imx8mp: Implement gneral purpose timers
  hw/arm/fsl-imx8mp: Add Ethernet controller
  hw/arm/fsl-imx8mp: Add USB support
  hw/arm/fsl-imx8mp: Add boot ROM
  hw/arm/fsl-imx8mp: Add on-chip RAM
  hw/rtc: Add Ricoh RS5C372 RTC emulation

 MAINTAINERS                         |  15 +
 docs/system/arm/imx8mp-evk.rst      |  72 +++
 docs/system/target-arm.rst          |   1 +
 include/hw/arm/fsl-imx8mp.h         | 285 +++++++++++
 include/hw/misc/imx8mp_analog.h     |  81 +++
 include/hw/misc/imx8mp_ccm.h        |  30 ++
 include/hw/pci-host/designware.h    |   7 +
 include/hw/pci-host/fsl_imx8m_phy.h |  27 +
 include/hw/timer/imx_gpt.h          |   1 +
 include/hw/usb/hcd-dwc3.h           |   2 +-
 hw/arm/fsl-imx8mp.c                 | 736 ++++++++++++++++++++++++++++
 hw/arm/imx8mp-evk.c                 |  74 +++
 hw/misc/imx8mp_analog.c             | 160 ++++++
 hw/misc/imx8mp_ccm.c                | 175 +++++++
 hw/pci-host/designware.c            |  18 +-
 hw/pci-host/fsl_imx8m_phy.c         |  88 ++++
 hw/rtc/rs5c372.c                    | 227 +++++++++
 hw/timer/imx_gpt.c                  |  25 +
 hw/usb/hcd-dwc3.c                   |   5 +
 hw/arm/Kconfig                      |  24 +
 hw/arm/meson.build                  |   2 +
 hw/gpio/Kconfig                     |  10 +
 hw/misc/Kconfig                     |  14 +-
 hw/misc/meson.build                 |   2 +
 hw/pci-host/Kconfig                 |   3 +
 hw/pci-host/meson.build             |   1 +
 hw/rtc/Kconfig                      |   5 +
 hw/rtc/meson.build                  |   1 +
 hw/rtc/trace-events                 |   4 +
 pc-bios/imx8mp-boot.rom             | Bin 0 -> 258048 bytes
 pc-bios/meson.build                 |   1 +
 31 files changed, 2086 insertions(+), 10 deletions(-)
 create mode 100644 docs/system/arm/imx8mp-evk.rst
 create mode 100644 include/hw/arm/fsl-imx8mp.h
 create mode 100644 include/hw/misc/imx8mp_analog.h
 create mode 100644 include/hw/misc/imx8mp_ccm.h
 create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
 create mode 100644 hw/arm/fsl-imx8mp.c
 create mode 100644 hw/arm/imx8mp-evk.c
 create mode 100644 hw/misc/imx8mp_analog.c
 create mode 100644 hw/misc/imx8mp_ccm.c
 create mode 100644 hw/pci-host/fsl_imx8m_phy.c
 create mode 100644 hw/rtc/rs5c372.c
 create mode 100644 pc-bios/imx8mp-boot.rom

-- 
2.48.1



^ permalink raw reply	[flat|nested] 52+ messages in thread

* [PATCH v2 01/18] hw/usb/hcd-dwc3: Align global registers size with Linux
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
@ 2025-02-04  9:20 ` Bernhard Beschow
  2025-02-04  9:20 ` [PATCH v2 02/18] hw/pci-host/designware: Prevent device attachment on internal PCIe root bus Bernhard Beschow
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

While at it add missing GUSB2RHBCTL register as found in i.MX 8M Plus reference
manual.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 include/hw/usb/hcd-dwc3.h | 2 +-
 hw/usb/hcd-dwc3.c         | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
index f752a27e94..dbdf12b21d 100644
--- a/include/hw/usb/hcd-dwc3.h
+++ b/include/hw/usb/hcd-dwc3.h
@@ -35,7 +35,7 @@
 #define USB_DWC3(obj) \
      OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
 
-#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
+#define USB_DWC3_R_MAX (0x600 / 4)
 #define DWC3_SIZE 0x10000
 
 typedef struct USBDWC3 {
diff --git a/hw/usb/hcd-dwc3.c b/hw/usb/hcd-dwc3.c
index 9ce9ba0b04..0bceee2712 100644
--- a/hw/usb/hcd-dwc3.c
+++ b/hw/usb/hcd-dwc3.c
@@ -343,6 +343,8 @@ REG32(GFLADJ, 0x530)
     FIELD(GFLADJ, GFLADJ_REFCLK_FLADJ, 8, 14)
     FIELD(GFLADJ, GFLADJ_30MHZ_SDBND_SEL, 7, 1)
     FIELD(GFLADJ, GFLADJ_30MHZ, 0, 6)
+REG32(GUSB2RHBCTL, 0x540)
+    FIELD(GUSB2RHBCTL, OVRD_L1TIMEOUT, 0, 4)
 
 #define DWC3_GLOBAL_OFFSET 0xC100
 static void reset_csr(USBDWC3 * s)
@@ -560,6 +562,9 @@ static const RegisterAccessInfo usb_dwc3_regs_info[] = {
         .rsvd = 0x40,
         .ro = 0x400040,
         .unimp = 0xffffffff,
+    },{ .name = "GUSB2RHBCTL",  .addr = A_GUSB2RHBCTL,
+        .rsvd = 0xfffffff0,
+        .unimp = 0xffffffff,
     }
 };
 
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 02/18] hw/pci-host/designware: Prevent device attachment on internal PCIe root bus
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
  2025-02-04  9:20 ` [PATCH v2 01/18] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
@ 2025-02-04  9:20 ` Bernhard Beschow
  2025-02-17 13:36   ` Peter Maydell
  2025-02-04  9:20 ` [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations Bernhard Beschow
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

On the real device, the PCIe root bus is only connected to a PCIe bridge and
does not allow for direct attachment of devices. Doing so in QEMU results in no
PCI devices being detected by Linux. Instead, PCI devices should plug into the
secondary PCIe bus spawned by the internal PCIe bridge.

Unfortunately, QEMU defaults to plugging devices into the PCIe root bus. To work
around this, every PCI device created on the command line needs an extra
`bus=dw-pcie` option which is error prone. Fix that by marking the PCIe root bus
as full which makes QEMU decend into the child PCIe bus.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 include/hw/pci-host/designware.h |  7 +++++++
 hw/pci-host/designware.c         | 18 +++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index bf8b278978..a35a3bd06c 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -25,12 +25,19 @@
 #include "hw/pci/pci_bridge.h"
 #include "qom/object.h"
 
+#define TYPE_DESIGNWARE_PCIE_ROOT_BUS "designware-pcie-root-BUS"
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERootBus, DESIGNWARE_PCIE_ROOT_BUS)
+
 #define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
 OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
 
 #define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
 OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
 
+struct DesignwarePCIERootBus {
+    PCIBus parent;
+};
+
 typedef struct DesignwarePCIEViewport {
     DesignwarePCIERoot *root;
 
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index 3e8c36e6a7..c07740bfaa 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -55,6 +55,17 @@
 #define DESIGNWARE_PCIE_ATU_DEVFN(x)               (((x) >> 16) & 0xff)
 #define DESIGNWARE_PCIE_ATU_UPPER_TARGET           0x91C
 
+static void designware_pcie_root_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    /*
+     * Designware has only a single root complex. Enforce the limit on the
+     * parent bus
+     */
+    k->max_dev = 1;
+}
+
 static DesignwarePCIEHost *
 designware_pcie_root_to_host(DesignwarePCIERoot *root)
 {
@@ -699,7 +710,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
                                      &s->pci.memory,
                                      &s->pci.io,
                                      0, 4,
-                                     TYPE_PCIE_BUS);
+                                     TYPE_DESIGNWARE_PCIE_ROOT_BUS);
     pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
     memory_region_init(&s->pci.address_space_root,
@@ -754,6 +765,11 @@ static void designware_pcie_host_init(Object *obj)
 
 static const TypeInfo designware_pcie_types[] = {
     {
+        .name           = TYPE_DESIGNWARE_PCIE_ROOT_BUS,
+        .parent         = TYPE_PCIE_BUS,
+        .instance_size  = sizeof(DesignwarePCIERootBus),
+        .class_init     = designware_pcie_root_bus_class_init,
+    }, {
         .name           = TYPE_DESIGNWARE_PCIE_HOST,
         .parent         = TYPE_PCI_HOST_BRIDGE,
         .instance_size  = sizeof(DesignwarePCIEHost),
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
  2025-02-04  9:20 ` [PATCH v2 01/18] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
  2025-02-04  9:20 ` [PATCH v2 02/18] hw/pci-host/designware: Prevent device attachment on internal PCIe root bus Bernhard Beschow
@ 2025-02-04  9:20 ` Bernhard Beschow
  2025-02-17 13:35   ` Peter Maydell
  2025-02-04  9:20 ` [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

While at it and since they are user-creatable, build them when
CONFIG_I2C_DEVICES is set.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 hw/gpio/Kconfig | 10 ++++++++++
 hw/misc/Kconfig |  8 --------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
index c423e10f59..007048c688 100644
--- a/hw/gpio/Kconfig
+++ b/hw/gpio/Kconfig
@@ -16,6 +16,16 @@ config SIFIVE_GPIO
 config STM32L4X5_GPIO
     bool
 
+config PCA9552
+    bool
+    depends on I2C
+    default y if I2C_DEVICES
+
+config PCA9554
+    bool
+    depends on I2C
+    default y if I2C_DEVICES
+
 config PCF8574
     bool
     depends on I2C
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 8f9ce2f68c..4271e2f4ac 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -30,14 +30,6 @@ config EDU
     default y if TEST_DEVICES
     depends on PCI && MSI_NONBROKEN
 
-config PCA9552
-    bool
-    depends on I2C
-
-config PCA9554
-    bool
-    depends on I2C
-
 config I2C_ECHO
     bool
     default y if TEST_DEVICES
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (2 preceding siblings ...)
  2025-02-04  9:20 ` [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations Bernhard Beschow
@ 2025-02-04  9:20 ` Bernhard Beschow
  2025-02-10 17:30   ` Peter Maydell
  2025-02-04  9:20 ` [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
serial. All other devices of the A53 memory map are represented as
TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
for running Linux without it crashing due to invalid memory accesses.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 MAINTAINERS                    |   9 +
 docs/system/arm/imx8mp-evk.rst |  56 +++++
 docs/system/target-arm.rst     |   1 +
 include/hw/arm/fsl-imx8mp.h    | 189 +++++++++++++++++
 hw/arm/fsl-imx8mp.c            | 371 +++++++++++++++++++++++++++++++++
 hw/arm/imx8mp-evk.c            |  55 +++++
 hw/arm/Kconfig                 |  12 ++
 hw/arm/meson.build             |   2 +
 8 files changed, 695 insertions(+)
 create mode 100644 docs/system/arm/imx8mp-evk.rst
 create mode 100644 include/hw/arm/fsl-imx8mp.h
 create mode 100644 hw/arm/fsl-imx8mp.c
 create mode 100644 hw/arm/imx8mp-evk.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0cf37fce7b..8db59114bc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -820,6 +820,15 @@ F: hw/pci-host/designware.c
 F: include/hw/pci-host/designware.h
 F: docs/system/arm/mcimx7d-sabre.rst
 
+MCIMX8MP-EVK / i.MX8MP
+M: Bernhard Beschow <shentey@gmail.com>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/arm/imx8mp-evk.c
+F: hw/arm/fsl-imx8mp.c
+F: include/hw/arm/fsl-imx8mp.h
+F: docs/system/arm/imx8mp-evk.rst
+
 MPS2 / MPS3
 M: Peter Maydell <peter.maydell@linaro.org>
 L: qemu-arm@nongnu.org
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
new file mode 100644
index 0000000000..a9c1fab390
--- /dev/null
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -0,0 +1,56 @@
+NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
+================================================
+
+The QEMU i.MX 8M Plus EVK board emulation is intended to emulate a plain i.MX 8M
+Plus system on chip (SoC). All peripherals the real board has such as flash and
+I2C devices are intended to be added via configuration, e.g. command line.
+
+Supported devices
+-----------------
+
+The ``imx8mp-evk`` machine implements the following devices:
+
+ * Up to 4 Cortex-A53 Cores
+ * Generic Interrupt Controller (GICv3)
+ * 4 UARTs
+
+Boot options
+------------
+
+The ``imx8mp-evk`` machine can start using the standard -kernel functionality
+for loading a Linux kernel.
+
+Direct Linux Kernel Boot
+''''''''''''''''''''''''
+
+Probably the easiest way to get started with a whole Linux system on the machine
+is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
+of writing and involves two steps. First run the following commands in the
+toplevel directory of the Buildroot source tree:
+
+.. code-block:: bash
+
+  $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
+  $ make freescale_imx8mpevk_defconfig
+  $ make
+
+Once finished successfully there is an ``output/image`` subfolder. Navigate into
+it patch the device tree needs to be patched with the following commands which
+will remove the ``cpu-idle-states`` properties from CPU nodes:
+
+.. code-block:: bash
+
+  $ dtc imx8mp-evk.dtb | sed '/cpu-idle-states/d' > imx8mp-evk-patched.dts
+  $ dtc imx8mp-evk-patched.dts -o imx8mp-evk-patched.dtb
+
+Now that everything is prepared the newly built image can be run in the QEMU
+``imx8mp-evk`` machine:
+
+.. code-block:: bash
+
+  $ qemu-system-aarch64 -M imx8mp-evk -smp 4 -m 3G \
+      -display none -serial null -serial stdio \
+      -kernel Image \
+      -dtb imx8mp-evk-patched.dtb \
+      -initrd rootfs.cpio \
+      -append "root=/dev/ram"
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index 9aaa9c414c..a43ec8f10e 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -95,6 +95,7 @@ Board-specific documentation
    arm/imx25-pdk
    arm/mcimx6ul-evk
    arm/mcimx7d-sabre
+   arm/imx8mp-evk
    arm/orangepi
    arm/raspi
    arm/collie
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
new file mode 100644
index 0000000000..57e23d1b69
--- /dev/null
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -0,0 +1,189 @@
+/*
+ * i.MX 8M Plus SoC Definitions
+ *
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef FSL_IMX8MP_H
+#define FSL_IMX8MP_H
+
+#include "cpu.h"
+#include "hw/char/imx_serial.h"
+#include "hw/intc/arm_gicv3_common.h"
+#include "qom/object.h"
+#include "qemu/units.h"
+
+#define TYPE_FSL_IMX8MP "fsl-imx8mp"
+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
+
+#define FSL_IMX8MP_RAM_START        0x40000000
+#define FSL_IMX8MP_RAM_SIZE_MAX     (8 * GiB)
+
+enum FslImx8mpConfiguration {
+    FSL_IMX8MP_NUM_CPUS         = 4,
+    FSL_IMX8MP_NUM_IRQS         = 160,
+    FSL_IMX8MP_NUM_UARTS        = 4,
+};
+
+struct FslImx8mpState {
+    DeviceState    parent_obj;
+
+    ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
+    GICv3State         gic;
+    IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
+};
+
+enum FslImx8mpMemoryRegions {
+    FSL_IMX8MP_A53_DAP,
+    FSL_IMX8MP_AIPS1_CONFIGURATION,
+    FSL_IMX8MP_AIPS2_CONFIGURATION,
+    FSL_IMX8MP_AIPS3_CONFIGURATION,
+    FSL_IMX8MP_AIPS4_CONFIGURATION,
+    FSL_IMX8MP_AIPS5_CONFIGURATION,
+    FSL_IMX8MP_ANA_OSC,
+    FSL_IMX8MP_ANA_PLL,
+    FSL_IMX8MP_ANA_TSENSOR,
+    FSL_IMX8MP_APBH_DMA,
+    FSL_IMX8MP_ASRC,
+    FSL_IMX8MP_AUDIO_BLK_CTRL,
+    FSL_IMX8MP_AUDIO_DSP,
+    FSL_IMX8MP_AUDIO_XCVR_RX,
+    FSL_IMX8MP_AUD_IRQ_STEER,
+    FSL_IMX8MP_BOOT_ROM,
+    FSL_IMX8MP_BOOT_ROM_PROTECTED,
+    FSL_IMX8MP_CAAM,
+    FSL_IMX8MP_CAAM_MEM,
+    FSL_IMX8MP_CCM,
+    FSL_IMX8MP_CSU,
+    FSL_IMX8MP_DDR_BLK_CTRL,
+    FSL_IMX8MP_DDR_CTL,
+    FSL_IMX8MP_DDR_PERF_MON,
+    FSL_IMX8MP_DDR_PHY,
+    FSL_IMX8MP_DDR_PHY_BROADCAST,
+    FSL_IMX8MP_ECSPI1,
+    FSL_IMX8MP_ECSPI2,
+    FSL_IMX8MP_ECSPI3,
+    FSL_IMX8MP_EDMA_CHANNELS,
+    FSL_IMX8MP_EDMA_MANAGEMENT_PAGE,
+    FSL_IMX8MP_ENET1,
+    FSL_IMX8MP_ENET2_TSN,
+    FSL_IMX8MP_FLEXCAN1,
+    FSL_IMX8MP_FLEXCAN2,
+    FSL_IMX8MP_GIC_DIST,
+    FSL_IMX8MP_GIC_REDIST,
+    FSL_IMX8MP_GPC,
+    FSL_IMX8MP_GPIO1,
+    FSL_IMX8MP_GPIO2,
+    FSL_IMX8MP_GPIO3,
+    FSL_IMX8MP_GPIO4,
+    FSL_IMX8MP_GPIO5,
+    FSL_IMX8MP_GPT1,
+    FSL_IMX8MP_GPT2,
+    FSL_IMX8MP_GPT3,
+    FSL_IMX8MP_GPT4,
+    FSL_IMX8MP_GPT5,
+    FSL_IMX8MP_GPT6,
+    FSL_IMX8MP_GPU2D,
+    FSL_IMX8MP_GPU3D,
+    FSL_IMX8MP_HDMI_TX,
+    FSL_IMX8MP_HDMI_TX_AUDLNK_MSTR,
+    FSL_IMX8MP_HSIO_BLK_CTL,
+    FSL_IMX8MP_I2C1,
+    FSL_IMX8MP_I2C2,
+    FSL_IMX8MP_I2C3,
+    FSL_IMX8MP_I2C4,
+    FSL_IMX8MP_I2C5,
+    FSL_IMX8MP_I2C6,
+    FSL_IMX8MP_INTERCONNECT,
+    FSL_IMX8MP_IOMUXC,
+    FSL_IMX8MP_IOMUXC_GPR,
+    FSL_IMX8MP_IPS_DEWARP,
+    FSL_IMX8MP_ISI,
+    FSL_IMX8MP_ISP1,
+    FSL_IMX8MP_ISP2,
+    FSL_IMX8MP_LCDIF1,
+    FSL_IMX8MP_LCDIF2,
+    FSL_IMX8MP_MEDIA_BLK_CTL,
+    FSL_IMX8MP_MIPI_CSI1,
+    FSL_IMX8MP_MIPI_CSI2,
+    FSL_IMX8MP_MIPI_DSI1,
+    FSL_IMX8MP_MU_1_A,
+    FSL_IMX8MP_MU_1_B,
+    FSL_IMX8MP_MU_2_A,
+    FSL_IMX8MP_MU_2_B,
+    FSL_IMX8MP_MU_3_A,
+    FSL_IMX8MP_MU_3_B,
+    FSL_IMX8MP_NPU,
+    FSL_IMX8MP_OCOTP_CTRL,
+    FSL_IMX8MP_OCRAM,
+    FSL_IMX8MP_OCRAM_S,
+    FSL_IMX8MP_PCIE1,
+    FSL_IMX8MP_PCIE1_MEM,
+    FSL_IMX8MP_PCIE_PHY1,
+    FSL_IMX8MP_PDM,
+    FSL_IMX8MP_PERFMON1,
+    FSL_IMX8MP_PERFMON2,
+    FSL_IMX8MP_PWM1,
+    FSL_IMX8MP_PWM2,
+    FSL_IMX8MP_PWM3,
+    FSL_IMX8MP_PWM4,
+    FSL_IMX8MP_QOSC,
+    FSL_IMX8MP_QSPI,
+    FSL_IMX8MP_QSPI1_RX_BUFFER,
+    FSL_IMX8MP_QSPI1_TX_BUFFER,
+    FSL_IMX8MP_QSPI_MEM,
+    FSL_IMX8MP_RAM,
+    FSL_IMX8MP_RDC,
+    FSL_IMX8MP_SAI1,
+    FSL_IMX8MP_SAI2,
+    FSL_IMX8MP_SAI3,
+    FSL_IMX8MP_SAI5,
+    FSL_IMX8MP_SAI6,
+    FSL_IMX8MP_SAI7,
+    FSL_IMX8MP_SDMA1,
+    FSL_IMX8MP_SDMA2,
+    FSL_IMX8MP_SDMA3,
+    FSL_IMX8MP_SEMAPHORE1,
+    FSL_IMX8MP_SEMAPHORE2,
+    FSL_IMX8MP_SEMAPHORE_HS,
+    FSL_IMX8MP_SNVS_HP,
+    FSL_IMX8MP_SPBA1,
+    FSL_IMX8MP_SPBA2,
+    FSL_IMX8MP_SRC,
+    FSL_IMX8MP_SYSCNT_CMP,
+    FSL_IMX8MP_SYSCNT_CTRL,
+    FSL_IMX8MP_SYSCNT_RD,
+    FSL_IMX8MP_TCM_DTCM,
+    FSL_IMX8MP_TCM_ITCM,
+    FSL_IMX8MP_TZASC,
+    FSL_IMX8MP_UART1,
+    FSL_IMX8MP_UART2,
+    FSL_IMX8MP_UART3,
+    FSL_IMX8MP_UART4,
+    FSL_IMX8MP_USB1,
+    FSL_IMX8MP_USB2,
+    FSL_IMX8MP_USDHC1,
+    FSL_IMX8MP_USDHC2,
+    FSL_IMX8MP_USDHC3,
+    FSL_IMX8MP_VPU,
+    FSL_IMX8MP_VPU_BLK_CTRL,
+    FSL_IMX8MP_VPU_G1_DECODER,
+    FSL_IMX8MP_VPU_G2_DECODER,
+    FSL_IMX8MP_VPU_VC8000E_ENCODER,
+    FSL_IMX8MP_WDOG1,
+    FSL_IMX8MP_WDOG2,
+    FSL_IMX8MP_WDOG3,
+};
+
+enum FslImx8mpIrqs {
+    FSL_IMX8MP_UART1_IRQ    = 26,
+    FSL_IMX8MP_UART2_IRQ    = 27,
+    FSL_IMX8MP_UART3_IRQ    = 28,
+    FSL_IMX8MP_UART4_IRQ    = 29,
+    FSL_IMX8MP_UART5_IRQ    = 30,
+    FSL_IMX8MP_UART6_IRQ    = 16,
+};
+
+#endif /* FSL_IMX8MP_H */
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
new file mode 100644
index 0000000000..0836d82ca0
--- /dev/null
+++ b/hw/arm/fsl-imx8mp.c
@@ -0,0 +1,371 @@
+/*
+ * i.MX 8M Plus SoC Implementation
+ *
+ * Based on hw/arm/fsl-imx6.c
+ *
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/bsa.h"
+#include "hw/arm/fsl-imx8mp.h"
+#include "hw/intc/arm_gicv3.h"
+#include "hw/misc/unimp.h"
+#include "hw/boards.h"
+#include "system/system.h"
+#include "target/arm/cpu-qom.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/error.h"
+
+static const struct {
+    hwaddr addr;
+    size_t size;
+    const char *name;
+} fsl_imx8mp_memmap[] = {
+    [FSL_IMX8MP_RAM] = { FSL_IMX8MP_RAM_START, FSL_IMX8MP_RAM_SIZE_MAX, "ram" },
+    [FSL_IMX8MP_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
+    [FSL_IMX8MP_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
+    [FSL_IMX8MP_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
+    [FSL_IMX8MP_DDR_BLK_CTRL] = { 0x3d000000, 1 * MiB, "ddr_blk_ctrl" },
+    [FSL_IMX8MP_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
+    [FSL_IMX8MP_AUDIO_DSP] = { 0x3b000000, 16 * MiB, "audio_dsp" },
+    [FSL_IMX8MP_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
+    [FSL_IMX8MP_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
+    [FSL_IMX8MP_NPU] = { 0x38500000, 2 * MiB, "npu" },
+    [FSL_IMX8MP_VPU] = { 0x38340000, 2 * MiB, "vpu" },
+    [FSL_IMX8MP_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
+    [FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
+    [FSL_IMX8MP_VPU_G2_DECODER] = { 0x38310000, 2 * MiB, "vpu_g2_decoder" },
+    [FSL_IMX8MP_VPU_G1_DECODER] = { 0x38300000, 2 * MiB, "vpu_g1_decoder" },
+    [FSL_IMX8MP_USB2] = { 0x38200000, 1 * MiB, "usb2" },
+    [FSL_IMX8MP_USB1] = { 0x38100000, 1 * MiB, "usb1" },
+    [FSL_IMX8MP_GPU2D] = { 0x38008000, 32 * KiB, "gpu2d" },
+    [FSL_IMX8MP_GPU3D] = { 0x38000000, 32 * KiB, "gpu3d" },
+    [FSL_IMX8MP_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
+    [FSL_IMX8MP_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
+    [FSL_IMX8MP_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
+    [FSL_IMX8MP_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
+
+    /* AIPS-5 Begin */
+    [FSL_IMX8MP_MU_3_B] = { 0x30e90000, 64 * KiB, "mu_3_b" },
+    [FSL_IMX8MP_MU_3_A] = { 0x30e80000, 64 * KiB, "mu_3_a" },
+    [FSL_IMX8MP_MU_2_B] = { 0x30e70000, 64 * KiB, "mu_2_b" },
+    [FSL_IMX8MP_MU_2_A] = { 0x30e60000, 64 * KiB, "mu_2_a" },
+    [FSL_IMX8MP_EDMA_CHANNELS] = { 0x30e40000, 128 * KiB, "edma_channels" },
+    [FSL_IMX8MP_EDMA_MANAGEMENT_PAGE] = { 0x30e30000, 64 * KiB, "edma_management_page" },
+    [FSL_IMX8MP_AUDIO_BLK_CTRL] = { 0x30e20000, 64 * KiB, "audio_blk_ctrl" },
+    [FSL_IMX8MP_SDMA2] = { 0x30e10000, 64 * KiB, "sdma2" },
+    [FSL_IMX8MP_SDMA3] = { 0x30e00000, 64 * KiB, "sdma3" },
+    [FSL_IMX8MP_AIPS5_CONFIGURATION] = { 0x30df0000, 64 * KiB, "aips5_configuration" },
+    [FSL_IMX8MP_SPBA2] = { 0x30cf0000, 64 * KiB, "spba2" },
+    [FSL_IMX8MP_AUDIO_XCVR_RX] = { 0x30cc0000, 64 * KiB, "audio_xcvr_rx" },
+    [FSL_IMX8MP_HDMI_TX_AUDLNK_MSTR] = { 0x30cb0000, 64 * KiB, "hdmi_tx_audlnk_mstr" },
+    [FSL_IMX8MP_PDM] = { 0x30ca0000, 64 * KiB, "pdm" },
+    [FSL_IMX8MP_ASRC] = { 0x30c90000, 64 * KiB, "asrc" },
+    [FSL_IMX8MP_SAI7] = { 0x30c80000, 64 * KiB, "sai7" },
+    [FSL_IMX8MP_SAI6] = { 0x30c60000, 64 * KiB, "sai6" },
+    [FSL_IMX8MP_SAI5] = { 0x30c50000, 64 * KiB, "sai5" },
+    [FSL_IMX8MP_SAI3] = { 0x30c30000, 64 * KiB, "sai3" },
+    [FSL_IMX8MP_SAI2] = { 0x30c20000, 64 * KiB, "sai2" },
+    [FSL_IMX8MP_SAI1] = { 0x30c10000, 64 * KiB, "sai1" },
+    /* AIPS-5 End */
+
+    /* AIPS-4 Begin */
+    [FSL_IMX8MP_HDMI_TX] = { 0x32fc0000, 128 * KiB, "hdmi_tx" },
+    [FSL_IMX8MP_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
+    [FSL_IMX8MP_HSIO_BLK_CTL] = { 0x32f10000, 64 * KiB, "hsio_blk_ctl" },
+    [FSL_IMX8MP_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
+    [FSL_IMX8MP_MEDIA_BLK_CTL] = { 0x32ec0000, 64 * KiB, "media_blk_ctl" },
+    [FSL_IMX8MP_LCDIF2] = { 0x32e90000, 64 * KiB, "lcdif2" },
+    [FSL_IMX8MP_LCDIF1] = { 0x32e80000, 64 * KiB, "lcdif1" },
+    [FSL_IMX8MP_MIPI_DSI1] = { 0x32e60000, 64 * KiB, "mipi_dsi1" },
+    [FSL_IMX8MP_MIPI_CSI2] = { 0x32e50000, 64 * KiB, "mipi_csi2" },
+    [FSL_IMX8MP_MIPI_CSI1] = { 0x32e40000, 64 * KiB, "mipi_csi1" },
+    [FSL_IMX8MP_IPS_DEWARP] = { 0x32e30000, 64 * KiB, "ips_dewarp" },
+    [FSL_IMX8MP_ISP2] = { 0x32e20000, 64 * KiB, "isp2" },
+    [FSL_IMX8MP_ISP1] = { 0x32e10000, 64 * KiB, "isp1" },
+    [FSL_IMX8MP_ISI] = { 0x32e00000, 64 * KiB, "isi" },
+    [FSL_IMX8MP_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
+    /* AIPS-4 End */
+
+    [FSL_IMX8MP_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
+
+    /* AIPS-3 Begin */
+    [FSL_IMX8MP_ENET2_TSN] = { 0x30bf0000, 64 * KiB, "enet2_tsn" },
+    [FSL_IMX8MP_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
+    [FSL_IMX8MP_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
+    [FSL_IMX8MP_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
+    [FSL_IMX8MP_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
+    [FSL_IMX8MP_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
+    [FSL_IMX8MP_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
+    [FSL_IMX8MP_I2C6] = { 0x30ae0000, 64 * KiB, "i2c6" },
+    [FSL_IMX8MP_I2C5] = { 0x30ad0000, 64 * KiB, "i2c5" },
+    [FSL_IMX8MP_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
+    [FSL_IMX8MP_MU_1_B] = { 0x30ab0000, 64 * KiB, "mu_1_b" },
+    [FSL_IMX8MP_MU_1_A] = { 0x30aa0000, 64 * KiB, "mu_1_a" },
+    [FSL_IMX8MP_AUD_IRQ_STEER] = { 0x30a80000, 64 * KiB, "aud_irq_steer" },
+    [FSL_IMX8MP_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
+    [FSL_IMX8MP_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
+    [FSL_IMX8MP_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
+    [FSL_IMX8MP_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
+    [FSL_IMX8MP_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
+    [FSL_IMX8MP_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
+    [FSL_IMX8MP_CAAM] = { 0x30900000, 256 * KiB, "caam" },
+    [FSL_IMX8MP_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
+    [FSL_IMX8MP_FLEXCAN2] = { 0x308d0000, 64 * KiB, "flexcan2" },
+    [FSL_IMX8MP_FLEXCAN1] = { 0x308c0000, 64 * KiB, "flexcan1" },
+    [FSL_IMX8MP_UART2] = { 0x30890000, 64 * KiB, "uart2" },
+    [FSL_IMX8MP_UART3] = { 0x30880000, 64 * KiB, "uart3" },
+    [FSL_IMX8MP_UART1] = { 0x30860000, 64 * KiB, "uart1" },
+    [FSL_IMX8MP_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
+    [FSL_IMX8MP_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
+    [FSL_IMX8MP_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
+    /* AIPS-3 End */
+
+    /* AIPS-2 Begin */
+    [FSL_IMX8MP_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
+    [FSL_IMX8MP_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
+    [FSL_IMX8MP_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
+    [FSL_IMX8MP_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
+    [FSL_IMX8MP_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
+    [FSL_IMX8MP_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
+    [FSL_IMX8MP_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
+    [FSL_IMX8MP_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
+    [FSL_IMX8MP_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
+    [FSL_IMX8MP_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
+    [FSL_IMX8MP_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
+    [FSL_IMX8MP_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
+    [FSL_IMX8MP_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
+    [FSL_IMX8MP_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
+    /* AIPS-2 End */
+
+    /* AIPS-1 Begin */
+    [FSL_IMX8MP_CSU] = { 0x303e0000, 64 * KiB, "csu" },
+    [FSL_IMX8MP_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
+    [FSL_IMX8MP_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
+    [FSL_IMX8MP_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
+    [FSL_IMX8MP_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
+    [FSL_IMX8MP_SRC] = { 0x30390000, 64 * KiB, "src" },
+    [FSL_IMX8MP_CCM] = { 0x30380000, 64 * KiB, "ccm" },
+    [FSL_IMX8MP_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
+    [FSL_IMX8MP_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
+    [FSL_IMX8MP_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
+    [FSL_IMX8MP_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
+    [FSL_IMX8MP_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
+    [FSL_IMX8MP_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
+    [FSL_IMX8MP_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
+    [FSL_IMX8MP_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
+    [FSL_IMX8MP_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
+    [FSL_IMX8MP_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
+    [FSL_IMX8MP_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
+    [FSL_IMX8MP_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
+    [FSL_IMX8MP_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
+    [FSL_IMX8MP_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
+    [FSL_IMX8MP_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
+    [FSL_IMX8MP_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
+    [FSL_IMX8MP_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
+    [FSL_IMX8MP_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
+    [FSL_IMX8MP_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
+    /* AIPS-1 End */
+
+    [FSL_IMX8MP_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
+    [FSL_IMX8MP_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
+    [FSL_IMX8MP_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
+    [FSL_IMX8MP_OCRAM] = { 0x00900000, 576 * KiB, "ocram" },
+    [FSL_IMX8MP_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
+    [FSL_IMX8MP_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
+    [FSL_IMX8MP_OCRAM_S] = { 0x00180000, 36 * KiB, "ocram_s" },
+    [FSL_IMX8MP_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
+    [FSL_IMX8MP_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
+    [FSL_IMX8MP_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
+};
+
+#define NAME_SIZE 20
+
+static void fsl_imx8mp_init(Object *obj)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+    FslImx8mpState *s = FSL_IMX8MP(obj);
+    char name[NAME_SIZE];
+    int i;
+
+    for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
+        snprintf(name, NAME_SIZE, "cpu%d", i);
+        object_initialize_child(obj, name, &s->cpu[i],
+                                ARM_CPU_TYPE_NAME("cortex-a53"));
+    }
+
+    object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
+
+    for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
+        snprintf(name, NAME_SIZE, "uart%d", i + 1);
+        object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
+    }
+}
+
+static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+    FslImx8mpState *s = FSL_IMX8MP(dev);
+    DeviceState *gicdev = DEVICE(&s->gic);
+    int i;
+
+    if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
+        error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
+                   TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus);
+        return;
+    }
+
+    /* CPUs */
+    for (i = 0; i < ms->smp.cpus; i++) {
+        /* On uniprocessor, the CBAR is set to 0 */
+        if (ms->smp.cpus > 1) {
+            object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
+                                    fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
+                                    &error_abort);
+        }
+
+        /*
+         * Magic value from Linux output: "arch_timer: cp15 timer(s) running at
+         * 8.00MHz (phys)".
+         */
+        object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
+                                &error_abort);
+
+        if (i) {
+            /*
+             * Secondary CPUs start in powered-down state (and can be
+             * powered up via the SRC system reset controller)
+             */
+            object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
+                                     true, &error_abort);
+        }
+
+        if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
+            return;
+        }
+    }
+
+    /* GIC */
+    {
+        SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
+        QList *redist_region_count;
+
+        qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
+        qdev_prop_set_uint32(gicdev, "num-irq",
+                             FSL_IMX8MP_NUM_IRQS + GIC_INTERNAL);
+        redist_region_count = qlist_new();
+        qlist_append_int(redist_region_count, ms->smp.cpus);
+        qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
+        object_property_set_link(OBJECT(&s->gic), "sysmem",
+                                 OBJECT(get_system_memory()), &error_fatal);
+        if (!sysbus_realize(gicsbd, errp)) {
+            return;
+        }
+        sysbus_mmio_map(gicsbd, 0, fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr);
+        sysbus_mmio_map(gicsbd, 1, fsl_imx8mp_memmap[FSL_IMX8MP_GIC_REDIST].addr);
+
+        /*
+         * Wire the outputs from each CPU's generic timer and the GICv3
+         * maintenance interrupt signal to the appropriate GIC PPI inputs, and
+         * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
+         */
+        for (i = 0; i < ms->smp.cpus; i++) {
+            DeviceState *cpudev = DEVICE(&s->cpu[i]);
+            int intidbase = FSL_IMX8MP_NUM_IRQS + i * GIC_INTERNAL;
+            qemu_irq irq;
+
+            /*
+             * Mapping from the output timer irq lines from the CPU to the
+             * GIC PPI inputs.
+             */
+            static const int timer_irqs[] = {
+                [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+                [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+                [GTIMER_HYP]  = ARCH_TIMER_NS_EL2_IRQ,
+                [GTIMER_SEC]  = ARCH_TIMER_S_EL1_IRQ,
+            };
+
+            for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
+                irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
+                qdev_connect_gpio_out(cpudev, j, irq);
+            }
+
+            irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
+            qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
+                                        0, irq);
+
+            irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
+            qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
+
+            sysbus_connect_irq(gicsbd, i,
+                               qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+            sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
+                               qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+        }
+    }
+
+    /* UARTs */
+    for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } serial_table[FSL_IMX8MP_NUM_UARTS] = {
+            { fsl_imx8mp_memmap[FSL_IMX8MP_UART1].addr, FSL_IMX8MP_UART1_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_UART2].addr, FSL_IMX8MP_UART2_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_UART3].addr, FSL_IMX8MP_UART3_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_UART4].addr, FSL_IMX8MP_UART4_IRQ },
+        };
+
+        qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+                           qdev_get_gpio_in(gicdev, serial_table[i].irq));
+    }
+
+    /* Unimplemented devices */
+    for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
+        switch (i) {
+        case FSL_IMX8MP_GIC_DIST:
+        case FSL_IMX8MP_GIC_REDIST:
+        case FSL_IMX8MP_RAM:
+        case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
+            /* device implemented and treated above */
+            break;
+
+        default:
+            create_unimplemented_device(fsl_imx8mp_memmap[i].name,
+                                        fsl_imx8mp_memmap[i].addr,
+                                        fsl_imx8mp_memmap[i].size);
+            break;
+        }
+    }
+}
+
+static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = fsl_imx8mp_realize;
+
+    dc->desc = "i.MX 8M Plus SoC";
+}
+
+static const TypeInfo fsl_imx8mp_types[] = {
+    {
+        .name = TYPE_FSL_IMX8MP,
+        .parent = TYPE_DEVICE,
+        .instance_size = sizeof(FslImx8mpState),
+        .instance_init = fsl_imx8mp_init,
+        .class_init = fsl_imx8mp_class_init,
+    },
+};
+
+DEFINE_TYPES(fsl_imx8mp_types)
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
new file mode 100644
index 0000000000..2756d4c21c
--- /dev/null
+++ b/hw/arm/imx8mp-evk.c
@@ -0,0 +1,55 @@
+/*
+ * NXP i.MX 8M Plus Evaluation Kit System Emulation
+ *
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/fsl-imx8mp.h"
+#include "hw/boards.h"
+#include "system/qtest.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+static void imx8mp_evk_init(MachineState *machine)
+{
+    static struct arm_boot_info boot_info;
+    FslImx8mpState *s;
+
+    if (machine->ram_size > FSL_IMX8MP_RAM_SIZE_MAX) {
+        error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
+                     machine->ram_size, FSL_IMX8MP_RAM_SIZE_MAX);
+        exit(1);
+    }
+
+    boot_info = (struct arm_boot_info) {
+        .loader_start = FSL_IMX8MP_RAM_START,
+        .board_id = -1,
+        .ram_size = machine->ram_size,
+        .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
+    };
+
+    s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
+    object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+    qdev_realize(DEVICE(s), NULL, &error_fatal);
+
+    memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
+                                machine->ram);
+
+    if (!qtest_enabled()) {
+        arm_load_kernel(&s->cpu[0], machine, &boot_info);
+    }
+}
+
+static void imx8mp_evk_machine_init(MachineClass *mc)
+{
+    mc->desc = "NXP i.MX 8M Plus EVK Board";
+    mc->init = imx8mp_evk_init;
+    mc->max_cpus = FSL_IMX8MP_NUM_CPUS;
+    mc->default_ram_id = "imx8mp-evk.ram";
+}
+DEFINE_MACHINE("imx8mp-evk", imx8mp_evk_machine_init)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 256013ca80..e22916df57 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -577,6 +577,18 @@ config FSL_IMX7
     select OR_IRQ
     select UNIMP
 
+config FSL_IMX8MP
+    bool
+    select ARM_GIC
+    select IMX
+    select UNIMP
+
+config FSL_IMX8MP_EVK
+    bool
+    default y
+    depends on TCG && AARCH64
+    select FSL_IMX8MP
+
 config ARM_SMMUV3
     bool
 
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 490234b3b8..79750ae7b1 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -53,6 +53,8 @@ arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
 arm_ss.add(when: 'CONFIG_MUSCA', if_true: files('musca.c'))
 arm_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
 arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
 arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
 arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
 arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (3 preceding siblings ...)
  2025-02-04  9:20 ` [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
@ 2025-02-04  9:20 ` Bernhard Beschow
  2025-02-04 23:15   ` Bernhard Beschow
  2025-02-04  9:21 ` [PATCH v2 06/18] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Fixes quite a few stack traces during the Linux boot process. Also provides the
clocks for devices added later, e.g. enet1.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 MAINTAINERS                     |   2 +
 docs/system/arm/imx8mp-evk.rst  |   1 +
 include/hw/arm/fsl-imx8mp.h     |   4 +
 include/hw/misc/imx8mp_analog.h |  81 +++++++++++++++
 include/hw/misc/imx8mp_ccm.h    |  30 ++++++
 hw/arm/fsl-imx8mp.c             |  20 ++++
 hw/misc/imx8mp_analog.c         | 160 +++++++++++++++++++++++++++++
 hw/misc/imx8mp_ccm.c            | 175 ++++++++++++++++++++++++++++++++
 hw/arm/Kconfig                  |   2 +
 hw/misc/Kconfig                 |   6 ++
 hw/misc/meson.build             |   2 +
 11 files changed, 483 insertions(+)
 create mode 100644 include/hw/misc/imx8mp_analog.h
 create mode 100644 include/hw/misc/imx8mp_ccm.h
 create mode 100644 hw/misc/imx8mp_analog.c
 create mode 100644 hw/misc/imx8mp_ccm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8db59114bc..5b5b0d0bed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -826,7 +826,9 @@ L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/imx8mp-evk.c
 F: hw/arm/fsl-imx8mp.c
+F: hw/misc/imx8mp_*.c
 F: include/hw/arm/fsl-imx8mp.h
+F: include/hw/misc/imx8mp_*.h
 F: docs/system/arm/imx8mp-evk.rst
 
 MPS2 / MPS3
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index a9c1fab390..e5039fc8c4 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -13,6 +13,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * Up to 4 Cortex-A53 Cores
  * Generic Interrupt Controller (GICv3)
  * 4 UARTs
+ * Clock Tree
 
 Boot options
 ------------
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 57e23d1b69..ce5188e7f2 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -12,6 +12,8 @@
 #include "cpu.h"
 #include "hw/char/imx_serial.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "hw/misc/imx8mp_analog.h"
+#include "hw/misc/imx8mp_ccm.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -32,6 +34,8 @@ struct FslImx8mpState {
 
     ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
     GICv3State         gic;
+    IMX8MPCCMState     ccm;
+    IMX8MPAnalogState  analog;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
 };
 
diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
new file mode 100644
index 0000000000..955f03215a
--- /dev/null
+++ b/include/hw/misc/imx8mp_analog.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX8MP ANALOG IP block emulation code
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IMX8MP_ANALOG_H
+#define IMX8MP_ANALOG_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+enum IMX8MPAnalogRegisters {
+    ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
+    ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
+    ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
+    ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
+    ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
+    ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
+    ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
+    ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
+    ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
+    ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
+    ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
+    ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
+    ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
+    ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
+    ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
+    ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
+    ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
+    ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
+    ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
+    ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
+    ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
+    ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
+    ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
+    ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
+    ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
+    ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
+    ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
+    ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
+    ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
+    ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
+    ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
+    ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
+    ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
+    ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
+    ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
+    ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
+    ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
+    ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
+    ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
+    ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
+    ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
+    ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
+    ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
+    ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
+    ANALOG_OSC_MISC_CFG = 0x124 / 4,
+    ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
+
+    ANALOG_DIGPROG = 0x800 / 4,
+    ANALOG_MAX,
+};
+
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
+
+struct IMX8MPAnalogState {
+    SysBusDevice parent_obj;
+
+    struct {
+        MemoryRegion container;
+        MemoryRegion analog;
+    } mmio;
+
+    uint32_t analog[ANALOG_MAX];
+};
+
+#endif /* IMX8MP_ANALOG_H */
diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
new file mode 100644
index 0000000000..685c8582ff
--- /dev/null
+++ b/include/hw/misc/imx8mp_ccm.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX 8M Plus CCM IP block emulation code
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IMX8MP_CCM_H
+#define IMX8MP_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
+
+enum IMX8MPCCMRegisters {
+    CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
+};
+
+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
+
+struct IMX8MPCCMState {
+    IMXCCMState parent_obj;
+
+    MemoryRegion iomem;
+
+    uint32_t ccm[CCM_MAX];
+};
+
+#endif /* IMX8MP_CCM_H */
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 0836d82ca0..a1a8843b3b 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -200,6 +200,10 @@ static void fsl_imx8mp_init(Object *obj)
 
     object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
 
+    object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
+
+    object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
+
     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
         snprintf(name, NAME_SIZE, "uart%d", i + 1);
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
@@ -308,6 +312,20 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         }
     }
 
+    /* CCM */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
+
+    /* Analog */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
+
     /* UARTs */
     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
         static const struct {
@@ -333,6 +351,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
         switch (i) {
+        case FSL_IMX8MP_ANA_PLL:
+        case FSL_IMX8MP_CCM:
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
         case FSL_IMX8MP_RAM:
diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
new file mode 100644
index 0000000000..71333b3e9e
--- /dev/null
+++ b/hw/misc/imx8mp_analog.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX 8M Plus ANALOG IP block emulation code
+ *
+ * Based on hw/misc/imx7_ccm.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx8mp_analog.h"
+#include "migration/vmstate.h"
+
+#define ANALOG_PLL_LOCK BIT(31)
+
+static void imx8mp_analog_reset(DeviceState *dev)
+{
+    IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
+
+    memset(s->analog, 0, sizeof(s->analog));
+
+    s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
+    s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
+    s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
+    s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
+    s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
+    s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
+    s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
+    s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
+    s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
+    s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
+    s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
+    s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
+    s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
+    s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
+    s->analog[ANALOG_DIGPROG] = 0x00824010;
+
+    /* all PLLs need to be locked */
+    s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
+}
+
+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
+{
+    IMX8MPAnalogState *s = opaque;
+
+    return s->analog[offset >> 2];
+}
+
+static void imx8mp_analog_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    IMX8MPAnalogState *s = opaque;
+
+    if (offset >> 2 == ANALOG_DIGPROG) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "Guest write to read-only ANALOG_DIGPROG register\n");
+    } else {
+        s->analog[offset >> 2] = value;
+    }
+}
+
+static const struct MemoryRegionOps imx8mp_analog_ops = {
+    .read = imx8mp_analog_read,
+    .write = imx8mp_analog_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+};
+
+static void imx8mp_analog_init(Object *obj)
+{
+    IMX8MPAnalogState *s = IMX8MP_ANALOG(obj);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_ANALOG, 0x10000);
+
+    memory_region_init_io(&s->mmio.analog, obj, &imx8mp_analog_ops, s,
+                          TYPE_IMX8MP_ANALOG, sizeof(s->analog));
+    memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
+
+    sysbus_init_mmio(sd, &s->mmio.container);
+}
+
+static const VMStateDescription vmstate_imx8mp_analog = {
+    .name = TYPE_IMX8MP_ANALOG,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(analog, IMX8MPAnalogState, ANALOG_MAX),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void imx8mp_analog_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    device_class_set_legacy_reset(dc, imx8mp_analog_reset);
+    dc->vmsd  = &vmstate_imx8mp_analog;
+    dc->desc  = "i.MX 8M Plus Analog Module";
+}
+
+static const TypeInfo imx8mp_ccm_types[] = {
+    {
+        .name          = TYPE_IMX8MP_ANALOG,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(IMX8MPAnalogState),
+        .instance_init = imx8mp_analog_init,
+        .class_init    = imx8mp_analog_class_init,
+    }
+};
+
+DEFINE_TYPES(imx8mp_ccm_types);
diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
new file mode 100644
index 0000000000..7c869ff86b
--- /dev/null
+++ b/hw/misc/imx8mp_ccm.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX 8M Plus CCM IP block emulation code
+ *
+ * Based on hw/misc/imx7_ccm.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx8mp_ccm.h"
+#include "migration/vmstate.h"
+
+#include "trace.h"
+
+#define CKIH_FREQ 16000000 /* 16MHz crystal input */
+
+static void imx8mp_ccm_reset(DeviceState *dev)
+{
+    IMX8MPCCMState *s = IMX8MP_CCM(dev);
+
+    memset(s->ccm, 0, sizeof(s->ccm));
+}
+
+#define CCM_INDEX(offset)   (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset)   ((offset) & (hwaddr)0xF)
+
+enum {
+    CCM_BITOP_NONE = 0x00,
+    CCM_BITOP_SET  = 0x04,
+    CCM_BITOP_CLR  = 0x08,
+    CCM_BITOP_TOG  = 0x0C,
+};
+
+static uint64_t imx8mp_set_clr_tog_read(void *opaque, hwaddr offset,
+                                        unsigned size)
+{
+    const uint32_t *mmio = opaque;
+
+    return mmio[CCM_INDEX(offset)];
+}
+
+static void imx8mp_set_clr_tog_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    const uint8_t  bitop = CCM_BITOP(offset);
+    const uint32_t index = CCM_INDEX(offset);
+    uint32_t *mmio = opaque;
+
+    switch (bitop) {
+    case CCM_BITOP_NONE:
+        mmio[index]  = value;
+        break;
+    case CCM_BITOP_SET:
+        mmio[index] |= value;
+        break;
+    case CCM_BITOP_CLR:
+        mmio[index] &= ~value;
+        break;
+    case CCM_BITOP_TOG:
+        mmio[index] ^= value;
+        break;
+    };
+}
+
+static const struct MemoryRegionOps imx8mp_set_clr_tog_ops = {
+    .read = imx8mp_set_clr_tog_read,
+    .write = imx8mp_set_clr_tog_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        /*
+         * Our device would not work correctly if the guest was doing
+         * unaligned access. This might not be a limitation on the real
+         * device but in practice there is no reason for a guest to access
+         * this device unaligned.
+         */
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+};
+
+static void imx8mp_ccm_init(Object *obj)
+{
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    IMX8MPCCMState *s = IMX8MP_CCM(obj);
+
+    memory_region_init_io(&s->iomem,
+                          obj,
+                          &imx8mp_set_clr_tog_ops,
+                          s->ccm,
+                          TYPE_IMX8MP_CCM ".ccm",
+                          sizeof(s->ccm));
+
+    sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx8mp_ccm = {
+    .name = TYPE_IMX8MP_CCM,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(ccm, IMX8MPCCMState, CCM_MAX),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static uint32_t imx8mp_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+    /*
+     * This function is "consumed" by GPT emulation code. Some clocks
+     * have fixed frequencies and we can provide requested frequency
+     * easily. However for CCM provided clocks (like IPG) each GPT
+     * timer can have its own clock root.
+     * This means we need additional information when calling this
+     * function to know the requester's identity.
+     */
+    uint32_t freq = 0;
+
+    switch (clock) {
+    case CLK_NONE:
+        break;
+    case CLK_32k:
+        freq = CKIL_FREQ;
+        break;
+    case CLK_HIGH:
+        freq = CKIH_FREQ;
+        break;
+    case CLK_IPG:
+    case CLK_IPG_HIGH:
+        /*
+         * For now we don't have a way to figure out the device this
+         * function is called for. Until then the IPG derived clocks
+         * are left unimplemented.
+         */
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n",
+                      TYPE_IMX8MP_CCM, __func__, clock);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
+                      TYPE_IMX8MP_CCM, __func__, clock);
+        break;
+    }
+
+    trace_ccm_clock_freq(clock, freq);
+
+    return freq;
+}
+
+static void imx8mp_ccm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
+
+    device_class_set_legacy_reset(dc, imx8mp_ccm_reset);
+    dc->vmsd  = &vmstate_imx8mp_ccm;
+    dc->desc  = "i.MX 8M Plus Clock Control Module";
+
+    ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
+}
+
+static const TypeInfo imx8mp_ccm_types[] = {
+    {
+        .name          = TYPE_IMX8MP_CCM,
+        .parent        = TYPE_IMX_CCM,
+        .instance_size = sizeof(IMX8MPCCMState),
+        .instance_init = imx8mp_ccm_init,
+        .class_init    = imx8mp_ccm_class_init,
+    },
+};
+
+DEFINE_TYPES(imx8mp_ccm_types);
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index e22916df57..0079c51734 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -580,6 +580,8 @@ config FSL_IMX7
 config FSL_IMX8MP
     bool
     select ARM_GIC
+    select FSL_IMX8MP_ANALOG
+    select FSL_IMX8MP_CCM
     select IMX
     select UNIMP
 
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 4271e2f4ac..82bd68b4bb 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -78,6 +78,12 @@ config IMX
     select SSI
     select USB_EHCI_SYSBUS
 
+config FSL_IMX8MP_ANALOG
+    bool
+
+config FSL_IMX8MP_CCM
+    bool
+
 config STM32_RCC
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 55f493521b..f9285cf2f1 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -55,6 +55,8 @@ system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
 system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
 system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
 system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
 system_ss.add(when: 'CONFIG_IMX', if_true: files(
   'imx25_ccm.c',
   'imx31_ccm.c',
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 06/18] hw/arm/fsl-imx8mp: Add SNVS
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (4 preceding siblings ...)
  2025-02-04  9:20 ` [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-04  9:21 ` [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

SNVS contains an RTC which allows Linux to deal correctly with time. This is
particularly useful when handling persistent storage which will be done in the
next patch.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    |  2 ++
 hw/arm/fsl-imx8mp.c            | 10 ++++++++++
 3 files changed, 13 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index e5039fc8c4..8f1237c74e 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -13,6 +13,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * Up to 4 Cortex-A53 Cores
  * Generic Interrupt Controller (GICv3)
  * 4 UARTs
+ * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
 Boot options
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index ce5188e7f2..26e24e99a1 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -12,6 +12,7 @@
 #include "cpu.h"
 #include "hw/char/imx_serial.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
 #include "hw/misc/imx8mp_ccm.h"
 #include "qom/object.h"
@@ -36,6 +37,7 @@ struct FslImx8mpState {
     GICv3State         gic;
     IMX8MPCCMState     ccm;
     IMX8MPAnalogState  analog;
+    IMX7SNVSState      snvs;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
 };
 
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index a1a8843b3b..32ca76c671 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -204,6 +204,8 @@ static void fsl_imx8mp_init(Object *obj)
 
     object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
 
+    object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
+
     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
         snprintf(name, NAME_SIZE, "uart%d", i + 1);
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
@@ -348,6 +350,13 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, serial_table[i].irq));
     }
 
+    /* SNVS */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
+
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
         switch (i) {
@@ -356,6 +365,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
         case FSL_IMX8MP_RAM:
+        case FSL_IMX8MP_SNVS_HP:
         case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
             /* device implemented and treated above */
             break;
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (5 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 06/18] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:25   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

The USDHC emulation allows for running real-world images such as those generated
by Buildroot. Convert the board documentation accordingly instead of running a
Linux kernel with ephemeral storage.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst | 16 +++++++++++-----
 include/hw/arm/fsl-imx8mp.h    |  7 +++++++
 hw/arm/fsl-imx8mp.c            | 28 ++++++++++++++++++++++++++++
 hw/arm/imx8mp-evk.c            | 18 ++++++++++++++++++
 hw/arm/Kconfig                 |  1 +
 5 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 8f1237c74e..475c42d76a 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -13,6 +13,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * Up to 4 Cortex-A53 Cores
  * Generic Interrupt Controller (GICv3)
  * 4 UARTs
+ * 3 USDHC Storage Controllers
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
@@ -27,17 +28,22 @@ Direct Linux Kernel Boot
 
 Probably the easiest way to get started with a whole Linux system on the machine
 is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
-of writing and involves two steps. First run the following commands in the
+of writing and involves three steps. First run the following commands in the
 toplevel directory of the Buildroot source tree:
 
 .. code-block:: bash
 
-  $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
   $ make freescale_imx8mpevk_defconfig
   $ make
 
 Once finished successfully there is an ``output/image`` subfolder. Navigate into
-it patch the device tree needs to be patched with the following commands which
+it and resize the SD card image to a power of two:
+
+.. code-block:: bash
+
+  $ qemu-img resize sdcard.img 256M
+
+Finally, the device tree needs to be patched with the following commands which
 will remove the ``cpu-idle-states`` properties from CPU nodes:
 
 .. code-block:: bash
@@ -54,5 +60,5 @@ Now that everything is prepared the newly built image can be run in the QEMU
       -display none -serial null -serial stdio \
       -kernel Image \
       -dtb imx8mp-evk-patched.dtb \
-      -initrd rootfs.cpio \
-      -append "root=/dev/ram"
+      -append "root=/dev/mmcblk2p2" \
+      -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 26e24e99a1..349d55ca88 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -15,6 +15,7 @@
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
 #include "hw/misc/imx8mp_ccm.h"
+#include "hw/sd/sdhci.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -28,6 +29,7 @@ enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_CPUS         = 4,
     FSL_IMX8MP_NUM_IRQS         = 160,
     FSL_IMX8MP_NUM_UARTS        = 4,
+    FSL_IMX8MP_NUM_USDHCS       = 3,
 };
 
 struct FslImx8mpState {
@@ -39,6 +41,7 @@ struct FslImx8mpState {
     IMX8MPAnalogState  analog;
     IMX7SNVSState      snvs;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
+    SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
 };
 
 enum FslImx8mpMemoryRegions {
@@ -184,6 +187,10 @@ enum FslImx8mpMemoryRegions {
 };
 
 enum FslImx8mpIrqs {
+    FSL_IMX8MP_USDHC1_IRQ   = 22,
+    FSL_IMX8MP_USDHC2_IRQ   = 23,
+    FSL_IMX8MP_USDHC3_IRQ   = 24,
+
     FSL_IMX8MP_UART1_IRQ    = 26,
     FSL_IMX8MP_UART2_IRQ    = 27,
     FSL_IMX8MP_UART3_IRQ    = 28,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 32ca76c671..3e9fedf988 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -210,6 +210,11 @@ static void fsl_imx8mp_init(Object *obj)
         snprintf(name, NAME_SIZE, "uart%d", i + 1);
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
     }
+
+    for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
+        snprintf(name, NAME_SIZE, "usdhc%d", i + 1);
+        object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
+    }
 }
 
 static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
@@ -350,6 +355,28 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, serial_table[i].irq));
     }
 
+    /* USDHCs */
+    for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } usdhc_table[FSL_IMX8MP_NUM_USDHCS] = {
+            { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC1].addr, FSL_IMX8MP_USDHC1_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC2].addr, FSL_IMX8MP_USDHC2_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC3].addr, FSL_IMX8MP_USDHC3_IRQ },
+        };
+
+        object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
+                                 SDHCI_VENDOR_IMX, &error_abort);
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
+                           qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
+    }
+
     /* SNVS */
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
         return;
@@ -367,6 +394,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_RAM:
         case FSL_IMX8MP_SNVS_HP:
         case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
+        case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
             /* device implemented and treated above */
             break;
 
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
index 2756d4c21c..27d9e9e8ee 100644
--- a/hw/arm/imx8mp-evk.c
+++ b/hw/arm/imx8mp-evk.c
@@ -11,6 +11,7 @@
 #include "hw/arm/boot.h"
 #include "hw/arm/fsl-imx8mp.h"
 #include "hw/boards.h"
+#include "hw/qdev-properties.h"
 #include "system/qtest.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
@@ -40,6 +41,23 @@ static void imx8mp_evk_init(MachineState *machine)
     memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
                                 machine->ram);
 
+    for (int i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
+        BusState *bus;
+        DeviceState *carddev;
+        BlockBackend *blk;
+        DriveInfo *di = drive_get(IF_SD, i, 0);
+
+        if (!di) {
+            continue;
+        }
+
+        blk = blk_by_legacy_dinfo(di);
+        bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
+        carddev = qdev_new(TYPE_SD_CARD);
+        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
+        qdev_realize_and_unref(carddev, bus, &error_fatal);
+    }
+
     if (!qtest_enabled()) {
         arm_load_kernel(&s->cpu[0], machine, &boot_info);
     }
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 0079c51734..7af8337354 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -583,6 +583,7 @@ config FSL_IMX8MP
     select FSL_IMX8MP_ANALOG
     select FSL_IMX8MP_CCM
     select IMX
+    select SDHCI
     select UNIMP
 
 config FSL_IMX8MP_EVK
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (6 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-17 13:40   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 09/18] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Linux checks for the PLLs in the PHY to be locked, so implement a model
emulating that.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 MAINTAINERS                         |  2 +
 docs/system/arm/imx8mp-evk.rst      |  1 +
 include/hw/arm/fsl-imx8mp.h         | 10 ++++
 include/hw/pci-host/fsl_imx8m_phy.h | 27 +++++++++
 hw/arm/fsl-imx8mp.c                 | 30 ++++++++++
 hw/pci-host/fsl_imx8m_phy.c         | 88 +++++++++++++++++++++++++++++
 hw/arm/Kconfig                      |  3 +
 hw/pci-host/Kconfig                 |  3 +
 hw/pci-host/meson.build             |  1 +
 9 files changed, 165 insertions(+)
 create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
 create mode 100644 hw/pci-host/fsl_imx8m_phy.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 5b5b0d0bed..94af3d90e4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -827,8 +827,10 @@ S: Maintained
 F: hw/arm/imx8mp-evk.c
 F: hw/arm/fsl-imx8mp.c
 F: hw/misc/imx8mp_*.c
+F: hw/pci-host/fsl_imx8m_phy.c
 F: include/hw/arm/fsl-imx8mp.h
 F: include/hw/misc/imx8mp_*.h
+F: include/hw/pci-host/fsl_imx8m_phy.h
 F: docs/system/arm/imx8mp-evk.rst
 
 MPS2 / MPS3
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 475c42d76a..39df695df7 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -14,6 +14,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * Generic Interrupt Controller (GICv3)
  * 4 UARTs
  * 3 USDHC Storage Controllers
+ * 1 Designware PCI Express Controller
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 349d55ca88..4c70c887a8 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -15,6 +15,8 @@
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
 #include "hw/misc/imx8mp_ccm.h"
+#include "hw/pci-host/designware.h"
+#include "hw/pci-host/fsl_imx8m_phy.h"
 #include "hw/sd/sdhci.h"
 #include "qom/object.h"
 #include "qemu/units.h"
@@ -42,6 +44,8 @@ struct FslImx8mpState {
     IMX7SNVSState      snvs;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
+    DesignwarePCIEHost pcie;
+    FslImx8mPciePhyState   pcie_phy;
 };
 
 enum FslImx8mpMemoryRegions {
@@ -197,6 +201,12 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_UART4_IRQ    = 29,
     FSL_IMX8MP_UART5_IRQ    = 30,
     FSL_IMX8MP_UART6_IRQ    = 16,
+
+    FSL_IMX8MP_PCI_INTA_IRQ = 126,
+    FSL_IMX8MP_PCI_INTB_IRQ = 125,
+    FSL_IMX8MP_PCI_INTC_IRQ = 124,
+    FSL_IMX8MP_PCI_INTD_IRQ = 123,
+    FSL_IMX8MP_PCI_MSI_IRQ  = 140,
 };
 
 #endif /* FSL_IMX8MP_H */
diff --git a/include/hw/pci-host/fsl_imx8m_phy.h b/include/hw/pci-host/fsl_imx8m_phy.h
new file mode 100644
index 0000000000..385a904fff
--- /dev/null
+++ b/include/hw/pci-host/fsl_imx8m_phy.h
@@ -0,0 +1,27 @@
+/*
+ * i.MX8 PCIe PHY emulation
+ *
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_PCIHOST_FSLIMX8MPCIEPHY_H
+#define HW_PCIHOST_FSLIMX8MPCIEPHY_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "exec/memory.h"
+
+#define TYPE_FSL_IMX8M_PCIE_PHY "fsl-imx8m-pcie-phy"
+
+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mPciePhyState, FSL_IMX8M_PCIE_PHY)
+
+struct FslImx8mPciePhyState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+    uint8_t data[0x800];
+};
+
+#endif
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 3e9fedf988..faa6ada183 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -215,6 +215,10 @@ static void fsl_imx8mp_init(Object *obj)
         snprintf(name, NAME_SIZE, "usdhc%d", i + 1);
         object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
     }
+
+    object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+    object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
+                            TYPE_FSL_IMX8M_PCIE_PHY);
 }
 
 static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
@@ -384,6 +388,30 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
                     fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
 
+    /* PCIe */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_PCIE1].addr);
+
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0,
+                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTA_IRQ));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1,
+                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTB_IRQ));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2,
+                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTC_IRQ));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3,
+                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTD_IRQ));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4,
+                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_MSI_IRQ));
+
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
+
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
         switch (i) {
@@ -391,6 +419,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_CCM:
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
+        case FSL_IMX8MP_PCIE1:
+        case FSL_IMX8MP_PCIE_PHY1:
         case FSL_IMX8MP_RAM:
         case FSL_IMX8MP_SNVS_HP:
         case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
diff --git a/hw/pci-host/fsl_imx8m_phy.c b/hw/pci-host/fsl_imx8m_phy.c
new file mode 100644
index 0000000000..2f70e15c91
--- /dev/null
+++ b/hw/pci-host/fsl_imx8m_phy.c
@@ -0,0 +1,88 @@
+/*
+ * i.MX8 PCIe PHY emulation
+ *
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/pci-host/fsl_imx8m_phy.h"
+#include "migration/vmstate.h"
+
+#define CMN_REG075 0x1d4
+#define ANA_PLL_LOCK_DONE BIT(1)
+#define ANA_PLL_AFC_DONE BIT(0)
+
+static uint64_t fsl_imx8m_pcie_phy_read(void *opaque, hwaddr offset,
+                                        unsigned size)
+{
+    FslImx8mPciePhyState *s = opaque;
+
+    if (offset == CMN_REG075) {
+        return s->data[offset] | ANA_PLL_LOCK_DONE | ANA_PLL_AFC_DONE;
+    }
+
+    return s->data[offset];
+}
+
+static void fsl_imx8m_pcie_phy_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    FslImx8mPciePhyState *s = opaque;
+
+    s->data[offset] = value;
+}
+
+static const MemoryRegionOps fsl_imx8m_pcie_phy_ops = {
+    .read = fsl_imx8m_pcie_phy_read,
+    .write = fsl_imx8m_pcie_phy_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void fsl_imx8m_pcie_phy_realize(DeviceState *dev, Error **errp)
+{
+    FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &fsl_imx8m_pcie_phy_ops, s,
+                          TYPE_FSL_IMX8M_PCIE_PHY, ARRAY_SIZE(s->data));
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+}
+
+static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
+    .name = "fsl-imx8m-pcie-phy",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
+                            ARRAY_SIZE(((FslImx8mPciePhyState *)NULL)->data)),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = fsl_imx8m_pcie_phy_realize;
+    dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
+}
+
+static const TypeInfo fsl_imx8m_pcie_phy_types[] = {
+    {
+        .name = TYPE_FSL_IMX8M_PCIE_PHY,
+        .parent = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(FslImx8mPciePhyState),
+        .class_init = fsl_imx8m_pcie_phy_class_init,
+    }
+};
+
+DEFINE_TYPES(fsl_imx8m_pcie_phy_types)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7af8337354..f1e140a29d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -579,10 +579,13 @@ config FSL_IMX7
 
 config FSL_IMX8MP
     bool
+    imply PCI_DEVICES
     select ARM_GIC
     select FSL_IMX8MP_ANALOG
     select FSL_IMX8MP_CCM
     select IMX
+    select PCI_EXPRESS_DESIGNWARE
+    select PCI_EXPRESS_FSL_IMX8M_PHY
     select SDHCI
     select UNIMP
 
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
index c91880b237..35c0415242 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -99,6 +99,9 @@ config ASTRO
     bool
     select PCI
 
+config PCI_EXPRESS_FSL_IMX8M_PHY
+    bool
+
 config GT64120
     bool
     select PCI
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
index 3001e93a43..937a0f72ac 100644
--- a/hw/pci-host/meson.build
+++ b/hw/pci-host/meson.build
@@ -28,6 +28,7 @@ pci_ss.add(when: 'CONFIG_ARTICIA', if_true: files('articia.c'))
 pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
 
 # ARM devices
+pci_ss.add(when: 'CONFIG_PCI_EXPRESS_FSL_IMX8M_PHY', if_true: files('fsl_imx8m_phy.c'))
 pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
 
 # HPPA devices
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 09/18] hw/arm/fsl-imx8mp: Add GPIO controllers
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (7 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:26   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 10/18] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    | 14 +++++++++
 hw/arm/fsl-imx8mp.c            | 55 ++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 39df695df7..a89aad6f92 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -15,6 +15,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 4 UARTs
  * 3 USDHC Storage Controllers
  * 1 Designware PCI Express Controller
+ * 5 GPIO Controllers
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 4c70c887a8..18ea52d083 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -11,6 +11,7 @@
 
 #include "cpu.h"
 #include "hw/char/imx_serial.h"
+#include "hw/gpio/imx_gpio.h"
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
@@ -29,6 +30,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
 
 enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_CPUS         = 4,
+    FSL_IMX8MP_NUM_GPIOS        = 5,
     FSL_IMX8MP_NUM_IRQS         = 160,
     FSL_IMX8MP_NUM_UARTS        = 4,
     FSL_IMX8MP_NUM_USDHCS       = 3,
@@ -39,6 +41,7 @@ struct FslImx8mpState {
 
     ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
     GICv3State         gic;
+    IMXGPIOState       gpio[FSL_IMX8MP_NUM_GPIOS];
     IMX8MPCCMState     ccm;
     IMX8MPAnalogState  analog;
     IMX7SNVSState      snvs;
@@ -202,6 +205,17 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_UART5_IRQ    = 30,
     FSL_IMX8MP_UART6_IRQ    = 16,
 
+    FSL_IMX8MP_GPIO1_LOW_IRQ  = 64,
+    FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
+    FSL_IMX8MP_GPIO2_LOW_IRQ  = 66,
+    FSL_IMX8MP_GPIO2_HIGH_IRQ = 67,
+    FSL_IMX8MP_GPIO3_LOW_IRQ  = 68,
+    FSL_IMX8MP_GPIO3_HIGH_IRQ = 69,
+    FSL_IMX8MP_GPIO4_LOW_IRQ  = 70,
+    FSL_IMX8MP_GPIO4_HIGH_IRQ = 71,
+    FSL_IMX8MP_GPIO5_LOW_IRQ  = 72,
+    FSL_IMX8MP_GPIO5_HIGH_IRQ = 73,
+
     FSL_IMX8MP_PCI_INTA_IRQ = 126,
     FSL_IMX8MP_PCI_INTB_IRQ = 125,
     FSL_IMX8MP_PCI_INTC_IRQ = 124,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index faa6ada183..13910dc44a 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -211,6 +211,11 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
+        snprintf(name, NAME_SIZE, "gpio%d", i + 1);
+        object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
+    }
+
     for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
         snprintf(name, NAME_SIZE, "usdhc%d", i + 1);
         object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
@@ -359,6 +364,55 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, serial_table[i].irq));
     }
 
+    /* GPIOs */
+    for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq_low;
+            unsigned int irq_high;
+        } gpio_table[FSL_IMX8MP_NUM_GPIOS] = {
+            {
+                fsl_imx8mp_memmap[FSL_IMX8MP_GPIO1].addr,
+                FSL_IMX8MP_GPIO1_LOW_IRQ,
+                FSL_IMX8MP_GPIO1_HIGH_IRQ
+            },
+            {
+                fsl_imx8mp_memmap[FSL_IMX8MP_GPIO2].addr,
+                FSL_IMX8MP_GPIO2_LOW_IRQ,
+                FSL_IMX8MP_GPIO2_HIGH_IRQ
+            },
+            {
+                fsl_imx8mp_memmap[FSL_IMX8MP_GPIO3].addr,
+                FSL_IMX8MP_GPIO3_LOW_IRQ,
+                FSL_IMX8MP_GPIO3_HIGH_IRQ
+            },
+            {
+                fsl_imx8mp_memmap[FSL_IMX8MP_GPIO4].addr,
+                FSL_IMX8MP_GPIO4_LOW_IRQ,
+                FSL_IMX8MP_GPIO4_HIGH_IRQ
+            },
+            {
+                fsl_imx8mp_memmap[FSL_IMX8MP_GPIO5].addr,
+                FSL_IMX8MP_GPIO5_LOW_IRQ,
+                FSL_IMX8MP_GPIO5_HIGH_IRQ
+            },
+        };
+
+        object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
+                                 &error_abort);
+        object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq",
+                                 true, &error_abort);
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
+                           qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
+                           qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
+    }
+
     /* USDHCs */
     for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
         static const struct {
@@ -419,6 +473,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_CCM:
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
+        case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
         case FSL_IMX8MP_PCIE1:
         case FSL_IMX8MP_PCIE_PHY1:
         case FSL_IMX8MP_RAM:
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 10/18] hw/arm/fsl-imx8mp: Add I2C controllers
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (8 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 09/18] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:26   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 11/18] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    | 11 +++++++++++
 hw/arm/fsl-imx8mp.c            | 29 +++++++++++++++++++++++++++++
 hw/arm/Kconfig                 |  2 ++
 4 files changed, 43 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index a89aad6f92..e63c5b7118 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -16,6 +16,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 3 USDHC Storage Controllers
  * 1 Designware PCI Express Controller
  * 5 GPIO Controllers
+ * 6 I2C Controllers
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 18ea52d083..2590056627 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -12,6 +12,7 @@
 #include "cpu.h"
 #include "hw/char/imx_serial.h"
 #include "hw/gpio/imx_gpio.h"
+#include "hw/i2c/imx_i2c.h"
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
@@ -31,6 +32,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
 enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_CPUS         = 4,
     FSL_IMX8MP_NUM_GPIOS        = 5,
+    FSL_IMX8MP_NUM_I2CS         = 6,
     FSL_IMX8MP_NUM_IRQS         = 160,
     FSL_IMX8MP_NUM_UARTS        = 4,
     FSL_IMX8MP_NUM_USDHCS       = 3,
@@ -45,6 +47,7 @@ struct FslImx8mpState {
     IMX8MPCCMState     ccm;
     IMX8MPAnalogState  analog;
     IMX7SNVSState      snvs;
+    IMXI2CState        i2c[FSL_IMX8MP_NUM_I2CS];
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
     DesignwarePCIEHost pcie;
@@ -205,6 +208,11 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_UART5_IRQ    = 30,
     FSL_IMX8MP_UART6_IRQ    = 16,
 
+    FSL_IMX8MP_I2C1_IRQ     = 35,
+    FSL_IMX8MP_I2C2_IRQ     = 36,
+    FSL_IMX8MP_I2C3_IRQ     = 37,
+    FSL_IMX8MP_I2C4_IRQ     = 38,
+
     FSL_IMX8MP_GPIO1_LOW_IRQ  = 64,
     FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
     FSL_IMX8MP_GPIO2_LOW_IRQ  = 66,
@@ -216,6 +224,9 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_GPIO5_LOW_IRQ  = 72,
     FSL_IMX8MP_GPIO5_HIGH_IRQ = 73,
 
+    FSL_IMX8MP_I2C5_IRQ     = 76,
+    FSL_IMX8MP_I2C6_IRQ     = 77,
+
     FSL_IMX8MP_PCI_INTA_IRQ = 126,
     FSL_IMX8MP_PCI_INTB_IRQ = 125,
     FSL_IMX8MP_PCI_INTC_IRQ = 124,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 13910dc44a..1971c76aaa 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -211,6 +211,11 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
+        snprintf(name, NAME_SIZE, "i2c%d", i + 1);
+        object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
+    }
+
     for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
         snprintf(name, NAME_SIZE, "gpio%d", i + 1);
         object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
@@ -364,6 +369,29 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, serial_table[i].irq));
     }
 
+    /* I2Cs */
+    for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } i2c_table[FSL_IMX8MP_NUM_I2CS] = {
+            { fsl_imx8mp_memmap[FSL_IMX8MP_I2C1].addr, FSL_IMX8MP_I2C1_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_I2C2].addr, FSL_IMX8MP_I2C2_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_I2C3].addr, FSL_IMX8MP_I2C3_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_I2C4].addr, FSL_IMX8MP_I2C4_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_I2C5].addr, FSL_IMX8MP_I2C5_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_I2C6].addr, FSL_IMX8MP_I2C6_IRQ },
+        };
+
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
+                           qdev_get_gpio_in(gicdev, i2c_table[i].irq));
+    }
+
     /* GPIOs */
     for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
         static const struct {
@@ -474,6 +502,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
         case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
+        case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
         case FSL_IMX8MP_PCIE1:
         case FSL_IMX8MP_PCIE_PHY1:
         case FSL_IMX8MP_RAM:
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index f1e140a29d..4a8695f22a 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -579,11 +579,13 @@ config FSL_IMX7
 
 config FSL_IMX8MP
     bool
+    imply I2C_DEVICES
     imply PCI_DEVICES
     select ARM_GIC
     select FSL_IMX8MP_ANALOG
     select FSL_IMX8MP_CCM
     select IMX
+    select IMX_I2C
     select PCI_EXPRESS_DESIGNWARE
     select PCI_EXPRESS_FSL_IMX8M_PHY
     select SDHCI
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 11/18] hw/arm/fsl-imx8mp: Add SPI controllers
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (9 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 10/18] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:26   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 12/18] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    |  8 ++++++++
 hw/arm/fsl-imx8mp.c            | 26 ++++++++++++++++++++++++++
 3 files changed, 35 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index e63c5b7118..eb7df2059f 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -17,6 +17,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 1 Designware PCI Express Controller
  * 5 GPIO Controllers
  * 6 I2C Controllers
+ * 3 SPI Controllers
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 2590056627..296a87eb50 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -20,6 +20,7 @@
 #include "hw/pci-host/designware.h"
 #include "hw/pci-host/fsl_imx8m_phy.h"
 #include "hw/sd/sdhci.h"
+#include "hw/ssi/imx_spi.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -31,6 +32,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
 
 enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_CPUS         = 4,
+    FSL_IMX8MP_NUM_ECSPIS       = 3,
     FSL_IMX8MP_NUM_GPIOS        = 5,
     FSL_IMX8MP_NUM_I2CS         = 6,
     FSL_IMX8MP_NUM_IRQS         = 160,
@@ -47,6 +49,7 @@ struct FslImx8mpState {
     IMX8MPCCMState     ccm;
     IMX8MPAnalogState  analog;
     IMX7SNVSState      snvs;
+    IMXSPIState        spi[FSL_IMX8MP_NUM_ECSPIS];
     IMXI2CState        i2c[FSL_IMX8MP_NUM_I2CS];
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
@@ -208,6 +211,11 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_UART5_IRQ    = 30,
     FSL_IMX8MP_UART6_IRQ    = 16,
 
+    FSL_IMX8MP_ECSPI1_IRQ   = 31,
+    FSL_IMX8MP_ECSPI2_IRQ   = 32,
+    FSL_IMX8MP_ECSPI3_IRQ   = 33,
+    FSL_IMX8MP_ECSPI4_IRQ   = 34,
+
     FSL_IMX8MP_I2C1_IRQ     = 35,
     FSL_IMX8MP_I2C2_IRQ     = 36,
     FSL_IMX8MP_I2C3_IRQ     = 37,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 1971c76aaa..fa39dfd2da 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -226,6 +226,11 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
+        snprintf(name, NAME_SIZE, "spi%d", i + 1);
+        object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
+    }
+
     object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
     object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
                             TYPE_FSL_IMX8M_PCIE_PHY);
@@ -463,6 +468,26 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
     }
 
+    /* ECSPIs */
+    for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } spi_table[FSL_IMX8MP_NUM_ECSPIS] = {
+            { fsl_imx8mp_memmap[FSL_IMX8MP_ECSPI1].addr, FSL_IMX8MP_ECSPI1_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_ECSPI2].addr, FSL_IMX8MP_ECSPI2_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_ECSPI3].addr, FSL_IMX8MP_ECSPI3_IRQ },
+        };
+
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
+                           qdev_get_gpio_in(gicdev, spi_table[i].irq));
+    }
+
     /* SNVS */
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
         return;
@@ -502,6 +527,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
         case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
+        case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
         case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
         case FSL_IMX8MP_PCIE1:
         case FSL_IMX8MP_PCIE_PHY1:
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 12/18] hw/arm/fsl-imx8mp: Add watchdog support
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (10 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 11/18] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:27   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    |  7 +++++++
 hw/arm/fsl-imx8mp.c            | 28 ++++++++++++++++++++++++++++
 hw/arm/Kconfig                 |  1 +
 4 files changed, 37 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index eb7df2059f..15514055b5 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -18,6 +18,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 5 GPIO Controllers
  * 6 I2C Controllers
  * 3 SPI Controllers
+ * 3 Watchdogs
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 296a87eb50..dfbdc6ac7f 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -21,6 +21,7 @@
 #include "hw/pci-host/fsl_imx8m_phy.h"
 #include "hw/sd/sdhci.h"
 #include "hw/ssi/imx_spi.h"
+#include "hw/watchdog/wdt_imx2.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -38,6 +39,7 @@ enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_IRQS         = 160,
     FSL_IMX8MP_NUM_UARTS        = 4,
     FSL_IMX8MP_NUM_USDHCS       = 3,
+    FSL_IMX8MP_NUM_WDTS         = 3,
 };
 
 struct FslImx8mpState {
@@ -53,6 +55,7 @@ struct FslImx8mpState {
     IMXI2CState        i2c[FSL_IMX8MP_NUM_I2CS];
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
+    IMX2WdtState       wdt[FSL_IMX8MP_NUM_WDTS];
     DesignwarePCIEHost pcie;
     FslImx8mPciePhyState   pcie_phy;
 };
@@ -235,6 +238,10 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_I2C5_IRQ     = 76,
     FSL_IMX8MP_I2C6_IRQ     = 77,
 
+    FSL_IMX8MP_WDOG1_IRQ    = 78,
+    FSL_IMX8MP_WDOG2_IRQ    = 79,
+    FSL_IMX8MP_WDOG3_IRQ    = 10,
+
     FSL_IMX8MP_PCI_INTA_IRQ = 126,
     FSL_IMX8MP_PCI_INTB_IRQ = 125,
     FSL_IMX8MP_PCI_INTC_IRQ = 124,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index fa39dfd2da..6646f1c8b4 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -231,6 +231,11 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
+        snprintf(name, NAME_SIZE, "wdt%d", i);
+        object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
+    }
+
     object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
     object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
                             TYPE_FSL_IMX8M_PCIE_PHY);
@@ -495,6 +500,28 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
                     fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
 
+    /* Watchdogs */
+    for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } wdog_table[FSL_IMX8MP_NUM_WDTS] = {
+            { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG1].addr, FSL_IMX8MP_WDOG1_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG2].addr, FSL_IMX8MP_WDOG2_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG3].addr, FSL_IMX8MP_WDOG3_IRQ },
+        };
+
+        object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
+                                 true, &error_abort);
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
+                           qdev_get_gpio_in(gicdev, wdog_table[i].irq));
+    }
+
     /* PCIe */
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
         return;
@@ -535,6 +562,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_SNVS_HP:
         case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
         case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
+        case FSL_IMX8MP_WDOG1 ... FSL_IMX8MP_WDOG3:
             /* device implemented and treated above */
             break;
 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 4a8695f22a..71102ac0a9 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -590,6 +590,7 @@ config FSL_IMX8MP
     select PCI_EXPRESS_FSL_IMX8M_PHY
     select SDHCI
     select UNIMP
+    select WDT_IMX2
 
 config FSL_IMX8MP_EVK
     bool
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (11 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 12/18] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:29   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 14/18] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    | 11 +++++++
 include/hw/timer/imx_gpt.h     |  1 +
 hw/arm/fsl-imx8mp.c            | 53 ++++++++++++++++++++++++++++++++++
 hw/timer/imx_gpt.c             | 25 ++++++++++++++++
 hw/arm/Kconfig                 |  1 +
 6 files changed, 92 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 15514055b5..9293cabb85 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -19,6 +19,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 6 I2C Controllers
  * 3 SPI Controllers
  * 3 Watchdogs
+ * 6 General Purpose Timers
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index dfbdc6ac7f..975887751b 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -17,10 +17,12 @@
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
 #include "hw/misc/imx8mp_ccm.h"
+#include "hw/or-irq.h"
 #include "hw/pci-host/designware.h"
 #include "hw/pci-host/fsl_imx8m_phy.h"
 #include "hw/sd/sdhci.h"
 #include "hw/ssi/imx_spi.h"
+#include "hw/timer/imx_gpt.h"
 #include "hw/watchdog/wdt_imx2.h"
 #include "qom/object.h"
 #include "qemu/units.h"
@@ -35,6 +37,7 @@ enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_CPUS         = 4,
     FSL_IMX8MP_NUM_ECSPIS       = 3,
     FSL_IMX8MP_NUM_GPIOS        = 5,
+    FSL_IMX8MP_NUM_GPTS         = 6,
     FSL_IMX8MP_NUM_I2CS         = 6,
     FSL_IMX8MP_NUM_IRQS         = 160,
     FSL_IMX8MP_NUM_UARTS        = 4,
@@ -47,6 +50,7 @@ struct FslImx8mpState {
 
     ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
     GICv3State         gic;
+    IMXGPTState        gpt[FSL_IMX8MP_NUM_GPTS];
     IMXGPIOState       gpio[FSL_IMX8MP_NUM_GPIOS];
     IMX8MPCCMState     ccm;
     IMX8MPAnalogState  analog;
@@ -58,6 +62,7 @@ struct FslImx8mpState {
     IMX2WdtState       wdt[FSL_IMX8MP_NUM_WDTS];
     DesignwarePCIEHost pcie;
     FslImx8mPciePhyState   pcie_phy;
+    OrIRQState         gpt5_gpt6_irq;
 };
 
 enum FslImx8mpMemoryRegions {
@@ -224,6 +229,12 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_I2C3_IRQ     = 37,
     FSL_IMX8MP_I2C4_IRQ     = 38,
 
+    FSL_IMX8MP_GPT1_IRQ      = 55,
+    FSL_IMX8MP_GPT2_IRQ      = 54,
+    FSL_IMX8MP_GPT3_IRQ      = 53,
+    FSL_IMX8MP_GPT4_IRQ      = 52,
+    FSL_IMX8MP_GPT5_GPT6_IRQ = 51,
+
     FSL_IMX8MP_GPIO1_LOW_IRQ  = 64,
     FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
     FSL_IMX8MP_GPIO2_LOW_IRQ  = 66,
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
index 5a1230da35..5488f7e4df 100644
--- a/include/hw/timer/imx_gpt.h
+++ b/include/hw/timer/imx_gpt.h
@@ -80,6 +80,7 @@
 #define TYPE_IMX6_GPT "imx6.gpt"
 #define TYPE_IMX6UL_GPT "imx6ul.gpt"
 #define TYPE_IMX7_GPT "imx7.gpt"
+#define TYPE_IMX8MP_GPT "imx8mp.gpt"
 
 #define TYPE_IMX_GPT TYPE_IMX25_GPT
 
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 6646f1c8b4..43395df628 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -211,6 +211,13 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
+        snprintf(name, NAME_SIZE, "gpt%d", i + 1);
+        object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX8MP_GPT);
+    }
+    object_initialize_child(obj, "gpt5-gpt6-irq", &s->gpt5_gpt6_irq,
+                            TYPE_OR_IRQ);
+
     for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
         snprintf(name, NAME_SIZE, "i2c%d", i + 1);
         object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
@@ -379,6 +386,52 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, serial_table[i].irq));
     }
 
+    /* GPTs */
+    object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2,
+                            &error_abort);
+    if (!qdev_realize(DEVICE(&s->gpt5_gpt6_irq), NULL, errp)) {
+        return;
+    }
+
+    qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0,
+                          qdev_get_gpio_in(gicdev, FSL_IMX8MP_GPT5_GPT6_IRQ));
+
+    for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
+        static const hwaddr gpt_addrs[FSL_IMX8MP_NUM_GPTS] = {
+            fsl_imx8mp_memmap[FSL_IMX8MP_GPT1].addr,
+            fsl_imx8mp_memmap[FSL_IMX8MP_GPT2].addr,
+            fsl_imx8mp_memmap[FSL_IMX8MP_GPT3].addr,
+            fsl_imx8mp_memmap[FSL_IMX8MP_GPT4].addr,
+            fsl_imx8mp_memmap[FSL_IMX8MP_GPT5].addr,
+            fsl_imx8mp_memmap[FSL_IMX8MP_GPT6].addr,
+        };
+
+        s->gpt[i].ccm = IMX_CCM(&s->ccm);
+
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_addrs[i]);
+
+        if (i < FSL_IMX8MP_NUM_GPTS - 2) {
+            static const unsigned int gpt_irqs[FSL_IMX8MP_NUM_GPTS - 2] = {
+                FSL_IMX8MP_GPT1_IRQ,
+                FSL_IMX8MP_GPT2_IRQ,
+                FSL_IMX8MP_GPT3_IRQ,
+                FSL_IMX8MP_GPT4_IRQ,
+            };
+
+            sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
+                               qdev_get_gpio_in(gicdev, gpt_irqs[i]));
+        } else {
+            int irq = i - FSL_IMX8MP_NUM_GPTS + 2;
+
+            sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
+                               qdev_get_gpio_in(DEVICE(&s->gpt5_gpt6_irq), irq));
+        }
+    }
+
     /* I2Cs */
     for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
         static const struct {
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 11eca9fa4d..200a89225b 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -126,6 +126,17 @@ static const IMXClk imx7_gpt_clocks[] = {
     CLK_NONE,      /* 111 not defined */
 };
 
+static const IMXClk imx8mp_gpt_clocks[] = {
+    CLK_NONE,      /* 000 No clock source */
+    CLK_IPG,       /* 001 ipg_clk, 532MHz */
+    CLK_IPG_HIGH,  /* 010 ipg_clk_highfreq */
+    CLK_EXT,       /* 011 External clock */
+    CLK_32k,       /* 100 ipg_clk_32k */
+    CLK_HIGH,      /* 101 ipg_clk_16M */
+    CLK_NONE,      /* 110 not defined */
+    CLK_NONE,      /* 111 not defined */
+};
+
 /* Must be called from within ptimer_transaction_begin/commit block */
 static void imx_gpt_set_freq(IMXGPTState *s)
 {
@@ -552,6 +563,13 @@ static void imx7_gpt_init(Object *obj)
     s->clocks = imx7_gpt_clocks;
 }
 
+static void imx8mp_gpt_init(Object *obj)
+{
+    IMXGPTState *s = IMX_GPT(obj);
+
+    s->clocks = imx8mp_gpt_clocks;
+}
+
 static const TypeInfo imx25_gpt_info = {
     .name = TYPE_IMX25_GPT,
     .parent = TYPE_SYS_BUS_DEVICE,
@@ -584,6 +602,12 @@ static const TypeInfo imx7_gpt_info = {
     .instance_init = imx7_gpt_init,
 };
 
+static const TypeInfo imx8mp_gpt_info = {
+    .name = TYPE_IMX8MP_GPT,
+    .parent = TYPE_IMX25_GPT,
+    .instance_init = imx8mp_gpt_init,
+};
+
 static void imx_gpt_register_types(void)
 {
     type_register_static(&imx25_gpt_info);
@@ -591,6 +615,7 @@ static void imx_gpt_register_types(void)
     type_register_static(&imx6_gpt_info);
     type_register_static(&imx6ul_gpt_info);
     type_register_static(&imx7_gpt_info);
+    type_register_static(&imx8mp_gpt_info);
 }
 
 type_init(imx_gpt_register_types)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 71102ac0a9..f2859f6a88 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -586,6 +586,7 @@ config FSL_IMX8MP
     select FSL_IMX8MP_CCM
     select IMX
     select IMX_I2C
+    select OR_IRQ
     select PCI_EXPRESS_DESIGNWARE
     select PCI_EXPRESS_FSL_IMX8M_PHY
     select SDHCI
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 14/18] hw/arm/fsl-imx8mp: Add Ethernet controller
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (12 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:30   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 15/18] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

The i.MX 8M Plus SoC actually has two ethernet controllers, the usual ENET one
and a Designware one. There is no device model for the latter, so only add the
ENET one.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    |  8 ++++++++
 hw/arm/fsl-imx8mp.c            | 24 ++++++++++++++++++++++++
 hw/arm/imx8mp-evk.c            |  1 +
 hw/arm/Kconfig                 |  1 +
 5 files changed, 35 insertions(+)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 9293cabb85..4109387b6e 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -15,6 +15,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 4 UARTs
  * 3 USDHC Storage Controllers
  * 1 Designware PCI Express Controller
+ * 1 Ethernet Controller
  * 5 GPIO Controllers
  * 6 I2C Controllers
  * 3 SPI Controllers
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 975887751b..e292c31a3d 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -17,6 +17,7 @@
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
 #include "hw/misc/imx8mp_ccm.h"
+#include "hw/net/imx_fec.h"
 #include "hw/or-irq.h"
 #include "hw/pci-host/designware.h"
 #include "hw/pci-host/fsl_imx8m_phy.h"
@@ -58,11 +59,15 @@ struct FslImx8mpState {
     IMXSPIState        spi[FSL_IMX8MP_NUM_ECSPIS];
     IMXI2CState        i2c[FSL_IMX8MP_NUM_I2CS];
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
+    IMXFECState        enet;
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
     IMX2WdtState       wdt[FSL_IMX8MP_NUM_WDTS];
     DesignwarePCIEHost pcie;
     FslImx8mPciePhyState   pcie_phy;
     OrIRQState         gpt5_gpt6_irq;
+
+    uint32_t           phy_num;
+    bool               phy_connected;
 };
 
 enum FslImx8mpMemoryRegions {
@@ -253,6 +258,9 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_WDOG2_IRQ    = 79,
     FSL_IMX8MP_WDOG3_IRQ    = 10,
 
+    FSL_IMX8MP_ENET1_MAC_IRQ    = 118,
+    FSL_IMX6_ENET1_MAC_1588_IRQ = 121,
+
     FSL_IMX8MP_PCI_INTA_IRQ = 126,
     FSL_IMX8MP_PCI_INTB_IRQ = 125,
     FSL_IMX8MP_PCI_INTC_IRQ = 124,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 43395df628..665123cf9c 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -243,6 +243,8 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
     }
 
+    object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
+
     object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
     object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
                             TYPE_FSL_IMX8M_PCIE_PHY);
@@ -546,6 +548,21 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, spi_table[i].irq));
     }
 
+    /* ENET1 */
+    object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
+                             &error_abort);
+    object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
+    qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
+                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
+                       qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
+
     /* SNVS */
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
         return;
@@ -608,6 +625,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_GIC_REDIST:
         case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
         case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
+        case FSL_IMX8MP_ENET1:
         case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
         case FSL_IMX8MP_PCIE1:
         case FSL_IMX8MP_PCIE_PHY1:
@@ -628,10 +646,16 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     }
 }
 
+static const Property fsl_imx8mp_properties[] = {
+    DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0),
+    DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState, phy_connected, true),
+};
+
 static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
+    device_class_set_props(dc, fsl_imx8mp_properties);
     dc->realize = fsl_imx8mp_realize;
 
     dc->desc = "i.MX 8M Plus SoC";
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
index 27d9e9e8ee..e1a7892fd7 100644
--- a/hw/arm/imx8mp-evk.c
+++ b/hw/arm/imx8mp-evk.c
@@ -36,6 +36,7 @@ static void imx8mp_evk_init(MachineState *machine)
 
     s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
     object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+    object_property_set_uint(OBJECT(s), "fec1-phy-num", 1, &error_fatal);
     qdev_realize(DEVICE(s), NULL, &error_fatal);
 
     memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index f2859f6a88..7767a8725a 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -585,6 +585,7 @@ config FSL_IMX8MP
     select FSL_IMX8MP_ANALOG
     select FSL_IMX8MP_CCM
     select IMX
+    select IMX_FEC
     select IMX_I2C
     select OR_IRQ
     select PCI_EXPRESS_DESIGNWARE
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 15/18] hw/arm/fsl-imx8mp: Add USB support
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (13 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 14/18] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:31   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Split the USB MMIO regions to better keep track of the implemented vs.
unimplemented regions.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 docs/system/arm/imx8mp-evk.rst |  1 +
 include/hw/arm/fsl-imx8mp.h    | 12 +++++++++++
 hw/arm/fsl-imx8mp.c            | 37 ++++++++++++++++++++++++++++++++--
 hw/arm/Kconfig                 |  1 +
 4 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 4109387b6e..b3d657be10 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -16,6 +16,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * 3 USDHC Storage Controllers
  * 1 Designware PCI Express Controller
  * 1 Ethernet Controller
+ * 2 Designware USB 3 Controllers
  * 5 GPIO Controllers
  * 6 I2C Controllers
  * 3 SPI Controllers
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index e292c31a3d..5247e972b8 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -24,6 +24,7 @@
 #include "hw/sd/sdhci.h"
 #include "hw/ssi/imx_spi.h"
 #include "hw/timer/imx_gpt.h"
+#include "hw/usb/hcd-dwc3.h"
 #include "hw/watchdog/wdt_imx2.h"
 #include "qom/object.h"
 #include "qemu/units.h"
@@ -42,6 +43,7 @@ enum FslImx8mpConfiguration {
     FSL_IMX8MP_NUM_I2CS         = 6,
     FSL_IMX8MP_NUM_IRQS         = 160,
     FSL_IMX8MP_NUM_UARTS        = 4,
+    FSL_IMX8MP_NUM_USBS         = 2,
     FSL_IMX8MP_NUM_USDHCS       = 3,
     FSL_IMX8MP_NUM_WDTS         = 3,
 };
@@ -62,6 +64,7 @@ struct FslImx8mpState {
     IMXFECState        enet;
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
     IMX2WdtState       wdt[FSL_IMX8MP_NUM_WDTS];
+    USBDWC3            usb[FSL_IMX8MP_NUM_USBS];
     DesignwarePCIEHost pcie;
     FslImx8mPciePhyState   pcie_phy;
     OrIRQState         gpt5_gpt6_irq;
@@ -199,6 +202,12 @@ enum FslImx8mpMemoryRegions {
     FSL_IMX8MP_UART4,
     FSL_IMX8MP_USB1,
     FSL_IMX8MP_USB2,
+    FSL_IMX8MP_USB1_DEV,
+    FSL_IMX8MP_USB2_DEV,
+    FSL_IMX8MP_USB1_OTG,
+    FSL_IMX8MP_USB2_OTG,
+    FSL_IMX8MP_USB1_GLUE,
+    FSL_IMX8MP_USB2_GLUE,
     FSL_IMX8MP_USDHC1,
     FSL_IMX8MP_USDHC2,
     FSL_IMX8MP_USDHC3,
@@ -234,6 +243,9 @@ enum FslImx8mpIrqs {
     FSL_IMX8MP_I2C3_IRQ     = 37,
     FSL_IMX8MP_I2C4_IRQ     = 38,
 
+    FSL_IMX8MP_USB1_IRQ     = 40,
+    FSL_IMX8MP_USB2_IRQ     = 41,
+
     FSL_IMX8MP_GPT1_IRQ      = 55,
     FSL_IMX8MP_GPT2_IRQ      = 54,
     FSL_IMX8MP_GPT3_IRQ      = 53,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 665123cf9c..14d696957a 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -40,8 +40,14 @@ static const struct {
     [FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
     [FSL_IMX8MP_VPU_G2_DECODER] = { 0x38310000, 2 * MiB, "vpu_g2_decoder" },
     [FSL_IMX8MP_VPU_G1_DECODER] = { 0x38300000, 2 * MiB, "vpu_g1_decoder" },
-    [FSL_IMX8MP_USB2] = { 0x38200000, 1 * MiB, "usb2" },
-    [FSL_IMX8MP_USB1] = { 0x38100000, 1 * MiB, "usb1" },
+    [FSL_IMX8MP_USB2_GLUE] = { 0x382f0000, 0x100, "usb2_glue" },
+    [FSL_IMX8MP_USB2_OTG] = { 0x3820cc00, 0x100, "usb2_otg" },
+    [FSL_IMX8MP_USB2_DEV] = { 0x3820c700, 0x500, "usb2_dev" },
+    [FSL_IMX8MP_USB2] = { 0x38200000, 0xc700, "usb2" },
+    [FSL_IMX8MP_USB1_GLUE] = { 0x381f0000, 0x100, "usb1_glue" },
+    [FSL_IMX8MP_USB1_OTG] = { 0x3810cc00, 0x100, "usb1_otg" },
+    [FSL_IMX8MP_USB1_DEV] = { 0x3810c700, 0x500, "usb1_dev" },
+    [FSL_IMX8MP_USB1] = { 0x38100000, 0xc700, "usb1" },
     [FSL_IMX8MP_GPU2D] = { 0x38008000, 32 * KiB, "gpu2d" },
     [FSL_IMX8MP_GPU3D] = { 0x38000000, 32 * KiB, "gpu3d" },
     [FSL_IMX8MP_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
@@ -233,6 +239,11 @@ static void fsl_imx8mp_init(Object *obj)
         object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_USBS; i++) {
+        snprintf(name, NAME_SIZE, "usb%d", i);
+        object_initialize_child(obj, name, &s->usb[i], TYPE_USB_DWC3);
+    }
+
     for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
         snprintf(name, NAME_SIZE, "spi%d", i + 1);
         object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
@@ -528,6 +539,27 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
     }
 
+    /* USBs */
+    for (i = 0; i < FSL_IMX8MP_NUM_USBS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } usb_table[FSL_IMX8MP_NUM_USBS] = {
+            { fsl_imx8mp_memmap[FSL_IMX8MP_USB1].addr, FSL_IMX8MP_USB1_IRQ },
+            { fsl_imx8mp_memmap[FSL_IMX8MP_USB2].addr, FSL_IMX8MP_USB2_IRQ },
+        };
+
+        qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p2", 1);
+        qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p3", 1);
+        qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2);
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) {
+            return;
+        }
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
+                           qdev_get_gpio_in(gicdev, usb_table[i].irq));
+    }
+
     /* ECSPIs */
     for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
         static const struct {
@@ -632,6 +664,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_RAM:
         case FSL_IMX8MP_SNVS_HP:
         case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
+        case FSL_IMX8MP_USB1 ... FSL_IMX8MP_USB2:
         case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
         case FSL_IMX8MP_WDOG1 ... FSL_IMX8MP_WDOG3:
             /* device implemented and treated above */
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7767a8725a..6daa9c651f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -592,6 +592,7 @@ config FSL_IMX8MP
     select PCI_EXPRESS_FSL_IMX8M_PHY
     select SDHCI
     select UNIMP
+    select USB_DWC3
     select WDT_IMX2
 
 config FSL_IMX8MP_EVK
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (14 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 15/18] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-17 13:28   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 17/18] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
  2025-02-04  9:21 ` [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

On a real device, the boot ROM contains the very first instructions the CPU
executes. Also, U-Boot calls into the ROM to determine the boot device. While
we're not actually implementing this here, let's create the infrastructure and
add a dummy ROM with all zeros. This allows for implementing a ROM later without
touching the source code and even allows for users to provide their own ROMs.

The imx8mp-boot.rom was created with
`dd if=/dev/zero of=imx8mp-boot.rom bs=1 count=258048`.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 MAINTAINERS                 |   1 +
 include/hw/arm/fsl-imx8mp.h |   1 +
 hw/arm/fsl-imx8mp.c         |  18 ++++++++++++++++++
 pc-bios/imx8mp-boot.rom     | Bin 0 -> 258048 bytes
 pc-bios/meson.build         |   1 +
 5 files changed, 21 insertions(+)
 create mode 100644 pc-bios/imx8mp-boot.rom

diff --git a/MAINTAINERS b/MAINTAINERS
index 94af3d90e4..ee837a3f6e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -831,6 +831,7 @@ F: hw/pci-host/fsl_imx8m_phy.c
 F: include/hw/arm/fsl-imx8mp.h
 F: include/hw/misc/imx8mp_*.h
 F: include/hw/pci-host/fsl_imx8m_phy.h
+F: pc-bios/imx8mp*
 F: docs/system/arm/imx8mp-evk.rst
 
 MPS2 / MPS3
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 5247e972b8..4dbe30f524 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -68,6 +68,7 @@ struct FslImx8mpState {
     DesignwarePCIEHost pcie;
     FslImx8mPciePhyState   pcie_phy;
     OrIRQState         gpt5_gpt6_irq;
+    MemoryRegion       boot_rom;
 
     uint32_t           phy_num;
     bool               phy_connected;
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 14d696957a..6439639110 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -9,12 +9,14 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/datadir.h"
 #include "exec/address-spaces.h"
 #include "hw/arm/bsa.h"
 #include "hw/arm/fsl-imx8mp.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/misc/unimp.h"
 #include "hw/boards.h"
+#include "hw/loader.h"
 #include "system/system.h"
 #include "target/arm/cpu-qom.h"
 #include "qapi/qmp/qlist.h"
@@ -266,6 +268,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     MachineState *ms = MACHINE(qdev_get_machine());
     FslImx8mpState *s = FSL_IMX8MP(dev);
     DeviceState *gicdev = DEVICE(&s->gic);
+    g_autofree char *filename = NULL;
     int i;
 
     if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
@@ -648,10 +651,25 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
                     fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
 
+    /* ROM memory */
+    if (!memory_region_init_rom(&s->boot_rom, OBJECT(dev),
+                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].name,
+                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].size,
+                                errp)) {
+        return;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "imx8mp-boot.rom");
+    load_image_size(filename, memory_region_get_ram_ptr(&s->boot_rom),
+                    memory_region_size(&s->boot_rom));
+    memory_region_add_subregion(get_system_memory(),
+                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].addr,
+                                &s->boot_rom);
+
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
         switch (i) {
         case FSL_IMX8MP_ANA_PLL:
+        case FSL_IMX8MP_BOOT_ROM:
         case FSL_IMX8MP_CCM:
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
diff --git a/pc-bios/imx8mp-boot.rom b/pc-bios/imx8mp-boot.rom
new file mode 100644
index 0000000000000000000000000000000000000000..5324b5eed200e723d048f8476e4d96d45622fd4d
GIT binary patch
literal 258048
zcmeIuF#!Mo0K%a4Pi+Q&h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM
z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*
z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd
z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA
zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj
zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r
z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@
z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK
zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5
zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM
z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*
z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd
z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA
zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj
zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r
z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@
z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK
zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5
zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM
z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*
z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd
z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>f$Z
E2JkHa0RR91

literal 0
HcmV?d00001

diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index b68b29cc7d..64d3286fdd 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -60,6 +60,7 @@ blobs = [
   'efi-virtio.rom',
   'efi-e1000e.rom',
   'efi-vmxnet3.rom',
+  'imx8mp-boot.rom',
   'qemu-nsis.bmp',
   'multiboot.bin',
   'multiboot_dma.bin',
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 17/18] hw/arm/fsl-imx8mp: Add on-chip RAM
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (15 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:31   ` Peter Maydell
  2025-02-04  9:21 ` [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 include/hw/arm/fsl-imx8mp.h |  1 +
 hw/arm/fsl-imx8mp.c         | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 4dbe30f524..03f057c7db 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -69,6 +69,7 @@ struct FslImx8mpState {
     FslImx8mPciePhyState   pcie_phy;
     OrIRQState         gpt5_gpt6_irq;
     MemoryRegion       boot_rom;
+    MemoryRegion       ocram;
 
     uint32_t           phy_num;
     bool               phy_connected;
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 6439639110..e0dfe06e15 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -665,6 +665,16 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
                                 fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].addr,
                                 &s->boot_rom);
 
+    /* On-Chip RAM */
+    if (!memory_region_init_ram(&s->ocram, NULL, "imx8mp.ocram",
+                                fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].size,
+                                errp)) {
+        return;
+    }
+    memory_region_add_subregion(get_system_memory(),
+                                fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].addr,
+                                &s->ocram);
+
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
         switch (i) {
@@ -677,6 +687,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
         case FSL_IMX8MP_ENET1:
         case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
+        case FSL_IMX8MP_OCRAM:
         case FSL_IMX8MP_PCIE1:
         case FSL_IMX8MP_PCIE_PHY1:
         case FSL_IMX8MP_RAM:
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (16 preceding siblings ...)
  2025-02-04  9:21 ` [PATCH v2 17/18] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
@ 2025-02-04  9:21 ` Bernhard Beschow
  2025-02-06 17:32   ` Peter Maydell
  17 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04  9:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Bernhard Beschow, qemu-arm, Peter Maydell, Andrey Smirnov,
	Paolo Bonzini

The implementation just allows Linux to determine date and time.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 MAINTAINERS         |   1 +
 hw/rtc/rs5c372.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++
 hw/rtc/Kconfig      |   5 +
 hw/rtc/meson.build  |   1 +
 hw/rtc/trace-events |   4 +
 5 files changed, 238 insertions(+)
 create mode 100644 hw/rtc/rs5c372.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ee837a3f6e..d87435adba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -828,6 +828,7 @@ F: hw/arm/imx8mp-evk.c
 F: hw/arm/fsl-imx8mp.c
 F: hw/misc/imx8mp_*.c
 F: hw/pci-host/fsl_imx8m_phy.c
+F: hw/rtc/rs5c372.c
 F: include/hw/arm/fsl-imx8mp.h
 F: include/hw/misc/imx8mp_*.h
 F: include/hw/pci-host/fsl_imx8m_phy.h
diff --git a/hw/rtc/rs5c372.c b/hw/rtc/rs5c372.c
new file mode 100644
index 0000000000..d300f93e13
--- /dev/null
+++ b/hw/rtc/rs5c372.c
@@ -0,0 +1,227 @@
+/*
+ * Ricoh RS5C372, R222x I2C RTC
+ *
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * Based on hw/rtc/ds1338.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/i2c/i2c.h"
+#include "migration/vmstate.h"
+#include "qemu/bcd.h"
+#include "qom/object.h"
+#include "system/rtc.h"
+#include "trace.h"
+
+#define NVRAM_SIZE 0x10
+
+/* Flags definitions */
+#define SECONDS_CH 0x80
+#define HOURS_PM   0x20
+#define CTRL2_24   0x20
+
+#define TYPE_RS5C372 "rs5c372"
+OBJECT_DECLARE_SIMPLE_TYPE(RS5C372State, RS5C372)
+
+struct RS5C372State {
+    I2CSlave parent_obj;
+
+    int64_t offset;
+    uint8_t wday_offset;
+    uint8_t nvram[NVRAM_SIZE];
+    uint8_t ptr;
+    uint8_t tx_format;
+    bool addr_byte;
+};
+
+static const VMStateDescription vmstate_rs5c372 = {
+    .name = "rs5c372",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_I2C_SLAVE(parent_obj, RS5C372State),
+        VMSTATE_INT64(offset, RS5C372State),
+        VMSTATE_UINT8_V(wday_offset, RS5C372State, 2),
+        VMSTATE_UINT8_ARRAY(nvram, RS5C372State, NVRAM_SIZE),
+        VMSTATE_UINT8(ptr, RS5C372State),
+        VMSTATE_UINT8(tx_format, RS5C372State),
+        VMSTATE_BOOL(addr_byte, RS5C372State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void capture_current_time(RS5C372State *s)
+{
+    /*
+     * Capture the current time into the secondary registers which will be
+     * actually read by the data transfer operation.
+     */
+    struct tm now;
+    qemu_get_timedate(&now, s->offset);
+    s->nvram[0] = to_bcd(now.tm_sec);
+    s->nvram[1] = to_bcd(now.tm_min);
+    if (s->nvram[0xf] & CTRL2_24) {
+        s->nvram[2] = to_bcd(now.tm_hour);
+    } else {
+        int tmp = now.tm_hour;
+        if (tmp % 12 == 0) {
+            tmp += 12;
+        }
+        if (tmp <= 12) {
+            s->nvram[2] = to_bcd(tmp);
+        } else {
+            s->nvram[2] = HOURS_PM | to_bcd(tmp - 12);
+        }
+    }
+    s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
+    s->nvram[4] = to_bcd(now.tm_mday);
+    s->nvram[5] = to_bcd(now.tm_mon + 1);
+    s->nvram[6] = to_bcd(now.tm_year - 100);
+}
+
+static void inc_regptr(RS5C372State *s)
+{
+    s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1);
+}
+
+static int rs5c372_event(I2CSlave *i2c, enum i2c_event event)
+{
+    RS5C372State *s = RS5C372(i2c);
+
+    switch (event) {
+    case I2C_START_RECV:
+        /*
+         * In h/w, capture happens on any START condition, not just a
+         * START_RECV, but there is no need to actually capture on
+         * START_SEND, because the guest can't get at that data
+         * without going through a START_RECV which would overwrite it.
+         */
+        capture_current_time(s);
+        s->ptr = 0xf;
+        break;
+    case I2C_START_SEND:
+        s->addr_byte = true;
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static uint8_t rs5c372_recv(I2CSlave *i2c)
+{
+    RS5C372State *s = RS5C372(i2c);
+    uint8_t res;
+
+    res  = s->nvram[s->ptr];
+
+    trace_rs5c372_recv(s->ptr, res);
+
+    inc_regptr(s);
+    return res;
+}
+
+static int rs5c372_send(I2CSlave *i2c, uint8_t data)
+{
+    RS5C372State *s = RS5C372(i2c);
+
+    if (s->addr_byte) {
+        s->ptr = data >> 4;
+        s->tx_format = data & 0xf;
+        s->addr_byte = false;
+        return 0;
+    }
+
+    trace_rs5c372_send(s->ptr, data);
+
+    if (s->ptr < 7) {
+        /* Time register. */
+        struct tm now;
+        qemu_get_timedate(&now, s->offset);
+        switch (s->ptr) {
+        case 0:
+            now.tm_sec = from_bcd(data & 0x7f);
+            break;
+        case 1:
+            now.tm_min = from_bcd(data & 0x7f);
+            break;
+        case 2:
+            if (s->nvram[0xf] & CTRL2_24) {
+                now.tm_hour = from_bcd(data & 0x3f);
+            } else {
+                int tmp = from_bcd(data & (HOURS_PM - 1));
+                if (data & HOURS_PM) {
+                    tmp += 12;
+                }
+                if (tmp % 12 == 0) {
+                    tmp -= 12;
+                }
+                now.tm_hour = tmp;
+            }
+            break;
+        case 3:
+            {
+                /*
+                 * The day field is supposed to contain a value in the range
+                 * 1-7. Otherwise behavior is undefined.
+                 */
+                int user_wday = (data & 7) - 1;
+                s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
+            }
+            break;
+        case 4:
+            now.tm_mday = from_bcd(data & 0x3f);
+            break;
+        case 5:
+            now.tm_mon = from_bcd(data & 0x1f) - 1;
+            break;
+        case 6:
+            now.tm_year = from_bcd(data) + 100;
+            break;
+        }
+        s->offset = qemu_timedate_diff(&now);
+    } else {
+        s->nvram[s->ptr] = data;
+    }
+    inc_regptr(s);
+    return 0;
+}
+
+static void rs5c372_reset(DeviceState *dev)
+{
+    RS5C372State *s = RS5C372(dev);
+
+    /* The clock is running and synchronized with the host */
+    s->offset = 0;
+    s->wday_offset = 0;
+    memset(s->nvram, 0, NVRAM_SIZE);
+    s->ptr = 0;
+    s->addr_byte = false;
+}
+
+static void rs5c372_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->event = rs5c372_event;
+    k->recv = rs5c372_recv;
+    k->send = rs5c372_send;
+    device_class_set_legacy_reset(dc, rs5c372_reset);
+    dc->vmsd = &vmstate_rs5c372;
+}
+
+static const TypeInfo rs5c372_types[] = {
+    {
+        .name          = TYPE_RS5C372,
+        .parent        = TYPE_I2C_SLAVE,
+        .instance_size = sizeof(RS5C372State),
+        .class_init    = rs5c372_class_init,
+    },
+};
+
+DEFINE_TYPES(rs5c372_types)
diff --git a/hw/rtc/Kconfig b/hw/rtc/Kconfig
index 2fe04ec1d0..315b0e4ecc 100644
--- a/hw/rtc/Kconfig
+++ b/hw/rtc/Kconfig
@@ -26,3 +26,8 @@ config GOLDFISH_RTC
 
 config LS7A_RTC
     bool
+
+config RS5C372_RTC
+    bool
+    depends on I2C
+    default y if I2C_DEVICES
diff --git a/hw/rtc/meson.build b/hw/rtc/meson.build
index 8ecc2d792c..6c87864dc0 100644
--- a/hw/rtc/meson.build
+++ b/hw/rtc/meson.build
@@ -13,3 +13,4 @@ system_ss.add(when: 'CONFIG_GOLDFISH_RTC', if_true: files('goldfish_rtc.c'))
 system_ss.add(when: 'CONFIG_LS7A_RTC', if_true: files('ls7a_rtc.c'))
 system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-rtc.c'))
 system_ss.add(when: 'CONFIG_MC146818RTC', if_true: files('mc146818rtc.c'))
+system_ss.add(when: 'CONFIG_RS5C372_RTC', if_true: files('rs5c372.c'))
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
index 8012afe102..b9f2852d35 100644
--- a/hw/rtc/trace-events
+++ b/hw/rtc/trace-events
@@ -35,3 +35,7 @@ m48txx_nvram_mem_write(uint32_t addr, uint32_t value) "mem write addr:0x%04x val
 # goldfish_rtc.c
 goldfish_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
 goldfish_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
+
+# rs5c372.c
+rs5c372_recv(uint32_t addr, uint8_t value) "[0x%" PRIx32 "] -> 0x%02" PRIx8
+rs5c372_send(uint32_t addr, uint8_t value) "[0x%" PRIx32 "] <- 0x%02" PRIx8
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree
  2025-02-04  9:20 ` [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
@ 2025-02-04 23:15   ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-04 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Andrey Smirnov, Paolo Bonzini



Am 4. Februar 2025 09:20:59 UTC schrieb Bernhard Beschow <shentey@gmail.com>:
>Fixes quite a few stack traces during the Linux boot process. Also provides the
>clocks for devices added later, e.g. enet1.
>
>Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>---
> MAINTAINERS                     |   2 +
> docs/system/arm/imx8mp-evk.rst  |   1 +
> include/hw/arm/fsl-imx8mp.h     |   4 +
> include/hw/misc/imx8mp_analog.h |  81 +++++++++++++++
> include/hw/misc/imx8mp_ccm.h    |  30 ++++++
> hw/arm/fsl-imx8mp.c             |  20 ++++
> hw/misc/imx8mp_analog.c         | 160 +++++++++++++++++++++++++++++
> hw/misc/imx8mp_ccm.c            | 175 ++++++++++++++++++++++++++++++++
> hw/arm/Kconfig                  |   2 +
> hw/misc/Kconfig                 |   6 ++
> hw/misc/meson.build             |   2 +
> 11 files changed, 483 insertions(+)
> create mode 100644 include/hw/misc/imx8mp_analog.h
> create mode 100644 include/hw/misc/imx8mp_ccm.h
> create mode 100644 hw/misc/imx8mp_analog.c
> create mode 100644 hw/misc/imx8mp_ccm.c
>
>diff --git a/MAINTAINERS b/MAINTAINERS
>index 8db59114bc..5b5b0d0bed 100644
>--- a/MAINTAINERS
>+++ b/MAINTAINERS
>@@ -826,7 +826,9 @@ L: qemu-arm@nongnu.org
> S: Maintained
> F: hw/arm/imx8mp-evk.c
> F: hw/arm/fsl-imx8mp.c
>+F: hw/misc/imx8mp_*.c
> F: include/hw/arm/fsl-imx8mp.h
>+F: include/hw/misc/imx8mp_*.h
> F: docs/system/arm/imx8mp-evk.rst
> 
> MPS2 / MPS3
>diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
>index a9c1fab390..e5039fc8c4 100644
>--- a/docs/system/arm/imx8mp-evk.rst
>+++ b/docs/system/arm/imx8mp-evk.rst
>@@ -13,6 +13,7 @@ The ``imx8mp-evk`` machine implements the following devices:
>  * Up to 4 Cortex-A53 Cores
>  * Generic Interrupt Controller (GICv3)
>  * 4 UARTs
>+ * Clock Tree
> 
> Boot options
> ------------
>diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
>index 57e23d1b69..ce5188e7f2 100644
>--- a/include/hw/arm/fsl-imx8mp.h
>+++ b/include/hw/arm/fsl-imx8mp.h
>@@ -12,6 +12,8 @@
> #include "cpu.h"
> #include "hw/char/imx_serial.h"
> #include "hw/intc/arm_gicv3_common.h"
>+#include "hw/misc/imx8mp_analog.h"
>+#include "hw/misc/imx8mp_ccm.h"
> #include "qom/object.h"
> #include "qemu/units.h"
> 
>@@ -32,6 +34,8 @@ struct FslImx8mpState {
> 
>     ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
>     GICv3State         gic;
>+    IMX8MPCCMState     ccm;
>+    IMX8MPAnalogState  analog;
>     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
> };
> 
>diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
>new file mode 100644
>index 0000000000..955f03215a
>--- /dev/null
>+++ b/include/hw/misc/imx8mp_analog.h
>@@ -0,0 +1,81 @@
>+/*
>+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
>+ *
>+ * i.MX8MP ANALOG IP block emulation code
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#ifndef IMX8MP_ANALOG_H
>+#define IMX8MP_ANALOG_H
>+
>+#include "qom/object.h"
>+#include "hw/sysbus.h"
>+
>+enum IMX8MPAnalogRegisters {
>+    ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
>+    ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
>+    ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
>+    ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
>+    ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
>+    ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
>+    ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
>+    ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
>+    ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
>+    ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
>+    ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
>+    ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
>+    ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
>+    ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
>+    ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
>+    ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
>+    ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
>+    ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
>+    ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
>+    ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
>+    ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
>+    ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
>+    ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
>+    ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
>+    ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
>+    ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
>+    ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
>+    ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
>+    ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
>+    ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
>+    ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
>+    ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
>+    ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
>+    ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
>+    ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
>+    ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
>+    ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
>+    ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
>+    ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
>+    ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
>+    ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
>+    ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
>+    ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
>+    ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
>+    ANALOG_OSC_MISC_CFG = 0x124 / 4,
>+    ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
>+
>+    ANALOG_DIGPROG = 0x800 / 4,
>+    ANALOG_MAX,
>+};
>+
>+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
>+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
>+
>+struct IMX8MPAnalogState {
>+    SysBusDevice parent_obj;
>+
>+    struct {
>+        MemoryRegion container;
>+        MemoryRegion analog;
>+    } mmio;
>+
>+    uint32_t analog[ANALOG_MAX];
>+};
>+
>+#endif /* IMX8MP_ANALOG_H */
>diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
>new file mode 100644
>index 0000000000..685c8582ff
>--- /dev/null
>+++ b/include/hw/misc/imx8mp_ccm.h
>@@ -0,0 +1,30 @@
>+/*
>+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
>+ *
>+ * i.MX 8M Plus CCM IP block emulation code
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#ifndef IMX8MP_CCM_H
>+#define IMX8MP_CCM_H
>+
>+#include "hw/misc/imx_ccm.h"
>+#include "qom/object.h"
>+
>+enum IMX8MPCCMRegisters {
>+    CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
>+};
>+
>+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
>+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
>+
>+struct IMX8MPCCMState {
>+    IMXCCMState parent_obj;
>+
>+    MemoryRegion iomem;
>+
>+    uint32_t ccm[CCM_MAX];
>+};
>+
>+#endif /* IMX8MP_CCM_H */
>diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
>index 0836d82ca0..a1a8843b3b 100644
>--- a/hw/arm/fsl-imx8mp.c
>+++ b/hw/arm/fsl-imx8mp.c
>@@ -200,6 +200,10 @@ static void fsl_imx8mp_init(Object *obj)
> 
>     object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
> 
>+    object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
>+
>+    object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
>+
>     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
>         snprintf(name, NAME_SIZE, "uart%d", i + 1);
>         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>@@ -308,6 +312,20 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
>         }
>     }
> 
>+    /* CCM */
>+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
>+        return;
>+    }
>+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
>+                    fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
>+
>+    /* Analog */
>+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
>+        return;
>+    }
>+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
>+                    fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
>+
>     /* UARTs */
>     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
>         static const struct {
>@@ -333,6 +351,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
>     /* Unimplemented devices */
>     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
>         switch (i) {
>+        case FSL_IMX8MP_ANA_PLL:
>+        case FSL_IMX8MP_CCM:
>         case FSL_IMX8MP_GIC_DIST:
>         case FSL_IMX8MP_GIC_REDIST:
>         case FSL_IMX8MP_RAM:
>diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
>new file mode 100644
>index 0000000000..71333b3e9e
>--- /dev/null
>+++ b/hw/misc/imx8mp_analog.c
>@@ -0,0 +1,160 @@
>+/*
>+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
>+ *
>+ * i.MX 8M Plus ANALOG IP block emulation code
>+ *
>+ * Based on hw/misc/imx7_ccm.c
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#include "qemu/osdep.h"
>+#include "qemu/log.h"
>+
>+#include "hw/misc/imx8mp_analog.h"
>+#include "migration/vmstate.h"
>+
>+#define ANALOG_PLL_LOCK BIT(31)
>+
>+static void imx8mp_analog_reset(DeviceState *dev)
>+{
>+    IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
>+
>+    memset(s->analog, 0, sizeof(s->analog));
>+
>+    s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
>+    s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
>+    s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
>+    s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
>+    s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
>+    s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
>+    s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
>+    s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
>+    s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
>+    s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
>+    s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
>+    s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
>+    s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
>+    s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
>+    s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
>+    s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
>+    s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
>+    s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
>+    s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
>+    s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
>+    s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
>+    s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
>+    s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
>+    s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
>+    s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
>+    s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
>+    s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
>+    s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
>+    s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
>+    s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
>+    s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
>+    s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
>+    s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
>+    s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
>+    s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
>+    s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
>+    s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
>+    s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
>+    s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
>+    s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
>+    s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
>+    s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
>+    s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
>+    s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
>+    s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
>+    s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
>+    s->analog[ANALOG_DIGPROG] = 0x00824010;
>+
>+    /* all PLLs need to be locked */
>+    s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+    s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
>+}
>+
>+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
>+{
>+    IMX8MPAnalogState *s = opaque;
>+
>+    return s->analog[offset >> 2];
>+}
>+
>+static void imx8mp_analog_write(void *opaque, hwaddr offset,
>+                                uint64_t value, unsigned size)
>+{
>+    IMX8MPAnalogState *s = opaque;
>+
>+    if (offset >> 2 == ANALOG_DIGPROG) {
>+        qemu_log_mask(LOG_GUEST_ERROR,
>+                      "Guest write to read-only ANALOG_DIGPROG register\n");
>+    } else {
>+        s->analog[offset >> 2] = value;
>+    }
>+}
>+
>+static const struct MemoryRegionOps imx8mp_analog_ops = {
>+    .read = imx8mp_analog_read,
>+    .write = imx8mp_analog_write,
>+    .endianness = DEVICE_NATIVE_ENDIAN,
>+    .impl = {
>+        .min_access_size = 4,
>+        .max_access_size = 4,
>+        .unaligned = false,
>+    },
>+};
>+
>+static void imx8mp_analog_init(Object *obj)
>+{
>+    IMX8MPAnalogState *s = IMX8MP_ANALOG(obj);
>+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
>+
>+    memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_ANALOG, 0x10000);
>+
>+    memory_region_init_io(&s->mmio.analog, obj, &imx8mp_analog_ops, s,
>+                          TYPE_IMX8MP_ANALOG, sizeof(s->analog));
>+    memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
>+
>+    sysbus_init_mmio(sd, &s->mmio.container);
>+}
>+
>+static const VMStateDescription vmstate_imx8mp_analog = {
>+    .name = TYPE_IMX8MP_ANALOG,
>+    .version_id = 1,
>+    .minimum_version_id = 1,
>+    .fields = (const VMStateField[]) {
>+        VMSTATE_UINT32_ARRAY(analog, IMX8MPAnalogState, ANALOG_MAX),
>+        VMSTATE_END_OF_LIST()
>+    },
>+};
>+
>+static void imx8mp_analog_class_init(ObjectClass *klass, void *data)
>+{
>+    DeviceClass *dc = DEVICE_CLASS(klass);
>+
>+    device_class_set_legacy_reset(dc, imx8mp_analog_reset);
>+    dc->vmsd  = &vmstate_imx8mp_analog;
>+    dc->desc  = "i.MX 8M Plus Analog Module";
>+}
>+
>+static const TypeInfo imx8mp_ccm_types[] = {
>+    {
>+        .name          = TYPE_IMX8MP_ANALOG,
>+        .parent        = TYPE_SYS_BUS_DEVICE,
>+        .instance_size = sizeof(IMX8MPAnalogState),
>+        .instance_init = imx8mp_analog_init,
>+        .class_init    = imx8mp_analog_class_init,
>+    }
>+};
>+
>+DEFINE_TYPES(imx8mp_ccm_types);

s/imx8mp_ccm_types/imx8mp_analog_types/ will be fixed in next iteration

>diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
>new file mode 100644
>index 0000000000..7c869ff86b
>--- /dev/null
>+++ b/hw/misc/imx8mp_ccm.c
>@@ -0,0 +1,175 @@
>+/*
>+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
>+ *
>+ * i.MX 8M Plus CCM IP block emulation code
>+ *
>+ * Based on hw/misc/imx7_ccm.c
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#include "qemu/osdep.h"
>+#include "qemu/log.h"
>+
>+#include "hw/misc/imx8mp_ccm.h"
>+#include "migration/vmstate.h"
>+
>+#include "trace.h"
>+
>+#define CKIH_FREQ 16000000 /* 16MHz crystal input */
>+
>+static void imx8mp_ccm_reset(DeviceState *dev)
>+{
>+    IMX8MPCCMState *s = IMX8MP_CCM(dev);
>+
>+    memset(s->ccm, 0, sizeof(s->ccm));
>+}
>+
>+#define CCM_INDEX(offset)   (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
>+#define CCM_BITOP(offset)   ((offset) & (hwaddr)0xF)
>+
>+enum {
>+    CCM_BITOP_NONE = 0x00,
>+    CCM_BITOP_SET  = 0x04,
>+    CCM_BITOP_CLR  = 0x08,
>+    CCM_BITOP_TOG  = 0x0C,
>+};
>+
>+static uint64_t imx8mp_set_clr_tog_read(void *opaque, hwaddr offset,
>+                                        unsigned size)
>+{
>+    const uint32_t *mmio = opaque;
>+
>+    return mmio[CCM_INDEX(offset)];
>+}
>+
>+static void imx8mp_set_clr_tog_write(void *opaque, hwaddr offset,
>+                                     uint64_t value, unsigned size)
>+{
>+    const uint8_t  bitop = CCM_BITOP(offset);
>+    const uint32_t index = CCM_INDEX(offset);
>+    uint32_t *mmio = opaque;
>+
>+    switch (bitop) {
>+    case CCM_BITOP_NONE:
>+        mmio[index]  = value;
>+        break;
>+    case CCM_BITOP_SET:
>+        mmio[index] |= value;
>+        break;
>+    case CCM_BITOP_CLR:
>+        mmio[index] &= ~value;
>+        break;
>+    case CCM_BITOP_TOG:
>+        mmio[index] ^= value;
>+        break;
>+    };
>+}
>+
>+static const struct MemoryRegionOps imx8mp_set_clr_tog_ops = {
>+    .read = imx8mp_set_clr_tog_read,
>+    .write = imx8mp_set_clr_tog_write,
>+    .endianness = DEVICE_NATIVE_ENDIAN,
>+    .impl = {
>+        /*
>+         * Our device would not work correctly if the guest was doing
>+         * unaligned access. This might not be a limitation on the real
>+         * device but in practice there is no reason for a guest to access
>+         * this device unaligned.
>+         */
>+        .min_access_size = 4,
>+        .max_access_size = 4,
>+        .unaligned = false,
>+    },
>+};
>+
>+static void imx8mp_ccm_init(Object *obj)
>+{
>+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
>+    IMX8MPCCMState *s = IMX8MP_CCM(obj);
>+
>+    memory_region_init_io(&s->iomem,
>+                          obj,
>+                          &imx8mp_set_clr_tog_ops,
>+                          s->ccm,
>+                          TYPE_IMX8MP_CCM ".ccm",
>+                          sizeof(s->ccm));
>+
>+    sysbus_init_mmio(sd, &s->iomem);
>+}
>+
>+static const VMStateDescription vmstate_imx8mp_ccm = {
>+    .name = TYPE_IMX8MP_CCM,
>+    .version_id = 1,
>+    .minimum_version_id = 1,
>+    .fields = (const VMStateField[]) {
>+        VMSTATE_UINT32_ARRAY(ccm, IMX8MPCCMState, CCM_MAX),
>+        VMSTATE_END_OF_LIST()
>+    },
>+};
>+
>+static uint32_t imx8mp_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
>+{
>+    /*
>+     * This function is "consumed" by GPT emulation code. Some clocks
>+     * have fixed frequencies and we can provide requested frequency
>+     * easily. However for CCM provided clocks (like IPG) each GPT
>+     * timer can have its own clock root.
>+     * This means we need additional information when calling this
>+     * function to know the requester's identity.
>+     */
>+    uint32_t freq = 0;
>+
>+    switch (clock) {
>+    case CLK_NONE:
>+        break;
>+    case CLK_32k:
>+        freq = CKIL_FREQ;
>+        break;
>+    case CLK_HIGH:
>+        freq = CKIH_FREQ;
>+        break;
>+    case CLK_IPG:
>+    case CLK_IPG_HIGH:
>+        /*
>+         * For now we don't have a way to figure out the device this
>+         * function is called for. Until then the IPG derived clocks
>+         * are left unimplemented.
>+         */
>+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n",
>+                      TYPE_IMX8MP_CCM, __func__, clock);
>+        break;
>+    default:
>+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
>+                      TYPE_IMX8MP_CCM, __func__, clock);
>+        break;
>+    }
>+
>+    trace_ccm_clock_freq(clock, freq);
>+
>+    return freq;
>+}
>+
>+static void imx8mp_ccm_class_init(ObjectClass *klass, void *data)
>+{
>+    DeviceClass *dc = DEVICE_CLASS(klass);
>+    IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
>+
>+    device_class_set_legacy_reset(dc, imx8mp_ccm_reset);
>+    dc->vmsd  = &vmstate_imx8mp_ccm;
>+    dc->desc  = "i.MX 8M Plus Clock Control Module";
>+
>+    ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
>+}
>+
>+static const TypeInfo imx8mp_ccm_types[] = {
>+    {
>+        .name          = TYPE_IMX8MP_CCM,
>+        .parent        = TYPE_IMX_CCM,
>+        .instance_size = sizeof(IMX8MPCCMState),
>+        .instance_init = imx8mp_ccm_init,
>+        .class_init    = imx8mp_ccm_class_init,
>+    },
>+};
>+
>+DEFINE_TYPES(imx8mp_ccm_types);
>diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>index e22916df57..0079c51734 100644
>--- a/hw/arm/Kconfig
>+++ b/hw/arm/Kconfig
>@@ -580,6 +580,8 @@ config FSL_IMX7
> config FSL_IMX8MP
>     bool
>     select ARM_GIC
>+    select FSL_IMX8MP_ANALOG
>+    select FSL_IMX8MP_CCM
>     select IMX
>     select UNIMP
> 
>diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
>index 4271e2f4ac..82bd68b4bb 100644
>--- a/hw/misc/Kconfig
>+++ b/hw/misc/Kconfig
>@@ -78,6 +78,12 @@ config IMX
>     select SSI
>     select USB_EHCI_SYSBUS
> 
>+config FSL_IMX8MP_ANALOG
>+    bool
>+
>+config FSL_IMX8MP_CCM
>+    bool
>+
> config STM32_RCC
>     bool
> 
>diff --git a/hw/misc/meson.build b/hw/misc/meson.build
>index 55f493521b..f9285cf2f1 100644
>--- a/hw/misc/meson.build
>+++ b/hw/misc/meson.build
>@@ -55,6 +55,8 @@ system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
> system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
> system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
> system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
>+system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
>+system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
> system_ss.add(when: 'CONFIG_IMX', if_true: files(
>   'imx25_ccm.c',
>   'imx31_ccm.c',


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers
  2025-02-04  9:21 ` [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
@ 2025-02-06 17:25   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:25 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> The USDHC emulation allows for running real-world images such as those generated
> by Buildroot. Convert the board documentation accordingly instead of running a
> Linux kernel with ephemeral storage.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst | 16 +++++++++++-----
>  include/hw/arm/fsl-imx8mp.h    |  7 +++++++
>  hw/arm/fsl-imx8mp.c            | 28 ++++++++++++++++++++++++++++
>  hw/arm/imx8mp-evk.c            | 18 ++++++++++++++++++
>  hw/arm/Kconfig                 |  1 +
>  5 files changed, 65 insertions(+), 5 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 09/18] hw/arm/fsl-imx8mp: Add GPIO controllers
  2025-02-04  9:21 ` [PATCH v2 09/18] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
@ 2025-02-06 17:26   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:26 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 10/18] hw/arm/fsl-imx8mp: Add I2C controllers
  2025-02-04  9:21 ` [PATCH v2 10/18] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
@ 2025-02-06 17:26   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:26 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst |  1 +
>  include/hw/arm/fsl-imx8mp.h    | 11 +++++++++++
>  hw/arm/fsl-imx8mp.c            | 29 +++++++++++++++++++++++++++++
>  hw/arm/Kconfig                 |  2 ++
>  4 files changed, 43 insertions(+)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 11/18] hw/arm/fsl-imx8mp: Add SPI controllers
  2025-02-04  9:21 ` [PATCH v2 11/18] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
@ 2025-02-06 17:26   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:26 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst |  1 +
>  include/hw/arm/fsl-imx8mp.h    |  8 ++++++++
>  hw/arm/fsl-imx8mp.c            | 26 ++++++++++++++++++++++++++
>  3 files changed, 35 insertions(+)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 12/18] hw/arm/fsl-imx8mp: Add watchdog support
  2025-02-04  9:21 ` [PATCH v2 12/18] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
@ 2025-02-06 17:27   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:27 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst |  1 +
>  include/hw/arm/fsl-imx8mp.h    |  7 +++++++
>  hw/arm/fsl-imx8mp.c            | 28 ++++++++++++++++++++++++++++
>  hw/arm/Kconfig                 |  1 +
>  4 files changed, 37 insertions(+)
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers
  2025-02-04  9:21 ` [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
@ 2025-02-06 17:29   ` Peter Maydell
  2025-02-07  8:08     ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:29 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst |  1 +
>  include/hw/arm/fsl-imx8mp.h    | 11 +++++++
>  include/hw/timer/imx_gpt.h     |  1 +
>  hw/arm/fsl-imx8mp.c            | 53 ++++++++++++++++++++++++++++++++++
>  hw/timer/imx_gpt.c             | 25 ++++++++++++++++
>  hw/arm/Kconfig                 |  1 +
>  6 files changed, 92 insertions(+)

Typo in the subject: "general". Otherwise

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 14/18] hw/arm/fsl-imx8mp: Add Ethernet controller
  2025-02-04  9:21 ` [PATCH v2 14/18] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
@ 2025-02-06 17:30   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:30 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> The i.MX 8M Plus SoC actually has two ethernet controllers, the usual ENET one
> and a Designware one. There is no device model for the latter, so only add the
> ENET one.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst |  1 +
>  include/hw/arm/fsl-imx8mp.h    |  8 ++++++++
>  hw/arm/fsl-imx8mp.c            | 24 ++++++++++++++++++++++++
>  hw/arm/imx8mp-evk.c            |  1 +
>  hw/arm/Kconfig                 |  1 +
>  5 files changed, 35 insertions(+)
>


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 15/18] hw/arm/fsl-imx8mp: Add USB support
  2025-02-04  9:21 ` [PATCH v2 15/18] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
@ 2025-02-06 17:31   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:31 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Split the USB MMIO regions to better keep track of the implemented vs.
> unimplemented regions.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  docs/system/arm/imx8mp-evk.rst |  1 +
>  include/hw/arm/fsl-imx8mp.h    | 12 +++++++++++
>  hw/arm/fsl-imx8mp.c            | 37 ++++++++++++++++++++++++++++++++--
>  hw/arm/Kconfig                 |  1 +
>  4 files changed, 49 insertions(+), 2 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 17/18] hw/arm/fsl-imx8mp: Add on-chip RAM
  2025-02-04  9:21 ` [PATCH v2 17/18] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
@ 2025-02-06 17:31   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:31 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  include/hw/arm/fsl-imx8mp.h |  1 +
>  hw/arm/fsl-imx8mp.c         | 11 +++++++++++
>  2 files changed, 12 insertions(+)
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-02-04  9:21 ` [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
@ 2025-02-06 17:32   ` Peter Maydell
  2025-02-06 21:58     ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-06 17:32 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> The implementation just allows Linux to determine date and time.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  MAINTAINERS         |   1 +
>  hw/rtc/rs5c372.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++
>  hw/rtc/Kconfig      |   5 +
>  hw/rtc/meson.build  |   1 +
>  hw/rtc/trace-events |   4 +
>  5 files changed, 238 insertions(+)
>  create mode 100644 hw/rtc/rs5c372.c

Should there be a patch after this one that adds this device
to your board ?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-02-06 17:32   ` Peter Maydell
@ 2025-02-06 21:58     ` Bernhard Beschow
  2025-02-10 14:26       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-06 21:58 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 6. Februar 2025 17:32:31 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> The implementation just allows Linux to determine date and time.
>>
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> ---
>>  MAINTAINERS         |   1 +
>>  hw/rtc/rs5c372.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++
>>  hw/rtc/Kconfig      |   5 +
>>  hw/rtc/meson.build  |   1 +
>>  hw/rtc/trace-events |   4 +
>>  5 files changed, 238 insertions(+)
>>  create mode 100644 hw/rtc/rs5c372.c
>
>Should there be a patch after this one that adds this device
>to your board ?

As per Kconfig the board selects I2C_DEVICES and this device is "default y if I2C_DEVICES". I've deliberately not hardcoded this device to the board to make it emulate a plain i.MX 8M Plus SoC (see also board documentation).

Best regards,
Bernhard
 
>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers
  2025-02-06 17:29   ` Peter Maydell
@ 2025-02-07  8:08     ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-07  8:08 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 6. Februar 2025 17:29:16 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> ---
>>  docs/system/arm/imx8mp-evk.rst |  1 +
>>  include/hw/arm/fsl-imx8mp.h    | 11 +++++++
>>  include/hw/timer/imx_gpt.h     |  1 +
>>  hw/arm/fsl-imx8mp.c            | 53 ++++++++++++++++++++++++++++++++++
>>  hw/timer/imx_gpt.c             | 25 ++++++++++++++++
>>  hw/arm/Kconfig                 |  1 +
>>  6 files changed, 92 insertions(+)
>
>Typo in the subject: "general". Otherwise

Will be fixed in v3.
>
>Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

Thanks,
Bernhard

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-02-06 21:58     ` Bernhard Beschow
@ 2025-02-10 14:26       ` Philippe Mathieu-Daudé
  2025-02-10 22:48         ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-10 14:26 UTC (permalink / raw)
  To: Bernhard Beschow, Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On 6/2/25 22:58, Bernhard Beschow wrote:
> 
> 
> Am 6. Februar 2025 17:32:31 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>> On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>>
>>> The implementation just allows Linux to determine date and time.
>>>
>>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>>> ---
>>>   MAINTAINERS         |   1 +
>>>   hw/rtc/rs5c372.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++
>>>   hw/rtc/Kconfig      |   5 +
>>>   hw/rtc/meson.build  |   1 +
>>>   hw/rtc/trace-events |   4 +
>>>   5 files changed, 238 insertions(+)
>>>   create mode 100644 hw/rtc/rs5c372.c
>>
>> Should there be a patch after this one that adds this device
>> to your board ?
> 
> As per Kconfig the board selects I2C_DEVICES and this device is "default y if I2C_DEVICES". I've deliberately not hardcoded this device to the board to make it emulate a plain i.MX 8M Plus SoC (see also board documentation).

Then maybe add a test to be sure it is not bitroting?


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board
  2025-02-04  9:20 ` [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
@ 2025-02-10 17:30   ` Peter Maydell
  2025-02-10 22:44     ` Bernhard Beschow
  2025-02-23 11:40     ` Bernhard Beschow
  0 siblings, 2 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-10 17:30 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
> serial. All other devices of the A53 memory map are represented as
> TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
> for running Linux without it crashing due to invalid memory accesses.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---



> --- /dev/null
> +++ b/docs/system/arm/imx8mp-evk.rst
> @@ -0,0 +1,56 @@
> +NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
> +================================================
> +
> +The QEMU i.MX 8M Plus EVK board emulation is intended to emulate a plain i.MX 8M
> +Plus system on chip (SoC). All peripherals the real board has such as flash and
> +I2C devices are intended to be added via configuration, e.g. command line.

Why do this? If they're on the real hardware board, we should
be creating them by default in the machine model in QEMU.
Command line options are for devices that are optional and
pluggable by the user on the hardware.

> +Supported devices
> +-----------------
> +
> +The ``imx8mp-evk`` machine implements the following devices:
> +
> + * Up to 4 Cortex-A53 Cores

"cores"

> + * Generic Interrupt Controller (GICv3)
> + * 4 UARTs
> +
> +Boot options
> +------------
> +
> +The ``imx8mp-evk`` machine can start using the standard -kernel functionality
> +for loading a Linux kernel.
> +
> +Direct Linux Kernel Boot
> +''''''''''''''''''''''''
> +
> +Probably the easiest way to get started with a whole Linux system on the machine
> +is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
> +of writing and involves two steps. First run the following commands in the
> +toplevel directory of the Buildroot source tree:
> +
> +.. code-block:: bash
> +
> +  $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
> +  $ make freescale_imx8mpevk_defconfig
> +  $ make
> +
> +Once finished successfully there is an ``output/image`` subfolder. Navigate into
> +it patch the device tree needs to be patched with the following commands which
> +will remove the ``cpu-idle-states`` properties from CPU nodes:

This sentence seems to be confused in the middle -- cut-and-paste
error ?

> +
> +.. code-block:: bash
> +
> +  $ dtc imx8mp-evk.dtb | sed '/cpu-idle-states/d' > imx8mp-evk-patched.dts
> +  $ dtc imx8mp-evk-patched.dts -o imx8mp-evk-patched.dtb
> +
> +Now that everything is prepared the newly built image can be run in the QEMU
> +``imx8mp-evk`` machine:

> +#define NAME_SIZE 20
> +
> +static void fsl_imx8mp_init(Object *obj)
> +{
> +    MachineState *ms = MACHINE(qdev_get_machine());
> +    FslImx8mpState *s = FSL_IMX8MP(obj);
> +    char name[NAME_SIZE];

Better than fixed sized char arrays for object names
is to use
   g_autofree char *name = g_strdup_printf("cpu%d", i);
inside the block of each for() loop etc.

> +    int i;
> +
> +    for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
> +        snprintf(name, NAME_SIZE, "cpu%d", i);
> +        object_initialize_child(obj, name, &s->cpu[i],
> +                                ARM_CPU_TYPE_NAME("cortex-a53"));
> +    }
> +
> +    object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
> +
> +    for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
> +        snprintf(name, NAME_SIZE, "uart%d", i + 1);
> +        object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
> +    }
> +}
> +
> +static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
> +{
> +    MachineState *ms = MACHINE(qdev_get_machine());
> +    FslImx8mpState *s = FSL_IMX8MP(dev);
> +    DeviceState *gicdev = DEVICE(&s->gic);
> +    int i;
> +
> +    if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
> +        error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
> +                   TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus);
> +        return;
> +    }
> +
> +    /* CPUs */
> +    for (i = 0; i < ms->smp.cpus; i++) {
> +        /* On uniprocessor, the CBAR is set to 0 */
> +        if (ms->smp.cpus > 1) {
> +            object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
> +                                    fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
> +                                    &error_abort);
> +        }
> +
> +        /*
> +         * Magic value from Linux output: "arch_timer: cp15 timer(s) running at
> +         * 8.00MHz (phys)".
> +         */
> +        object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
> +                                &error_abort);

This is the CNTFRQ value in Hz. The datasheet actually tells you
this, so we don't need to call it a magic number (section 4.11.4.1.6.4
of the i.MX 8M Plus Applications Processor Reference Manual says the
base frequency of the system counter is 8MHz).

(Incidentally the memory mapped system counter is a stock Arm
IP block and I have about 60% of a model of it, I just haven't
needed to upstream it yet because in practice no guest software
really tries to mess with it. If we turn out to need it for
this SoC that would be a reason for me to clean it up and
send it out. But I suspect we don't need it in practice.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board
  2025-02-10 17:30   ` Peter Maydell
@ 2025-02-10 22:44     ` Bernhard Beschow
  2025-02-11 10:06       ` Peter Maydell
  2025-02-23 11:40     ` Bernhard Beschow
  1 sibling, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-10 22:44 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 10. Februar 2025 17:30:01 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
>> serial. All other devices of the A53 memory map are represented as
>> TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
>> for running Linux without it crashing due to invalid memory accesses.
>>
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> ---
>
>
>
>> --- /dev/null
>> +++ b/docs/system/arm/imx8mp-evk.rst
>> @@ -0,0 +1,56 @@
>> +NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
>> +================================================
>> +
>> +The QEMU i.MX 8M Plus EVK board emulation is intended to emulate a plain i.MX 8M
>> +Plus system on chip (SoC). All peripherals the real board has such as flash and
>> +I2C devices are intended to be added via configuration, e.g. command line.
>
>Why do this? If they're on the real hardware board, we should
>be creating them by default in the machine model in QEMU.
>Command line options are for devices that are optional and
>pluggable by the user on the hardware.

My goal is to be able to model a custom, proprietary machine which runs in a CI. In order to avoid peripherals getting in the way, the idea is to have a machine which essentially exposes the plain SoC, and allow users to "decorate" it themselves. Is an EVK machine the wrong approach for this? Are there any other ways to achieve this, e.g. with -nodefaults?

>
>> +Supported devices
>> +-----------------
>> +
>> +The ``imx8mp-evk`` machine implements the following devices:
>> +
>> + * Up to 4 Cortex-A53 Cores
>
>"cores"

Fixed in v3.

>
>> + * Generic Interrupt Controller (GICv3)
>> + * 4 UARTs
>> +
>> +Boot options
>> +------------
>> +
>> +The ``imx8mp-evk`` machine can start using the standard -kernel functionality
>> +for loading a Linux kernel.
>> +
>> +Direct Linux Kernel Boot
>> +''''''''''''''''''''''''
>> +
>> +Probably the easiest way to get started with a whole Linux system on the machine
>> +is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
>> +of writing and involves two steps. First run the following commands in the
>> +toplevel directory of the Buildroot source tree:
>> +
>> +.. code-block:: bash
>> +
>> +  $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
>> +  $ make freescale_imx8mpevk_defconfig
>> +  $ make
>> +
>> +Once finished successfully there is an ``output/image`` subfolder. Navigate into
>> +it patch the device tree needs to be patched with the following commands which
>> +will remove the ``cpu-idle-states`` properties from CPU nodes:
>
>This sentence seems to be confused in the middle -- cut-and-paste
>error ?

Yeah, probably. Fixed in v3.

>
>> +
>> +.. code-block:: bash
>> +
>> +  $ dtc imx8mp-evk.dtb | sed '/cpu-idle-states/d' > imx8mp-evk-patched.dts
>> +  $ dtc imx8mp-evk-patched.dts -o imx8mp-evk-patched.dtb
>> +
>> +Now that everything is prepared the newly built image can be run in the QEMU
>> +``imx8mp-evk`` machine:
>
>> +#define NAME_SIZE 20
>> +
>> +static void fsl_imx8mp_init(Object *obj)
>> +{
>> +    MachineState *ms = MACHINE(qdev_get_machine());
>> +    FslImx8mpState *s = FSL_IMX8MP(obj);
>> +    char name[NAME_SIZE];
>
>Better than fixed sized char arrays for object names
>is to use
>   g_autofree char *name = g_strdup_printf("cpu%d", i);
>inside the block of each for() loop etc.

Will fix for v3, touching subsequent patches.

>
>> +    int i;
>> +
>> +    for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
>> +        snprintf(name, NAME_SIZE, "cpu%d", i);
>> +        object_initialize_child(obj, name, &s->cpu[i],
>> +                                ARM_CPU_TYPE_NAME("cortex-a53"));
>> +    }
>> +
>> +    object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
>> +
>> +    for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
>> +        snprintf(name, NAME_SIZE, "uart%d", i + 1);
>> +        object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>> +    }
>> +}
>> +
>> +static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
>> +{
>> +    MachineState *ms = MACHINE(qdev_get_machine());
>> +    FslImx8mpState *s = FSL_IMX8MP(dev);
>> +    DeviceState *gicdev = DEVICE(&s->gic);
>> +    int i;
>> +
>> +    if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
>> +        error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>> +                   TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus);
>> +        return;
>> +    }
>> +
>> +    /* CPUs */
>> +    for (i = 0; i < ms->smp.cpus; i++) {
>> +        /* On uniprocessor, the CBAR is set to 0 */
>> +        if (ms->smp.cpus > 1) {
>> +            object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>> +                                    fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
>> +                                    &error_abort);
>> +        }
>> +
>> +        /*
>> +         * Magic value from Linux output: "arch_timer: cp15 timer(s) running at
>> +         * 8.00MHz (phys)".
>> +         */
>> +        object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>> +                                &error_abort);
>
>This is the CNTFRQ value in Hz. The datasheet actually tells you
>this, so we don't need to call it a magic number (section 4.11.4.1.6.4
>of the i.MX 8M Plus Applications Processor Reference Manual says the
>base frequency of the system counter is 8MHz).

Ah, so then it's the "nxp,sysctr-timer"-compatible counter in the device tree? I've stared my own implementation but didn't see the relation to the cp15 timer. Thanks for clarifying this. I'd comment: 'CNTFID0 base frequency in Hz'.

>
>(Incidentally the memory mapped system counter is a stock Arm
>IP block and I have about 60% of a model of it, I just haven't
>needed to upstream it yet because in practice no guest software
>really tries to mess with it. If we turn out to need it for
>this SoC that would be a reason for me to clean it up and
>send it out. But I suspect we don't need it in practice.)

The ugly workaround for the cpu-idle-states above is actually related to this counter, IIUC. I suppose that QEMU doesn't support these idle states, it only seems to support WFI. But if it did, then this counter would wake up the CPUs (if I'm not mistaken, I'm no expert here). It would be nice to be able to boot the machine via U-Boot, and I wonder if that could fix the idle states when there are PSCI handlers in the secure world. Again, this probably also requires the counter implementation. Looking into U-Boot, TF-A, and OP-TEE is on my plan, but right now I'm focusing on direct kernel boot.

Best regards,
Bernhard

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-02-10 14:26       ` Philippe Mathieu-Daudé
@ 2025-02-10 22:48         ` Bernhard Beschow
  2025-02-23 10:57           ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-10 22:48 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 10. Februar 2025 14:26:00 UTC schrieb "Philippe Mathieu-Daudé" <philmd@linaro.org>:
>On 6/2/25 22:58, Bernhard Beschow wrote:
>> 
>> 
>> Am 6. Februar 2025 17:32:31 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>>> On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>>> 
>>>> The implementation just allows Linux to determine date and time.
>>>> 
>>>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>>>> ---
>>>>   MAINTAINERS         |   1 +
>>>>   hw/rtc/rs5c372.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++
>>>>   hw/rtc/Kconfig      |   5 +
>>>>   hw/rtc/meson.build  |   1 +
>>>>   hw/rtc/trace-events |   4 +
>>>>   5 files changed, 238 insertions(+)
>>>>   create mode 100644 hw/rtc/rs5c372.c
>>> 
>>> Should there be a patch after this one that adds this device
>>> to your board ?
>> 
>> As per Kconfig the board selects I2C_DEVICES and this device is "default y if I2C_DEVICES". I've deliberately not hardcoded this device to the board to make it emulate a plain i.MX 8M Plus SoC (see also board documentation).
>
>Then maybe add a test to be sure it is not bitroting?

Good idea. I haven't written a test in QEMU yet but I could certainly draw some inspiration from ds1338-test.c. This may take an iteration longer but won't be forgotten.

Best regards,
Bernhard


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board
  2025-02-10 22:44     ` Bernhard Beschow
@ 2025-02-11 10:06       ` Peter Maydell
  2025-02-11 23:40         ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-11 10:06 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Mon, 10 Feb 2025 at 22:44, Bernhard Beschow <shentey@gmail.com> wrote:
>
>
>
> Am 10. Februar 2025 17:30:01 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
> >On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
> >>
> >> As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
> >> serial. All other devices of the A53 memory map are represented as
> >> TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
> >> for running Linux without it crashing due to invalid memory accesses.
> >>
> >> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> >> ---
> >
> >
> >
> >> --- /dev/null
> >> +++ b/docs/system/arm/imx8mp-evk.rst
> >> @@ -0,0 +1,56 @@
> >> +NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
> >> +================================================
> >> +
> >> +The QEMU i.MX 8M Plus EVK board emulation is intended to emulate a plain i.MX 8M
> >> +Plus system on chip (SoC). All peripherals the real board has such as flash and
> >> +I2C devices are intended to be added via configuration, e.g. command line.
> >
> >Why do this? If they're on the real hardware board, we should
> >be creating them by default in the machine model in QEMU.
> >Command line options are for devices that are optional and
> >pluggable by the user on the hardware.
>
> My goal is to be able to model a custom, proprietary machine which runs in a CI. In order to avoid peripherals getting in the way, the idea is to have a machine which essentially exposes the plain SoC, and allow users to "decorate" it themselves. Is an EVK machine the wrong approach for this? Are there any other ways to achieve this, e.g. with -nodefaults?

That's not really a usage model QEMU currently supports. We generally
speaking model what the actual hardware does. In the same way,
if you were running CI on the real EVK board your CI would have
to deal with those devices being present.

> >> +        /*
> >> +         * Magic value from Linux output: "arch_timer: cp15 timer(s) running at
> >> +         * 8.00MHz (phys)".
> >> +         */
> >> +        object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
> >> +                                &error_abort);
> >
> >This is the CNTFRQ value in Hz. The datasheet actually tells you
> >this, so we don't need to call it a magic number (section 4.11.4.1.6.4
> >of the i.MX 8M Plus Applications Processor Reference Manual says the
> >base frequency of the system counter is 8MHz).
>
> Ah, so then it's the "nxp,sysctr-timer"-compatible counter in
> the device tree? I've stared my own implementation but didn't
> see the relation to the cp15 timer. Thanks for clarifying this.

Yeah; I haven't actually checked carefully whether there
are NXP specifics here, as that device-tree compat string
suggests. But it's almost certainly the same general principle:
there's a memory-mapped system counter which is the global
source of the system count, and each CPU consumes that count
and uses it to feed its generic timers and counters. So if
you mess with the enable on the memory mapped system counter
then this causes the CPU's timers/counters to stop ticking.

I modelled this similarly to the in-tree M-profile
sse-counter and sse-timer, where you link the timer to
the counter and there's an API that lets the timer know
when the counter is enabled/disabled, changes frequency, etc.
This needs changes to the timer and counter code in the CPU
itself. (You can get away without doing this if you assume
that the guest code never tries to actually disable the system
counter or pick a non-default frequency, which is typically true:
it will just want to set it up to a single standard config and
then leave it alone.)

> >(Incidentally the memory mapped system counter is a stock Arm
> >IP block and I have about 60% of a model of it, I just haven't
> >needed to upstream it yet because in practice no guest software
> >really tries to mess with it. If we turn out to need it for
> >this SoC that would be a reason for me to clean it up and
> >send it out. But I suspect we don't need it in practice.)
>
> The ugly workaround for the cpu-idle-states above is actually related to this counter, IIUC. I suppose that QEMU doesn't support these idle states, it only seems to support WFI. But if it did, then this counter would wake up the CPUs (if I'm not mistaken, I'm no expert here). It would be nice to be able to boot the machine via U-Boot, and I wonder if that could fix the idle states when there are PSCI handlers in the secure world. Again, this probably also requires the counter implementation. Looking into U-Boot, TF-A, and OP-TEE is on my plan, but right now I'm focusing on direct kernel boot.

Hmm, if the system counter can generate interrupts then
it might be different from the Arm IP block in that
respect. I'd have to check the datasheet. Anyway, as
you suggest this is all something we can postpone until
we need to care about running EL3 firmware in the guest.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board
  2025-02-11 10:06       ` Peter Maydell
@ 2025-02-11 23:40         ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-11 23:40 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 11. Februar 2025 10:06:19 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Mon, 10 Feb 2025 at 22:44, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>>
>>
>> Am 10. Februar 2025 17:30:01 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>> >On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>> >>
>> >> As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
>> >> serial. All other devices of the A53 memory map are represented as
>> >> TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
>> >> for running Linux without it crashing due to invalid memory accesses.
>> >>
>> >> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> >> ---
>> >
>> >
>> >
>> >> --- /dev/null
>> >> +++ b/docs/system/arm/imx8mp-evk.rst
>> >> @@ -0,0 +1,56 @@
>> >> +NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
>> >> +================================================
>> >> +
>> >> +The QEMU i.MX 8M Plus EVK board emulation is intended to emulate a plain i.MX 8M
>> >> +Plus system on chip (SoC). All peripherals the real board has such as flash and
>> >> +I2C devices are intended to be added via configuration, e.g. command line.
>> >
>> >Why do this? If they're on the real hardware board, we should
>> >be creating them by default in the machine model in QEMU.
>> >Command line options are for devices that are optional and
>> >pluggable by the user on the hardware.
>>
>> My goal is to be able to model a custom, proprietary machine which runs in a CI. In order to avoid peripherals getting in the way, the idea is to have a machine which essentially exposes the plain SoC, and allow users to "decorate" it themselves. Is an EVK machine the wrong approach for this? Are there any other ways to achieve this, e.g. with -nodefaults?
>
>That's not really a usage model QEMU currently supports. We generally
>speaking model what the actual hardware does. 

Why not support such usage model? The machine in this series works amazingly well for our purposes. If modeling a concrete board implies hardcoding peripherals, would modeling an artificial "board" which just contains the SoC work instead? IOW should I drop the "-evk" suffix from the machine and claim it only models the SoC?

>In the same way,
>if you were running CI on the real EVK board your CI would have
>to deal with those devices being present.
>
>> >> +        /*
>> >> +         * Magic value from Linux output: "arch_timer: cp15 timer(s) running at
>> >> +         * 8.00MHz (phys)".
>> >> +         */
>> >> +        object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>> >> +                                &error_abort);
>> >
>> >This is the CNTFRQ value in Hz. The datasheet actually tells you
>> >this, so we don't need to call it a magic number (section 4.11.4.1.6.4
>> >of the i.MX 8M Plus Applications Processor Reference Manual says the
>> >base frequency of the system counter is 8MHz).
>>
>> Ah, so then it's the "nxp,sysctr-timer"-compatible counter in
>> the device tree? I've stared my own implementation but didn't
>> see the relation to the cp15 timer. Thanks for clarifying this.
>
>Yeah; I haven't actually checked carefully whether there
>are NXP specifics here, as that device-tree compat string
>suggests. But it's almost certainly the same general principle:
>there's a memory-mapped system counter which is the global
>source of the system count, and each CPU consumes that count
>and uses it to feed its generic timers and counters. So if
>you mess with the enable on the memory mapped system counter
>then this causes the CPU's timers/counters to stop ticking.

Yeah, this also is how I understand the documentation of the system counter in the reference manual.

>
>I modelled this similarly to the in-tree M-profile
>sse-counter and sse-timer, where you link the timer to
>the counter and there's an API that lets the timer know
>when the counter is enabled/disabled, changes frequency, etc.
>This needs changes to the timer and counter code in the CPU
>itself. (You can get away without doing this if you assume
>that the guest code never tries to actually disable the system
>counter or pick a non-default frequency, which is typically true:
>it will just want to set it up to a single standard config and
>then leave it alone.)

I have this implementation which puts the focus more on waking up the CPUs via the IRQ: <https://github.com/shentok/qemu/commit/1aa0887a5ff926572ab40b39fe5a087acb3ff249> The IRQ fires but doesn't wake any CPU in case of direct kernel boot since the IRQ is masked in EL1 (rich OS mode) and EL3 isn't set up.

>
>> >(Incidentally the memory mapped system counter is a stock Arm
>> >IP block and I have about 60% of a model of it, I just haven't
>> >needed to upstream it yet because in practice no guest software
>> >really tries to mess with it. If we turn out to need it for
>> >this SoC that would be a reason for me to clean it up and
>> >send it out. But I suspect we don't need it in practice.)
>>
>> The ugly workaround for the cpu-idle-states above is actually related to this counter, IIUC. I suppose that QEMU doesn't support these idle states, it only seems to support WFI. But if it did, then this counter would wake up the CPUs (if I'm not mistaken, I'm no expert here). It would be nice to be able to boot the machine via U-Boot, and I wonder if that could fix the idle states when there are PSCI handlers in the secure world. Again, this probably also requires the counter implementation. Looking into U-Boot, TF-A, and OP-TEE is on my plan, but right now I'm focusing on direct kernel boot.
>
>Hmm, if the system counter can generate interrupts then
>it might be different from the Arm IP block in that
>respect. I'd have to check the datasheet. Anyway, as
>you suggest this is all something we can postpone until
>we need to care about running EL3 firmware in the guest.

Yeah, this would probably work with U-Boot then. But for direct kernel boot we'd need support beyond WFI directly in QEMU -- which is currently missing, right?

Best regards,
Bernhard

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM
  2025-02-04  9:21 ` [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
@ 2025-02-17 13:28   ` Peter Maydell
  2025-02-17 22:48     ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-17 13:28 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> On a real device, the boot ROM contains the very first instructions the CPU
> executes. Also, U-Boot calls into the ROM to determine the boot device. While
> we're not actually implementing this here, let's create the infrastructure and
> add a dummy ROM with all zeros. This allows for implementing a ROM later without
> touching the source code and even allows for users to provide their own ROMs.
>
> The imx8mp-boot.rom was created with
> `dd if=/dev/zero of=imx8mp-boot.rom bs=1 count=258048`.

If it's all zeroes, we don't need to commit it to git as a binary,
we can generate it at build time. (We should avoid having
binaries in git as much as we can manage.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations
  2025-02-04  9:20 ` [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations Bernhard Beschow
@ 2025-02-17 13:35   ` Peter Maydell
  2025-02-17 19:39     ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-17 13:35 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> While at it and since they are user-creatable, build them when
> CONFIG_I2C_DEVICES is set.

The patch subject says this is just a rearrangement
of the Kconfig stanzas with no behaviour change, but then the
commit message body includes one.

If you want to build these when CONFIG_I2C_DEVICES is set,
that should be its own patch that does that.

(The move of the Kconfig bits to hw/gpio is fixing a bug
in 6328d8ffa6cb9d ("misc/pca955*: Move models under hw/gpio"),
which moved the code but forgot to move the Kconfig sections.)

Separately, it's unclear to me how worthwhile it is to add
these to CONFIG_I2C_DEVICES, because they're GPIO devices,
which means there's not much you can do with them as a user:
as far as I know you can't wire the output/input GPIO lines
up to anything. We have the device models mainly for boards
which provide them, so that guest code that expects to see
them doesn't fall over on bootup, and because the board
model code does have the APIs to wire up the GPIO lines.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 02/18] hw/pci-host/designware: Prevent device attachment on internal PCIe root bus
  2025-02-04  9:20 ` [PATCH v2 02/18] hw/pci-host/designware: Prevent device attachment on internal PCIe root bus Bernhard Beschow
@ 2025-02-17 13:36   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-17 13:36 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> On the real device, the PCIe root bus is only connected to a PCIe bridge and
> does not allow for direct attachment of devices. Doing so in QEMU results in no
> PCI devices being detected by Linux. Instead, PCI devices should plug into the
> secondary PCIe bus spawned by the internal PCIe bridge.
>
> Unfortunately, QEMU defaults to plugging devices into the PCIe root bus. To work
> around this, every PCI device created on the command line needs an extra
> `bus=dw-pcie` option which is error prone. Fix that by marking the PCIe root bus
> as full which makes QEMU decend into the child PCIe bus.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>  include/hw/pci-host/designware.h |  7 +++++++
>  hw/pci-host/designware.c         | 18 +++++++++++++++++-
>  2 files changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
> index bf8b278978..a35a3bd06c 100644
> --- a/include/hw/pci-host/designware.h
> +++ b/include/hw/pci-host/designware.h
> @@ -25,12 +25,19 @@
>  #include "hw/pci/pci_bridge.h"
>  #include "qom/object.h"
>
> +#define TYPE_DESIGNWARE_PCIE_ROOT_BUS "designware-pcie-root-BUS"
> +OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERootBus, DESIGNWARE_PCIE_ROOT_BUS)
> +
>  #define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
>  OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
>
>  #define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
>  OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
>
> +struct DesignwarePCIERootBus {
> +    PCIBus parent;
> +};
> +
>  typedef struct DesignwarePCIEViewport {
>      DesignwarePCIERoot *root;
>
> diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
> index 3e8c36e6a7..c07740bfaa 100644
> --- a/hw/pci-host/designware.c
> +++ b/hw/pci-host/designware.c
> @@ -55,6 +55,17 @@
>  #define DESIGNWARE_PCIE_ATU_DEVFN(x)               (((x) >> 16) & 0xff)
>  #define DESIGNWARE_PCIE_ATU_UPPER_TARGET           0x91C
>
> +static void designware_pcie_root_bus_class_init(ObjectClass *klass, void *data)
> +{
> +    BusClass *k = BUS_CLASS(klass);
> +
> +    /*
> +     * Designware has only a single root complex. Enforce the limit on the
> +     * parent bus
> +     */
> +    k->max_dev = 1;
> +}

This seems to be what we do in at least one other PCI host
controller, so

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support
  2025-02-04  9:21 ` [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
@ 2025-02-17 13:40   ` Peter Maydell
  2025-02-17 16:33     ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-17 13:40 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Linux checks for the PLLs in the PHY to be locked, so implement a model
> emulating that.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---

> +static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
> +    .name = "fsl-imx8m-pcie-phy",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (const VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
> +                            ARRAY_SIZE(((FslImx8mPciePhyState *)NULL)->data)),

Use a defined constant for the number of array elements, please.
We don't do this thing with ARRAY_SIZE of a cast NULL pointer
anywhere else in the codebase.

> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = fsl_imx8m_pcie_phy_realize;
> +    dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
> +}

This is missing the reset method.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support
  2025-02-17 13:40   ` Peter Maydell
@ 2025-02-17 16:33     ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-17 16:33 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 17. Februar 2025 13:40:48 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> Linux checks for the PLLs in the PHY to be locked, so implement a model
>> emulating that.
>>
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> ---
>
>> +static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
>> +    .name = "fsl-imx8m-pcie-phy",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .fields = (const VMStateField[]) {
>> +        VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
>> +                            ARRAY_SIZE(((FslImx8mPciePhyState *)NULL)->data)),
>
>Use a defined constant for the number of array elements, please.
>We don't do this thing with ARRAY_SIZE of a cast NULL pointer
>anywhere else in the codebase.

Ack -- will change to a named constant. I think I took inspiration from <https://gitlab.com/qemu-project/qemu/-/blob/v9.2.1/hw/scsi/vmw_pvscsi.c?ref_type=tags#L1276>

>
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    dc->realize = fsl_imx8m_pcie_phy_realize;
>> +    dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
>> +}
>
>This is missing the reset method.

Indeed. I'll add it.

Thanks for the review,
Bernhard

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations
  2025-02-17 13:35   ` Peter Maydell
@ 2025-02-17 19:39     ` Bernhard Beschow
  2025-02-18 10:33       ` Peter Maydell
  0 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-17 19:39 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 17. Februar 2025 13:35:04 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> While at it and since they are user-creatable, build them when
>> CONFIG_I2C_DEVICES is set.
>
>The patch subject says this is just a rearrangement
>of the Kconfig stanzas with no behaviour change, but then the
>commit message body includes one.
>
>If you want to build these when CONFIG_I2C_DEVICES is set,
>that should be its own patch that does that.
>
>(The move of the Kconfig bits to hw/gpio is fixing a bug
>in 6328d8ffa6cb9d ("misc/pca955*: Move models under hw/gpio"),
>which moved the code but forgot to move the Kconfig sections.)

Okay, I'll split the patch and use above commit message.

>
>Separately, it's unclear to me how worthwhile it is to add
>these to CONFIG_I2C_DEVICES, because they're GPIO devices,
>which means there's not much you can do with them as a user:
>as far as I know you can't wire the output/input GPIO lines
>up to anything. We have the device models mainly for boards
>which provide them, so that guest code that expects to see
>them doesn't fall over on bootup, and because the board
>model code does have the APIs to wire up the GPIO lines.

It's basically to satisfy Linux which will clog the i2c bus if such a GPIO expander is configured in the DTB but missing in the emulation (it will defer probing which will never make progress). Once it is its own patch we can decide separately how to proceed with it, e.g. dropping.

Best regards,
Bernhard

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM
  2025-02-17 13:28   ` Peter Maydell
@ 2025-02-17 22:48     ` Bernhard Beschow
  2025-02-23 11:04       ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-17 22:48 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 17. Februar 2025 13:28:42 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> On a real device, the boot ROM contains the very first instructions the CPU
>> executes. Also, U-Boot calls into the ROM to determine the boot device. While
>> we're not actually implementing this here, let's create the infrastructure and
>> add a dummy ROM with all zeros. This allows for implementing a ROM later without
>> touching the source code and even allows for users to provide their own ROMs.
>>
>> The imx8mp-boot.rom was created with
>> `dd if=/dev/zero of=imx8mp-boot.rom bs=1 count=258048`.
>
>If it's all zeroes, we don't need to commit it to git as a binary,
>we can generate it at build time. (We should avoid having
>binaries in git as much as we can manage.)

I went with this solution since it trivially works on any build platform. Any idea how to generate the file in a portable way?

Thanks,
Bernhard

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations
  2025-02-17 19:39     ` Bernhard Beschow
@ 2025-02-18 10:33       ` Peter Maydell
  2025-02-19 21:43         ` Bernhard Beschow
  0 siblings, 1 reply; 52+ messages in thread
From: Peter Maydell @ 2025-02-18 10:33 UTC (permalink / raw)
  To: Bernhard Beschow; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini

On Mon, 17 Feb 2025 at 20:21, Bernhard Beschow <shentey@gmail.com> wrote:
>
>
>
> Am 17. Februar 2025 13:35:04 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
> >On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
> >>
> >> While at it and since they are user-creatable, build them when
> >> CONFIG_I2C_DEVICES is set.
> >
> >The patch subject says this is just a rearrangement
> >of the Kconfig stanzas with no behaviour change, but then the
> >commit message body includes one.
> >
> >If you want to build these when CONFIG_I2C_DEVICES is set,
> >that should be its own patch that does that.
> >
> >(The move of the Kconfig bits to hw/gpio is fixing a bug
> >in 6328d8ffa6cb9d ("misc/pca955*: Move models under hw/gpio"),
> >which moved the code but forgot to move the Kconfig sections.)
>
> Okay, I'll split the patch and use above commit message.
>
> >
> >Separately, it's unclear to me how worthwhile it is to add
> >these to CONFIG_I2C_DEVICES, because they're GPIO devices,
> >which means there's not much you can do with them as a user:
> >as far as I know you can't wire the output/input GPIO lines
> >up to anything. We have the device models mainly for boards
> >which provide them, so that guest code that expects to see
> >them doesn't fall over on bootup, and because the board
> >model code does have the APIs to wire up the GPIO lines.
>
> It's basically to satisfy Linux which will clog the i2c bus if such a GPIO expander is configured in the DTB but missing in the emulation (it will defer probing which will never make progress). Once it is its own patch we can decide separately how to proceed with it, e.g. dropping.

If Linux wants to see it because it's in the dtb for the
hardware it sounds like the right answer is that we
should create it in the board code, which we can do
without adding it to CONFIG_I2C_DEVICES, because we
can make the board code's Kconfig do "select PCA9552",
like the aspeed board does already.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations
  2025-02-18 10:33       ` Peter Maydell
@ 2025-02-19 21:43         ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-19 21:43 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 18. Februar 2025 10:33:26 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Mon, 17 Feb 2025 at 20:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>>
>>
>> Am 17. Februar 2025 13:35:04 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>> >On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>> >>
>> >> While at it and since they are user-creatable, build them when
>> >> CONFIG_I2C_DEVICES is set.
>> >
>> >The patch subject says this is just a rearrangement
>> >of the Kconfig stanzas with no behaviour change, but then the
>> >commit message body includes one.
>> >
>> >If you want to build these when CONFIG_I2C_DEVICES is set,
>> >that should be its own patch that does that.
>> >
>> >(The move of the Kconfig bits to hw/gpio is fixing a bug
>> >in 6328d8ffa6cb9d ("misc/pca955*: Move models under hw/gpio"),
>> >which moved the code but forgot to move the Kconfig sections.)
>>
>> Okay, I'll split the patch and use above commit message.
>>
>> >
>> >Separately, it's unclear to me how worthwhile it is to add
>> >these to CONFIG_I2C_DEVICES, because they're GPIO devices,
>> >which means there's not much you can do with them as a user:
>> >as far as I know you can't wire the output/input GPIO lines
>> >up to anything. We have the device models mainly for boards
>> >which provide them, so that guest code that expects to see
>> >them doesn't fall over on bootup, and because the board
>> >model code does have the APIs to wire up the GPIO lines.
>>
>> It's basically to satisfy Linux which will clog the i2c bus if such a GPIO expander is configured in the DTB but missing in the emulation (it will defer probing which will never make progress). Once it is its own patch we can decide separately how to proceed with it, e.g. dropping.
>
>If Linux wants to see it because it's in the dtb for the
>hardware it sounds like the right answer is that we
>should create it in the board code, which we can do
>without adding it to CONFIG_I2C_DEVICES, because we
>can make the board code's Kconfig do "select PCA9552",
>like the aspeed board does already.

These devices are primarily intended for modeling our custom hardware on the command line, for the purpose explained in [1]. While the real imx8mp-evk has a tca6416, I'd rather avoid creating it in board code, even if there was a model for it in QEMU. The reason is that the machine works fine without it as is, and that omitting hardcoded peripherals seems to increase the utility of the machine because it allows users to customize their machines without hardcoded peripherals getting into their way.

Since the two device models in this patch work by chance if other machines select them I'm fine with not implying CONFIG_I2C_DEVICES.

Best regards,
Bernhard

[1] https://lore.kernel.org/qemu-devel/831901E4-69B2-4637-8507-77C7BF4DA65D@gmail.com/

>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-02-10 22:48         ` Bernhard Beschow
@ 2025-02-23 10:57           ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-23 10:57 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 10. Februar 2025 22:48:24 UTC schrieb Bernhard Beschow <shentey@gmail.com>:
>
>
>Am 10. Februar 2025 14:26:00 UTC schrieb "Philippe Mathieu-Daudé" <philmd@linaro.org>:
>>On 6/2/25 22:58, Bernhard Beschow wrote:
>>> 
>>> 
>>> Am 6. Februar 2025 17:32:31 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>>>> On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>>>> 
>>>>> The implementation just allows Linux to determine date and time.
>>>>> 
>>>>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>>>>> ---
>>>>>   MAINTAINERS         |   1 +
>>>>>   hw/rtc/rs5c372.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++
>>>>>   hw/rtc/Kconfig      |   5 +
>>>>>   hw/rtc/meson.build  |   1 +
>>>>>   hw/rtc/trace-events |   4 +
>>>>>   5 files changed, 238 insertions(+)
>>>>>   create mode 100644 hw/rtc/rs5c372.c
>>>> 
>>>> Should there be a patch after this one that adds this device
>>>> to your board ?
>>> 
>>> As per Kconfig the board selects I2C_DEVICES and this device is "default y if I2C_DEVICES". I've deliberately not hardcoded this device to the board to make it emulate a plain i.MX 8M Plus SoC (see also board documentation).
>>
>>Then maybe add a test to be sure it is not bitroting?
>
>Good idea. I haven't written a test in QEMU yet but I could certainly draw some inspiration from ds1338-test.c. This may take an iteration longer but won't be forgotten.

There will be a test similar to ds1338-test.c in v3.

>
>Best regards,
>Bernhard


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM
  2025-02-17 22:48     ` Bernhard Beschow
@ 2025-02-23 11:04       ` Bernhard Beschow
  0 siblings, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-23 11:04 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 17. Februar 2025 22:48:23 UTC schrieb Bernhard Beschow <shentey@gmail.com>:
>
>
>Am 17. Februar 2025 13:28:42 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>>
>>> On a real device, the boot ROM contains the very first instructions the CPU
>>> executes. Also, U-Boot calls into the ROM to determine the boot device. While
>>> we're not actually implementing this here, let's create the infrastructure and
>>> add a dummy ROM with all zeros. This allows for implementing a ROM later without
>>> touching the source code and even allows for users to provide their own ROMs.
>>>
>>> The imx8mp-boot.rom was created with
>>> `dd if=/dev/zero of=imx8mp-boot.rom bs=1 count=258048`.
>>
>>If it's all zeroes, we don't need to commit it to git as a binary,
>>we can generate it at build time. (We should avoid having
>>binaries in git as much as we can manage.)
>
>I went with this solution since it trivially works on any build platform. Any idea how to generate the file in a portable way?

Besides this question, the compressed size of the file in Git is just 276 bytes:

  $ git hash-object pc-bios/imx8mp-boot.rom
  5324b5eed200e723d048f8476e4d96d45622fd4d
  $ git verify-pack -v .git/objects/pack/pack-*.idx | grep 5324b5eed2
  5324b5eed200e723d048f8476e4d96d45622fd4d blob   258048 276 787647

Is it really worth generating it during the build process?

Best regards,
Bernhard

>
>Thanks,
>Bernhard
>
>>
>>thanks
>>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board
  2025-02-10 17:30   ` Peter Maydell
  2025-02-10 22:44     ` Bernhard Beschow
@ 2025-02-23 11:40     ` Bernhard Beschow
  1 sibling, 0 replies; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-23 11:40 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, qemu-arm, Andrey Smirnov, Paolo Bonzini



Am 10. Februar 2025 17:30:01 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 4 Feb 2025 at 09:21, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>> As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
>> serial. All other devices of the A53 memory map are represented as
>> TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
>> for running Linux without it crashing due to invalid memory accesses.
>>
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> ---
>
>
>
>> --- /dev/null
>> +++ b/docs/system/arm/imx8mp-evk.rst
>> @@ -0,0 +1,56 @@
>> +NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
>> +================================================
>> +
>> +The QEMU i.MX 8M Plus EVK board emulation is intended to emulate a plain i.MX 8M
>> +Plus system on chip (SoC). All peripherals the real board has such as flash and
>> +I2C devices are intended to be added via configuration, e.g. command line.
>
>Why do this? If they're on the real hardware board, we should
>be creating them by default in the machine model in QEMU.
>Command line options are for devices that are optional and
>pluggable by the user on the hardware.

I'll rephrase the board description to be similar to the mcimx7d-sabre machine. In fact, I've modeled this machine like it.

Best regards,
Bernhard

>
>> +Supported devices
>> +-----------------
>> +
>> +The ``imx8mp-evk`` machine implements the following devices:
>> +
>> + * Up to 4 Cortex-A53 Cores
>
>"cores"
>
>> + * Generic Interrupt Controller (GICv3)
>> + * 4 UARTs
>> +
>> +Boot options
>> +------------
>> +
>> +The ``imx8mp-evk`` machine can start using the standard -kernel functionality
>> +for loading a Linux kernel.
>> +
>> +Direct Linux Kernel Boot
>> +''''''''''''''''''''''''
>> +
>> +Probably the easiest way to get started with a whole Linux system on the machine
>> +is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
>> +of writing and involves two steps. First run the following commands in the
>> +toplevel directory of the Buildroot source tree:
>> +
>> +.. code-block:: bash
>> +
>> +  $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
>> +  $ make freescale_imx8mpevk_defconfig
>> +  $ make
>> +
>> +Once finished successfully there is an ``output/image`` subfolder. Navigate into
>> +it patch the device tree needs to be patched with the following commands which
>> +will remove the ``cpu-idle-states`` properties from CPU nodes:
>
>This sentence seems to be confused in the middle -- cut-and-paste
>error ?
>
>> +
>> +.. code-block:: bash
>> +
>> +  $ dtc imx8mp-evk.dtb | sed '/cpu-idle-states/d' > imx8mp-evk-patched.dts
>> +  $ dtc imx8mp-evk-patched.dts -o imx8mp-evk-patched.dtb
>> +
>> +Now that everything is prepared the newly built image can be run in the QEMU
>> +``imx8mp-evk`` machine:
>
>> +#define NAME_SIZE 20
>> +
>> +static void fsl_imx8mp_init(Object *obj)
>> +{
>> +    MachineState *ms = MACHINE(qdev_get_machine());
>> +    FslImx8mpState *s = FSL_IMX8MP(obj);
>> +    char name[NAME_SIZE];
>
>Better than fixed sized char arrays for object names
>is to use
>   g_autofree char *name = g_strdup_printf("cpu%d", i);
>inside the block of each for() loop etc.
>
>> +    int i;
>> +
>> +    for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
>> +        snprintf(name, NAME_SIZE, "cpu%d", i);
>> +        object_initialize_child(obj, name, &s->cpu[i],
>> +                                ARM_CPU_TYPE_NAME("cortex-a53"));
>> +    }
>> +
>> +    object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
>> +
>> +    for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
>> +        snprintf(name, NAME_SIZE, "uart%d", i + 1);
>> +        object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>> +    }
>> +}
>> +
>> +static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
>> +{
>> +    MachineState *ms = MACHINE(qdev_get_machine());
>> +    FslImx8mpState *s = FSL_IMX8MP(dev);
>> +    DeviceState *gicdev = DEVICE(&s->gic);
>> +    int i;
>> +
>> +    if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
>> +        error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>> +                   TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus);
>> +        return;
>> +    }
>> +
>> +    /* CPUs */
>> +    for (i = 0; i < ms->smp.cpus; i++) {
>> +        /* On uniprocessor, the CBAR is set to 0 */
>> +        if (ms->smp.cpus > 1) {
>> +            object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>> +                                    fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
>> +                                    &error_abort);
>> +        }
>> +
>> +        /*
>> +         * Magic value from Linux output: "arch_timer: cp15 timer(s) running at
>> +         * 8.00MHz (phys)".
>> +         */
>> +        object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>> +                                &error_abort);
>
>This is the CNTFRQ value in Hz. The datasheet actually tells you
>this, so we don't need to call it a magic number (section 4.11.4.1.6.4
>of the i.MX 8M Plus Applications Processor Reference Manual says the
>base frequency of the system counter is 8MHz).
>
>(Incidentally the memory mapped system counter is a stock Arm
>IP block and I have about 60% of a model of it, I just haven't
>needed to upstream it yet because in practice no guest software
>really tries to mess with it. If we turn out to need it for
>this SoC that would be a reason for me to clean it up and
>send it out. But I suspect we don't need it in practice.)
>
>thanks
>-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree
  2025-02-23 11:46 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
@ 2025-02-23 11:46 ` Bernhard Beschow
  2025-02-25 14:21   ` Peter Maydell
  0 siblings, 1 reply; 52+ messages in thread
From: Bernhard Beschow @ 2025-02-23 11:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Jean-Christophe Dubois, qemu-arm, Peter Maydell,
	Marc-André Lureau, Laurent Vivier, Andrey Smirnov,
	Bernhard Beschow, Fabiano Rosas, Alistair Francis,
	Edgar E. Iglesias, Philippe Mathieu-Daudé

Fixes quite a few stack traces during the Linux boot process. Also provides the
clocks for devices added later, e.g. enet1.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 MAINTAINERS                     |   2 +
 docs/system/arm/imx8mp-evk.rst  |   1 +
 include/hw/arm/fsl-imx8mp.h     |   4 +
 include/hw/misc/imx8mp_analog.h |  81 +++++++++++++++
 include/hw/misc/imx8mp_ccm.h    |  30 ++++++
 hw/arm/fsl-imx8mp.c             |  20 ++++
 hw/misc/imx8mp_analog.c         | 160 +++++++++++++++++++++++++++++
 hw/misc/imx8mp_ccm.c            | 175 ++++++++++++++++++++++++++++++++
 hw/arm/Kconfig                  |   2 +
 hw/misc/Kconfig                 |   6 ++
 hw/misc/meson.build             |   2 +
 11 files changed, 483 insertions(+)
 create mode 100644 include/hw/misc/imx8mp_analog.h
 create mode 100644 include/hw/misc/imx8mp_ccm.h
 create mode 100644 hw/misc/imx8mp_analog.c
 create mode 100644 hw/misc/imx8mp_ccm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 374fe98724..8ea7fb4c7a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -826,7 +826,9 @@ L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/imx8mp-evk.c
 F: hw/arm/fsl-imx8mp.c
+F: hw/misc/imx8mp_*.c
 F: include/hw/arm/fsl-imx8mp.h
+F: include/hw/misc/imx8mp_*.h
 F: docs/system/arm/imx8mp-evk.rst
 
 MPS2 / MPS3
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index b23fdcc743..f0df346113 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -12,6 +12,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * Up to 4 Cortex-A53 cores
  * Generic Interrupt Controller (GICv3)
  * 4 UARTs
+ * Clock Tree
 
 Boot options
 ------------
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 57e23d1b69..ce5188e7f2 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -12,6 +12,8 @@
 #include "cpu.h"
 #include "hw/char/imx_serial.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "hw/misc/imx8mp_analog.h"
+#include "hw/misc/imx8mp_ccm.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -32,6 +34,8 @@ struct FslImx8mpState {
 
     ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
     GICv3State         gic;
+    IMX8MPCCMState     ccm;
+    IMX8MPAnalogState  analog;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
 };
 
diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
new file mode 100644
index 0000000000..955f03215a
--- /dev/null
+++ b/include/hw/misc/imx8mp_analog.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX8MP ANALOG IP block emulation code
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IMX8MP_ANALOG_H
+#define IMX8MP_ANALOG_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+enum IMX8MPAnalogRegisters {
+    ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
+    ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
+    ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
+    ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
+    ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
+    ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
+    ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
+    ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
+    ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
+    ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
+    ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
+    ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
+    ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
+    ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
+    ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
+    ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
+    ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
+    ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
+    ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
+    ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
+    ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
+    ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
+    ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
+    ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
+    ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
+    ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
+    ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
+    ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
+    ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
+    ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
+    ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
+    ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
+    ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
+    ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
+    ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
+    ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
+    ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
+    ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
+    ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
+    ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
+    ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
+    ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
+    ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
+    ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
+    ANALOG_OSC_MISC_CFG = 0x124 / 4,
+    ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
+
+    ANALOG_DIGPROG = 0x800 / 4,
+    ANALOG_MAX,
+};
+
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
+
+struct IMX8MPAnalogState {
+    SysBusDevice parent_obj;
+
+    struct {
+        MemoryRegion container;
+        MemoryRegion analog;
+    } mmio;
+
+    uint32_t analog[ANALOG_MAX];
+};
+
+#endif /* IMX8MP_ANALOG_H */
diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
new file mode 100644
index 0000000000..685c8582ff
--- /dev/null
+++ b/include/hw/misc/imx8mp_ccm.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX 8M Plus CCM IP block emulation code
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IMX8MP_CCM_H
+#define IMX8MP_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
+
+enum IMX8MPCCMRegisters {
+    CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
+};
+
+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
+
+struct IMX8MPCCMState {
+    IMXCCMState parent_obj;
+
+    MemoryRegion iomem;
+
+    uint32_t ccm[CCM_MAX];
+};
+
+#endif /* IMX8MP_CCM_H */
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 484b45c0d8..2b86de45a0 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -197,6 +197,10 @@ static void fsl_imx8mp_init(Object *obj)
 
     object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
 
+    object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
+
+    object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
+
     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
         g_autofree char *name = g_strdup_printf("uart%d", i + 1);
         object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
@@ -304,6 +308,20 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
         }
     }
 
+    /* CCM */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
+
+    /* Analog */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
+                    fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
+
     /* UARTs */
     for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
         static const struct {
@@ -329,6 +347,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
         switch (i) {
+        case FSL_IMX8MP_ANA_PLL:
+        case FSL_IMX8MP_CCM:
         case FSL_IMX8MP_GIC_DIST:
         case FSL_IMX8MP_GIC_REDIST:
         case FSL_IMX8MP_RAM:
diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
new file mode 100644
index 0000000000..f7e7c83cc4
--- /dev/null
+++ b/hw/misc/imx8mp_analog.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX 8M Plus ANALOG IP block emulation code
+ *
+ * Based on hw/misc/imx7_ccm.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx8mp_analog.h"
+#include "migration/vmstate.h"
+
+#define ANALOG_PLL_LOCK BIT(31)
+
+static void imx8mp_analog_reset(DeviceState *dev)
+{
+    IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
+
+    memset(s->analog, 0, sizeof(s->analog));
+
+    s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
+    s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
+    s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
+    s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
+    s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
+    s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
+    s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
+    s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
+    s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
+    s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
+    s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
+    s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
+    s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
+    s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
+    s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
+    s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
+    s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
+    s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
+    s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
+    s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
+    s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
+    s->analog[ANALOG_DIGPROG] = 0x00824010;
+
+    /* all PLLs need to be locked */
+    s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
+    s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
+}
+
+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
+{
+    IMX8MPAnalogState *s = opaque;
+
+    return s->analog[offset >> 2];
+}
+
+static void imx8mp_analog_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    IMX8MPAnalogState *s = opaque;
+
+    if (offset >> 2 == ANALOG_DIGPROG) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "Guest write to read-only ANALOG_DIGPROG register\n");
+    } else {
+        s->analog[offset >> 2] = value;
+    }
+}
+
+static const struct MemoryRegionOps imx8mp_analog_ops = {
+    .read = imx8mp_analog_read,
+    .write = imx8mp_analog_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+};
+
+static void imx8mp_analog_init(Object *obj)
+{
+    IMX8MPAnalogState *s = IMX8MP_ANALOG(obj);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_ANALOG, 0x10000);
+
+    memory_region_init_io(&s->mmio.analog, obj, &imx8mp_analog_ops, s,
+                          TYPE_IMX8MP_ANALOG, sizeof(s->analog));
+    memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
+
+    sysbus_init_mmio(sd, &s->mmio.container);
+}
+
+static const VMStateDescription imx8mp_analog_vmstate = {
+    .name = TYPE_IMX8MP_ANALOG,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(analog, IMX8MPAnalogState, ANALOG_MAX),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void imx8mp_analog_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    device_class_set_legacy_reset(dc, imx8mp_analog_reset);
+    dc->vmsd  = &imx8mp_analog_vmstate;
+    dc->desc  = "i.MX 8M Plus Analog Module";
+}
+
+static const TypeInfo imx8mp_analog_types[] = {
+    {
+        .name          = TYPE_IMX8MP_ANALOG,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(IMX8MPAnalogState),
+        .instance_init = imx8mp_analog_init,
+        .class_init    = imx8mp_analog_class_init,
+    }
+};
+
+DEFINE_TYPES(imx8mp_analog_types);
diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
new file mode 100644
index 0000000000..1a1c932427
--- /dev/null
+++ b/hw/misc/imx8mp_ccm.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX 8M Plus CCM IP block emulation code
+ *
+ * Based on hw/misc/imx7_ccm.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx8mp_ccm.h"
+#include "migration/vmstate.h"
+
+#include "trace.h"
+
+#define CKIH_FREQ 16000000 /* 16MHz crystal input */
+
+static void imx8mp_ccm_reset(DeviceState *dev)
+{
+    IMX8MPCCMState *s = IMX8MP_CCM(dev);
+
+    memset(s->ccm, 0, sizeof(s->ccm));
+}
+
+#define CCM_INDEX(offset)   (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset)   ((offset) & (hwaddr)0xF)
+
+enum {
+    CCM_BITOP_NONE = 0x00,
+    CCM_BITOP_SET  = 0x04,
+    CCM_BITOP_CLR  = 0x08,
+    CCM_BITOP_TOG  = 0x0C,
+};
+
+static uint64_t imx8mp_set_clr_tog_read(void *opaque, hwaddr offset,
+                                        unsigned size)
+{
+    const uint32_t *mmio = opaque;
+
+    return mmio[CCM_INDEX(offset)];
+}
+
+static void imx8mp_set_clr_tog_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    const uint8_t  bitop = CCM_BITOP(offset);
+    const uint32_t index = CCM_INDEX(offset);
+    uint32_t *mmio = opaque;
+
+    switch (bitop) {
+    case CCM_BITOP_NONE:
+        mmio[index]  = value;
+        break;
+    case CCM_BITOP_SET:
+        mmio[index] |= value;
+        break;
+    case CCM_BITOP_CLR:
+        mmio[index] &= ~value;
+        break;
+    case CCM_BITOP_TOG:
+        mmio[index] ^= value;
+        break;
+    };
+}
+
+static const struct MemoryRegionOps imx8mp_set_clr_tog_ops = {
+    .read = imx8mp_set_clr_tog_read,
+    .write = imx8mp_set_clr_tog_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        /*
+         * Our device would not work correctly if the guest was doing
+         * unaligned access. This might not be a limitation on the real
+         * device but in practice there is no reason for a guest to access
+         * this device unaligned.
+         */
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+};
+
+static void imx8mp_ccm_init(Object *obj)
+{
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    IMX8MPCCMState *s = IMX8MP_CCM(obj);
+
+    memory_region_init_io(&s->iomem,
+                          obj,
+                          &imx8mp_set_clr_tog_ops,
+                          s->ccm,
+                          TYPE_IMX8MP_CCM ".ccm",
+                          sizeof(s->ccm));
+
+    sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription imx8mp_ccm_vmstate = {
+    .name = TYPE_IMX8MP_CCM,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(ccm, IMX8MPCCMState, CCM_MAX),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static uint32_t imx8mp_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+    /*
+     * This function is "consumed" by GPT emulation code. Some clocks
+     * have fixed frequencies and we can provide requested frequency
+     * easily. However for CCM provided clocks (like IPG) each GPT
+     * timer can have its own clock root.
+     * This means we need additional information when calling this
+     * function to know the requester's identity.
+     */
+    uint32_t freq = 0;
+
+    switch (clock) {
+    case CLK_NONE:
+        break;
+    case CLK_32k:
+        freq = CKIL_FREQ;
+        break;
+    case CLK_HIGH:
+        freq = CKIH_FREQ;
+        break;
+    case CLK_IPG:
+    case CLK_IPG_HIGH:
+        /*
+         * For now we don't have a way to figure out the device this
+         * function is called for. Until then the IPG derived clocks
+         * are left unimplemented.
+         */
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n",
+                      TYPE_IMX8MP_CCM, __func__, clock);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
+                      TYPE_IMX8MP_CCM, __func__, clock);
+        break;
+    }
+
+    trace_ccm_clock_freq(clock, freq);
+
+    return freq;
+}
+
+static void imx8mp_ccm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
+
+    device_class_set_legacy_reset(dc, imx8mp_ccm_reset);
+    dc->vmsd  = &imx8mp_ccm_vmstate;
+    dc->desc  = "i.MX 8M Plus Clock Control Module";
+
+    ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
+}
+
+static const TypeInfo imx8mp_ccm_types[] = {
+    {
+        .name          = TYPE_IMX8MP_CCM,
+        .parent        = TYPE_IMX_CCM,
+        .instance_size = sizeof(IMX8MPCCMState),
+        .instance_init = imx8mp_ccm_init,
+        .class_init    = imx8mp_ccm_class_init,
+    },
+};
+
+DEFINE_TYPES(imx8mp_ccm_types);
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 0a7de40861..f77c451ba3 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -596,6 +596,8 @@ config FSL_IMX7
 config FSL_IMX8MP
     bool
     select ARM_GIC
+    select FSL_IMX8MP_ANALOG
+    select FSL_IMX8MP_CCM
     select IMX
     select UNIMP
 
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 4271e2f4ac..82bd68b4bb 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -78,6 +78,12 @@ config IMX
     select SSI
     select USB_EHCI_SYSBUS
 
+config FSL_IMX8MP_ANALOG
+    bool
+
+config FSL_IMX8MP_CCM
+    bool
+
 config STM32_RCC
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index edd36a334d..0b5187a2f7 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -55,6 +55,8 @@ system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
 system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
 system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
 system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
 system_ss.add(when: 'CONFIG_IMX', if_true: files(
   'imx25_ccm.c',
   'imx31_ccm.c',
-- 
2.48.1



^ permalink raw reply related	[flat|nested] 52+ messages in thread

* Re: [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree
  2025-02-23 11:46 ` [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
@ 2025-02-25 14:21   ` Peter Maydell
  0 siblings, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2025-02-25 14:21 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Jean-Christophe Dubois, qemu-arm,
	Marc-André Lureau, Laurent Vivier, Andrey Smirnov,
	Fabiano Rosas, Alistair Francis, Edgar E. Iglesias,
	Philippe Mathieu-Daudé

On Sun, 23 Feb 2025 at 11:47, Bernhard Beschow <shentey@gmail.com> wrote:
>
> Fixes quite a few stack traces during the Linux boot process. Also provides the
> clocks for devices added later, e.g. enet1.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2025-02-25 14:22 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-04  9:20 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
2025-02-04  9:20 ` [PATCH v2 01/18] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
2025-02-04  9:20 ` [PATCH v2 02/18] hw/pci-host/designware: Prevent device attachment on internal PCIe root bus Bernhard Beschow
2025-02-17 13:36   ` Peter Maydell
2025-02-04  9:20 ` [PATCH v2 03/18] hw/gpio/pca955*: Move Kconfig switches next to implementations Bernhard Beschow
2025-02-17 13:35   ` Peter Maydell
2025-02-17 19:39     ` Bernhard Beschow
2025-02-18 10:33       ` Peter Maydell
2025-02-19 21:43         ` Bernhard Beschow
2025-02-04  9:20 ` [PATCH v2 04/18] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
2025-02-10 17:30   ` Peter Maydell
2025-02-10 22:44     ` Bernhard Beschow
2025-02-11 10:06       ` Peter Maydell
2025-02-11 23:40         ` Bernhard Beschow
2025-02-23 11:40     ` Bernhard Beschow
2025-02-04  9:20 ` [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
2025-02-04 23:15   ` Bernhard Beschow
2025-02-04  9:21 ` [PATCH v2 06/18] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
2025-02-04  9:21 ` [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
2025-02-06 17:25   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 08/18] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
2025-02-17 13:40   ` Peter Maydell
2025-02-17 16:33     ` Bernhard Beschow
2025-02-04  9:21 ` [PATCH v2 09/18] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
2025-02-06 17:26   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 10/18] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
2025-02-06 17:26   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 11/18] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
2025-02-06 17:26   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 12/18] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
2025-02-06 17:27   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 13/18] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
2025-02-06 17:29   ` Peter Maydell
2025-02-07  8:08     ` Bernhard Beschow
2025-02-04  9:21 ` [PATCH v2 14/18] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
2025-02-06 17:30   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 15/18] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
2025-02-06 17:31   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 16/18] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
2025-02-17 13:28   ` Peter Maydell
2025-02-17 22:48     ` Bernhard Beschow
2025-02-23 11:04       ` Bernhard Beschow
2025-02-04  9:21 ` [PATCH v2 17/18] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
2025-02-06 17:31   ` Peter Maydell
2025-02-04  9:21 ` [PATCH v2 18/18] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
2025-02-06 17:32   ` Peter Maydell
2025-02-06 21:58     ` Bernhard Beschow
2025-02-10 14:26       ` Philippe Mathieu-Daudé
2025-02-10 22:48         ` Bernhard Beschow
2025-02-23 10:57           ` Bernhard Beschow
  -- strict thread matches above, loose matches on Subject: below --
2025-02-23 11:46 [PATCH v2 00/18] Add i.MX 8M Plus EVK machine Bernhard Beschow
2025-02-23 11:46 ` [PATCH v2 05/18] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
2025-02-25 14:21   ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).