[PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers

2025-02-23 Thread 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.

Reviewed-by: Peter Maydell 
Signed-off-by: Bernhard Beschow 
---
 docs/system/arm/imx8mp-evk.rst | 18 --
 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, 66 insertions(+), 6 deletions(-)

diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
index 22541c5442..879c822356 100644
--- a/docs/system/arm/imx8mp-evk.rst
+++ b/docs/system/arm/imx8mp-evk.rst
@@ -12,6 +12,7 @@ The ``imx8mp-evk`` machine implements the following devices:
  * Up to 4 Cortex-A53 cores
  * Generic Interrupt Controller (GICv3)
  * 4 UARTs
+ * 3 USDHC Storage Controllers
  * Secure Non-Volatile Storage (SNVS) including an RTC
  * Clock Tree
 
@@ -26,18 +27,23 @@ Direct Linux Kernel Boot
 
 Probably the easiest way to get started with a whole Linux system on the 
machine
 is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
-of writing and involves two steps. First run the following commands in the
+of writing and involves three steps. First run the following commands in the
 toplevel directory of the Buildroot source tree:
 
 .. code-block:: bash
 
-  $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
   $ make freescale_imx8mpevk_defconfig
   $ make
 
 Once finished successfully there is an ``output/image`` subfolder. Navigate 
into
-it and patch the device tree with the following commands which will remove the
-``cpu-idle-states`` properties from CPU nodes:
+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
 
@@ -52,5 +58,5 @@ Now that everything is prepared the machine can be started as 
follows:
   -display none -serial null -serial stdio \
   -kernel Image \
   -dtb imx8mp-evk-patched.dtb \
-  -initrd rootfs.cpio \
-  -append "root=/dev/ram"
+  -append "root=/dev/mmcblk2p2" \
+  -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 26e24e99a1..349d55ca88 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -15,6 +15,7 @@
 #include "hw/misc/imx7_snvs.h"
 #include "hw/misc/imx8mp_analog.h"
 #include "hw/misc/imx8mp_ccm.h"
+#include "hw/sd/sdhci.h"
 #include "qom/object.h"
 #include "qemu/units.h"
 
@@ -28,6 +29,7 @@ enum FslImx8mpConfiguration {
 FSL_IMX8MP_NUM_CPUS = 4,
 FSL_IMX8MP_NUM_IRQS = 160,
 FSL_IMX8MP_NUM_UARTS= 4,
+FSL_IMX8MP_NUM_USDHCS   = 3,
 };
 
 struct FslImx8mpState {
@@ -39,6 +41,7 @@ struct FslImx8mpState {
 IMX8MPAnalogState  analog;
 IMX7SNVSState  snvs;
 IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
+SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
 };
 
 enum FslImx8mpMemoryRegions {
@@ -184,6 +187,10 @@ enum FslImx8mpMemoryRegions {
 };
 
 enum FslImx8mpIrqs {
+FSL_IMX8MP_USDHC1_IRQ   = 22,
+FSL_IMX8MP_USDHC2_IRQ   = 23,
+FSL_IMX8MP_USDHC3_IRQ   = 24,
+
 FSL_IMX8MP_UART1_IRQ= 26,
 FSL_IMX8MP_UART2_IRQ= 27,
 FSL_IMX8MP_UART3_IRQ= 28,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index de47ac1804..ad26c1e2f0 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -207,6 +207,11 @@ static void fsl_imx8mp_init(Object *obj)
 g_autofree char *name = g_strdup_printf("uart%d", i + 1);
 object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
 }
+
+for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
+g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
+object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
+}
 }
 
 static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
@@ -346,6 +351,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_

Re: [PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers

2025-02-06 Thread Peter Maydell
On Tue, 4 Feb 2025 at 09:21, 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 
> ---
>  docs/system/arm/imx8mp-evk.rst | 16 +++-
>  include/hw/arm/fsl-imx8mp.h|  7 +++
>  hw/arm/fsl-imx8mp.c| 28 
>  hw/arm/imx8mp-evk.c| 18 ++
>  hw/arm/Kconfig |  1 +
>  5 files changed, 65 insertions(+), 5 deletions(-)

Reviewed-by: Peter Maydell 

thanks
-- PMM



[PATCH v2 07/18] hw/arm/fsl-imx8mp: Add USDHC storage controllers

2025-02-04 Thread 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 
---
 docs/system/arm/imx8mp-evk.rst | 16 +++-
 include/hw/arm/fsl-imx8mp.h|  7 +++
 hw/arm/fsl-imx8mp.c| 28 
 hw/arm/imx8mp-evk.c| 18 ++
 hw/arm/Kconfig |  1 +
 5 files changed, 65 insertions(+), 5 deletions(-)

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