From: Gaurav Sharma <gaurav.sharma_7@nxp.com>
It enables emulation of SD/MMC cards through a virtual SDHCI interface
The emulated SDHCI controller allows guest OS to use emulated storage as
a standard block device.
This will allow running the images such as those generated
by Buildroot.
Reviewed-by: Philippe Mathieu-Daude <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Bernhard Beschow <shentey@gmail.com>
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/arm/Kconfig | 1 +
hw/arm/fsl-imx8mm.c | 25 +++++++++++++++++++++++++
hw/arm/imx8mm-evk.c | 17 +++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 7 +++++++
4 files changed, 50 insertions(+)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 26dc3e6ed1..74e8c431a2 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -623,6 +623,7 @@ config FSL_IMX8MM
select FSL_IMX8MP_ANALOG
select FSL_IMX8MP_CCM
select IMX
+ select SDHCI
config FSL_IMX8MM_EVK
bool
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 8999bc701e..2a4d4d5e6d 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -180,6 +180,10 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
}
+ for (i = 0; i < FSL_IMX8MM_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_imx8mm_realize(DeviceState *dev, Error **errp)
@@ -357,6 +361,26 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
fsl_imx8mm_memmap[FSL_IMX8MM_OCRAM].addr,
&s->ocram);
+ /* USDHCs */
+ for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } usdhc_table[FSL_IMX8MM_NUM_USDHCS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC1].addr, FSL_IMX8MM_USDHC1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC2].addr, FSL_IMX8MM_USDHC2_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC3].addr, FSL_IMX8MM_USDHC3_IRQ },
+ };
+
+ 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;
@@ -375,6 +399,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_OCRAM:
case FSL_IMX8MM_SNVS_HP:
case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
+ case FSL_IMX8MM_USDHC1 ... FSL_IMX8MM_USDHC3:
/* device implemented and treated above */
break;
diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c
index 0a8cce8866..dfdf3cd4f8 100644
--- a/hw/arm/imx8mm-evk.c
+++ b/hw/arm/imx8mm-evk.c
@@ -84,6 +84,23 @@ static void imx8mm_evk_init(MachineState *machine)
memory_region_add_subregion(get_system_memory(), FSL_IMX8MM_RAM_START,
machine->ram);
+ for (int i = 0; i < FSL_IMX8MM_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/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 8a172b89e0..93a30a2f55 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -16,6 +16,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"
@@ -29,6 +30,7 @@ enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_CPUS = 4,
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
+ FSL_IMX8MM_NUM_USDHCS = 3,
};
struct FslImx8mmState {
@@ -41,6 +43,7 @@ struct FslImx8mmState {
IMX7SNVSState snvs;
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
MemoryRegion ocram;
+ SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
};
enum FslImx8mmMemoryRegions {
@@ -155,6 +158,10 @@ enum FslImx8mmMemoryRegions {
};
enum FslImx8mmIrqs {
+ FSL_IMX8MM_USDHC1_IRQ = 22,
+ FSL_IMX8MM_USDHC2_IRQ = 23,
+ FSL_IMX8MM_USDHC3_IRQ = 24,
+
FSL_IMX8MM_UART1_IRQ = 26,
FSL_IMX8MM_UART2_IRQ = 27,
FSL_IMX8MM_UART3_IRQ = 28,
--
2.43.0