qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/21] Add i.MX 8M Plus EVK machine
@ 2025-01-20 20:37 Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 01/21] hw/char/imx_serial: Fix reset value of UFCR register Bernhard Beschow
                   ` (20 more replies)
  0 siblings, 21 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 includes the unreviewed patches of [3] and is structured as follows:
The first four patches fix some issues in device models reused by the new
machine. Patches 5-18 add the machine step by step which includes documentation.
Patches 19 and 20 add some further device models that I'd like to use with the
new machine. The last patch is a fix I created during debugging but I don't rely
on it.

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.
The TCA6416 emulation is taken from the Xilinx fork where it is used in some
cadence machines. Would the respective upstream maintainers be willing to
maintain the device model upstream instead?

[1] https://www.nxp.com/design/design-center/development-boards-and-designs/8MPLUSLPD4-EVK
[2] https://archlinuxarm.org/platforms/armv8/generic
[3] https://patchew.org/QEMU/20250111183711.2338-1-shentey@gmail.com/

Supersedes: 20250111183711.2338-1-shentey@gmail.com

Bernhard Beschow (21):
  hw/char/imx_serial: Fix reset value of UFCR register
  hw/char/imx_serial: Update all state before restarting ageing timer
  hw/pci-host/designware: Expose MSI IRQ
  hw/usb/hcd-dwc3: Align global registers size with Linux
  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
  hw/i2c: Import TCA6416 emulation from Xilinx
  hw/gpio/imx_gpio: Don't clear input GPIO values upon reset

 MAINTAINERS                         |  16 +
 docs/system/arm/imx8mp-evk.rst      |  84 ++++
 docs/system/target-arm.rst          |   1 +
 include/hw/arm/fsl-imx6.h           |   4 +-
 include/hw/arm/fsl-imx7.h           |   4 +-
 include/hw/arm/fsl-imx8mp.h         | 284 +++++++++++
 include/hw/char/imx_serial.h        |   2 +-
 include/hw/misc/imx8mp_ccm.h        |  97 ++++
 include/hw/pci-host/designware.h    |   1 +
 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-imx6.c                   |  13 +-
 hw/arm/fsl-imx7.c                   |  13 +-
 hw/arm/fsl-imx8mp.c                 | 736 ++++++++++++++++++++++++++++
 hw/arm/imx8mp-evk.c                 |  74 +++
 hw/char/imx_serial.c                |   7 +-
 hw/gpio/imx_gpio.c                  |   1 -
 hw/gpio/tca6416.c                   | 122 +++++
 hw/misc/imx8mp_ccm.c                | 315 ++++++++++++
 hw/pci-host/designware.c            |   7 +-
 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                      |  25 +
 hw/arm/meson.build                  |   2 +
 hw/gpio/Kconfig                     |   5 +
 hw/gpio/meson.build                 |   1 +
 hw/gpio/trace-events                |   4 +
 hw/misc/meson.build                 |   1 +
 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 +
 38 files changed, 2195 insertions(+), 14 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_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/gpio/tca6416.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] 50+ messages in thread

* [PATCH 01/21] hw/char/imx_serial: Fix reset value of UFCR register
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 02/21] hw/char/imx_serial: Update all state before restarting ageing timer Bernhard Beschow
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

The value of the UCFR register is respected when echoing characters to the
terminal, but its reset value is reserved. Fix the reset value to the one
documented in the datasheet.

While at it move the related attribute out of the section of unimplemented
registers since its value is actually respected.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 include/hw/char/imx_serial.h | 2 +-
 hw/char/imx_serial.c         | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
index 65f0e97c76..90ba3ff18c 100644
--- a/include/hw/char/imx_serial.h
+++ b/include/hw/char/imx_serial.h
@@ -109,13 +109,13 @@ struct IMXSerialState {
     uint32_t ucr1;
     uint32_t ucr2;
     uint32_t uts1;
+    uint32_t ufcr;
 
     /*
      * The registers below are implemented just so that the
      * guest OS sees what it has written
      */
     uint32_t onems;
-    uint32_t ufcr;
     uint32_t ubmr;
     uint32_t ubrc;
     uint32_t ucr3;
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 7c353fde50..cb6761d40e 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -160,6 +160,7 @@ static void imx_serial_reset(IMXSerialState *s)
     s->ucr3 = 0x700;
     s->ubmr = 0;
     s->ubrc = 4;
+    s->ufcr = BIT(11) | BIT(0);
 
     fifo32_reset(&s->rx_fifo);
     timer_del(&s->ageing_timer);
-- 
2.48.1



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

* [PATCH 02/21] hw/char/imx_serial: Update all state before restarting ageing timer
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 01/21] hw/char/imx_serial: Fix reset value of UFCR register Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 03/21] hw/pci-host/designware: Expose MSI IRQ Bernhard Beschow
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

Fixes characters to be "echoed" after each keystroke rather than after every
other since imx_serial_rx_fifo_ageing_timer_restart() would see ~UTS1_RXEMPTY
only after every other keystroke.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 hw/char/imx_serial.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index cb6761d40e..38b4865157 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -401,14 +401,14 @@ static void imx_put_data(void *opaque, uint32_t value)
     if (fifo32_num_used(&s->rx_fifo) >= rxtl) {
         s->usr1 |= USR1_RRDY;
     }
-
-    imx_serial_rx_fifo_ageing_timer_restart(s);
-
     s->usr2 |= USR2_RDR;
     s->uts1 &= ~UTS1_RXEMPTY;
     if (value & URXD_BRK) {
         s->usr2 |= USR2_BRCD;
     }
+
+    imx_serial_rx_fifo_ageing_timer_restart(s);
+
     imx_update(s);
 }
 
-- 
2.48.1



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

* [PATCH 03/21] hw/pci-host/designware: Expose MSI IRQ
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 01/21] hw/char/imx_serial: Fix reset value of UFCR register Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 02/21] hw/char/imx_serial: Update all state before restarting ageing timer Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 04/21] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

Fixes INTD and MSI interrupts poking the same IRQ line without keeping track of
each other's IRQ level. Furthermore, SoCs such as the i.MX 8M Plus don't share
the MSI IRQ with the INTx lines, so expose it as a dedicated pin.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 include/hw/arm/fsl-imx6.h        |  4 +++-
 include/hw/arm/fsl-imx7.h        |  4 +++-
 include/hw/pci-host/designware.h |  1 +
 hw/arm/fsl-imx6.c                | 13 ++++++++++++-
 hw/arm/fsl-imx7.c                | 13 ++++++++++++-
 hw/pci-host/designware.c         |  7 +++----
 hw/arm/Kconfig                   |  2 ++
 7 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 61c593ffd2..9da32fc189 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -33,6 +33,7 @@
 #include "hw/usb/chipidea.h"
 #include "hw/usb/imx-usb-phy.h"
 #include "hw/pci-host/designware.h"
+#include "hw/or-irq.h"
 #include "exec/memory.h"
 #include "cpu.h"
 #include "qom/object.h"
@@ -73,6 +74,7 @@ struct FslIMX6State {
     ChipideaState      usb[FSL_IMX6_NUM_USBS];
     IMXFECState        eth;
     DesignwarePCIEHost pcie;
+    OrIRQState         pcie4_msi_irq;
     MemoryRegion       rom;
     MemoryRegion       caam;
     MemoryRegion       ocram;
@@ -457,7 +459,7 @@ struct FslIMX6State {
 #define FSL_IMX6_PCIE1_IRQ 120
 #define FSL_IMX6_PCIE2_IRQ 121
 #define FSL_IMX6_PCIE3_IRQ 122
-#define FSL_IMX6_PCIE4_IRQ 123
+#define FSL_IMX6_PCIE4_MSI_IRQ 123
 #define FSL_IMX6_DCIC1_IRQ 124
 #define FSL_IMX6_DCIC2_IRQ 125
 #define FSL_IMX6_MLB150_HIGH_IRQ 126
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 411fa1c2e3..aa7818c499 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -36,6 +36,7 @@
 #include "hw/net/imx_fec.h"
 #include "hw/pci-host/designware.h"
 #include "hw/usb/chipidea.h"
+#include "hw/or-irq.h"
 #include "cpu.h"
 #include "qom/object.h"
 #include "qemu/units.h"
@@ -85,6 +86,7 @@ struct FslIMX7State {
     IMX7GPRState       gpr;
     ChipideaState      usb[FSL_IMX7_NUM_USBS];
     DesignwarePCIEHost pcie;
+    OrIRQState         pcie4_msi_irq;
     MemoryRegion       rom;
     MemoryRegion       caam;
     MemoryRegion       ocram;
@@ -428,7 +430,7 @@ enum FslIMX7IRQs {
     FSL_IMX7_PCI_INTA_IRQ = 125,
     FSL_IMX7_PCI_INTB_IRQ = 124,
     FSL_IMX7_PCI_INTC_IRQ = 123,
-    FSL_IMX7_PCI_INTD_IRQ = 122,
+    FSL_IMX7_PCI_INTD_MSI_IRQ = 122,
 
     FSL_IMX7_UART7_IRQ    = 126,
 
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index c484e377a8..bf8b278978 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -86,6 +86,7 @@ struct DesignwarePCIEHost {
         MemoryRegion io;
 
         qemu_irq     irqs[4];
+        qemu_irq     msi;
     } pci;
 
     MemoryRegion mmio;
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index ac8c66e242..88b9ccff49 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -106,6 +106,8 @@ static void fsl_imx6_init(Object *obj)
     object_initialize_child(obj, "eth", &s->eth, TYPE_IMX_ENET);
 
     object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+    object_initialize_child(obj, "pcie4-msi-irq", &s->pcie4_msi_irq,
+                            TYPE_OR_IRQ);
 }
 
 static void fsl_imx6_realize(DeviceState *dev, Error **errp)
@@ -435,14 +437,23 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
     sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX6_PCIe_REG_ADDR);
 
+    object_property_set_int(OBJECT(&s->pcie4_msi_irq), "num-lines", 2,
+                            &error_abort);
+    qdev_realize(DEVICE(&s->pcie4_msi_irq), NULL, &error_abort);
+
+    irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE4_MSI_IRQ);
+    qdev_connect_gpio_out(DEVICE(&s->pcie4_msi_irq), 0, irq);
+
     irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE1_IRQ);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
     irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE2_IRQ);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
     irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE3_IRQ);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
-    irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE4_IRQ);
+    irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 0);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
+    irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 1);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, irq);
 
     /*
      * PCIe PHY
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 05e3389fbe..004bf49937 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -150,6 +150,8 @@ static void fsl_imx7_init(Object *obj)
      * PCIE
      */
     object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+    object_initialize_child(obj, "pcie4-msi-irq", &s->pcie4_msi_irq,
+                            TYPE_OR_IRQ);
 
     /*
      * USBs
@@ -597,14 +599,23 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
     sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
 
+    object_property_set_int(OBJECT(&s->pcie4_msi_irq), "num-lines", 2,
+                            &error_abort);
+    qdev_realize(DEVICE(&s->pcie4_msi_irq), NULL, &error_abort);
+
+    irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_MSI_IRQ);
+    qdev_connect_gpio_out(DEVICE(&s->pcie4_msi_irq), 0, irq);
+
     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
-    irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
+    irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 0);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
+    irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 1);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, irq);
 
     /*
      * USBs
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index c3fc37b904..3e8c36e6a7 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -55,8 +55,6 @@
 #define DESIGNWARE_PCIE_ATU_DEVFN(x)               (((x) >> 16) & 0xff)
 #define DESIGNWARE_PCIE_ATU_UPPER_TARGET           0x91C
 
-#define DESIGNWARE_PCIE_IRQ_MSI                    3
-
 static DesignwarePCIEHost *
 designware_pcie_root_to_host(DesignwarePCIERoot *root)
 {
@@ -90,7 +88,7 @@ static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
     root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
 
     if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
-        qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1);
+        qemu_set_irq(host->pci.msi, 1);
     }
 }
 
@@ -335,7 +333,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
     case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
         root->msi.intr[0].status ^= val;
         if (!root->msi.intr[0].status) {
-            qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0);
+            qemu_set_irq(host->pci.msi, 0);
         }
         break;
 
@@ -680,6 +678,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
         sysbus_init_irq(sbd, &s->pci.irqs[i]);
     }
+    sysbus_init_irq(sbd, &s->pci.msi);
 
     memory_region_init_io(&s->mmio,
                           OBJECT(s),
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index e779b5af95..fe47e259b8 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -513,6 +513,7 @@ config FSL_IMX6
     select IMX_I2C
     select IMX_USBPHY
     select WDT_IMX2
+    select OR_IRQ
     select PL310  # cache controller
     select PCI_EXPRESS_DESIGNWARE
     select SDHCI
@@ -571,6 +572,7 @@ config FSL_IMX7
     select IMX_FEC
     select IMX_I2C
     select WDT_IMX2
+    select OR_IRQ
     select PCI_EXPRESS_DESIGNWARE
     select SDHCI
     select UNIMP
-- 
2.48.1



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

* [PATCH 04/21] hw/usb/hcd-dwc3: Align global registers size with Linux
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (2 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 03/21] hw/pci-host/designware: Expose MSI IRQ Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-28 14:21   ` Peter Maydell
  2025-01-20 20:37 ` [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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

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] 50+ messages in thread

* [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (3 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 04/21] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-28 14:29   ` Peter Maydell
  2025-01-20 20:37 ` [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 |  47 +++++
 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                 |  13 ++
 hw/arm/meson.build             |   2 +
 8 files changed, 687 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 846b81e3ec..cace8cf25b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -819,6 +819,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: Odd Fixes
+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..184f1ef7e6
--- /dev/null
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -0,0 +1,47 @@
+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
+''''''''''''''''''''''''
+
+Linux mainline v6.12 release is tested at the time of writing. To build a Linux
+mainline kernel that can be booted by the ``imx8mp-evk`` machine, simply
+configure the kernel using the defconfig configuration:
+
+.. code-block:: bash
+
+  $ export ARCH=arm64
+  $ export CROSS_COMPILE=aarch64-linux-gnu-
+  $ make defconfig
+  $ make
+
+To boot the newly built Linux kernel in QEMU with the ``imx8mp-evk`` machine,
+run:
+
+.. code-block:: bash
+
+  $ qemu-system-aarch64 -M imx8mp-evk -smp 4 -m 3G \
+      -display none -serial null -serial stdio \
+      -kernel arch/arm64/boot/Image \
+      -dtb arch/arm64/boot/dts/freescale/imx8mp-evk.dtb \
+      -initrd /path/to/rootfs.ext4 \
+      -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..6b2cdb2c0a
--- /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 form 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 fe47e259b8..adb4ed8076 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -577,6 +577,19 @@ config FSL_IMX7
     select SDHCI
     select UNIMP
 
+config FSL_IMX8MP
+    bool
+    imply TEST_DEVICES
+    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] 50+ messages in thread

* [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (4 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-28 14:35   ` Peter Maydell
  2025-01-20 20:37 ` [PATCH 07/21] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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    |   3 +
 include/hw/misc/imx8mp_ccm.h   |  97 ++++++++++
 hw/arm/fsl-imx8mp.c            |  20 +++
 hw/misc/imx8mp_ccm.c           | 315 +++++++++++++++++++++++++++++++++
 hw/misc/meson.build            |   1 +
 7 files changed, 439 insertions(+)
 create mode 100644 include/hw/misc/imx8mp_ccm.h
 create mode 100644 hw/misc/imx8mp_ccm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cace8cf25b..3c60581fe7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -825,7 +825,9 @@ L: qemu-arm@nongnu.org
 S: Odd Fixes
 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 184f1ef7e6..3de4a73530 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..979cdbd8c4 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/imx8mp_ccm.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -32,6 +33,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_ccm.h b/include/hw/misc/imx8mp_ccm.h
new file mode 100644
index 0000000000..2378c157de
--- /dev/null
+++ b/include/hw/misc/imx8mp_ccm.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX8MP CCM, ANALOG IP blocks 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 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,
+};
+
+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];
+};
+
+
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
+
+struct IMX8MPAnalogState {
+    IMXCCMState parent_obj;
+
+    struct {
+        MemoryRegion container;
+        MemoryRegion analog;
+    } mmio;
+
+    uint32_t analog[ANALOG_MAX];
+};
+
+#endif /* IMX8MP_CCM_H */
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 6b2cdb2c0a..311b8ee0cd 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_ccm.c b/hw/misc/imx8mp_ccm.c
new file mode 100644
index 0000000000..17658eb876
--- /dev/null
+++ b/hw/misc/imx8mp_ccm.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
+ *
+ * i.MX8MP CCM, PMU and ANALOG IP blocks 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 */
+
+#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 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 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_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 void imx8mp_analog_init(Object *obj)
+{
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    IMX8MPAnalogState *s = IMX8MP_ANALOG(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_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.MX8MP Clock Control Module";
+
+    ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
+}
+
+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.MX8MP Analog Module";
+}
+
+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,
+    },
+    {
+        .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/meson.build b/hw/misc/meson.build
index 55f493521b..d556965821 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -65,6 +65,7 @@ system_ss.add(when: 'CONFIG_IMX', if_true: files(
   'imx7_src.c',
   'imx7_gpr.c',
   'imx7_snvs.c',
+  'imx8mp_ccm.c',
   'imx_ccm.c',
   'imx_rngc.c',
 ))
-- 
2.48.1



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

* [PATCH 07/21] hw/arm/fsl-imx8mp: Add SNVS
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (5 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-28 14:31   ` Peter Maydell
  2025-01-20 20:37 ` [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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.

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 3de4a73530..d7d08cc198 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 979cdbd8c4..9d2a757c2a 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_ccm.h"
 #include "qom/object.h"
 #include "qemu/units.h"
@@ -35,6 +36,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 311b8ee0cd..0abde2b1fc 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] 50+ messages in thread

* [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (6 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 07/21] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-21  2:52   ` BALATON Zoltan
  2025-01-20 20:37 ` [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 | 39 +++++++++++++++++++++++-----------
 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, 81 insertions(+), 12 deletions(-)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index d7d08cc198..1514bc5864 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
 
@@ -25,25 +26,39 @@ for loading a Linux kernel.
 Direct Linux Kernel Boot
 ''''''''''''''''''''''''
 
-Linux mainline v6.12 release is tested at the time of writing. To build a Linux
-mainline kernel that can be booted by the ``imx8mp-evk`` machine, simply
-configure the kernel using the defconfig configuration:
+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 three steps. First run the following command in the
+toplevel directory of the Buildroot source tree:
 
 .. code-block:: bash
 
-  $ export ARCH=arm64
-  $ export CROSS_COMPILE=aarch64-linux-gnu-
-  $ make defconfig
+  $ make freescale_imx8mpevk_defconfig
   $ make
 
-To boot the newly built Linux kernel in QEMU with the ``imx8mp-evk`` machine,
-run:
+Once finished successfully there is an ``output/image`` subfolder. Navigate into
+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
+
+  $ 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 arch/arm64/boot/Image \
-      -dtb arch/arm64/boot/dts/freescale/imx8mp-evk.dtb \
-      -initrd /path/to/rootfs.ext4 \
-      -append "root=/dev/ram"
+      -kernel Image \
+      -dtb imx8mp-evk-patched.dtb \
+      -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 9d2a757c2a..9832c05e8c 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -14,6 +14,7 @@
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_ccm.h"
+#include "hw/sd/sdhci.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -27,6 +28,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 {
@@ -38,6 +40,7 @@ struct FslImx8mpState {
     IMX8MPAnalogState  analog;
     IMX7SNVSState      snvs;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
+    SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
 };
 
 enum FslImx8mpMemoryRegions {
@@ -183,6 +186,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 0abde2b1fc..612ea7bf93 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 adb4ed8076..f880c03d35 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -582,6 +582,7 @@ config FSL_IMX8MP
     imply TEST_DEVICES
     select ARM_GIC
     select IMX
+    select SDHCI
     select UNIMP
 
 config FSL_IMX8MP_EVK
-- 
2.48.1



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

* [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (7 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-28 14:33   ` Peter Maydell
  2025-01-20 20:37 ` [PATCH 10/21] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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      | 13 +++++
 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, 177 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 3c60581fe7..76b416831d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -826,8 +826,10 @@ S: Odd Fixes
 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 1514bc5864..8d48580cb4 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
 
@@ -62,3 +63,15 @@ Now that everything is prepared the newly built image can be run in the QEMU
       -dtb imx8mp-evk-patched.dtb \
       -append "root=/dev/mmcblk2p2" \
       -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
+
+Using PCI Devices
+-----------------
+
+The PCI Express controller spawns two PCI buses, of which only one can be used.
+By default QEMU assigns the wrong bus, so the correct one has to be specified
+manually by adding ``bus=dw-pcie``. For example, when adding an Intel e1000
+network card, the command line looks like:
+
+.. code-block:: bash
+
+  $ qemu-system-aarch64 -M imximp-evk ... -device virtio-net-pci,bus=dw-pcie
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 9832c05e8c..bc80a21966 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -14,6 +14,8 @@
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/misc/imx7_snvs.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"
@@ -41,6 +43,8 @@ struct FslImx8mpState {
     IMX7SNVSState      snvs;
     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
     SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
+    DesignwarePCIEHost pcie;
+    FslImx8mPciePhyState   pcie_phy;
 };
 
 enum FslImx8mpMemoryRegions {
@@ -196,6 +200,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 612ea7bf93..d15dcaa9de 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 f880c03d35..f065718416 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -579,9 +579,12 @@ config FSL_IMX7
 
 config FSL_IMX8MP
     bool
+    imply PCI_DEVICES
     imply TEST_DEVICES
     select ARM_GIC
     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] 50+ messages in thread

* [PATCH 10/21] hw/arm/fsl-imx8mp: Add GPIO controllers
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (8 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 11/21] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 8d48580cb4..d974581fb1 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 bc80a21966..c91964a465 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_ccm.h"
@@ -28,6 +29,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,
@@ -38,6 +40,7 @@ struct FslImx8mpState {
 
     ARMCPU             cpu[FSL_IMX8MP_NUM_CPUS];
     GICv3State         gic;
+    IMXGPIOState       gpio[FSL_IMX8MP_NUM_GPIOS];
     IMX8MPCCMState     ccm;
     IMX8MPAnalogState  analog;
     IMX7SNVSState      snvs;
@@ -201,6 +204,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 d15dcaa9de..c62d0e4479 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] 50+ messages in thread

* [PATCH 11/21] hw/arm/fsl-imx8mp: Add I2C controllers
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (9 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 10/21] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 12/21] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 d974581fb1..2bcfe34f48 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 c91964a465..7e6f997d37 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_ccm.h"
@@ -30,6 +31,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,
@@ -44,6 +46,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;
@@ -204,6 +207,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,
@@ -215,6 +223,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 c62d0e4479..f2d890ffb3 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 f065718416..8d796e05c8 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -581,8 +581,10 @@ config FSL_IMX8MP
     bool
     imply PCI_DEVICES
     imply TEST_DEVICES
+    imply I2C_DEVICES
     select ARM_GIC
     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] 50+ messages in thread

* [PATCH 12/21] hw/arm/fsl-imx8mp: Add SPI controllers
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (10 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 11/21] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 13/21] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 2bcfe34f48..da0435fe55 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 7e6f997d37..f019687cd2 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -19,6 +19,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"
 
@@ -30,6 +31,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,
@@ -46,6 +48,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];
@@ -207,6 +210,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 f2d890ffb3..5897c34922 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] 50+ messages in thread

* [PATCH 13/21] hw/arm/fsl-imx8mp: Add watchdog support
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (11 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 12/21] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 14/21] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 da0435fe55..4f964a715f 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 f019687cd2..81948a2a5e 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -20,6 +20,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"
 
@@ -37,6 +38,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 {
@@ -52,6 +54,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;
 };
@@ -234,6 +237,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 5897c34922..2e0cd4e911 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 8d796e05c8..a1910db717 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -589,6 +589,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] 50+ messages in thread

* [PATCH 14/21] hw/arm/fsl-imx8mp: Implement gneral purpose timers
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (12 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 13/21] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 15/21] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 4f964a715f..8a17b170c0 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 81948a2a5e..bceaf1ffd6 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -16,10 +16,12 @@
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/misc/imx7_snvs.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"
@@ -34,6 +36,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,
@@ -46,6 +49,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;
@@ -57,6 +61,7 @@ struct FslImx8mpState {
     IMX2WdtState       wdt[FSL_IMX8MP_NUM_WDTS];
     DesignwarePCIEHost pcie;
     FslImx8mPciePhyState   pcie_phy;
+    OrIRQState         gpt5_gpt6_irq;
 };
 
 enum FslImx8mpMemoryRegions {
@@ -223,6 +228,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 2e0cd4e911..c40811d078 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 a1910db717..8ebcf3339e 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -585,6 +585,7 @@ config FSL_IMX8MP
     select ARM_GIC
     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] 50+ messages in thread

* [PATCH 15/21] hw/arm/fsl-imx8mp: Add Ethernet controller
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (13 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 14/21] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 16/21] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 8a17b170c0..a3a17fc41f 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 bceaf1ffd6..8fe27ac9bd 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -16,6 +16,7 @@
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/misc/imx7_snvs.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"
@@ -57,11 +58,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 {
@@ -252,6 +257,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 c40811d078..3bb719d0e8 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 8ebcf3339e..0e49ac4d5c 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -584,6 +584,7 @@ config FSL_IMX8MP
     imply I2C_DEVICES
     select ARM_GIC
     select IMX
+    select IMX_FEC
     select IMX_I2C
     select OR_IRQ
     select PCI_EXPRESS_DESIGNWARE
-- 
2.48.1



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

* [PATCH 16/21] hw/arm/fsl-imx8mp: Add USB support
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (14 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 15/21] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 a3a17fc41f..af1f02d8e8 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 8fe27ac9bd..1b8a5cbbba 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -23,6 +23,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"
@@ -41,6 +42,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,
 };
@@ -61,6 +63,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;
@@ -198,6 +201,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,
@@ -233,6 +242,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 3bb719d0e8..5b9781a424 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 0e49ac4d5c..c9b47270ac 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -591,6 +591,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] 50+ messages in thread

* [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (15 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 16/21] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-21  3:00   ` BALATON Zoltan
  2025-01-20 20:37 ` [PATCH 18/21] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
                   ` (3 subsequent siblings)
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 76b416831d..d2cdc790ff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -830,6 +830,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 1b8a5cbbba..326c4ddf69 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -67,6 +67,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 5b9781a424..9688e2e962 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_ram(&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] 50+ messages in thread

* [PATCH 18/21] hw/arm/fsl-imx8mp: Add on-chip RAM
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (16 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 19/21] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 326c4ddf69..e0442665fc 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -68,6 +68,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 9688e2e962..cb4b0ae5bb 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] 50+ messages in thread

* [PATCH 19/21] hw/rtc: Add Ricoh RS5C372 RTC emulation
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (17 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 18/21] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx Bernhard Beschow
  2025-01-20 20:37 ` [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset Bernhard Beschow
  20 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

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 d2cdc790ff..7531d65429 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -827,6 +827,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] 50+ messages in thread

* [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (18 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 19/21] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-21  3:07   ` BALATON Zoltan
                     ` (2 more replies)
  2025-01-20 20:37 ` [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset Bernhard Beschow
  20 siblings, 3 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

Xilinx QEMU implements a TCA6416 device model which may be useful for the
broader QEMU community, so upstream it. In the Xilinx fork, the device model
gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
"hw/*/cadence_*" maintainers.

The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
modifications:
* Use OBJECT_DECLARE_SIMPLE_TYPE()
* Port from DPRINTF() to trace events
* Follow QEMU conventions for naming of state struct
* Rename type to not contain a ','
* Use DEFINE_TYPES() macro
* Implement under hw/gpio since device is i2c client and gpio provider
* Have dedicated Kconfig switch

Signed-off-by: Bernhard Beschow <shentey@gmail.com>

--
I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
willing to maintain this device model?
---
 MAINTAINERS          |   1 +
 hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
 hw/gpio/Kconfig      |   5 ++
 hw/gpio/meson.build  |   1 +
 hw/gpio/trace-events |   4 ++
 5 files changed, 133 insertions(+)
 create mode 100644 hw/gpio/tca6416.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7531d65429..0cac9c90bc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1030,6 +1030,7 @@ S: Maintained
 F: hw/*/xilinx_*
 F: hw/*/cadence_*
 F: hw/misc/zynq_slcr.c
+F: hw/gpio/tca6416.c
 F: hw/adc/zynq-xadc.c
 F: include/hw/misc/zynq_slcr.h
 F: include/hw/adc/zynq-xadc.h
diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
new file mode 100644
index 0000000000..81ed7a654d
--- /dev/null
+++ b/hw/gpio/tca6416.c
@@ -0,0 +1,122 @@
+/*
+ * QEMU model of TCA6416 16-Bit I/O Expander
+ *
+ * Copyright (c) 2018 Xilinx Inc.
+ *
+ * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "hw/i2c/i2c.h"
+#include "trace.h"
+
+#define TYPE_TCA6416 "tca6416"
+OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
+
+#define IN_PORT0    0
+#define IN_PORT1    1
+#define OUT_PORT0   2
+#define OUT_PORT1   3
+#define POL_INV0    4
+#define POL_INV1    5
+#define CONF_PORT0  6
+#define CONF_PORT1  7
+#define RMAX (CONF_PORT1 + 1)
+
+enum tca6416_events {
+     ADDR_DONE,
+     ADDRESSING,
+};
+
+struct Tca6416State {
+     I2CSlave i2c;
+
+     uint8_t addr;
+     uint8_t state;
+     uint8_t regs[RMAX];
+};
+
+static uint8_t tca6416_read(I2CSlave *i2c)
+{
+    Tca6416State *s = TCA6416(i2c);
+    uint8_t ret;
+
+    ret = s->regs[s->addr];
+    trace_tca6416_read(ret);
+    return ret;
+}
+
+static int tca6416_write(I2CSlave *i2c, uint8_t data)
+{
+    Tca6416State *s = TCA6416(i2c);
+
+    trace_tca6416_write(data);
+    if (s->state == ADDRESSING) {
+        s->addr = data;
+    } else {
+        s->regs[s->addr] = data;
+    }
+
+    return 0;
+}
+
+static void tca6416_realize(DeviceState *dev, Error **errp)
+{
+    Tca6416State *s = TCA6416(dev);
+
+    s->regs[CONF_PORT0] = 0xFF;
+    s->regs[CONF_PORT1] = 0xFF;
+}
+
+static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
+{
+    Tca6416State *s = TCA6416(i2c);
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->state = ADDRESSING;
+        break;
+    default:
+         s->state = ADDR_DONE;
+    };
+    return 0;
+}
+
+static void tca6416_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    dc->realize = tca6416_realize;
+    k->recv = tca6416_read;
+    k->send = tca6416_write;
+    k->event = tca6416_event;
+}
+
+static const TypeInfo tca6416_types[] = {
+    {
+        .name = TYPE_TCA6416,
+        .parent = TYPE_I2C_SLAVE,
+        .class_init = tca6416_class_init,
+        .instance_size = sizeof(Tca6416State),
+    }
+};
+
+DEFINE_TYPES(tca6416_types)
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
index c423e10f59..a240cf2de2 100644
--- a/hw/gpio/Kconfig
+++ b/hw/gpio/Kconfig
@@ -20,5 +20,10 @@ config PCF8574
     bool
     depends on I2C
 
+config TCA6416
+    bool
+    depends on I2C
+    default y if I2C_DEVICES
+
 config ZAURUS_SCOOP
     bool
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
index 74840619c0..b3ff7c7460 100644
--- a/hw/gpio/meson.build
+++ b/hw/gpio/meson.build
@@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
 system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
 system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
 system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
+system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
index cea896b28f..6724f2efb8 100644
--- a/hw/gpio/trace-events
+++ b/hw/gpio/trace-events
@@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
 stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
 stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
 stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
+
+# tca6416.c
+tca6416_write(uint8_t value) "0x%02x"
+tca6416_read(uint8_t value) "0x%02x"
-- 
2.48.1



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

* [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset
  2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
                   ` (19 preceding siblings ...)
  2025-01-20 20:37 ` [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx Bernhard Beschow
@ 2025-01-20 20:37 ` Bernhard Beschow
  2025-01-28 14:33   ` Gustavo Romero
  20 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-20 20:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias, Bernhard Beschow

Input GPIO values such as a present SD card may get notified before the GPIO
controller itself gets reset. Claring the input values thus loses data. Assuming
that input GPIO events are only fired when the state changes, the input values
shouldn't be reset.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
---
 hw/gpio/imx_gpio.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/gpio/imx_gpio.c b/hw/gpio/imx_gpio.c
index 549a281ed7..25546221e0 100644
--- a/hw/gpio/imx_gpio.c
+++ b/hw/gpio/imx_gpio.c
@@ -298,7 +298,6 @@ static void imx_gpio_reset(DeviceState *dev)
 
     s->dr       = 0;
     s->gdir     = 0;
-    s->psr      = 0;
     s->icr      = 0;
     s->imr      = 0;
     s->isr      = 0;
-- 
2.48.1



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

* Re: [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers
  2025-01-20 20:37 ` [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
@ 2025-01-21  2:52   ` BALATON Zoltan
  2025-02-03 23:01     ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: BALATON Zoltan @ 2025-01-21  2:52 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025, Bernhard Beschow 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 | 39 +++++++++++++++++++++++-----------
> 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, 81 insertions(+), 12 deletions(-)
>
> diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
> index d7d08cc198..1514bc5864 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
>
> @@ -25,25 +26,39 @@ for loading a Linux kernel.
> Direct Linux Kernel Boot
> ''''''''''''''''''''''''
>
> -Linux mainline v6.12 release is tested at the time of writing. To build a Linux
> -mainline kernel that can be booted by the ``imx8mp-evk`` machine, simply
> -configure the kernel using the defconfig configuration:
> +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 three steps. First run the following command in the
> +toplevel directory of the Buildroot source tree:
>
> .. code-block:: bash
>
> -  $ export ARCH=arm64
> -  $ export CROSS_COMPILE=aarch64-linux-gnu-
> -  $ make defconfig
> +  $ make freescale_imx8mpevk_defconfig
>   $ make

Adding documentation that is removed a few patches later seems 
unnecessary. Maybe you could keep the bare kernel docs as that could also 
be useful or not add it in the first place? But if this is already written 
keeping it may make more sense than dropping it.

Regards,
BALATON Zoltan

>
> -To boot the newly built Linux kernel in QEMU with the ``imx8mp-evk`` machine,
> -run:
> +Once finished successfully there is an ``output/image`` subfolder. Navigate into
> +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
> +
> +  $ 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 arch/arm64/boot/Image \
> -      -dtb arch/arm64/boot/dts/freescale/imx8mp-evk.dtb \
> -      -initrd /path/to/rootfs.ext4 \
> -      -append "root=/dev/ram"
> +      -kernel Image \
> +      -dtb imx8mp-evk-patched.dtb \
> +      -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 9d2a757c2a..9832c05e8c 100644
> --- a/include/hw/arm/fsl-imx8mp.h
> +++ b/include/hw/arm/fsl-imx8mp.h
> @@ -14,6 +14,7 @@
> #include "hw/intc/arm_gicv3_common.h"
> #include "hw/misc/imx7_snvs.h"
> #include "hw/misc/imx8mp_ccm.h"
> +#include "hw/sd/sdhci.h"
> #include "qom/object.h"
> #include "qemu/units.h"
>
> @@ -27,6 +28,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 {
> @@ -38,6 +40,7 @@ struct FslImx8mpState {
>     IMX8MPAnalogState  analog;
>     IMX7SNVSState      snvs;
>     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
> +    SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
> };
>
> enum FslImx8mpMemoryRegions {
> @@ -183,6 +186,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 0abde2b1fc..612ea7bf93 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 adb4ed8076..f880c03d35 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -582,6 +582,7 @@ config FSL_IMX8MP
>     imply TEST_DEVICES
>     select ARM_GIC
>     select IMX
> +    select SDHCI
>     select UNIMP
>
> config FSL_IMX8MP_EVK
>


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

* Re: [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM
  2025-01-20 20:37 ` [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
@ 2025-01-21  3:00   ` BALATON Zoltan
  2025-01-21 21:03     ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: BALATON Zoltan @ 2025-01-21  3:00 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025, Bernhard Beschow 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`.
>
> 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 76b416831d..d2cdc790ff 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -830,6 +830,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 1b8a5cbbba..326c4ddf69 100644
> --- a/include/hw/arm/fsl-imx8mp.h
> +++ b/include/hw/arm/fsl-imx8mp.h
> @@ -67,6 +67,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 5b9781a424..9688e2e962 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_ram(&s->boot_rom, OBJECT(dev),
> +                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].name,
> +                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].size,
> +                                errp)) {
> +        return;
> +    }

If it's ROM why not memory_region_init_rom?

Regards,
BALATON Zoltan

> +    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',
>


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-01-20 20:37 ` [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx Bernhard Beschow
@ 2025-01-21  3:07   ` BALATON Zoltan
  2025-01-28 22:20     ` Bernhard Beschow
  2025-01-30  1:14   ` Corey Minyard
  2025-01-30 23:05   ` Philippe Mathieu-Daudé
  2 siblings, 1 reply; 50+ messages in thread
From: BALATON Zoltan @ 2025-01-21  3:07 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025, Bernhard Beschow wrote:
> Xilinx QEMU implements a TCA6416 device model which may be useful for the
> broader QEMU community, so upstream it. In the Xilinx fork, the device model
> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
> "hw/*/cadence_*" maintainers.
>
> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
> modifications:
> * Use OBJECT_DECLARE_SIMPLE_TYPE()
> * Port from DPRINTF() to trace events
> * Follow QEMU conventions for naming of state struct
> * Rename type to not contain a ','
> * Use DEFINE_TYPES() macro
> * Implement under hw/gpio since device is i2c client and gpio provider
> * Have dedicated Kconfig switch
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>
> --
> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
> willing to maintain this device model?
> ---
> MAINTAINERS          |   1 +
> hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
> hw/gpio/Kconfig      |   5 ++
> hw/gpio/meson.build  |   1 +
> hw/gpio/trace-events |   4 ++
> 5 files changed, 133 insertions(+)
> create mode 100644 hw/gpio/tca6416.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7531d65429..0cac9c90bc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1030,6 +1030,7 @@ S: Maintained
> F: hw/*/xilinx_*
> F: hw/*/cadence_*
> F: hw/misc/zynq_slcr.c
> +F: hw/gpio/tca6416.c
> F: hw/adc/zynq-xadc.c
> F: include/hw/misc/zynq_slcr.h
> F: include/hw/adc/zynq-xadc.h
> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
> new file mode 100644
> index 0000000000..81ed7a654d
> --- /dev/null
> +++ b/hw/gpio/tca6416.c
> @@ -0,0 +1,122 @@
> +/*
> + * QEMU model of TCA6416 16-Bit I/O Expander
> + *
> + * Copyright (c) 2018 Xilinx Inc.
> + *
> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +#include "qemu/osdep.h"
> +#include "hw/i2c/i2c.h"
> +#include "trace.h"
> +
> +#define TYPE_TCA6416 "tca6416"
> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
> +
> +#define IN_PORT0    0
> +#define IN_PORT1    1
> +#define OUT_PORT0   2
> +#define OUT_PORT1   3
> +#define POL_INV0    4
> +#define POL_INV1    5
> +#define CONF_PORT0  6
> +#define CONF_PORT1  7
> +#define RMAX (CONF_PORT1 + 1)

Maybe make this list an enum? (But also fine as it is.)

Regards,
BALATON Zoltan

> +
> +enum tca6416_events {
> +     ADDR_DONE,
> +     ADDRESSING,
> +};
> +
> +struct Tca6416State {
> +     I2CSlave i2c;
> +
> +     uint8_t addr;
> +     uint8_t state;
> +     uint8_t regs[RMAX];
> +};
> +
> +static uint8_t tca6416_read(I2CSlave *i2c)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +    uint8_t ret;
> +
> +    ret = s->regs[s->addr];
> +    trace_tca6416_read(ret);
> +    return ret;
> +}
> +
> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +
> +    trace_tca6416_write(data);
> +    if (s->state == ADDRESSING) {
> +        s->addr = data;
> +    } else {
> +        s->regs[s->addr] = data;
> +    }
> +
> +    return 0;
> +}
> +
> +static void tca6416_realize(DeviceState *dev, Error **errp)
> +{
> +    Tca6416State *s = TCA6416(dev);
> +
> +    s->regs[CONF_PORT0] = 0xFF;
> +    s->regs[CONF_PORT1] = 0xFF;
> +}
> +
> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +
> +    switch (event) {
> +    case I2C_START_SEND:
> +        s->state = ADDRESSING;
> +        break;
> +    default:
> +         s->state = ADDR_DONE;
> +    };
> +    return 0;
> +}
> +
> +static void tca6416_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
> +
> +    dc->realize = tca6416_realize;
> +    k->recv = tca6416_read;
> +    k->send = tca6416_write;
> +    k->event = tca6416_event;
> +}
> +
> +static const TypeInfo tca6416_types[] = {
> +    {
> +        .name = TYPE_TCA6416,
> +        .parent = TYPE_I2C_SLAVE,
> +        .class_init = tca6416_class_init,
> +        .instance_size = sizeof(Tca6416State),
> +    }
> +};
> +
> +DEFINE_TYPES(tca6416_types)
> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
> index c423e10f59..a240cf2de2 100644
> --- a/hw/gpio/Kconfig
> +++ b/hw/gpio/Kconfig
> @@ -20,5 +20,10 @@ config PCF8574
>     bool
>     depends on I2C
>
> +config TCA6416
> +    bool
> +    depends on I2C
> +    default y if I2C_DEVICES
> +
> config ZAURUS_SCOOP
>     bool
> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
> index 74840619c0..b3ff7c7460 100644
> --- a/hw/gpio/meson.build
> +++ b/hw/gpio/meson.build
> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
> system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
> system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
> system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
> index cea896b28f..6724f2efb8 100644
> --- a/hw/gpio/trace-events
> +++ b/hw/gpio/trace-events
> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
> stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
> stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
> stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
> +
> +# tca6416.c
> +tca6416_write(uint8_t value) "0x%02x"
> +tca6416_read(uint8_t value) "0x%02x"
>


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

* Re: [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM
  2025-01-21  3:00   ` BALATON Zoltan
@ 2025-01-21 21:03     ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-21 21:03 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 21. Januar 2025 03:00:17 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Mon, 20 Jan 2025, Bernhard Beschow 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`.
>> 
>> 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 76b416831d..d2cdc790ff 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -830,6 +830,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 1b8a5cbbba..326c4ddf69 100644
>> --- a/include/hw/arm/fsl-imx8mp.h
>> +++ b/include/hw/arm/fsl-imx8mp.h
>> @@ -67,6 +67,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 5b9781a424..9688e2e962 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_ram(&s->boot_rom, OBJECT(dev),
>> +                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].name,
>> +                                fsl_imx8mp_memmap[FSL_IMX8MP_BOOT_ROM].size,
>> +                                errp)) {
>> +        return;
>> +    }
>
>If it's ROM why not memory_region_init_rom?

Indeed, this should be memory_region_init_rom(). Will be fixed in next iteration.

Thanks,
Bernhard

>
>Regards,
>BALATON Zoltan
>
>> +    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',
>> 


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

* Re: [PATCH 04/21] hw/usb/hcd-dwc3: Align global registers size with Linux
  2025-01-20 20:37 ` [PATCH 04/21] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
@ 2025-01-28 14:21   ` Peter Maydell
  0 siblings, 0 replies; 50+ messages in thread
From: Peter Maydell @ 2025-01-28 14:21 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025 at 20:38, Bernhard Beschow <shentey@gmail.com> wrote:
>
> While at it add missing GUSB2RHBCTL register as found in i.MX 8M Plus reference
> manual.
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


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

* Re: [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board
  2025-01-20 20:37 ` [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
@ 2025-01-28 14:29   ` Peter Maydell
  2025-01-28 22:16     ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: Peter Maydell @ 2025-01-28 14:29 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025 at 20:38, 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>
> ---
>  MAINTAINERS                    |   9 +
>  docs/system/arm/imx8mp-evk.rst |  47 +++++
>  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                 |  13 ++
>  hw/arm/meson.build             |   2 +
>  8 files changed, 687 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 846b81e3ec..cace8cf25b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -819,6 +819,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: Odd Fixes

I'd rather we didn't take on a new board model that
starts out in the "odd fixes" state. If you don't
have enough time to look after it, it seems unlikely
that anybody else is going to want to take it over.

> +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

> +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 form Linux output: "arch_timer: cp15 timer(s) running at
> +         * 8.00MHz (phys)".

"from"

> +         */
> +        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;
> +        }
> +    }
> +

> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index fe47e259b8..adb4ed8076 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -577,6 +577,19 @@ config FSL_IMX7
>      select SDHCI
>      select UNIMP
>
> +config FSL_IMX8MP
> +    bool
> +    imply TEST_DEVICES

Why do we need TEST_DEVICES ?

> +    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

Looks good otherwise.

thanks
-- PMM


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

* Re: [PATCH 07/21] hw/arm/fsl-imx8mp: Add SNVS
  2025-01-20 20:37 ` [PATCH 07/21] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
@ 2025-01-28 14:31   ` Peter Maydell
  0 siblings, 0 replies; 50+ messages in thread
From: Peter Maydell @ 2025-01-28 14:31 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025 at 20:38, Bernhard Beschow <shentey@gmail.com> wrote:
>
> 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.
>
> 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(+)
>

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

thanks
-- PMM


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

* Re: [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support
  2025-01-20 20:37 ` [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
@ 2025-01-28 14:33   ` Peter Maydell
  2025-01-28 22:04     ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: Peter Maydell @ 2025-01-28 14:33 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025 at 20:38, 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>

> diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
> index 1514bc5864..8d48580cb4 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
>
> @@ -62,3 +63,15 @@ Now that everything is prepared the newly built image can be run in the QEMU
>        -dtb imx8mp-evk-patched.dtb \
>        -append "root=/dev/mmcblk2p2" \
>        -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
> +
> +Using PCI Devices
> +-----------------
> +
> +The PCI Express controller spawns two PCI buses, of which only one can be used.
> +By default QEMU assigns the wrong bus, so the correct one has to be specified
> +manually by adding ``bus=dw-pcie``. For example, when adding an Intel e1000
> +network card, the command line looks like:
> +
> +.. code-block:: bash
> +
> +  $ qemu-system-aarch64 -M imximp-evk ... -device virtio-net-pci,bus=dw-pcie

Why does this happen? Isn't there some way to make QEMU default to
using the right bus? Otherwise there's likely to be a lot of
user confusion because PCI "doesn't work"...

thanks
-- PMM


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

* Re: [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset
  2025-01-20 20:37 ` [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset Bernhard Beschow
@ 2025-01-28 14:33   ` Gustavo Romero
  2025-02-03 23:06     ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: Gustavo Romero @ 2025-01-28 14:33 UTC (permalink / raw)
  To: Bernhard Beschow, qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias

Hi,

On 1/20/25 17:37, Bernhard Beschow wrote:
> Input GPIO values such as a present SD card may get notified before the GPIO
> controller itself gets reset. Claring the input values thus loses data. Assuming

                                 ^- nit: Clearing


Cheers,
Gustavo

> that input GPIO events are only fired when the state changes, the input values
> shouldn't be reset.
> 
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> ---
>   hw/gpio/imx_gpio.c | 1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/hw/gpio/imx_gpio.c b/hw/gpio/imx_gpio.c
> index 549a281ed7..25546221e0 100644
> --- a/hw/gpio/imx_gpio.c
> +++ b/hw/gpio/imx_gpio.c
> @@ -298,7 +298,6 @@ static void imx_gpio_reset(DeviceState *dev)
>   
>       s->dr       = 0;
>       s->gdir     = 0;
> -    s->psr      = 0;
>       s->icr      = 0;
>       s->imr      = 0;
>       s->isr      = 0;



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

* Re: [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree
  2025-01-20 20:37 ` [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
@ 2025-01-28 14:35   ` Peter Maydell
  2025-01-28 21:53     ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: Peter Maydell @ 2025-01-28 14:35 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Mon, 20 Jan 2025 at 20:38, 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>
> ---
>  MAINTAINERS                    |   2 +
>  docs/system/arm/imx8mp-evk.rst |   1 +
>  include/hw/arm/fsl-imx8mp.h    |   3 +
>  include/hw/misc/imx8mp_ccm.h   |  97 ++++++++++
>  hw/arm/fsl-imx8mp.c            |  20 +++
>  hw/misc/imx8mp_ccm.c           | 315 +++++++++++++++++++++++++++++++++
>  hw/misc/meson.build            |   1 +
>  7 files changed, 439 insertions(+)
>  create mode 100644 include/hw/misc/imx8mp_ccm.h
>  create mode 100644 hw/misc/imx8mp_ccm.c
> diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
> new file mode 100644
> index 0000000000..2378c157de
> --- /dev/null
> +++ b/include/hw/misc/imx8mp_ccm.h
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
> + *
> + * i.MX8MP CCM, ANALOG IP blocks 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 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,
> +};
> +
> +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];
> +};
> +
> +
> +#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
> +OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
> +
> +struct IMX8MPAnalogState {
> +    IMXCCMState parent_obj;
> +
> +    struct {
> +        MemoryRegion container;
> +        MemoryRegion analog;
> +    } mmio;
> +
> +    uint32_t analog[ANALOG_MAX];
> +};
> +
> +#endif /* IMX8MP_CCM_H */

This seems to be implementing two separate devices in a single
source file. Generally we prefer one device per file. Is
there a reason they can't be split?

thanks
-- PMM


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

* Re: [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree
  2025-01-28 14:35   ` Peter Maydell
@ 2025-01-28 21:53     ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-28 21:53 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 28. Januar 2025 14:35:14 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Mon, 20 Jan 2025 at 20:38, 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>
>> ---
>>  MAINTAINERS                    |   2 +
>>  docs/system/arm/imx8mp-evk.rst |   1 +
>>  include/hw/arm/fsl-imx8mp.h    |   3 +
>>  include/hw/misc/imx8mp_ccm.h   |  97 ++++++++++
>>  hw/arm/fsl-imx8mp.c            |  20 +++
>>  hw/misc/imx8mp_ccm.c           | 315 +++++++++++++++++++++++++++++++++
>>  hw/misc/meson.build            |   1 +
>>  7 files changed, 439 insertions(+)
>>  create mode 100644 include/hw/misc/imx8mp_ccm.h
>>  create mode 100644 hw/misc/imx8mp_ccm.c
>> diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
>> new file mode 100644
>> index 0000000000..2378c157de
>> --- /dev/null
>> +++ b/include/hw/misc/imx8mp_ccm.h
>> @@ -0,0 +1,97 @@
>> +/*
>> + * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
>> + *
>> + * i.MX8MP CCM, ANALOG IP blocks 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 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,
>> +};
>> +
>> +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];
>> +};
>> +
>> +
>> +#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
>> +OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
>> +
>> +struct IMX8MPAnalogState {
>> +    IMXCCMState parent_obj;
>> +
>> +    struct {
>> +        MemoryRegion container;
>> +        MemoryRegion analog;
>> +    } mmio;
>> +
>> +    uint32_t analog[ANALOG_MAX];
>> +};
>> +
>> +#endif /* IMX8MP_CCM_H */
>
>This seems to be implementing two separate devices in a single
>source file. Generally we prefer one device per file. Is
>there a reason they can't be split?

I took inspiration from i.mx7 where these two are also implemented in one file, presumably because both share some code. This isn't the case here so I'm more than happy to split.

Best regards,
Bernhard

>
>thanks
>-- PMM


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

* Re: [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support
  2025-01-28 14:33   ` Peter Maydell
@ 2025-01-28 22:04     ` Bernhard Beschow
  2025-01-29 17:54       ` BALATON Zoltan
  0 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-28 22:04 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 28. Januar 2025 14:33:14 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Mon, 20 Jan 2025 at 20:38, 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>
>
>> diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
>> index 1514bc5864..8d48580cb4 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
>>
>> @@ -62,3 +63,15 @@ Now that everything is prepared the newly built image can be run in the QEMU
>>        -dtb imx8mp-evk-patched.dtb \
>>        -append "root=/dev/mmcblk2p2" \
>>        -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>> +
>> +Using PCI Devices
>> +-----------------
>> +
>> +The PCI Express controller spawns two PCI buses, of which only one can be used.
>> +By default QEMU assigns the wrong bus, so the correct one has to be specified
>> +manually by adding ``bus=dw-pcie``. For example, when adding an Intel e1000
>> +network card, the command line looks like:
>> +
>> +.. code-block:: bash
>> +
>> +  $ qemu-system-aarch64 -M imximp-evk ... -device virtio-net-pci,bus=dw-pcie
>
>Why does this happen? Isn't there some way to make QEMU default to
>using the right bus? Otherwise there's likely to be a lot of
>user confusion because PCI "doesn't work"...

Yeah, this is really confusing and I forget about it myself. I'd appreciate any hints here.

Best regards,
Bernhard

>
>thanks
>-- PMM


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

* Re: [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board
  2025-01-28 14:29   ` Peter Maydell
@ 2025-01-28 22:16     ` Bernhard Beschow
  2025-01-29 12:17       ` Peter Maydell
  0 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-28 22:16 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 28. Januar 2025 14:29:53 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Mon, 20 Jan 2025 at 20:38, 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>
>> ---
>>  MAINTAINERS                    |   9 +
>>  docs/system/arm/imx8mp-evk.rst |  47 +++++
>>  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                 |  13 ++
>>  hw/arm/meson.build             |   2 +
>>  8 files changed, 687 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 846b81e3ec..cace8cf25b 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -819,6 +819,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: Odd Fixes
>
>I'd rather we didn't take on a new board model that
>starts out in the "odd fixes" state. If you don't
>have enough time to look after it, it seems unlikely
>that anybody else is going to want to take it over.

I'd look after it, but I'd also not raise expectations regarding commercial grade support. What state would you suggest?

>
>> +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
>
>> +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 form Linux output: "arch_timer: cp15 timer(s) running at
>> +         * 8.00MHz (phys)".
>
>"from"

Will fix.

>
>> +         */
>> +        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;
>> +        }
>> +    }
>> +
>
>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>> index fe47e259b8..adb4ed8076 100644
>> --- a/hw/arm/Kconfig
>> +++ b/hw/arm/Kconfig
>> @@ -577,6 +577,19 @@ config FSL_IMX7
>>      select SDHCI
>>      select UNIMP
>>
>> +config FSL_IMX8MP
>> +    bool
>> +    imply TEST_DEVICES
>
>Why do we need TEST_DEVICES ?

Copied from FSL_IMX7. Will drop.

>
>> +    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
>
>Looks good otherwise.

Thanks,
Bernhard

>
>thanks
>-- PMM


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-01-21  3:07   ` BALATON Zoltan
@ 2025-01-28 22:20     ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-28 22:20 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 21. Januar 2025 03:07:39 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Mon, 20 Jan 2025, Bernhard Beschow wrote:
>> Xilinx QEMU implements a TCA6416 device model which may be useful for the
>> broader QEMU community, so upstream it. In the Xilinx fork, the device model
>> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
>> "hw/*/cadence_*" maintainers.
>> 
>> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
>> modifications:
>> * Use OBJECT_DECLARE_SIMPLE_TYPE()
>> * Port from DPRINTF() to trace events
>> * Follow QEMU conventions for naming of state struct
>> * Rename type to not contain a ','
>> * Use DEFINE_TYPES() macro
>> * Implement under hw/gpio since device is i2c client and gpio provider
>> * Have dedicated Kconfig switch
>> 
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> 
>> --
>> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
>> willing to maintain this device model?
>> ---
>> MAINTAINERS          |   1 +
>> hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
>> hw/gpio/Kconfig      |   5 ++
>> hw/gpio/meson.build  |   1 +
>> hw/gpio/trace-events |   4 ++
>> 5 files changed, 133 insertions(+)
>> create mode 100644 hw/gpio/tca6416.c
>> 
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 7531d65429..0cac9c90bc 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1030,6 +1030,7 @@ S: Maintained
>> F: hw/*/xilinx_*
>> F: hw/*/cadence_*
>> F: hw/misc/zynq_slcr.c
>> +F: hw/gpio/tca6416.c
>> F: hw/adc/zynq-xadc.c
>> F: include/hw/misc/zynq_slcr.h
>> F: include/hw/adc/zynq-xadc.h
>> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
>> new file mode 100644
>> index 0000000000..81ed7a654d
>> --- /dev/null
>> +++ b/hw/gpio/tca6416.c
>> @@ -0,0 +1,122 @@
>> +/*
>> + * QEMU model of TCA6416 16-Bit I/O Expander
>> + *
>> + * Copyright (c) 2018 Xilinx Inc.
>> + *
>> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>> + * of this software and associated documentation files (the "Software"), to deal
>> + * in the Software without restriction, including without limitation the rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +#include "qemu/osdep.h"
>> +#include "hw/i2c/i2c.h"
>> +#include "trace.h"
>> +
>> +#define TYPE_TCA6416 "tca6416"
>> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
>> +
>> +#define IN_PORT0    0
>> +#define IN_PORT1    1
>> +#define OUT_PORT0   2
>> +#define OUT_PORT1   3
>> +#define POL_INV0    4
>> +#define POL_INV1    5
>> +#define CONF_PORT0  6
>> +#define CONF_PORT1  7
>> +#define RMAX (CONF_PORT1 + 1)
>
>Maybe make this list an enum? (But also fine as it is.)

Good idea indeed. I'd address this once maintainership is clarified.

Best regards,
Bernhard

>
>Regards,
>BALATON Zoltan
>
>> +
>> +enum tca6416_events {
>> +     ADDR_DONE,
>> +     ADDRESSING,
>> +};
>> +
>> +struct Tca6416State {
>> +     I2CSlave i2c;
>> +
>> +     uint8_t addr;
>> +     uint8_t state;
>> +     uint8_t regs[RMAX];
>> +};
>> +
>> +static uint8_t tca6416_read(I2CSlave *i2c)
>> +{
>> +    Tca6416State *s = TCA6416(i2c);
>> +    uint8_t ret;
>> +
>> +    ret = s->regs[s->addr];
>> +    trace_tca6416_read(ret);
>> +    return ret;
>> +}
>> +
>> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
>> +{
>> +    Tca6416State *s = TCA6416(i2c);
>> +
>> +    trace_tca6416_write(data);
>> +    if (s->state == ADDRESSING) {
>> +        s->addr = data;
>> +    } else {
>> +        s->regs[s->addr] = data;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static void tca6416_realize(DeviceState *dev, Error **errp)
>> +{
>> +    Tca6416State *s = TCA6416(dev);
>> +
>> +    s->regs[CONF_PORT0] = 0xFF;
>> +    s->regs[CONF_PORT1] = 0xFF;
>> +}
>> +
>> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
>> +{
>> +    Tca6416State *s = TCA6416(i2c);
>> +
>> +    switch (event) {
>> +    case I2C_START_SEND:
>> +        s->state = ADDRESSING;
>> +        break;
>> +    default:
>> +         s->state = ADDR_DONE;
>> +    };
>> +    return 0;
>> +}
>> +
>> +static void tca6416_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
>> +
>> +    dc->realize = tca6416_realize;
>> +    k->recv = tca6416_read;
>> +    k->send = tca6416_write;
>> +    k->event = tca6416_event;
>> +}
>> +
>> +static const TypeInfo tca6416_types[] = {
>> +    {
>> +        .name = TYPE_TCA6416,
>> +        .parent = TYPE_I2C_SLAVE,
>> +        .class_init = tca6416_class_init,
>> +        .instance_size = sizeof(Tca6416State),
>> +    }
>> +};
>> +
>> +DEFINE_TYPES(tca6416_types)
>> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
>> index c423e10f59..a240cf2de2 100644
>> --- a/hw/gpio/Kconfig
>> +++ b/hw/gpio/Kconfig
>> @@ -20,5 +20,10 @@ config PCF8574
>>     bool
>>     depends on I2C
>> 
>> +config TCA6416
>> +    bool
>> +    depends on I2C
>> +    default y if I2C_DEVICES
>> +
>> config ZAURUS_SCOOP
>>     bool
>> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
>> index 74840619c0..b3ff7c7460 100644
>> --- a/hw/gpio/meson.build
>> +++ b/hw/gpio/meson.build
>> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
>> system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
>> system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
>> system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
>> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
>> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
>> index cea896b28f..6724f2efb8 100644
>> --- a/hw/gpio/trace-events
>> +++ b/hw/gpio/trace-events
>> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
>> stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
>> stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
>> stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
>> +
>> +# tca6416.c
>> +tca6416_write(uint8_t value) "0x%02x"
>> +tca6416_read(uint8_t value) "0x%02x"
>> 


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

* Re: [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board
  2025-01-28 22:16     ` Bernhard Beschow
@ 2025-01-29 12:17       ` Peter Maydell
  2025-01-29 13:04         ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: Peter Maydell @ 2025-01-29 12:17 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Tue, 28 Jan 2025 at 22:16, Bernhard Beschow <shentey@gmail.com> wrote:
>
>
>
> Am 28. Januar 2025 14:29:53 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
> >On Mon, 20 Jan 2025 at 20:38, Bernhard Beschow <shentey@gmail.com> wrote:
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 846b81e3ec..cace8cf25b 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -819,6 +819,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: Odd Fixes
> >
> >I'd rather we didn't take on a new board model that
> >starts out in the "odd fixes" state. If you don't
> >have enough time to look after it, it seems unlikely
> >that anybody else is going to want to take it over.
>
> I'd look after it, but I'd also not raise expectations
> regarding commercial grade support. What state would you
> suggest?

That's
      Maintained:  Someone actually looks after it.
(There's another step above that which is
      Supported:   Someone is actually paid to look after this.)

thanks
-- PMM


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

* Re: [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board
  2025-01-29 12:17       ` Peter Maydell
@ 2025-01-29 13:04         ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-01-29 13:04 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 29. Januar 2025 12:17:33 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>On Tue, 28 Jan 2025 at 22:16, Bernhard Beschow <shentey@gmail.com> wrote:
>>
>>
>>
>> Am 28. Januar 2025 14:29:53 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>> >On Mon, 20 Jan 2025 at 20:38, Bernhard Beschow <shentey@gmail.com> wrote:
>> >>
>> >> diff --git a/MAINTAINERS b/MAINTAINERS
>> >> index 846b81e3ec..cace8cf25b 100644
>> >> --- a/MAINTAINERS
>> >> +++ b/MAINTAINERS
>> >> @@ -819,6 +819,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: Odd Fixes
>> >
>> >I'd rather we didn't take on a new board model that
>> >starts out in the "odd fixes" state. If you don't
>> >have enough time to look after it, it seems unlikely
>> >that anybody else is going to want to take it over.
>>
>> I'd look after it, but I'd also not raise expectations
>> regarding commercial grade support. What state would you
>> suggest?
>
>That's
>      Maintained:  Someone actually looks after it.
>(There's another step above that which is
>      Supported:   Someone is actually paid to look after this.)

Alright, that's what I meant. Will fix.

Best regards,
Bernhard

>
>thanks
>-- PMM


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

* Re: [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support
  2025-01-28 22:04     ` Bernhard Beschow
@ 2025-01-29 17:54       ` BALATON Zoltan
  2025-02-01 14:45         ` Bernhard Beschow
  0 siblings, 1 reply; 50+ messages in thread
From: BALATON Zoltan @ 2025-01-29 17:54 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: Peter Maydell, qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

On Tue, 28 Jan 2025, Bernhard Beschow wrote:
> Am 28. Januar 2025 14:33:14 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>> On Mon, 20 Jan 2025 at 20:38, 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>
>>
>>> diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
>>> index 1514bc5864..8d48580cb4 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
>>>
>>> @@ -62,3 +63,15 @@ Now that everything is prepared the newly built image can be run in the QEMU
>>>        -dtb imx8mp-evk-patched.dtb \
>>>        -append "root=/dev/mmcblk2p2" \
>>>        -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>>> +
>>> +Using PCI Devices
>>> +-----------------
>>> +
>>> +The PCI Express controller spawns two PCI buses, of which only one can be used.
>>> +By default QEMU assigns the wrong bus, so the correct one has to be specified
>>> +manually by adding ``bus=dw-pcie``. For example, when adding an Intel e1000
>>> +network card, the command line looks like:
>>> +
>>> +.. code-block:: bash
>>> +
>>> +  $ qemu-system-aarch64 -M imximp-evk ... -device virtio-net-pci,bus=dw-pcie
>>
>> Why does this happen? Isn't there some way to make QEMU default to
>> using the right bus? Otherwise there's likely to be a lot of
>> user confusion because PCI "doesn't work"...
>
> Yeah, this is really confusing and I forget about it myself. I'd appreciate any hints here.

I'm not sure but I think the PCI bus created last will be used by default 
so maybe swapping the order these are created may help.

Regards,
BALATON Zoltan

> Best regards,
> Bernhard
>
>>
>> thanks
>> -- PMM
>
>


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-01-20 20:37 ` [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx Bernhard Beschow
  2025-01-21  3:07   ` BALATON Zoltan
@ 2025-01-30  1:14   ` Corey Minyard
  2025-01-30 23:05   ` Philippe Mathieu-Daudé
  2 siblings, 0 replies; 50+ messages in thread
From: Corey Minyard @ 2025-01-30  1:14 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias

I'm not sure about ownership here, but from an I2C point of view this
all looks ok.

Reviewed-by: Corey Minyard <cminyard@mvista.com>

On Mon, Jan 20, 2025 at 12:43 PM Bernhard Beschow <shentey@gmail.com> wrote:
>
> Xilinx QEMU implements a TCA6416 device model which may be useful for the
> broader QEMU community, so upstream it. In the Xilinx fork, the device model
> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
> "hw/*/cadence_*" maintainers.
>
> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
> modifications:
> * Use OBJECT_DECLARE_SIMPLE_TYPE()
> * Port from DPRINTF() to trace events
> * Follow QEMU conventions for naming of state struct
> * Rename type to not contain a ','
> * Use DEFINE_TYPES() macro
> * Implement under hw/gpio since device is i2c client and gpio provider
> * Have dedicated Kconfig switch
>
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>
> --
> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
> willing to maintain this device model?
> ---
>  MAINTAINERS          |   1 +
>  hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
>  hw/gpio/Kconfig      |   5 ++
>  hw/gpio/meson.build  |   1 +
>  hw/gpio/trace-events |   4 ++
>  5 files changed, 133 insertions(+)
>  create mode 100644 hw/gpio/tca6416.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7531d65429..0cac9c90bc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1030,6 +1030,7 @@ S: Maintained
>  F: hw/*/xilinx_*
>  F: hw/*/cadence_*
>  F: hw/misc/zynq_slcr.c
> +F: hw/gpio/tca6416.c
>  F: hw/adc/zynq-xadc.c
>  F: include/hw/misc/zynq_slcr.h
>  F: include/hw/adc/zynq-xadc.h
> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
> new file mode 100644
> index 0000000000..81ed7a654d
> --- /dev/null
> +++ b/hw/gpio/tca6416.c
> @@ -0,0 +1,122 @@
> +/*
> + * QEMU model of TCA6416 16-Bit I/O Expander
> + *
> + * Copyright (c) 2018 Xilinx Inc.
> + *
> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +#include "qemu/osdep.h"
> +#include "hw/i2c/i2c.h"
> +#include "trace.h"
> +
> +#define TYPE_TCA6416 "tca6416"
> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
> +
> +#define IN_PORT0    0
> +#define IN_PORT1    1
> +#define OUT_PORT0   2
> +#define OUT_PORT1   3
> +#define POL_INV0    4
> +#define POL_INV1    5
> +#define CONF_PORT0  6
> +#define CONF_PORT1  7
> +#define RMAX (CONF_PORT1 + 1)
> +
> +enum tca6416_events {
> +     ADDR_DONE,
> +     ADDRESSING,
> +};
> +
> +struct Tca6416State {
> +     I2CSlave i2c;
> +
> +     uint8_t addr;
> +     uint8_t state;
> +     uint8_t regs[RMAX];
> +};
> +
> +static uint8_t tca6416_read(I2CSlave *i2c)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +    uint8_t ret;
> +
> +    ret = s->regs[s->addr];
> +    trace_tca6416_read(ret);
> +    return ret;
> +}
> +
> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +
> +    trace_tca6416_write(data);
> +    if (s->state == ADDRESSING) {
> +        s->addr = data;
> +    } else {
> +        s->regs[s->addr] = data;
> +    }
> +
> +    return 0;
> +}
> +
> +static void tca6416_realize(DeviceState *dev, Error **errp)
> +{
> +    Tca6416State *s = TCA6416(dev);
> +
> +    s->regs[CONF_PORT0] = 0xFF;
> +    s->regs[CONF_PORT1] = 0xFF;
> +}
> +
> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +
> +    switch (event) {
> +    case I2C_START_SEND:
> +        s->state = ADDRESSING;
> +        break;
> +    default:
> +         s->state = ADDR_DONE;
> +    };
> +    return 0;
> +}
> +
> +static void tca6416_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
> +
> +    dc->realize = tca6416_realize;
> +    k->recv = tca6416_read;
> +    k->send = tca6416_write;
> +    k->event = tca6416_event;
> +}
> +
> +static const TypeInfo tca6416_types[] = {
> +    {
> +        .name = TYPE_TCA6416,
> +        .parent = TYPE_I2C_SLAVE,
> +        .class_init = tca6416_class_init,
> +        .instance_size = sizeof(Tca6416State),
> +    }
> +};
> +
> +DEFINE_TYPES(tca6416_types)
> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
> index c423e10f59..a240cf2de2 100644
> --- a/hw/gpio/Kconfig
> +++ b/hw/gpio/Kconfig
> @@ -20,5 +20,10 @@ config PCF8574
>      bool
>      depends on I2C
>
> +config TCA6416
> +    bool
> +    depends on I2C
> +    default y if I2C_DEVICES
> +
>  config ZAURUS_SCOOP
>      bool
> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
> index 74840619c0..b3ff7c7460 100644
> --- a/hw/gpio/meson.build
> +++ b/hw/gpio/meson.build
> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
>  system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
>  system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
>  system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
> index cea896b28f..6724f2efb8 100644
> --- a/hw/gpio/trace-events
> +++ b/hw/gpio/trace-events
> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
>  stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
>  stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
>  stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
> +
> +# tca6416.c
> +tca6416_write(uint8_t value) "0x%02x"
> +tca6416_read(uint8_t value) "0x%02x"
> --
> 2.48.1
>
>


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-01-20 20:37 ` [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx Bernhard Beschow
  2025-01-21  3:07   ` BALATON Zoltan
  2025-01-30  1:14   ` Corey Minyard
@ 2025-01-30 23:05   ` Philippe Mathieu-Daudé
  2025-02-01 15:28     ` Bernhard Beschow
  2 siblings, 1 reply; 50+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-01-30 23:05 UTC (permalink / raw)
  To: Bernhard Beschow, qemu-devel, Sai Pavan Boddu, Edgar E. Iglesias,
	Francisco Iglesias, Dmitrii Sharikhin
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias

Cc'ing AMD folks

Hi Bernhard,

TL;DR; can't you use the PCF8574 which is a more complete model of I/O
expander? (See hw/gpio/pcf8574.c)

On 20/1/25 21:37, Bernhard Beschow wrote:
> Xilinx QEMU implements a TCA6416 device model which may be useful for the
> broader QEMU community, so upstream it. In the Xilinx fork, the device model
> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
> "hw/*/cadence_*" maintainers.
> 
> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
> modifications:
> * Use OBJECT_DECLARE_SIMPLE_TYPE()
> * Port from DPRINTF() to trace events
> * Follow QEMU conventions for naming of state struct
> * Rename type to not contain a ','
> * Use DEFINE_TYPES() macro
> * Implement under hw/gpio since device is i2c client and gpio provider
> * Have dedicated Kconfig switch
> 
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> 
> --
> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
> willing to maintain this device model?
> ---
>   MAINTAINERS          |   1 +
>   hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
>   hw/gpio/Kconfig      |   5 ++
>   hw/gpio/meson.build  |   1 +
>   hw/gpio/trace-events |   4 ++
>   5 files changed, 133 insertions(+)
>   create mode 100644 hw/gpio/tca6416.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7531d65429..0cac9c90bc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1030,6 +1030,7 @@ S: Maintained
>   F: hw/*/xilinx_*
>   F: hw/*/cadence_*
>   F: hw/misc/zynq_slcr.c
> +F: hw/gpio/tca6416.c
>   F: hw/adc/zynq-xadc.c
>   F: include/hw/misc/zynq_slcr.h
>   F: include/hw/adc/zynq-xadc.h
> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
> new file mode 100644
> index 0000000000..81ed7a654d
> --- /dev/null
> +++ b/hw/gpio/tca6416.c
> @@ -0,0 +1,122 @@
> +/*
> + * QEMU model of TCA6416 16-Bit I/O Expander

Please add datasheet reference.

> + *
> + * Copyright (c) 2018 Xilinx Inc.
> + *
> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.

Sai/Edgar/Francisco, should we update to AMD here? Remove or update the
email address? Also, can you Ack the replacement of this license by a
SPDX tag?

> + */
> +#include "qemu/osdep.h"
> +#include "hw/i2c/i2c.h"
> +#include "trace.h"
> +
> +#define TYPE_TCA6416 "tca6416"
> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
> +
> +#define IN_PORT0    0
> +#define IN_PORT1    1
> +#define OUT_PORT0   2
> +#define OUT_PORT1   3
> +#define POL_INV0    4
> +#define POL_INV1    5
> +#define CONF_PORT0  6
> +#define CONF_PORT1  7

enum up to here?

> +#define RMAX (CONF_PORT1 + 1)
> +
> +enum tca6416_events {
> +     ADDR_DONE,
> +     ADDRESSING,
> +};
> +
> +struct Tca6416State {
> +     I2CSlave i2c;
> +
> +     uint8_t addr;
> +     uint8_t state;
> +     uint8_t regs[RMAX];
> +};
> +
> +static uint8_t tca6416_read(I2CSlave *i2c)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +    uint8_t ret;
> +
> +    ret = s->regs[s->addr];
> +    trace_tca6416_read(ret);
> +    return ret;
> +}
> +
> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +
> +    trace_tca6416_write(data);
> +    if (s->state == ADDRESSING) {
> +        s->addr = data;

I suppose HW masks here.

           s->addr = data & 0xf;

> +    } else {
> +        s->regs[s->addr] = data;

(otherwise this could overflow).

So this device isn't doing anything actually (I'd have
expected 1 IRQ and 16 GPIO lines). What is the point,
at least in this state?

> +    }
> +
> +    return 0;
> +}
> +
> +static void tca6416_realize(DeviceState *dev, Error **errp)
> +{
> +    Tca6416State *s = TCA6416(dev);
> +

Missing:

        s->regs[OUT_PORT0] = 0xff;
        s->regs[OUT_PORT1] = 0xff;
        s->regs[POL_INV0] = 0x00;
        s->regs[POL_INV1] = 0x00;

> +    s->regs[CONF_PORT0] = 0xFF;
> +    s->regs[CONF_PORT1] = 0xFF;

Style is 0xff.

That said, this is not a REALIZE but RESET handler.

> +}
> +
> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
> +{
> +    Tca6416State *s = TCA6416(i2c);
> +
> +    switch (event) {
> +    case I2C_START_SEND:
> +        s->state = ADDRESSING;
> +        break;
> +    default:
> +         s->state = ADDR_DONE;
> +    };
> +    return 0;
> +}
> +
> +static void tca6416_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
> +
> +    dc->realize = tca6416_realize;

(tca6416_realize is a reset handler).

Please complete:

        dc->desc = "TCA6416 I/O Expander";
        set_bit(DEVICE_CATEGORY_MISC, dc->categories);

No migration state?

> +    k->recv = tca6416_read;
> +    k->send = tca6416_write;
> +    k->event = tca6416_event;
 > +}> +
> +static const TypeInfo tca6416_types[] = {
> +    {
> +        .name = TYPE_TCA6416,
> +        .parent = TYPE_I2C_SLAVE,
> +        .class_init = tca6416_class_init,
> +        .instance_size = sizeof(Tca6416State),
> +    }
> +};
> +
> +DEFINE_TYPES(tca6416_types)
> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
> index c423e10f59..a240cf2de2 100644
> --- a/hw/gpio/Kconfig
> +++ b/hw/gpio/Kconfig
> @@ -20,5 +20,10 @@ config PCF8574
>       bool
>       depends on I2C
>   
> +config TCA6416
> +    bool
> +    depends on I2C
> +    default y if I2C_DEVICES
> +
>   config ZAURUS_SCOOP
>       bool
> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
> index 74840619c0..b3ff7c7460 100644
> --- a/hw/gpio/meson.build
> +++ b/hw/gpio/meson.build
> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
>   system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
>   system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
>   system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
> index cea896b28f..6724f2efb8 100644
> --- a/hw/gpio/trace-events
> +++ b/hw/gpio/trace-events
> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
>   stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
>   stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
>   stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
> +
> +# tca6416.c
> +tca6416_write(uint8_t value) "0x%02x"

"wr 0x%02x"

> +tca6416_read(uint8_t value) "0x%02x"

"rd ..."

Regards,

Phil.


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

* Re: [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support
  2025-01-29 17:54       ` BALATON Zoltan
@ 2025-02-01 14:45         ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-01 14:45 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: Peter Maydell, qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 29. Januar 2025 17:54:46 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Tue, 28 Jan 2025, Bernhard Beschow wrote:
>> Am 28. Januar 2025 14:33:14 UTC schrieb Peter Maydell <peter.maydell@linaro.org>:
>>> On Mon, 20 Jan 2025 at 20:38, 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>
>>> 
>>>> diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
>>>> index 1514bc5864..8d48580cb4 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
>>>> 
>>>> @@ -62,3 +63,15 @@ Now that everything is prepared the newly built image can be run in the QEMU
>>>>        -dtb imx8mp-evk-patched.dtb \
>>>>        -append "root=/dev/mmcblk2p2" \
>>>>        -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>>>> +
>>>> +Using PCI Devices
>>>> +-----------------
>>>> +
>>>> +The PCI Express controller spawns two PCI buses, of which only one can be used.
>>>> +By default QEMU assigns the wrong bus, so the correct one has to be specified
>>>> +manually by adding ``bus=dw-pcie``. For example, when adding an Intel e1000
>>>> +network card, the command line looks like:
>>>> +
>>>> +.. code-block:: bash
>>>> +
>>>> +  $ qemu-system-aarch64 -M imximp-evk ... -device virtio-net-pci,bus=dw-pcie
>>> 
>>> Why does this happen? Isn't there some way to make QEMU default to
>>> using the right bus? Otherwise there's likely to be a lot of
>>> user confusion because PCI "doesn't work"...
>> 
>> Yeah, this is really confusing and I forget about it myself. I'd appreciate any hints here.
>
>I'm not sure but I think the PCI bus created last will be used by default so maybe swapping the order these are created may help.

Turns out there is BusClass::max_dev which is respected when a parent bus for a user-created device is sought. I'll draw inspiration from pnv_phb4.

Best regards,
Bernhard

>
>Regards,
>BALATON Zoltan
>
>> Best regards,
>> Bernhard
>> 
>>> 
>>> thanks
>>> -- PMM
>> 
>> 


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-01-30 23:05   ` Philippe Mathieu-Daudé
@ 2025-02-01 15:28     ` Bernhard Beschow
  2025-02-02 17:09       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-01 15:28 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel, Sai Pavan Boddu,
	Edgar E. Iglesias, Francisco Iglesias, Dmitrii Sharikhin
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias



Am 30. Januar 2025 23:05:53 UTC schrieb "Philippe Mathieu-Daudé" <philmd@linaro.org>:
>Cc'ing AMD folks
>
>Hi Bernhard,
>
>TL;DR; can't you use the PCF8574 which is a more complete model of I/O
>expander? (See hw/gpio/pcf8574.c)

If it is software-compatible then I could use it. I'm modeling a real board whose device tree I'd like to use unchanged, so I don't have much choice. The only reason I need it is because its absence clogs the i2c bus.

Best regards,
Bernhard

>
>On 20/1/25 21:37, Bernhard Beschow wrote:
>> Xilinx QEMU implements a TCA6416 device model which may be useful for the
>> broader QEMU community, so upstream it. In the Xilinx fork, the device model
>> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
>> "hw/*/cadence_*" maintainers.
>> 
>> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
>> modifications:
>> * Use OBJECT_DECLARE_SIMPLE_TYPE()
>> * Port from DPRINTF() to trace events
>> * Follow QEMU conventions for naming of state struct
>> * Rename type to not contain a ','
>> * Use DEFINE_TYPES() macro
>> * Implement under hw/gpio since device is i2c client and gpio provider
>> * Have dedicated Kconfig switch
>> 
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> 
>> --
>> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
>> willing to maintain this device model?
>> ---
>>   MAINTAINERS          |   1 +
>>   hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
>>   hw/gpio/Kconfig      |   5 ++
>>   hw/gpio/meson.build  |   1 +
>>   hw/gpio/trace-events |   4 ++
>>   5 files changed, 133 insertions(+)
>>   create mode 100644 hw/gpio/tca6416.c
>> 
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 7531d65429..0cac9c90bc 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1030,6 +1030,7 @@ S: Maintained
>>   F: hw/*/xilinx_*
>>   F: hw/*/cadence_*
>>   F: hw/misc/zynq_slcr.c
>> +F: hw/gpio/tca6416.c
>>   F: hw/adc/zynq-xadc.c
>>   F: include/hw/misc/zynq_slcr.h
>>   F: include/hw/adc/zynq-xadc.h
>> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
>> new file mode 100644
>> index 0000000000..81ed7a654d
>> --- /dev/null
>> +++ b/hw/gpio/tca6416.c
>> @@ -0,0 +1,122 @@
>> +/*
>> + * QEMU model of TCA6416 16-Bit I/O Expander
>
>Please add datasheet reference.
>
>> + *
>> + * Copyright (c) 2018 Xilinx Inc.
>> + *
>> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>> + * of this software and associated documentation files (the "Software"), to deal
>> + * in the Software without restriction, including without limitation the rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>
>Sai/Edgar/Francisco, should we update to AMD here? Remove or update the
>email address? Also, can you Ack the replacement of this license by a
>SPDX tag?
>
>> + */
>> +#include "qemu/osdep.h"
>> +#include "hw/i2c/i2c.h"
>> +#include "trace.h"
>> +
>> +#define TYPE_TCA6416 "tca6416"
>> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
>> +
>> +#define IN_PORT0    0
>> +#define IN_PORT1    1
>> +#define OUT_PORT0   2
>> +#define OUT_PORT1   3
>> +#define POL_INV0    4
>> +#define POL_INV1    5
>> +#define CONF_PORT0  6
>> +#define CONF_PORT1  7
>
>enum up to here?
>
>> +#define RMAX (CONF_PORT1 + 1)
>> +
>> +enum tca6416_events {
>> +     ADDR_DONE,
>> +     ADDRESSING,
>> +};
>> +
>> +struct Tca6416State {
>> +     I2CSlave i2c;
>> +
>> +     uint8_t addr;
>> +     uint8_t state;
>> +     uint8_t regs[RMAX];
>> +};
>> +
>> +static uint8_t tca6416_read(I2CSlave *i2c)
>> +{
>> +    Tca6416State *s = TCA6416(i2c);
>> +    uint8_t ret;
>> +
>> +    ret = s->regs[s->addr];
>> +    trace_tca6416_read(ret);
>> +    return ret;
>> +}
>> +
>> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
>> +{
>> +    Tca6416State *s = TCA6416(i2c);
>> +
>> +    trace_tca6416_write(data);
>> +    if (s->state == ADDRESSING) {
>> +        s->addr = data;
>
>I suppose HW masks here.
>
>          s->addr = data & 0xf;
>
>> +    } else {
>> +        s->regs[s->addr] = data;
>
>(otherwise this could overflow).
>
>So this device isn't doing anything actually (I'd have
>expected 1 IRQ and 16 GPIO lines). What is the point,
>at least in this state?
>
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static void tca6416_realize(DeviceState *dev, Error **errp)
>> +{
>> +    Tca6416State *s = TCA6416(dev);
>> +
>
>Missing:
>
>       s->regs[OUT_PORT0] = 0xff;
>       s->regs[OUT_PORT1] = 0xff;
>       s->regs[POL_INV0] = 0x00;
>       s->regs[POL_INV1] = 0x00;
>
>> +    s->regs[CONF_PORT0] = 0xFF;
>> +    s->regs[CONF_PORT1] = 0xFF;
>
>Style is 0xff.
>
>That said, this is not a REALIZE but RESET handler.
>
>> +}
>> +
>> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
>> +{
>> +    Tca6416State *s = TCA6416(i2c);
>> +
>> +    switch (event) {
>> +    case I2C_START_SEND:
>> +        s->state = ADDRESSING;
>> +        break;
>> +    default:
>> +         s->state = ADDR_DONE;
>> +    };
>> +    return 0;
>> +}
>> +
>> +static void tca6416_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
>> +
>> +    dc->realize = tca6416_realize;
>
>(tca6416_realize is a reset handler).
>
>Please complete:
>
>       dc->desc = "TCA6416 I/O Expander";
>       set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>
>No migration state?
>
>> +    k->recv = tca6416_read;
>> +    k->send = tca6416_write;
>> +    k->event = tca6416_event;
>> +}> +
>> +static const TypeInfo tca6416_types[] = {
>> +    {
>> +        .name = TYPE_TCA6416,
>> +        .parent = TYPE_I2C_SLAVE,
>> +        .class_init = tca6416_class_init,
>> +        .instance_size = sizeof(Tca6416State),
>> +    }
>> +};
>> +
>> +DEFINE_TYPES(tca6416_types)
>> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
>> index c423e10f59..a240cf2de2 100644
>> --- a/hw/gpio/Kconfig
>> +++ b/hw/gpio/Kconfig
>> @@ -20,5 +20,10 @@ config PCF8574
>>       bool
>>       depends on I2C
>>   +config TCA6416
>> +    bool
>> +    depends on I2C
>> +    default y if I2C_DEVICES
>> +
>>   config ZAURUS_SCOOP
>>       bool
>> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
>> index 74840619c0..b3ff7c7460 100644
>> --- a/hw/gpio/meson.build
>> +++ b/hw/gpio/meson.build
>> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
>>   system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
>>   system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
>>   system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
>> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
>> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
>> index cea896b28f..6724f2efb8 100644
>> --- a/hw/gpio/trace-events
>> +++ b/hw/gpio/trace-events
>> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
>>   stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
>>   stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
>>   stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
>> +
>> +# tca6416.c
>> +tca6416_write(uint8_t value) "0x%02x"
>
>"wr 0x%02x"
>
>> +tca6416_read(uint8_t value) "0x%02x"
>
>"rd ..."
>
>Regards,
>
>Phil.


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-02-01 15:28     ` Bernhard Beschow
@ 2025-02-02 17:09       ` Philippe Mathieu-Daudé
  2025-02-03  5:42         ` Dmitriy Sharikhin
  2025-02-03 22:38         ` Bernhard Beschow
  0 siblings, 2 replies; 50+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-02 17:09 UTC (permalink / raw)
  To: Bernhard Beschow, qemu-devel, Sai Pavan Boddu, Edgar E. Iglesias,
	Francisco Iglesias, Dmitrii Sharikhin
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias

On 1/2/25 16:28, Bernhard Beschow wrote:
> 
> 
> Am 30. Januar 2025 23:05:53 UTC schrieb "Philippe Mathieu-Daudé" <philmd@linaro.org>:
>> Cc'ing AMD folks
>>
>> Hi Bernhard,
>>
>> TL;DR; can't you use the PCF8574 which is a more complete model of I/O
>> expander? (See hw/gpio/pcf8574.c)
> 
> If it is software-compatible then I could use it. I'm modeling a real board whose device tree I'd like to use unchanged, so I don't have much choice. The only reason I need it is because its absence clogs the i2c bus.

No clue about compatibility. If you unfortunately need to add it,
then please address my comments in the next version.

> 
> Best regards,
> Bernhard
> 
>>
>> On 20/1/25 21:37, Bernhard Beschow wrote:
>>> Xilinx QEMU implements a TCA6416 device model which may be useful for the
>>> broader QEMU community, so upstream it. In the Xilinx fork, the device model
>>> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
>>> "hw/*/cadence_*" maintainers.
>>>
>>> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
>>> modifications:
>>> * Use OBJECT_DECLARE_SIMPLE_TYPE()
>>> * Port from DPRINTF() to trace events
>>> * Follow QEMU conventions for naming of state struct
>>> * Rename type to not contain a ','
>>> * Use DEFINE_TYPES() macro
>>> * Implement under hw/gpio since device is i2c client and gpio provider
>>> * Have dedicated Kconfig switch
>>>
>>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>>>
>>> --
>>> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
>>> willing to maintain this device model?
>>> ---
>>>    MAINTAINERS          |   1 +
>>>    hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
>>>    hw/gpio/Kconfig      |   5 ++
>>>    hw/gpio/meson.build  |   1 +
>>>    hw/gpio/trace-events |   4 ++
>>>    5 files changed, 133 insertions(+)
>>>    create mode 100644 hw/gpio/tca6416.c
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 7531d65429..0cac9c90bc 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -1030,6 +1030,7 @@ S: Maintained
>>>    F: hw/*/xilinx_*
>>>    F: hw/*/cadence_*
>>>    F: hw/misc/zynq_slcr.c
>>> +F: hw/gpio/tca6416.c
>>>    F: hw/adc/zynq-xadc.c
>>>    F: include/hw/misc/zynq_slcr.h
>>>    F: include/hw/adc/zynq-xadc.h
>>> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
>>> new file mode 100644
>>> index 0000000000..81ed7a654d
>>> --- /dev/null
>>> +++ b/hw/gpio/tca6416.c
>>> @@ -0,0 +1,122 @@
>>> +/*
>>> + * QEMU model of TCA6416 16-Bit I/O Expander
>>
>> Please add datasheet reference.
>>
>>> + *
>>> + * Copyright (c) 2018 Xilinx Inc.
>>> + *
>>> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>>> + * of this software and associated documentation files (the "Software"), to deal
>>> + * in the Software without restriction, including without limitation the rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>>> + * THE SOFTWARE.
>>
>> Sai/Edgar/Francisco, should we update to AMD here? Remove or update the
>> email address? Also, can you Ack the replacement of this license by a
>> SPDX tag?
>>
>>> + */
>>> +#include "qemu/osdep.h"
>>> +#include "hw/i2c/i2c.h"
>>> +#include "trace.h"
>>> +
>>> +#define TYPE_TCA6416 "tca6416"
>>> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
>>> +
>>> +#define IN_PORT0    0
>>> +#define IN_PORT1    1
>>> +#define OUT_PORT0   2
>>> +#define OUT_PORT1   3
>>> +#define POL_INV0    4
>>> +#define POL_INV1    5
>>> +#define CONF_PORT0  6
>>> +#define CONF_PORT1  7
>>
>> enum up to here?
>>
>>> +#define RMAX (CONF_PORT1 + 1)
>>> +
>>> +enum tca6416_events {
>>> +     ADDR_DONE,
>>> +     ADDRESSING,
>>> +};
>>> +
>>> +struct Tca6416State {
>>> +     I2CSlave i2c;
>>> +
>>> +     uint8_t addr;
>>> +     uint8_t state;
>>> +     uint8_t regs[RMAX];
>>> +};
>>> +
>>> +static uint8_t tca6416_read(I2CSlave *i2c)
>>> +{
>>> +    Tca6416State *s = TCA6416(i2c);
>>> +    uint8_t ret;
>>> +
>>> +    ret = s->regs[s->addr];
>>> +    trace_tca6416_read(ret);
>>> +    return ret;
>>> +}
>>> +
>>> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
>>> +{
>>> +    Tca6416State *s = TCA6416(i2c);
>>> +
>>> +    trace_tca6416_write(data);
>>> +    if (s->state == ADDRESSING) {
>>> +        s->addr = data;
>>
>> I suppose HW masks here.
>>
>>           s->addr = data & 0xf;
>>
>>> +    } else {
>>> +        s->regs[s->addr] = data;
>>
>> (otherwise this could overflow).
>>
>> So this device isn't doing anything actually (I'd have
>> expected 1 IRQ and 16 GPIO lines). What is the point,
>> at least in this state?
>>
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void tca6416_realize(DeviceState *dev, Error **errp)
>>> +{
>>> +    Tca6416State *s = TCA6416(dev);
>>> +
>>
>> Missing:
>>
>>        s->regs[OUT_PORT0] = 0xff;
>>        s->regs[OUT_PORT1] = 0xff;
>>        s->regs[POL_INV0] = 0x00;
>>        s->regs[POL_INV1] = 0x00;
>>
>>> +    s->regs[CONF_PORT0] = 0xFF;
>>> +    s->regs[CONF_PORT1] = 0xFF;
>>
>> Style is 0xff.
>>
>> That said, this is not a REALIZE but RESET handler.
>>
>>> +}
>>> +
>>> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
>>> +{
>>> +    Tca6416State *s = TCA6416(i2c);
>>> +
>>> +    switch (event) {
>>> +    case I2C_START_SEND:
>>> +        s->state = ADDRESSING;
>>> +        break;
>>> +    default:
>>> +         s->state = ADDR_DONE;
>>> +    };
>>> +    return 0;
>>> +}
>>> +
>>> +static void tca6416_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
>>> +
>>> +    dc->realize = tca6416_realize;
>>
>> (tca6416_realize is a reset handler).
>>
>> Please complete:
>>
>>        dc->desc = "TCA6416 I/O Expander";
>>        set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>>
>> No migration state?
>>
>>> +    k->recv = tca6416_read;
>>> +    k->send = tca6416_write;
>>> +    k->event = tca6416_event;
>>> +}> +
>>> +static const TypeInfo tca6416_types[] = {
>>> +    {
>>> +        .name = TYPE_TCA6416,
>>> +        .parent = TYPE_I2C_SLAVE,
>>> +        .class_init = tca6416_class_init,
>>> +        .instance_size = sizeof(Tca6416State),
>>> +    }
>>> +};
>>> +
>>> +DEFINE_TYPES(tca6416_types)
>>> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
>>> index c423e10f59..a240cf2de2 100644
>>> --- a/hw/gpio/Kconfig
>>> +++ b/hw/gpio/Kconfig
>>> @@ -20,5 +20,10 @@ config PCF8574
>>>        bool
>>>        depends on I2C
>>>    +config TCA6416
>>> +    bool
>>> +    depends on I2C
>>> +    default y if I2C_DEVICES
>>> +
>>>    config ZAURUS_SCOOP
>>>        bool
>>> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
>>> index 74840619c0..b3ff7c7460 100644
>>> --- a/hw/gpio/meson.build
>>> +++ b/hw/gpio/meson.build
>>> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
>>>    system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
>>>    system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
>>>    system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
>>> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
>>> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
>>> index cea896b28f..6724f2efb8 100644
>>> --- a/hw/gpio/trace-events
>>> +++ b/hw/gpio/trace-events
>>> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
>>>    stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
>>>    stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
>>>    stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
>>> +
>>> +# tca6416.c
>>> +tca6416_write(uint8_t value) "0x%02x"
>>
>> "wr 0x%02x"
>>
>>> +tca6416_read(uint8_t value) "0x%02x"
>>
>> "rd ..."
>>
>> Regards,
>>
>> Phil.



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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-02-02 17:09       ` Philippe Mathieu-Daudé
@ 2025-02-03  5:42         ` Dmitriy Sharikhin
  2025-02-04  8:13           ` Bernhard Beschow
  2025-02-17 18:06           ` Bernhard Beschow
  2025-02-03 22:38         ` Bernhard Beschow
  1 sibling, 2 replies; 50+ messages in thread
From: Dmitriy Sharikhin @ 2025-02-03  5:42 UTC (permalink / raw)
  To: sai.pavan.boddu@amd.com, edgar.iglesias@amd.com,
	francisco.iglesias@amd.com, shentey@gmail.com, philmd@linaro.org
  Cc: andrew.smirnov@gmail.com, alistair@alistair23.me,
	marcandre.lureau@redhat.com, qemu-arm@nongnu.org,
	peter.maydell@linaro.org, edgar.iglesias@gmail.com,
	jcd@tribudubois.net, pbonzini@redhat.com, qemu-devel@nongnu.org

At Sun, 02/02/2025 at 18:09 +0100, Philippe Mathieu-Daudé writes:
> No clue about compatibility. If you unfortunately need to add it,
> then please address my comments in the next version.
TCA6416 is _way_ more complex device than PCF8574. Basically PCF8574 is
shift register directly connected to IO lines, while TCA6416 is more like
fully-fledged GPIO controller with output direction, drive strength, interrupt
mask configuration etc etc.

In Linux kernel these devices are handled by family-compatible driver
   drivers/gpio/gpio-pca953x.c
Closest things by implementation in QEMU source tree are
   hw/gpio/pca9552.c and
   hw/gpio/pca9554.c
However they are NOT register-compatible with pca953x. I suppose, best
decision would be new driver for TCA6416 which eventually should support whole
pca953x family of I2C GPIO expanders.

Best regards,
Dmitrii

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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-02-02 17:09       ` Philippe Mathieu-Daudé
  2025-02-03  5:42         ` Dmitriy Sharikhin
@ 2025-02-03 22:38         ` Bernhard Beschow
  1 sibling, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-03 22:38 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel, Sai Pavan Boddu,
	Edgar E. Iglesias, Francisco Iglesias, Dmitrii Sharikhin
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias



Am 2. Februar 2025 17:09:06 UTC schrieb "Philippe Mathieu-Daudé" <philmd@linaro.org>:
>On 1/2/25 16:28, Bernhard Beschow wrote:
>> 
>> 
>> Am 30. Januar 2025 23:05:53 UTC schrieb "Philippe Mathieu-Daudé" <philmd@linaro.org>:
>>> Cc'ing AMD folks
>>> 
>>> Hi Bernhard,
>>> 
>>> TL;DR; can't you use the PCF8574 which is a more complete model of I/O
>>> expander? (See hw/gpio/pcf8574.c)
>> 
>> If it is software-compatible then I could use it. I'm modeling a real board whose device tree I'd like to use unchanged, so I don't have much choice. The only reason I need it is because its absence clogs the i2c bus.
>
>No clue about compatibility. If you unfortunately need to add it,
>then please address my comments in the next version.

Sure, I'll link your and Zoltan's comments as todos in the next version.

Best regards,
Bernhard

>
>> 
>> Best regards,
>> Bernhard
>> 
>>> 
>>> On 20/1/25 21:37, Bernhard Beschow wrote:
>>>> Xilinx QEMU implements a TCA6416 device model which may be useful for the
>>>> broader QEMU community, so upstream it. In the Xilinx fork, the device model
>>>> gets compiled whenever CONFIG_CADENCE is true, so have it maintained by the
>>>> "hw/*/cadence_*" maintainers.
>>>> 
>>>> The code is based on Xilinx QEMU version xilinx_v2024.2 plus the following
>>>> modifications:
>>>> * Use OBJECT_DECLARE_SIMPLE_TYPE()
>>>> * Port from DPRINTF() to trace events
>>>> * Follow QEMU conventions for naming of state struct
>>>> * Rename type to not contain a ','
>>>> * Use DEFINE_TYPES() macro
>>>> * Implement under hw/gpio since device is i2c client and gpio provider
>>>> * Have dedicated Kconfig switch
>>>> 
>>>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>>>> 
>>>> --
>>>> I have a use for TCA6416 emulation. Question: Are Xilinx Zynq maintainers
>>>> willing to maintain this device model?
>>>> ---
>>>>    MAINTAINERS          |   1 +
>>>>    hw/gpio/tca6416.c    | 122 +++++++++++++++++++++++++++++++++++++++++++
>>>>    hw/gpio/Kconfig      |   5 ++
>>>>    hw/gpio/meson.build  |   1 +
>>>>    hw/gpio/trace-events |   4 ++
>>>>    5 files changed, 133 insertions(+)
>>>>    create mode 100644 hw/gpio/tca6416.c
>>>> 
>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>> index 7531d65429..0cac9c90bc 100644
>>>> --- a/MAINTAINERS
>>>> +++ b/MAINTAINERS
>>>> @@ -1030,6 +1030,7 @@ S: Maintained
>>>>    F: hw/*/xilinx_*
>>>>    F: hw/*/cadence_*
>>>>    F: hw/misc/zynq_slcr.c
>>>> +F: hw/gpio/tca6416.c
>>>>    F: hw/adc/zynq-xadc.c
>>>>    F: include/hw/misc/zynq_slcr.h
>>>>    F: include/hw/adc/zynq-xadc.h
>>>> diff --git a/hw/gpio/tca6416.c b/hw/gpio/tca6416.c
>>>> new file mode 100644
>>>> index 0000000000..81ed7a654d
>>>> --- /dev/null
>>>> +++ b/hw/gpio/tca6416.c
>>>> @@ -0,0 +1,122 @@
>>>> +/*
>>>> + * QEMU model of TCA6416 16-Bit I/O Expander
>>> 
>>> Please add datasheet reference.
>>> 
>>>> + *
>>>> + * Copyright (c) 2018 Xilinx Inc.
>>>> + *
>>>> + * Written by Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
>>>> + *
>>>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>>>> + * of this software and associated documentation files (the "Software"), to deal
>>>> + * in the Software without restriction, including without limitation the rights
>>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>>>> + * copies of the Software, and to permit persons to whom the Software is
>>>> + * furnished to do so, subject to the following conditions:
>>>> + *
>>>> + * The above copyright notice and this permission notice shall be included in
>>>> + * all copies or substantial portions of the Software.
>>>> + *
>>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>>>> + * THE SOFTWARE.
>>> 
>>> Sai/Edgar/Francisco, should we update to AMD here? Remove or update the
>>> email address? Also, can you Ack the replacement of this license by a
>>> SPDX tag?
>>> 
>>>> + */
>>>> +#include "qemu/osdep.h"
>>>> +#include "hw/i2c/i2c.h"
>>>> +#include "trace.h"
>>>> +
>>>> +#define TYPE_TCA6416 "tca6416"
>>>> +OBJECT_DECLARE_SIMPLE_TYPE(Tca6416State, TCA6416)
>>>> +
>>>> +#define IN_PORT0    0
>>>> +#define IN_PORT1    1
>>>> +#define OUT_PORT0   2
>>>> +#define OUT_PORT1   3
>>>> +#define POL_INV0    4
>>>> +#define POL_INV1    5
>>>> +#define CONF_PORT0  6
>>>> +#define CONF_PORT1  7
>>> 
>>> enum up to here?
>>> 
>>>> +#define RMAX (CONF_PORT1 + 1)
>>>> +
>>>> +enum tca6416_events {
>>>> +     ADDR_DONE,
>>>> +     ADDRESSING,
>>>> +};
>>>> +
>>>> +struct Tca6416State {
>>>> +     I2CSlave i2c;
>>>> +
>>>> +     uint8_t addr;
>>>> +     uint8_t state;
>>>> +     uint8_t regs[RMAX];
>>>> +};
>>>> +
>>>> +static uint8_t tca6416_read(I2CSlave *i2c)
>>>> +{
>>>> +    Tca6416State *s = TCA6416(i2c);
>>>> +    uint8_t ret;
>>>> +
>>>> +    ret = s->regs[s->addr];
>>>> +    trace_tca6416_read(ret);
>>>> +    return ret;
>>>> +}
>>>> +
>>>> +static int tca6416_write(I2CSlave *i2c, uint8_t data)
>>>> +{
>>>> +    Tca6416State *s = TCA6416(i2c);
>>>> +
>>>> +    trace_tca6416_write(data);
>>>> +    if (s->state == ADDRESSING) {
>>>> +        s->addr = data;
>>> 
>>> I suppose HW masks here.
>>> 
>>>           s->addr = data & 0xf;
>>> 
>>>> +    } else {
>>>> +        s->regs[s->addr] = data;
>>> 
>>> (otherwise this could overflow).
>>> 
>>> So this device isn't doing anything actually (I'd have
>>> expected 1 IRQ and 16 GPIO lines). What is the point,
>>> at least in this state?
>>> 
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static void tca6416_realize(DeviceState *dev, Error **errp)
>>>> +{
>>>> +    Tca6416State *s = TCA6416(dev);
>>>> +
>>> 
>>> Missing:
>>> 
>>>        s->regs[OUT_PORT0] = 0xff;
>>>        s->regs[OUT_PORT1] = 0xff;
>>>        s->regs[POL_INV0] = 0x00;
>>>        s->regs[POL_INV1] = 0x00;
>>> 
>>>> +    s->regs[CONF_PORT0] = 0xFF;
>>>> +    s->regs[CONF_PORT1] = 0xFF;
>>> 
>>> Style is 0xff.
>>> 
>>> That said, this is not a REALIZE but RESET handler.
>>> 
>>>> +}
>>>> +
>>>> +static int tca6416_event(I2CSlave *i2c, enum i2c_event event)
>>>> +{
>>>> +    Tca6416State *s = TCA6416(i2c);
>>>> +
>>>> +    switch (event) {
>>>> +    case I2C_START_SEND:
>>>> +        s->state = ADDRESSING;
>>>> +        break;
>>>> +    default:
>>>> +         s->state = ADDR_DONE;
>>>> +    };
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static void tca6416_class_init(ObjectClass *klass, void *data)
>>>> +{
>>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>>> +    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
>>>> +
>>>> +    dc->realize = tca6416_realize;
>>> 
>>> (tca6416_realize is a reset handler).
>>> 
>>> Please complete:
>>> 
>>>        dc->desc = "TCA6416 I/O Expander";
>>>        set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>>> 
>>> No migration state?
>>> 
>>>> +    k->recv = tca6416_read;
>>>> +    k->send = tca6416_write;
>>>> +    k->event = tca6416_event;
>>>> +}> +
>>>> +static const TypeInfo tca6416_types[] = {
>>>> +    {
>>>> +        .name = TYPE_TCA6416,
>>>> +        .parent = TYPE_I2C_SLAVE,
>>>> +        .class_init = tca6416_class_init,
>>>> +        .instance_size = sizeof(Tca6416State),
>>>> +    }
>>>> +};
>>>> +
>>>> +DEFINE_TYPES(tca6416_types)
>>>> diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
>>>> index c423e10f59..a240cf2de2 100644
>>>> --- a/hw/gpio/Kconfig
>>>> +++ b/hw/gpio/Kconfig
>>>> @@ -20,5 +20,10 @@ config PCF8574
>>>>        bool
>>>>        depends on I2C
>>>>    +config TCA6416
>>>> +    bool
>>>> +    depends on I2C
>>>> +    default y if I2C_DEVICES
>>>> +
>>>>    config ZAURUS_SCOOP
>>>>        bool
>>>> diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
>>>> index 74840619c0..b3ff7c7460 100644
>>>> --- a/hw/gpio/meson.build
>>>> +++ b/hw/gpio/meson.build
>>>> @@ -18,3 +18,4 @@ system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
>>>>    system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
>>>>    system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
>>>>    system_ss.add(when: 'CONFIG_PCF8574', if_true: files('pcf8574.c'))
>>>> +system_ss.add(when: 'CONFIG_TCA6416', if_true: files('tca6416.c'))
>>>> diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
>>>> index cea896b28f..6724f2efb8 100644
>>>> --- a/hw/gpio/trace-events
>>>> +++ b/hw/gpio/trace-events
>>>> @@ -46,3 +46,7 @@ stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
>>>>    stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
>>>>    stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
>>>>    stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
>>>> +
>>>> +# tca6416.c
>>>> +tca6416_write(uint8_t value) "0x%02x"
>>> 
>>> "wr 0x%02x"
>>> 
>>>> +tca6416_read(uint8_t value) "0x%02x"
>>> 
>>> "rd ..."
>>> 
>>> Regards,
>>> 
>>> Phil.
>


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

* Re: [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers
  2025-01-21  2:52   ` BALATON Zoltan
@ 2025-02-03 23:01     ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-03 23:01 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
	Alistair Francis, Peter Maydell, Jean-Christophe Dubois, qemu-arm,
	Andrey Smirnov, Edgar E. Iglesias



Am 21. Januar 2025 02:52:58 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Mon, 20 Jan 2025, Bernhard Beschow 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 | 39 +++++++++++++++++++++++-----------
>> 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, 81 insertions(+), 12 deletions(-)
>> 
>> diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
>> index d7d08cc198..1514bc5864 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
>> 
>> @@ -25,25 +26,39 @@ for loading a Linux kernel.
>> Direct Linux Kernel Boot
>> ''''''''''''''''''''''''
>> 
>> -Linux mainline v6.12 release is tested at the time of writing. To build a Linux
>> -mainline kernel that can be booted by the ``imx8mp-evk`` machine, simply
>> -configure the kernel using the defconfig configuration:
>> +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 three steps. First run the following command in the
>> +toplevel directory of the Buildroot source tree:
>> 
>> .. code-block:: bash
>> 
>> -  $ export ARCH=arm64
>> -  $ export CROSS_COMPILE=aarch64-linux-gnu-
>> -  $ make defconfig
>> +  $ make freescale_imx8mpevk_defconfig
>>   $ make
>
>Adding documentation that is removed a few patches later seems unnecessary. Maybe you could keep the bare kernel docs as that could also be useful or not add it in the first place? But if this is already written keeping it may make more sense than dropping it.

I'd like the documentation to be complete and easy to follow at the same time. Buildroot achieves both, and allows for generating a cpio initrd instead. So I'd start with that which just requires minor adjustments here.

Best regards,
Bernhard

>
>Regards,
>BALATON Zoltan
>
>> 
>> -To boot the newly built Linux kernel in QEMU with the ``imx8mp-evk`` machine,
>> -run:
>> +Once finished successfully there is an ``output/image`` subfolder. Navigate into
>> +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
>> +
>> +  $ 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 arch/arm64/boot/Image \
>> -      -dtb arch/arm64/boot/dts/freescale/imx8mp-evk.dtb \
>> -      -initrd /path/to/rootfs.ext4 \
>> -      -append "root=/dev/ram"
>> +      -kernel Image \
>> +      -dtb imx8mp-evk-patched.dtb \
>> +      -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 9d2a757c2a..9832c05e8c 100644
>> --- a/include/hw/arm/fsl-imx8mp.h
>> +++ b/include/hw/arm/fsl-imx8mp.h
>> @@ -14,6 +14,7 @@
>> #include "hw/intc/arm_gicv3_common.h"
>> #include "hw/misc/imx7_snvs.h"
>> #include "hw/misc/imx8mp_ccm.h"
>> +#include "hw/sd/sdhci.h"
>> #include "qom/object.h"
>> #include "qemu/units.h"
>> 
>> @@ -27,6 +28,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 {
>> @@ -38,6 +40,7 @@ struct FslImx8mpState {
>>     IMX8MPAnalogState  analog;
>>     IMX7SNVSState      snvs;
>>     IMXSerialState     uart[FSL_IMX8MP_NUM_UARTS];
>> +    SDHCIState         usdhc[FSL_IMX8MP_NUM_USDHCS];
>> };
>> 
>> enum FslImx8mpMemoryRegions {
>> @@ -183,6 +186,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 0abde2b1fc..612ea7bf93 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 adb4ed8076..f880c03d35 100644
>> --- a/hw/arm/Kconfig
>> +++ b/hw/arm/Kconfig
>> @@ -582,6 +582,7 @@ config FSL_IMX8MP
>>     imply TEST_DEVICES
>>     select ARM_GIC
>>     select IMX
>> +    select SDHCI
>>     select UNIMP
>> 
>> config FSL_IMX8MP_EVK
>> 


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

* Re: [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset
  2025-01-28 14:33   ` Gustavo Romero
@ 2025-02-03 23:06     ` Bernhard Beschow
  0 siblings, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-03 23:06 UTC (permalink / raw)
  To: Gustavo Romero, qemu-devel
  Cc: Paolo Bonzini, Marc-André Lureau, Alistair Francis,
	Peter Maydell, Jean-Christophe Dubois, qemu-arm, Andrey Smirnov,
	Edgar E. Iglesias



Am 28. Januar 2025 14:33:27 UTC schrieb Gustavo Romero <gustavo.romero@linaro.org>:
>Hi,
>
>On 1/20/25 17:37, Bernhard Beschow wrote:
>> Input GPIO values such as a present SD card may get notified before the GPIO
>> controller itself gets reset. Claring the input values thus loses data. Assuming
>
>                                ^- nit: Clearing
>
>

Peter asked for a three-way reset in inbound devices while keeping the logic here as is. I'd drop this patch then.

Best regards,
Bernhard

>Cheers,
>Gustavo
>
>> that input GPIO events are only fired when the state changes, the input values
>> shouldn't be reset.
>> 
>> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
>> ---
>>   hw/gpio/imx_gpio.c | 1 -
>>   1 file changed, 1 deletion(-)
>> 
>> diff --git a/hw/gpio/imx_gpio.c b/hw/gpio/imx_gpio.c
>> index 549a281ed7..25546221e0 100644
>> --- a/hw/gpio/imx_gpio.c
>> +++ b/hw/gpio/imx_gpio.c
>> @@ -298,7 +298,6 @@ static void imx_gpio_reset(DeviceState *dev)
>>         s->dr       = 0;
>>       s->gdir     = 0;
>> -    s->psr      = 0;
>>       s->icr      = 0;
>>       s->imr      = 0;
>>       s->isr      = 0;
>


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-02-03  5:42         ` Dmitriy Sharikhin
@ 2025-02-04  8:13           ` Bernhard Beschow
  2025-02-17 18:06           ` Bernhard Beschow
  1 sibling, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-04  8:13 UTC (permalink / raw)
  To: Dmitriy Sharikhin, sai.pavan.boddu@amd.com,
	edgar.iglesias@amd.com, francisco.iglesias@amd.com,
	philmd@linaro.org
  Cc: andrew.smirnov@gmail.com, alistair@alistair23.me,
	marcandre.lureau@redhat.com, qemu-arm@nongnu.org,
	peter.maydell@linaro.org, edgar.iglesias@gmail.com,
	jcd@tribudubois.net, pbonzini@redhat.com, qemu-devel@nongnu.org



Am 3. Februar 2025 05:42:55 UTC schrieb Dmitriy Sharikhin <d.sharikhin@yadro.com>:
>At Sun, 02/02/2025 at 18:09 +0100, Philippe Mathieu-Daudé writes:
>> No clue about compatibility. If you unfortunately need to add it,
>> then please address my comments in the next version.
>TCA6416 is _way_ more complex device than PCF8574. Basically PCF8574 is
>shift register directly connected to IO lines, while TCA6416 is more like
>fully-fledged GPIO controller with output direction, drive strength, interrupt
>mask configuration etc etc.
>
>In Linux kernel these devices are handled by family-compatible driver
>   drivers/gpio/gpio-pca953x.c
>Closest things by implementation in QEMU source tree are
>   hw/gpio/pca9552.c and
>   hw/gpio/pca9554.c
>However they are NOT register-compatible with pca953x.

Thanks Dimitrii for the valuable hint! The pca9552 model works fine for my purposes -- which is just to avoid clogging the i2c bus.

>I suppose, best
>decision would be new driver for TCA6416 which eventually should support whole
>pca953x family of I2C GPIO expanders.

I'll drop this patch then.

Best regards,
Bernhard

>
>Best regards,
>Dmitrii


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

* Re: [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx
  2025-02-03  5:42         ` Dmitriy Sharikhin
  2025-02-04  8:13           ` Bernhard Beschow
@ 2025-02-17 18:06           ` Bernhard Beschow
  1 sibling, 0 replies; 50+ messages in thread
From: Bernhard Beschow @ 2025-02-17 18:06 UTC (permalink / raw)
  To: Dmitriy Sharikhin, sai.pavan.boddu@amd.com,
	edgar.iglesias@amd.com, francisco.iglesias@amd.com,
	philmd@linaro.org
  Cc: andrew.smirnov@gmail.com, alistair@alistair23.me,
	marcandre.lureau@redhat.com, qemu-arm@nongnu.org,
	peter.maydell@linaro.org, edgar.iglesias@gmail.com,
	jcd@tribudubois.net, pbonzini@redhat.com, qemu-devel@nongnu.org



Am 3. Februar 2025 05:42:55 UTC schrieb Dmitriy Sharikhin <d.sharikhin@yadro.com>:
>At Sun, 02/02/2025 at 18:09 +0100, Philippe Mathieu-Daudé writes:
>> No clue about compatibility. If you unfortunately need to add it,
>> then please address my comments in the next version.
>TCA6416 is _way_ more complex device than PCF8574. Basically PCF8574 is
>shift register directly connected to IO lines, while TCA6416 is more like
>fully-fledged GPIO controller with output direction, drive strength, interrupt
>mask configuration etc etc.
>
>In Linux kernel these devices are handled by family-compatible driver
>   drivers/gpio/gpio-pca953x.c
>Closest things by implementation in QEMU source tree are
>   hw/gpio/pca9552.c and
>   hw/gpio/pca9554.c
>However they are NOT register-compatible with pca953x. I suppose, best
>decision would be new driver for TCA6416 which eventually should support whole
>pca953x family of I2C GPIO expanders.

Just for the record: There has been an attempt to implement it: <https://lore.kernel.org/qemu-devel/20241107195453.2684138-3-titusr@google.com/>

>
>Best regards,
>Dmitrii


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

end of thread, other threads:[~2025-02-17 18:06 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-20 20:37 [PATCH 00/21] Add i.MX 8M Plus EVK machine Bernhard Beschow
2025-01-20 20:37 ` [PATCH 01/21] hw/char/imx_serial: Fix reset value of UFCR register Bernhard Beschow
2025-01-20 20:37 ` [PATCH 02/21] hw/char/imx_serial: Update all state before restarting ageing timer Bernhard Beschow
2025-01-20 20:37 ` [PATCH 03/21] hw/pci-host/designware: Expose MSI IRQ Bernhard Beschow
2025-01-20 20:37 ` [PATCH 04/21] hw/usb/hcd-dwc3: Align global registers size with Linux Bernhard Beschow
2025-01-28 14:21   ` Peter Maydell
2025-01-20 20:37 ` [PATCH 05/21] hw/arm: Add i.MX 8M Plus EVK board Bernhard Beschow
2025-01-28 14:29   ` Peter Maydell
2025-01-28 22:16     ` Bernhard Beschow
2025-01-29 12:17       ` Peter Maydell
2025-01-29 13:04         ` Bernhard Beschow
2025-01-20 20:37 ` [PATCH 06/21] hw/arm/fsl-imx8mp: Implement clock tree Bernhard Beschow
2025-01-28 14:35   ` Peter Maydell
2025-01-28 21:53     ` Bernhard Beschow
2025-01-20 20:37 ` [PATCH 07/21] hw/arm/fsl-imx8mp: Add SNVS Bernhard Beschow
2025-01-28 14:31   ` Peter Maydell
2025-01-20 20:37 ` [PATCH 08/21] hw/arm/fsl-imx8mp: Add USDHC storage controllers Bernhard Beschow
2025-01-21  2:52   ` BALATON Zoltan
2025-02-03 23:01     ` Bernhard Beschow
2025-01-20 20:37 ` [PATCH 09/21] hw/arm/fsl-imx8mp: Add PCIe support Bernhard Beschow
2025-01-28 14:33   ` Peter Maydell
2025-01-28 22:04     ` Bernhard Beschow
2025-01-29 17:54       ` BALATON Zoltan
2025-02-01 14:45         ` Bernhard Beschow
2025-01-20 20:37 ` [PATCH 10/21] hw/arm/fsl-imx8mp: Add GPIO controllers Bernhard Beschow
2025-01-20 20:37 ` [PATCH 11/21] hw/arm/fsl-imx8mp: Add I2C controllers Bernhard Beschow
2025-01-20 20:37 ` [PATCH 12/21] hw/arm/fsl-imx8mp: Add SPI controllers Bernhard Beschow
2025-01-20 20:37 ` [PATCH 13/21] hw/arm/fsl-imx8mp: Add watchdog support Bernhard Beschow
2025-01-20 20:37 ` [PATCH 14/21] hw/arm/fsl-imx8mp: Implement gneral purpose timers Bernhard Beschow
2025-01-20 20:37 ` [PATCH 15/21] hw/arm/fsl-imx8mp: Add Ethernet controller Bernhard Beschow
2025-01-20 20:37 ` [PATCH 16/21] hw/arm/fsl-imx8mp: Add USB support Bernhard Beschow
2025-01-20 20:37 ` [PATCH 17/21] hw/arm/fsl-imx8mp: Add boot ROM Bernhard Beschow
2025-01-21  3:00   ` BALATON Zoltan
2025-01-21 21:03     ` Bernhard Beschow
2025-01-20 20:37 ` [PATCH 18/21] hw/arm/fsl-imx8mp: Add on-chip RAM Bernhard Beschow
2025-01-20 20:37 ` [PATCH 19/21] hw/rtc: Add Ricoh RS5C372 RTC emulation Bernhard Beschow
2025-01-20 20:37 ` [PATCH 20/21] hw/i2c: Import TCA6416 emulation from Xilinx Bernhard Beschow
2025-01-21  3:07   ` BALATON Zoltan
2025-01-28 22:20     ` Bernhard Beschow
2025-01-30  1:14   ` Corey Minyard
2025-01-30 23:05   ` Philippe Mathieu-Daudé
2025-02-01 15:28     ` Bernhard Beschow
2025-02-02 17:09       ` Philippe Mathieu-Daudé
2025-02-03  5:42         ` Dmitriy Sharikhin
2025-02-04  8:13           ` Bernhard Beschow
2025-02-17 18:06           ` Bernhard Beschow
2025-02-03 22:38         ` Bernhard Beschow
2025-01-20 20:37 ` [PATCH 21/21] hw/gpio/imx_gpio: Don't clear input GPIO values upon reset Bernhard Beschow
2025-01-28 14:33   ` Gustavo Romero
2025-02-03 23:06     ` Bernhard Beschow

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).