@samitouri / QOSamiQemu / commits / d1139f2cc3

hw/arm/fsl-imx8mm: Adding support for USB controller

It enables emulation of USB on iMX8MM Enables testing and debugging of USB drivers 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>

Gaurav Sharma committed Apr 21, 2026 at 12:22 UTC d1139f2cc3e788835cae485b78eb98ec81291926
3 files changed +34
hw/arm/Kconfig
+1
@@ -631,6 +631,7 @@ config FSL_IMX8MM
631 select SDHCI
632 select PCI_EXPRESS_DESIGNWARE
633 select PCI_EXPRESS_FSL_IMX8M_PHY
634 + select USB_DWC3
635 select WDT_IMX2
636
637 config FSL_IMX8MM_EVK
hw/arm/fsl-imx8mm.c
+27
@@ -202,6 +202,11 @@ static void fsl_imx8mm_init(Object *obj)
202 object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
203 }
204
205 + for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
206 + g_autofree char *name = g_strdup_printf("usb%d", i);
207 + object_initialize_child(obj, name, &s->usb[i], TYPE_USB_DWC3);
208 + }
209 +
210 for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
211 g_autofree char *name = g_strdup_printf("spi%d", i + 1);
212 object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
@@ -529,6 +534,27 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
534 qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
535 }
536
537 + /* USBs */
538 + for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
539 + static const struct {
540 + hwaddr addr;
541 + unsigned int irq;
542 + } usb_table[FSL_IMX8MM_NUM_USBS] = {
543 + { fsl_imx8mm_memmap[FSL_IMX8MM_USB1].addr, FSL_IMX8MM_USB1_IRQ },
544 + { fsl_imx8mm_memmap[FSL_IMX8MM_USB2].addr, FSL_IMX8MM_USB2_IRQ },
545 + };
546 +
547 + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p2", 1);
548 + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p3", 1);
549 + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2);
550 + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) {
551 + return;
552 + }
553 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
554 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
555 + qdev_get_gpio_in(gicdev, usb_table[i].irq));
556 + }
557 +
558 /* ECSPIs */
559 for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
560 static const struct {
@@ -635,6 +661,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
661 case FSL_IMX8MM_OCRAM:
662 case FSL_IMX8MM_SNVS_HP:
663 case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
664 + case FSL_IMX8MM_USB1 ... FSL_IMX8MM_USB2:
665 case FSL_IMX8MM_USDHC1 ... FSL_IMX8MM_USDHC3:
666 case FSL_IMX8MM_WDOG1 ... FSL_IMX8MM_WDOG3:
667 /* device implemented and treated above */
include/hw/arm/fsl-imx8mm.h
+6
@@ -25,6 +25,7 @@
25 #include "hw/sd/sdhci.h"
26 #include "hw/ssi/imx_spi.h"
27 #include "hw/timer/imx_gpt.h"
28 +#include "hw/usb/hcd-dwc3.h"
29 #include "hw/watchdog/wdt_imx2.h"
30 #include "qom/object.h"
31 #include "qemu/units.h"
@@ -43,6 +44,7 @@ enum FslImx8mmConfiguration {
44 FSL_IMX8MM_NUM_I2CS = 4,
45 FSL_IMX8MM_NUM_IRQS = 128,
46 FSL_IMX8MM_NUM_UARTS = 4,
47 + FSL_IMX8MM_NUM_USBS = 2,
48 FSL_IMX8MM_NUM_USDHCS = 3,
49 FSL_IMX8MM_NUM_WDTS = 3,
50 };
@@ -64,6 +66,7 @@ struct FslImx8mmState {
66 IMXFECState enet;
67 SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
68 IMX2WdtState wdt[FSL_IMX8MM_NUM_WDTS];
69 + USBDWC3 usb[FSL_IMX8MM_NUM_USBS];
70 DesignwarePCIEHost pcie;
71 FslImx8mPciePhyState pcie_phy;
72 OrIRQState gpt5_gpt6_irq;
@@ -202,6 +205,9 @@ enum FslImx8mmIrqs {
205 FSL_IMX8MM_I2C3_IRQ = 37,
206 FSL_IMX8MM_I2C4_IRQ = 38,
207
208 + FSL_IMX8MM_USB1_IRQ = 40,
209 + FSL_IMX8MM_USB2_IRQ = 41,
210 +
211 FSL_IMX8MM_GPT1_IRQ = 55,
212 FSL_IMX8MM_GPT2_IRQ = 54,
213 FSL_IMX8MM_GPT3_IRQ = 53,