summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--gdbstub.c2
-rw-r--r--hw/arm/xlnx-versal-virt.c55
-rw-r--r--hw/arm/xlnx-versal.c26
-rw-r--r--hw/block/m25p80.c158
-rw-r--r--hw/core/loader.c67
-rw-r--r--hw/intc/meson.build1
-rw-r--r--hw/intc/nios2_iic.c95
-rw-r--r--hw/misc/zynq_slcr.c5
-rw-r--r--hw/nios2/10m50_devboard.c13
-rw-r--r--hw/nios2/cpu_pic.c67
-rw-r--r--hw/nios2/meson.build2
-rw-r--r--hw/openrisc/Kconfig1
-rw-r--r--hw/openrisc/meson.build2
-rw-r--r--hw/openrisc/openrisc_sim.c46
-rw-r--r--hw/openrisc/pic_cpu.c61
-rw-r--r--hw/usb/Kconfig10
-rw-r--r--hw/usb/hcd-dwc3.c689
-rw-r--r--hw/usb/meson.build3
-rw-r--r--hw/usb/xlnx-usb-subsystem.c94
-rw-r--r--hw/usb/xlnx-versal-usb2-ctrl-regs.c229
-rw-r--r--include/hw/arm/xlnx-versal.h9
-rw-r--r--include/hw/elf_ops.h5
-rw-r--r--include/hw/usb/hcd-dwc3.h55
-rw-r--r--include/hw/usb/xlnx-usb-subsystem.h45
-rw-r--r--include/hw/usb/xlnx-versal-usb2-ctrl-regs.h45
-rw-r--r--softmmu/vl.c1
-rw-r--r--target/nios2/cpu.c29
-rw-r--r--target/nios2/cpu.h3
-rw-r--r--target/nios2/op_helper.c9
-rw-r--r--target/openrisc/cpu.c32
-rw-r--r--target/openrisc/cpu.h1
32 files changed, 1557 insertions, 304 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 138b4ed461..bd8bacc06a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -259,7 +259,6 @@ M: Marek Vasut <marex@denx.de>
 S: Maintained
 F: target/nios2/
 F: hw/nios2/
-F: hw/intc/nios2_iic.c
 F: disas/nios2.c
 F: default-configs/nios2-softmmu.mak
 
diff --git a/gdbstub.c b/gdbstub.c
index f19f98ab1a..d99bc0bf2e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1243,7 +1243,7 @@ static int gdb_handle_vcont(const char *p)
         cur_action = *p++;
         if (cur_action == 'C' || cur_action == 'S') {
             cur_action = qemu_tolower(cur_action);
-            res = qemu_strtoul(p + 1, &p, 16, &tmp);
+            res = qemu_strtoul(p, &p, 16, &tmp);
             if (res) {
                 goto out;
             }
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index ee1282241e..8482cd6196 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -39,6 +39,8 @@ struct VersalVirt {
         uint32_t ethernet_phy[2];
         uint32_t clk_125Mhz;
         uint32_t clk_25Mhz;
+        uint32_t usb;
+        uint32_t dwc;
     } phandle;
     struct arm_boot_info binfo;
 
@@ -66,6 +68,8 @@ static void fdt_create(VersalVirt *s)
     s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
 
+    s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
+    s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
     /* Create /chosen node for load_dtb.  */
     qemu_fdt_add_subnode(s->fdt, "/chosen");
 
@@ -148,6 +152,56 @@ static void fdt_add_timer_nodes(VersalVirt *s)
                      compat, sizeof(compat));
 }
 
+static void fdt_add_usb_xhci_nodes(VersalVirt *s)
+{
+    const char clocknames[] = "bus_clk\0ref_clk";
+    const char irq_name[] = "dwc_usb3";
+    const char compatVersalDWC3[] = "xlnx,versal-dwc3";
+    const char compatDWC3[] = "snps,dwc3";
+    char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
+
+    qemu_fdt_add_subnode(s->fdt, name);
+    qemu_fdt_setprop(s->fdt, name, "compatible",
+                         compatVersalDWC3, sizeof(compatVersalDWC3));
+    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+                                 2, MM_USB2_CTRL_REGS,
+                                 2, MM_USB2_CTRL_REGS_SIZE);
+    qemu_fdt_setprop(s->fdt, name, "clock-names",
+                         clocknames, sizeof(clocknames));
+    qemu_fdt_setprop_cells(s->fdt, name, "clocks",
+                               s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
+    qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
+    qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
+    qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
+    qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
+    g_free(name);
+
+    name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
+                           MM_USB2_CTRL_REGS, MM_USB_0);
+    qemu_fdt_add_subnode(s->fdt, name);
+    qemu_fdt_setprop(s->fdt, name, "compatible",
+                     compatDWC3, sizeof(compatDWC3));
+    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+                                 2, MM_USB_0, 2, MM_USB_0_SIZE);
+    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
+                     irq_name, sizeof(irq_name));
+    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    qemu_fdt_setprop_cell(s->fdt, name,
+                          "snps,quirk-frame-length-adjustment", 0x20);
+    qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
+    qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
+    qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
+    qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
+    qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
+    qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
+    qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
+    qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
+    qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
+    g_free(name);
+}
+
 static void fdt_add_uart_nodes(VersalVirt *s)
 {
     uint64_t addrs[] = { MM_UART1, MM_UART0 };
@@ -515,6 +569,7 @@ static void versal_virt_init(MachineState *machine)
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_zdma_nodes(s);
+    fdt_add_usb_xhci_nodes(s);
     fdt_add_sd_nodes(s);
     fdt_add_rtc_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 12ba6c4eba..b0777166e8 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -145,6 +145,31 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
     }
 }
 
+static void versal_create_usbs(Versal *s, qemu_irq *pic)
+{
+    DeviceState *dev;
+    MemoryRegion *mr;
+
+    object_initialize_child(OBJECT(s), "usb2", &s->lpd.iou.usb,
+                            TYPE_XILINX_VERSAL_USB2);
+    dev = DEVICE(&s->lpd.iou.usb);
+
+    object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
+                             &error_abort);
+    qdev_prop_set_uint32(dev, "intrs", 1);
+    qdev_prop_set_uint32(dev, "slots", 2);
+
+    sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+    memory_region_add_subregion(&s->mr_ps, MM_USB_0, mr);
+
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_USB0_IRQ_0]);
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+    memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
+}
+
 static void versal_create_gems(Versal *s, qemu_irq *pic)
 {
     int i;
@@ -333,6 +358,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
     versal_create_apu_cpus(s);
     versal_create_apu_gic(s, pic);
     versal_create_uarts(s, pic);
+    versal_create_usbs(s, pic);
     versal_create_gems(s, pic);
     versal_create_admas(s, pic);
     versal_create_sds(s, pic);
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index d09a811767..c45afdd2cb 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -136,7 +136,7 @@ typedef struct FlashPartInfo {
 #define VCFG_WRAP_SEQUENTIAL 0x2
 #define NVCFG_XIP_MODE_DISABLED (7 << 9)
 #define NVCFG_XIP_MODE_MASK (7 << 9)
-#define VCFG_XIP_MODE_ENABLED (1 << 3)
+#define VCFG_XIP_MODE_DISABLED (1 << 3)
 #define CFG_DUMMY_CLK_LEN 4
 #define NVCFG_DUMMY_CLK_POS 12
 #define VCFG_DUMMY_CLK_POS 4
@@ -144,9 +144,9 @@ typedef struct FlashPartInfo {
 #define EVCFG_VPP_ACCELERATOR (1 << 3)
 #define EVCFG_RESET_HOLD_ENABLED (1 << 4)
 #define NVCFG_DUAL_IO_MASK (1 << 2)
-#define EVCFG_DUAL_IO_ENABLED (1 << 6)
+#define EVCFG_DUAL_IO_DISABLED (1 << 6)
 #define NVCFG_QUAD_IO_MASK (1 << 3)
-#define EVCFG_QUAD_IO_ENABLED (1 << 7)
+#define EVCFG_QUAD_IO_DISABLED (1 << 7)
 #define NVCFG_4BYTE_ADDR_MASK (1 << 0)
 #define NVCFG_LOWER_SEGMENT_MASK (1 << 1)
 
@@ -413,6 +413,12 @@ typedef enum {
     MAN_GENERIC,
 } Manufacturer;
 
+typedef enum {
+    MODE_STD = 0,
+    MODE_DIO = 1,
+    MODE_QIO = 2
+} SPIMode;
+
 #define M25P80_INTERNAL_DATA_BUFFER_SZ 16
 
 struct Flash {
@@ -768,8 +774,8 @@ static void reset_memory(Flash *s)
         s->volatile_cfg |= VCFG_DUMMY;
         s->volatile_cfg |= VCFG_WRAP_SEQUENTIAL;
         if ((s->nonvolatile_cfg & NVCFG_XIP_MODE_MASK)
-                                != NVCFG_XIP_MODE_DISABLED) {
-            s->volatile_cfg |= VCFG_XIP_MODE_ENABLED;
+                                == NVCFG_XIP_MODE_DISABLED) {
+            s->volatile_cfg |= VCFG_XIP_MODE_DISABLED;
         }
         s->volatile_cfg |= deposit32(s->volatile_cfg,
                             VCFG_DUMMY_CLK_POS,
@@ -784,10 +790,10 @@ static void reset_memory(Flash *s)
         s->enh_volatile_cfg |= EVCFG_VPP_ACCELERATOR;
         s->enh_volatile_cfg |= EVCFG_RESET_HOLD_ENABLED;
         if (s->nonvolatile_cfg & NVCFG_DUAL_IO_MASK) {
-            s->enh_volatile_cfg |= EVCFG_DUAL_IO_ENABLED;
+            s->enh_volatile_cfg |= EVCFG_DUAL_IO_DISABLED;
         }
         if (s->nonvolatile_cfg & NVCFG_QUAD_IO_MASK) {
-            s->enh_volatile_cfg |= EVCFG_QUAD_IO_ENABLED;
+            s->enh_volatile_cfg |= EVCFG_QUAD_IO_DISABLED;
         }
         if (!(s->nonvolatile_cfg & NVCFG_4BYTE_ADDR_MASK)) {
             s->four_bytes_address_mode = true;
@@ -820,6 +826,41 @@ static void reset_memory(Flash *s)
     trace_m25p80_reset_done(s);
 }
 
+static uint8_t numonyx_mode(Flash *s)
+{
+    if (!(s->enh_volatile_cfg & EVCFG_QUAD_IO_DISABLED)) {
+        return MODE_QIO;
+    } else if (!(s->enh_volatile_cfg & EVCFG_DUAL_IO_DISABLED)) {
+        return MODE_DIO;
+    } else {
+        return MODE_STD;
+    }
+}
+
+static uint8_t numonyx_extract_cfg_num_dummies(Flash *s)
+{
+    uint8_t num_dummies;
+    uint8_t mode;
+    assert(get_man(s) == MAN_NUMONYX);
+
+    mode = numonyx_mode(s);
+    num_dummies = extract32(s->volatile_cfg, 4, 4);
+
+    if (num_dummies == 0x0 || num_dummies == 0xf) {
+        switch (s->cmd_in_progress) {
+        case QIOR:
+        case QIOR4:
+            num_dummies = 10;
+            break;
+        default:
+            num_dummies = (mode == MODE_QIO) ? 10 : 8;
+            break;
+        }
+    }
+
+    return num_dummies;
+}
+
 static void decode_fast_read_cmd(Flash *s)
 {
     s->needed_bytes = get_addr_length(s);
@@ -829,7 +870,7 @@ static void decode_fast_read_cmd(Flash *s)
         s->needed_bytes += 8;
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
+        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
         break;
     case MAN_MACRONIX:
         if (extract32(s->volatile_cfg, 6, 2) == 1) {
@@ -868,7 +909,7 @@ static void decode_dio_read_cmd(Flash *s)
                                     );
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
+        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
         break;
     case MAN_MACRONIX:
         switch (extract32(s->volatile_cfg, 6, 2)) {
@@ -908,7 +949,7 @@ static void decode_qio_read_cmd(Flash *s)
                                     );
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
+        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
         break;
     case MAN_MACRONIX:
         switch (extract32(s->volatile_cfg, 6, 2)) {
@@ -950,14 +991,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
     case ERASE4_32K:
     case ERASE_SECTOR:
     case ERASE4_SECTOR:
-    case READ:
-    case READ4:
-    case DPP:
-    case QPP:
-    case QPP_4:
     case PP:
     case PP4:
-    case PP4_4:
     case DIE_ERASE:
     case RDID_90:
     case RDID_AB:
@@ -966,24 +1001,84 @@ static void decode_new_cmd(Flash *s, uint32_t value)
         s->len = 0;
         s->state = STATE_COLLECTING_DATA;
         break;
+    case READ:
+    case READ4:
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) == MODE_STD) {
+            s->needed_bytes = get_addr_length(s);
+            s->pos = 0;
+            s->len = 0;
+            s->state = STATE_COLLECTING_DATA;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "DIO or QIO mode\n", s->cmd_in_progress);
+        }
+        break;
+    case DPP:
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) != MODE_QIO) {
+            s->needed_bytes = get_addr_length(s);
+            s->pos = 0;
+            s->len = 0;
+            s->state = STATE_COLLECTING_DATA;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "QIO mode\n", s->cmd_in_progress);
+        }
+        break;
+    case QPP:
+    case QPP_4:
+    case PP4_4:
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) != MODE_DIO) {
+            s->needed_bytes = get_addr_length(s);
+            s->pos = 0;
+            s->len = 0;
+            s->state = STATE_COLLECTING_DATA;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "DIO mode\n", s->cmd_in_progress);
+        }
+        break;
 
     case FAST_READ:
     case FAST_READ4:
+        decode_fast_read_cmd(s);
+        break;
     case DOR:
     case DOR4:
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) != MODE_QIO) {
+            decode_fast_read_cmd(s);
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "QIO mode\n", s->cmd_in_progress);
+        }
+        break;
     case QOR:
     case QOR4:
-        decode_fast_read_cmd(s);
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) != MODE_DIO) {
+            decode_fast_read_cmd(s);
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "DIO mode\n", s->cmd_in_progress);
+        }
         break;
 
     case DIOR:
     case DIOR4:
-        decode_dio_read_cmd(s);
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) != MODE_QIO) {
+            decode_dio_read_cmd(s);
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "QIO mode\n", s->cmd_in_progress);
+        }
         break;
 
     case QIOR:
     case QIOR4:
-        decode_qio_read_cmd(s);
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) != MODE_DIO) {
+            decode_qio_read_cmd(s);
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute cmd %x in "
+                          "DIO mode\n", s->cmd_in_progress);
+        }
         break;
 
     case WRSR:
@@ -1035,17 +1130,22 @@ static void decode_new_cmd(Flash *s, uint32_t value)
         break;
 
     case JEDEC_READ:
-        trace_m25p80_populated_jedec(s);
-        for (i = 0; i < s->pi->id_len; i++) {
-            s->data[i] = s->pi->id[i];
-        }
-        for (; i < SPI_NOR_MAX_ID_LEN; i++) {
-            s->data[i] = 0;
-        }
+        if (get_man(s) != MAN_NUMONYX || numonyx_mode(s) == MODE_STD) {
+            trace_m25p80_populated_jedec(s);
+            for (i = 0; i < s->pi->id_len; i++) {
+                s->data[i] = s->pi->id[i];
+            }
+            for (; i < SPI_NOR_MAX_ID_LEN; i++) {
+                s->data[i] = 0;
+            }
 
-        s->len = SPI_NOR_MAX_ID_LEN;
-        s->pos = 0;
-        s->state = STATE_READING_DATA;
+            s->len = SPI_NOR_MAX_ID_LEN;
+            s->pos = 0;
+            s->state = STATE_READING_DATA;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Cannot execute JEDEC read "
+                          "in DIO or QIO mode\n");
+        }
         break;
 
     case RDCR:
diff --git a/hw/core/loader.c b/hw/core/loader.c
index fea22d265c..9feca32de9 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -1166,34 +1166,77 @@ static void rom_reset(void *unused)
     }
 }
 
+/* Return true if two consecutive ROMs in the ROM list overlap */
+static bool roms_overlap(Rom *last_rom, Rom *this_rom)
+{
+    if (!last_rom) {
+        return false;
+    }
+    return last_rom->as == this_rom->as &&
+        last_rom->addr + last_rom->romsize > this_rom->addr;
+}
+
+static const char *rom_as_name(Rom *rom)
+{
+    const char *name = rom->as ? rom->as->name : NULL;
+    return name ?: "anonymous";
+}
+
+static void rom_print_overlap_error_header(void)
+{
+    error_report("Some ROM regions are overlapping");
+    error_printf(
+        "These ROM regions might have been loaded by "
+        "direct user request or by default.\n"
+        "They could be BIOS/firmware images, a guest kernel, "
+        "initrd or some other file loaded into guest memory.\n"
+        "Check whether you intended to load all this guest code, and "
+        "whether it has been built to load to the correct addresses.\n");
+}
+
+static void rom_print_one_overlap_error(Rom *last_rom, Rom *rom)
+{
+    error_printf(
+        "\nThe following two regions overlap (in the %s address space):\n",
+        rom_as_name(rom));
+    error_printf(
+        "  %s (addresses 0x" TARGET_FMT_plx " - 0x" TARGET_FMT_plx ")\n",
+        last_rom->name, last_rom->addr, last_rom->addr + last_rom->romsize);
+    error_printf(
+        "  %s (addresses 0x" TARGET_FMT_plx " - 0x" TARGET_FMT_plx ")\n",
+        rom->name, rom->addr, rom->addr + rom->romsize);
+}
+
 int rom_check_and_register_reset(void)
 {
-    hwaddr addr = 0;
     MemoryRegionSection section;
-    Rom *rom;
-    AddressSpace *as = NULL;
+    Rom *rom, *last_rom = NULL;
+    bool found_overlap = false;
 
     QTAILQ_FOREACH(rom, &roms, next) {
         if (rom->fw_file) {
             continue;
         }
         if (!rom->mr) {
-            if ((addr > rom->addr) && (as == rom->as)) {
-                fprintf(stderr, "rom: requested regions overlap "
-                        "(rom %s. free=0x" TARGET_FMT_plx
-                        ", addr=0x" TARGET_FMT_plx ")\n",
-                        rom->name, addr, rom->addr);
-                return -1;
+            if (roms_overlap(last_rom, rom)) {
+                if (!found_overlap) {
+                    found_overlap = true;
+                    rom_print_overlap_error_header();
+                }
+                rom_print_one_overlap_error(last_rom, rom);
+                /* Keep going through the list so we report all overlaps */
             }
-            addr  = rom->addr;
-            addr += rom->romsize;
-            as = rom->as;
+            last_rom = rom;
         }
         section = memory_region_find(rom->mr ? rom->mr : get_system_memory(),
                                      rom->addr, 1);
         rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
         memory_region_unref(section.mr);
     }
+    if (found_overlap) {
+        return -1;
+    }
+
     qemu_register_reset(rom_reset, NULL);
     roms_loaded = 1;
     return 0;
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 3f82cc230a..7c3e9daf58 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -37,7 +37,6 @@ specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_plic.c'))
 specific_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c'))
 specific_ss.add(when: 'CONFIG_LOONGSON_LIOINTC', if_true: files('loongson_liointc.c'))
 specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gic.c'))
-specific_ss.add(when: 'CONFIG_NIOS2', if_true: files('nios2_iic.c'))
 specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c'))
 specific_ss.add(when: 'CONFIG_OMPIC', if_true: files('ompic.c'))
 specific_ss.add(when: 'CONFIG_OPENPIC_KVM', if_true: files('openpic_kvm.c'))
diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c
deleted file mode 100644
index 216db67059..0000000000
--- a/hw/intc/nios2_iic.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * QEMU Altera Internal Interrupt Controller.
- *
- * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/lgpl-2.1.html>
- */
-
-#include "qemu/osdep.h"
-#include "qemu/module.h"
-#include "qapi/error.h"
-
-#include "hw/irq.h"
-#include "hw/sysbus.h"
-#include "cpu.h"
-#include "qom/object.h"
-
-#define TYPE_ALTERA_IIC "altera,iic"
-OBJECT_DECLARE_SIMPLE_TYPE(AlteraIIC, ALTERA_IIC)
-
-struct AlteraIIC {
-    SysBusDevice  parent_obj;
-    void         *cpu;
-    qemu_irq      parent_irq;
-};
-
-static void update_irq(AlteraIIC *pv)
-{
-    CPUNios2State *env = &((Nios2CPU *)(pv->cpu))->env;
-
-    qemu_set_irq(pv->parent_irq,
-                 env->regs[CR_IPENDING] & env->regs[CR_IENABLE]);
-}
-
-static void irq_handler(void *opaque, int irq, int level)
-{
-    AlteraIIC *pv = opaque;
-    CPUNios2State *env = &((Nios2CPU *)(pv->cpu))->env;
-
-    env->regs[CR_IPENDING] &= ~(1 << irq);
-    env->regs[CR_IPENDING] |= !!level << irq;
-
-    update_irq(pv);
-}
-
-static void altera_iic_init(Object *obj)
-{
-    AlteraIIC *pv = ALTERA_IIC(obj);
-
-    qdev_init_gpio_in(DEVICE(pv), irq_handler, 32);
-    sysbus_init_irq(SYS_BUS_DEVICE(obj), &pv->parent_irq);
-}
-
-static void altera_iic_realize(DeviceState *dev, Error **errp)
-{
-    struct AlteraIIC *pv = ALTERA_IIC(dev);
-
-    pv->cpu = object_property_get_link(OBJECT(dev), "cpu", &error_abort);
-}
-
-static void altera_iic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    /* Reason: needs to be wired up, e.g. by nios2_10m50_ghrd_init() */
-    dc->user_creatable = false;
-    dc->realize = altera_iic_realize;
-}
-
-static TypeInfo altera_iic_info = {
-    .name          = TYPE_ALTERA_IIC,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(AlteraIIC),
-    .instance_init = altera_iic_init,
-    .class_init    = altera_iic_class_init,
-};
-
-static void altera_iic_register(void)
-{
-    type_register_static(&altera_iic_info);
-}
-
-type_init(altera_iic_register)
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index a2b28019e3..66504a9d3a 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -217,6 +217,11 @@ static uint64_t zynq_slcr_compute_pll(uint64_t input, uint32_t ctrl_reg)
         return 0;
     }
 
+    /* Consider zero feedback as maximum divide ratio possible */
+    if (!mult) {
+        mult = 1 << R_xxx_PLL_CTRL_PLL_FPDIV_LENGTH;
+    }
+
     /* frequency multiplier -> period division */
     return input / mult;
 }
diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c
index 5c13b74306..a14fc31e86 100644
--- a/hw/nios2/10m50_devboard.c
+++ b/hw/nios2/10m50_devboard.c
@@ -52,7 +52,7 @@ static void nios2_10m50_ghrd_init(MachineState *machine)
     ram_addr_t tcm_size = 0x1000;    /* 1 kiB, but QEMU limit is 4 kiB */
     ram_addr_t ram_base = 0x08000000;
     ram_addr_t ram_size = 0x08000000;
-    qemu_irq *cpu_irq, irq[32];
+    qemu_irq irq[32];
     int i;
 
     /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
@@ -75,17 +75,8 @@ static void nios2_10m50_ghrd_init(MachineState *machine)
 
     /* Create CPU -- FIXME */
     cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU));
-
-    /* Register: CPU interrupt controller (PIC) */
-    cpu_irq = nios2_cpu_pic_init(cpu);
-
-    /* Register: Internal Interrupt Controller (IIC) */
-    dev = qdev_new("altera,iic");
-    object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu));
-    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]);
     for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
+        irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i);
     }
 
     /* Register: Altera 16550 UART */
diff --git a/hw/nios2/cpu_pic.c b/hw/nios2/cpu_pic.c
deleted file mode 100644
index 5ea7e52ab8..0000000000
--- a/hw/nios2/cpu_pic.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Altera Nios2 CPU PIC
- *
- * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/lgpl-2.1.html>
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "hw/irq.h"
-
-#include "qemu/config-file.h"
-
-#include "boot.h"
-
-static void nios2_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    Nios2CPU *cpu = opaque;
-    CPUNios2State *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
-
-    if (type == CPU_INTERRUPT_HARD) {
-        env->irq_pending = level;
-
-        if (level && (env->regs[CR_STATUS] & CR_STATUS_PIE)) {
-            env->irq_pending = 0;
-            cpu_interrupt(cs, type);
-        } else if (!level) {
-            env->irq_pending = 0;
-            cpu_reset_interrupt(cs, type);
-        }
-    } else {
-        if (level) {
-            cpu_interrupt(cs, type);
-        } else {
-            cpu_reset_interrupt(cs, type);
-        }
-    }
-}
-
-void nios2_check_interrupts(CPUNios2State *env)
-{
-    if (env->irq_pending &&
-        (env->regs[CR_STATUS] & CR_STATUS_PIE)) {
-        env->irq_pending = 0;
-        cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HARD);
-    }
-}
-
-qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu)
-{
-    return qemu_allocate_irqs(nios2_pic_cpu_handler, cpu, 2);
-}
diff --git a/hw/nios2/meson.build b/hw/nios2/meson.build
index dd66ebb32f..6c58e8082b 100644
--- a/hw/nios2/meson.build
+++ b/hw/nios2/meson.build
@@ -1,5 +1,5 @@
 nios2_ss = ss.source_set()
-nios2_ss.add(files('boot.c', 'cpu_pic.c'))
+nios2_ss.add(files('boot.c'))
 nios2_ss.add(when: 'CONFIG_NIOS2_10M50', if_true: files('10m50_devboard.c'))
 nios2_ss.add(when: 'CONFIG_NIOS2_GENERIC_NOMMU', if_true: files('generic_nommu.c'))
 
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 6c1e86884e..8f284f3ba0 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -3,3 +3,4 @@ config OR1K_SIM
     select SERIAL
     select OPENCORES_ETH
     select OMPIC
+    select SPLIT_IRQ
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index 57c42558e1..947f63ee08 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,5 +1,5 @@
 openrisc_ss = ss.source_set()
-openrisc_ss.add(files('pic_cpu.c', 'cputimer.c'))
+openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: files('openrisc_sim.c'))
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index d752282e67..39f1d344ae 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -34,6 +34,7 @@
 #include "hw/sysbus.h"
 #include "sysemu/qtest.h"
 #include "sysemu/reset.h"
+#include "hw/core/split-irq.h"
 
 #define KERNEL_LOAD_ADDR 0x100
 
@@ -51,8 +52,13 @@ static void main_cpu_reset(void *opaque)
     cpu_set_pc(cs, boot_info.bootstrap_pc);
 }
 
+static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin)
+{
+    return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin);
+}
+
 static void openrisc_sim_net_init(hwaddr base, hwaddr descriptors,
-                                  int num_cpus, qemu_irq **cpu_irqs,
+                                  int num_cpus, OpenRISCCPU *cpus[],
                                   int irq_pin, NICInfo *nd)
 {
     DeviceState *dev;
@@ -64,15 +70,23 @@ static void openrisc_sim_net_init(hwaddr base, hwaddr descriptors,
 
     s = SYS_BUS_DEVICE(dev);
     sysbus_realize_and_unref(s, &error_fatal);
-    for (i = 0; i < num_cpus; i++) {
-        sysbus_connect_irq(s, 0, cpu_irqs[i][irq_pin]);
+    if (num_cpus > 1) {
+        DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
+        qdev_prop_set_uint32(splitter, "num-lines", num_cpus);
+        qdev_realize_and_unref(splitter, NULL, &error_fatal);
+        for (i = 0; i < num_cpus; i++) {
+            qdev_connect_gpio_out(splitter, i, get_cpu_irq(cpus, i, irq_pin));
+        }
+        sysbus_connect_irq(s, 0, qdev_get_gpio_in(splitter, 0));
+    } else {
+        sysbus_connect_irq(s, 0, get_cpu_irq(cpus, 0, irq_pin));
     }
     sysbus_mmio_map(s, 0, base);
     sysbus_mmio_map(s, 1, descriptors);
 }
 
 static void openrisc_sim_ompic_init(hwaddr base, int num_cpus,
-                                    qemu_irq **cpu_irqs, int irq_pin)
+                                    OpenRISCCPU *cpus[], int irq_pin)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -84,7 +98,7 @@ static void openrisc_sim_ompic_init(hwaddr base, int num_cpus,
     s = SYS_BUS_DEVICE(dev);
     sysbus_realize_and_unref(s, &error_fatal);
     for (i = 0; i < num_cpus; i++) {
-        sysbus_connect_irq(s, i, cpu_irqs[i][irq_pin]);
+        sysbus_connect_irq(s, i, get_cpu_irq(cpus, i, irq_pin));
     }
     sysbus_mmio_map(s, 0, base);
 }
@@ -127,26 +141,23 @@ static void openrisc_sim_init(MachineState *machine)
 {
     ram_addr_t ram_size = machine->ram_size;
     const char *kernel_filename = machine->kernel_filename;
-    OpenRISCCPU *cpu = NULL;
+    OpenRISCCPU *cpus[2] = {};
     MemoryRegion *ram;
-    qemu_irq *cpu_irqs[2];
     qemu_irq serial_irq;
     int n;
     unsigned int smp_cpus = machine->smp.cpus;
 
     assert(smp_cpus >= 1 && smp_cpus <= 2);
     for (n = 0; n < smp_cpus; n++) {
-        cpu = OPENRISC_CPU(cpu_create(machine->cpu_type));
-        if (cpu == NULL) {
+        cpus[n] = OPENRISC_CPU(cpu_create(machine->cpu_type));
+        if (cpus[n] == NULL) {
             fprintf(stderr, "Unable to find CPU definition!\n");
             exit(1);
         }
-        cpu_openrisc_pic_init(cpu);
-        cpu_irqs[n] = (qemu_irq *) cpu->env.irq;
 
-        cpu_openrisc_clock_init(cpu);
+        cpu_openrisc_clock_init(cpus[n]);
 
-        qemu_register_reset(main_cpu_reset, cpu);
+        qemu_register_reset(main_cpu_reset, cpus[n]);
     }
 
     ram = g_malloc(sizeof(*ram));
@@ -155,15 +166,16 @@ static void openrisc_sim_init(MachineState *machine)
 
     if (nd_table[0].used) {
         openrisc_sim_net_init(0x92000000, 0x92000400, smp_cpus,
-                              cpu_irqs, 4, nd_table);
+                              cpus, 4, nd_table);
     }
 
     if (smp_cpus > 1) {
-        openrisc_sim_ompic_init(0x98000000, smp_cpus, cpu_irqs, 1);
+        openrisc_sim_ompic_init(0x98000000, smp_cpus, cpus, 1);
 
-        serial_irq = qemu_irq_split(cpu_irqs[0][2], cpu_irqs[1][2]);
+        serial_irq = qemu_irq_split(get_cpu_irq(cpus, 0, 2),
+                                    get_cpu_irq(cpus, 1, 2));
     } else {
-        serial_irq = cpu_irqs[0][2];
+        serial_irq = get_cpu_irq(cpus, 0, 2);
     }
 
     serial_mm_init(get_system_memory(), 0x90000000, 0, serial_irq,
diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c
deleted file mode 100644
index 36f9350830..0000000000
--- a/hw/openrisc/pic_cpu.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * OpenRISC Programmable Interrupt Controller support.
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
- *                         Feng Gao <gf91597@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/irq.h"
-#include "cpu.h"
-
-/* OpenRISC pic handler */
-static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
-    CPUState *cs = CPU(cpu);
-    uint32_t irq_bit;
-
-    if (irq > 31 || irq < 0) {
-        return;
-    }
-
-    irq_bit = 1U << irq;
-
-    if (level) {
-        cpu->env.picsr |= irq_bit;
-    } else {
-        cpu->env.picsr &= ~irq_bit;
-    }
-
-    if (cpu->env.picsr & cpu->env.picmr) {
-        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-        cpu->env.picsr = 0;
-    }
-}
-
-void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
-{
-    int i;
-    qemu_irq *qi;
-    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
-
-    for (i = 0; i < NR_IRQS; i++) {
-        cpu->env.irq[i] = qi[i];
-    }
-}
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 7fbae18bc8..40093d7ea6 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -112,3 +112,13 @@ config IMX_USBPHY
     bool
     default y
     depends on USB
+
+config USB_DWC3
+    bool
+    select USB_XHCI_SYSBUS
+    select REGISTER
+
+config XLNX_USB_SUBSYS
+    bool
+    default y if XLNX_VERSAL
+    select USB_DWC3
diff --git a/hw/usb/hcd-dwc3.c b/hw/usb/hcd-dwc3.c
new file mode 100644
index 0000000000..d547d0538d
--- /dev/null
+++ b/hw/usb/hcd-dwc3.c
@@ -0,0 +1,689 @@
+/*
+ * QEMU model of the USB DWC3 host controller emulation.
+ *
+ * This model defines global register space of DWC3 controller. Global
+ * registers control the AXI/AHB interfaces properties, external FIFO support
+ * and event count support. All of which are unimplemented at present. We are
+ * only supporting core reset and read of ID register.
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal<fnu.vikram@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/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/usb/hcd-dwc3.h"
+#include "qapi/error.h"
+
+#ifndef USB_DWC3_ERR_DEBUG
+#define USB_DWC3_ERR_DEBUG 0
+#endif
+
+#define HOST_MODE           1
+#define FIFO_LEN         0x1000
+
+REG32(GSBUSCFG0, 0x00)
+    FIELD(GSBUSCFG0, DATRDREQINFO, 28, 4)
+    FIELD(GSBUSCFG0, DESRDREQINFO, 24, 4)
+    FIELD(GSBUSCFG0, DATWRREQINFO, 20, 4)
+    FIELD(GSBUSCFG0, DESWRREQINFO, 16, 4)
+    FIELD(GSBUSCFG0, RESERVED_15_12, 12, 4)
+    FIELD(GSBUSCFG0, DATBIGEND, 11, 1)
+    FIELD(GSBUSCFG0, DESBIGEND, 10, 1)
+    FIELD(GSBUSCFG0, RESERVED_9_8, 8, 2)
+    FIELD(GSBUSCFG0, INCR256BRSTENA, 7, 1)
+    FIELD(GSBUSCFG0, INCR128BRSTENA, 6, 1)
+    FIELD(GSBUSCFG0, INCR64BRSTENA, 5, 1)
+    FIELD(GSBUSCFG0, INCR32BRSTENA, 4, 1)
+    FIELD(GSBUSCFG0, INCR16BRSTENA, 3, 1)
+    FIELD(GSBUSCFG0, INCR8BRSTENA, 2, 1)
+    FIELD(GSBUSCFG0, INCR4BRSTENA, 1, 1)
+    FIELD(GSBUSCFG0, INCRBRSTENA, 0, 1)
+REG32(GSBUSCFG1, 0x04)
+    FIELD(GSBUSCFG1, RESERVED_31_13, 13, 19)
+    FIELD(GSBUSCFG1, EN1KPAGE, 12, 1)
+    FIELD(GSBUSCFG1, PIPETRANSLIMIT, 8, 4)
+    FIELD(GSBUSCFG1, RESERVED_7_0, 0, 8)
+REG32(GTXTHRCFG, 0x08)
+    FIELD(GTXTHRCFG, RESERVED_31, 31, 1)
+    FIELD(GTXTHRCFG, RESERVED_30, 30, 1)
+    FIELD(GTXTHRCFG, USBTXPKTCNTSEL, 29, 1)
+    FIELD(GTXTHRCFG, RESERVED_28, 28, 1)
+    FIELD(GTXTHRCFG, USBTXPKTCNT, 24, 4)
+    FIELD(GTXTHRCFG, USBMAXTXBURSTSIZE, 16, 8)
+    FIELD(GTXTHRCFG, RESERVED_15, 15, 1)
+    FIELD(GTXTHRCFG, RESERVED_14, 14, 1)
+    FIELD(GTXTHRCFG, RESERVED_13_11, 11, 3)
+    FIELD(GTXTHRCFG, RESERVED_10_0, 0, 11)
+REG32(GRXTHRCFG, 0x0c)
+    FIELD(GRXTHRCFG, RESERVED_31_30, 30, 2)
+    FIELD(GRXTHRCFG, USBRXPKTCNTSEL, 29, 1)
+    FIELD(GRXTHRCFG, RESERVED_28, 28, 1)
+    FIELD(GRXTHRCFG, USBRXPKTCNT, 24, 4)
+    FIELD(GRXTHRCFG, USBMAXRXBURSTSIZE, 19, 5)
+    FIELD(GRXTHRCFG, RESERVED_18_16, 16, 3)
+    FIELD(GRXTHRCFG, RESERVED_15, 15, 1)
+    FIELD(GRXTHRCFG, RESERVED_14_13, 13, 2)
+    FIELD(GRXTHRCFG, RESVISOCOUTSPC, 0, 13)
+REG32(GCTL, 0x10)
+    FIELD(GCTL, PWRDNSCALE, 19, 13)
+    FIELD(GCTL, MASTERFILTBYPASS, 18, 1)
+    FIELD(GCTL, BYPSSETADDR, 17, 1)
+    FIELD(GCTL, U2RSTECN, 16, 1)
+    FIELD(GCTL, FRMSCLDWN, 14, 2)
+    FIELD(GCTL, PRTCAPDIR, 12, 2)
+    FIELD(GCTL, CORESOFTRESET, 11, 1)
+    FIELD(GCTL, U1U2TIMERSCALE, 9, 1)
+    FIELD(GCTL, DEBUGATTACH, 8, 1)
+    FIELD(GCTL, RAMCLKSEL, 6, 2)
+    FIELD(GCTL, SCALEDOWN, 4, 2)
+    FIELD(GCTL, DISSCRAMBLE, 3, 1)
+    FIELD(GCTL, U2EXIT_LFPS, 2, 1)
+    FIELD(GCTL, GBLHIBERNATIONEN, 1, 1)
+    FIELD(GCTL, DSBLCLKGTNG, 0, 1)
+REG32(GPMSTS, 0x14)
+REG32(GSTS, 0x18)
+    FIELD(GSTS, CBELT, 20, 12)
+    FIELD(GSTS, RESERVED_19_12, 12, 8)
+    FIELD(GSTS, SSIC_IP, 11, 1)
+    FIELD(GSTS, OTG_IP, 10, 1)
+    FIELD(GSTS, BC_IP, 9, 1)
+    FIELD(GSTS, ADP_IP, 8, 1)
+    FIELD(GSTS, HOST_IP, 7, 1)
+    FIELD(GSTS, DEVICE_IP, 6, 1)
+    FIELD(GSTS, CSRTIMEOUT, 5, 1)
+    FIELD(GSTS, BUSERRADDRVLD, 4, 1)
+    FIELD(GSTS, RESERVED_3_2, 2, 2)
+    FIELD(GSTS, CURMOD, 0, 2)
+REG32(GUCTL1, 0x1c)
+    FIELD(GUCTL1, RESUME_OPMODE_HS_HOST, 10, 1)
+REG32(GSNPSID, 0x20)
+REG32(GGPIO, 0x24)
+    FIELD(GGPIO, GPO, 16, 16)
+    FIELD(GGPIO, GPI, 0, 16)
+REG32(GUID, 0x28)
+REG32(GUCTL, 0x2c)
+    FIELD(GUCTL, REFCLKPER, 22, 10)
+    FIELD(GUCTL, NOEXTRDL, 21, 1)
+    FIELD(GUCTL, RESERVED_20_18, 18, 3)
+    FIELD(GUCTL, SPRSCTRLTRANSEN, 17, 1)
+    FIELD(GUCTL, RESBWHSEPS, 16, 1)
+    FIELD(GUCTL, RESERVED_15, 15, 1)
+    FIELD(GUCTL, USBHSTINAUTORETRYEN, 14, 1)
+    FIELD(GUCTL, ENOVERLAPCHK, 13, 1)
+    FIELD(GUCTL, EXTCAPSUPPTEN, 12, 1)
+    FIELD(GUCTL, INSRTEXTRFSBODI, 11, 1)
+    FIELD(GUCTL, DTCT, 9, 2)
+    FIELD(GUCTL, DTFT, 0, 9)
+REG32(GBUSERRADDRLO, 0x30)
+REG32(GBUSERRADDRHI, 0x34)
+REG32(GHWPARAMS0, 0x40)
+    FIELD(GHWPARAMS0, GHWPARAMS0_31_24, 24, 8)
+    FIELD(GHWPARAMS0, GHWPARAMS0_23_16, 16, 8)
+    FIELD(GHWPARAMS0, GHWPARAMS0_15_8, 8, 8)
+    FIELD(GHWPARAMS0, GHWPARAMS0_7_6, 6, 2)
+    FIELD(GHWPARAMS0, GHWPARAMS0_5_3, 3, 3)
+    FIELD(GHWPARAMS0, GHWPARAMS0_2_0, 0, 3)
+REG32(GHWPARAMS1, 0x44)
+    FIELD(GHWPARAMS1, GHWPARAMS1_31, 31, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_30, 30, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_29, 29, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_28, 28, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_27, 27, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_26, 26, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_25_24, 24, 2)
+    FIELD(GHWPARAMS1, GHWPARAMS1_23, 23, 1)
+    FIELD(GHWPARAMS1, GHWPARAMS1_22_21, 21, 2)
+    FIELD(GHWPARAMS1, GHWPARAMS1_20_15, 15, 6)
+    FIELD(GHWPARAMS1, GHWPARAMS1_14_12, 12, 3)
+    FIELD(GHWPARAMS1, GHWPARAMS1_11_9, 9, 3)
+    FIELD(GHWPARAMS1, GHWPARAMS1_8_6, 6, 3)
+    FIELD(GHWPARAMS1, GHWPARAMS1_5_3, 3, 3)
+    FIELD(GHWPARAMS1, GHWPARAMS1_2_0, 0, 3)
+REG32(GHWPARAMS2, 0x48)
+REG32(GHWPARAMS3, 0x4c)
+    FIELD(GHWPARAMS3, GHWPARAMS3_31, 31, 1)
+    FIELD(GHWPARAMS3, GHWPARAMS3_30_23, 23, 8)
+    FIELD(GHWPARAMS3, GHWPARAMS3_22_18, 18, 5)
+    FIELD(GHWPARAMS3, GHWPARAMS3_17_12, 12, 6)
+    FIELD(GHWPARAMS3, GHWPARAMS3_11, 11, 1)
+    FIELD(GHWPARAMS3, GHWPARAMS3_10, 10, 1)
+    FIELD(GHWPARAMS3, GHWPARAMS3_9_8, 8, 2)
+    FIELD(GHWPARAMS3, GHWPARAMS3_7_6, 6, 2)
+    FIELD(GHWPARAMS3, GHWPARAMS3_5_4, 4, 2)
+    FIELD(GHWPARAMS3, GHWPARAMS3_3_2, 2, 2)
+    FIELD(GHWPARAMS3, GHWPARAMS3_1_0, 0, 2)
+REG32(GHWPARAMS4, 0x50)
+    FIELD(GHWPARAMS4, GHWPARAMS4_31_28, 28, 4)
+    FIELD(GHWPARAMS4, GHWPARAMS4_27_24, 24, 4)
+    FIELD(GHWPARAMS4, GHWPARAMS4_23, 23, 1)
+    FIELD(GHWPARAMS4, GHWPARAMS4_22, 22, 1)
+    FIELD(GHWPARAMS4, GHWPARAMS4_21, 21, 1)
+    FIELD(GHWPARAMS4, GHWPARAMS4_20_17, 17, 4)
+    FIELD(GHWPARAMS4, GHWPARAMS4_16_13, 13, 4)
+    FIELD(GHWPARAMS4, GHWPARAMS4_12, 12, 1)
+    FIELD(GHWPARAMS4, GHWPARAMS4_11, 11, 1)
+    FIELD(GHWPARAMS4, GHWPARAMS4_10_9, 9, 2)
+    FIELD(GHWPARAMS4, GHWPARAMS4_8_7, 7, 2)
+    FIELD(GHWPARAMS4, GHWPARAMS4_6, 6, 1)
+    FIELD(GHWPARAMS4, GHWPARAMS4_5_0, 0, 6)
+REG32(GHWPARAMS5, 0x54)
+    FIELD(GHWPARAMS5, GHWPARAMS5_31_28, 28, 4)
+    FIELD(GHWPARAMS5, GHWPARAMS5_27_22, 22, 6)
+    FIELD(GHWPARAMS5, GHWPARAMS5_21_16, 16, 6)
+    FIELD(GHWPARAMS5, GHWPARAMS5_15_10, 10, 6)
+    FIELD(GHWPARAMS5, GHWPARAMS5_9_4, 4, 6)
+    FIELD(GHWPARAMS5, GHWPARAMS5_3_0, 0, 4)
+REG32(GHWPARAMS6, 0x58)
+    FIELD(GHWPARAMS6, GHWPARAMS6_31_16, 16, 16)
+    FIELD(GHWPARAMS6, BUSFLTRSSUPPORT, 15, 1)
+    FIELD(GHWPARAMS6, BCSUPPORT, 14, 1)
+    FIELD(GHWPARAMS6, OTG_SS_SUPPORT, 13, 1)
+    FIELD(GHWPARAMS6, ADPSUPPORT, 12, 1)
+    FIELD(GHWPARAMS6, HNPSUPPORT, 11, 1)
+    FIELD(GHWPARAMS6, SRPSUPPORT, 10, 1)
+    FIELD(GHWPARAMS6, GHWPARAMS6_9_8, 8, 2)
+    FIELD(GHWPARAMS6, GHWPARAMS6_7, 7, 1)
+    FIELD(GHWPARAMS6, GHWPARAMS6_6, 6, 1)
+    FIELD(GHWPARAMS6, GHWPARAMS6_5_0, 0, 6)
+REG32(GHWPARAMS7, 0x5c)
+    FIELD(GHWPARAMS7, GHWPARAMS7_31_16, 16, 16)
+    FIELD(GHWPARAMS7, GHWPARAMS7_15_0, 0, 16)
+REG32(GDBGFIFOSPACE, 0x60)
+    FIELD(GDBGFIFOSPACE, SPACE_AVAILABLE, 16, 16)
+    FIELD(GDBGFIFOSPACE, RESERVED_15_9, 9, 7)
+    FIELD(GDBGFIFOSPACE, FIFO_QUEUE_SELECT, 0, 9)
+REG32(GUCTL2, 0x9c)
+    FIELD(GUCTL2, RESERVED_31_26, 26, 6)
+    FIELD(GUCTL2, EN_HP_PM_TIMER, 19, 7)
+    FIELD(GUCTL2, NOLOWPWRDUR, 15, 4)
+    FIELD(GUCTL2, RST_ACTBITLATER, 14, 1)
+    FIELD(GUCTL2, RESERVED_13, 13, 1)
+    FIELD(GUCTL2, DISABLECFC, 11, 1)
+REG32(GUSB2PHYCFG, 0x100)
+    FIELD(GUSB2PHYCFG, U2_FREECLK_EXISTS, 30, 1)
+    FIELD(GUSB2PHYCFG, ULPI_LPM_WITH_OPMODE_CHK, 29, 1)
+    FIELD(GUSB2PHYCFG, RESERVED_25, 25, 1)
+    FIELD(GUSB2PHYCFG, LSTRD, 22, 3)
+    FIELD(GUSB2PHYCFG, LSIPD, 19, 3)
+    FIELD(GUSB2PHYCFG, ULPIEXTVBUSINDIACTOR, 18, 1)
+    FIELD(GUSB2PHYCFG, ULPIEXTVBUSDRV, 17, 1)
+    FIELD(GUSB2PHYCFG, RESERVED_16, 16, 1)
+    FIELD(GUSB2PHYCFG, ULPIAUTORES, 15, 1)
+    FIELD(GUSB2PHYCFG, RESERVED_14, 14, 1)
+    FIELD(GUSB2PHYCFG, USBTRDTIM, 10, 4)
+    FIELD(GUSB2PHYCFG, XCVRDLY, 9, 1)
+    FIELD(GUSB2PHYCFG, ENBLSLPM, 8, 1)
+    FIELD(GUSB2PHYCFG, PHYSEL, 7, 1)
+    FIELD(GUSB2PHYCFG, SUSPENDUSB20, 6, 1)
+    FIELD(GUSB2PHYCFG, FSINTF, 5, 1)
+    FIELD(GUSB2PHYCFG, ULPI_UTMI_SEL, 4, 1)
+    FIELD(GUSB2PHYCFG, PHYIF, 3, 1)
+    FIELD(GUSB2PHYCFG, TOUTCAL, 0, 3)
+REG32(GUSB2I2CCTL, 0x140)
+REG32(GUSB2PHYACC_ULPI, 0x180)
+    FIELD(GUSB2PHYACC_ULPI, RESERVED_31_27, 27, 5)
+    FIELD(GUSB2PHYACC_ULPI, DISUIPIDRVR, 26, 1)
+    FIELD(GUSB2PHYACC_ULPI, NEWREGREQ, 25, 1)
+    FIELD(GUSB2PHYACC_ULPI, VSTSDONE, 24, 1)
+    FIELD(GUSB2PHYACC_ULPI, VSTSBSY, 23, 1)
+    FIELD(GUSB2PHYACC_ULPI, REGWR, 22, 1)
+    FIELD(GUSB2PHYACC_ULPI, REGADDR, 16, 6)
+    FIELD(GUSB2PHYACC_ULPI, EXTREGADDR, 8, 8)
+    FIELD(GUSB2PHYACC_ULPI, REGDATA, 0, 8)
+REG32(GTXFIFOSIZ0, 0x200)
+    FIELD(GTXFIFOSIZ0, TXFSTADDR_N, 16, 16)
+    FIELD(GTXFIFOSIZ0, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ1, 0x204)
+    FIELD(GTXFIFOSIZ1, TXFSTADDR_N, 16, 16)
+    FIELD(GTXFIFOSIZ1, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ2, 0x208)
+    FIELD(GTXFIFOSIZ2, TXFSTADDR_N, 16, 16)
+    FIELD(GTXFIFOSIZ2, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ3, 0x20c)
+    FIELD(GTXFIFOSIZ3, TXFSTADDR_N, 16, 16)
+    FIELD(GTXFIFOSIZ3, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ4, 0x210)
+    FIELD(GTXFIFOSIZ4, TXFSTADDR_N, 16, 16)
+    FIELD(GTXFIFOSIZ4, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ5, 0x214)
+    FIELD(GTXFIFOSIZ5, TXFSTADDR_N, 16, 16)
+    FIELD(GTXFIFOSIZ5, TXFDEP_N, 0, 16)
+REG32(GRXFIFOSIZ0, 0x280)
+    FIELD(GRXFIFOSIZ0, RXFSTADDR_N, 16, 16)
+    FIELD(GRXFIFOSIZ0, RXFDEP_N, 0, 16)
+REG32(GRXFIFOSIZ1, 0x284)
+    FIELD(GRXFIFOSIZ1, RXFSTADDR_N, 16, 16)
+    FIELD(GRXFIFOSIZ1, RXFDEP_N, 0, 16)
+REG32(GRXFIFOSIZ2, 0x288)
+    FIELD(GRXFIFOSIZ2, RXFSTADDR_N, 16, 16)
+    FIELD(GRXFIFOSIZ2, RXFDEP_N, 0, 16)
+REG32(GEVNTADRLO_0, 0x300)
+REG32(GEVNTADRHI_0, 0x304)
+REG32(GEVNTSIZ_0, 0x308)
+    FIELD(GEVNTSIZ_0, EVNTINTRPTMASK, 31, 1)
+    FIELD(GEVNTSIZ_0, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTSIZ_0, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_0, 0x30c)
+    FIELD(GEVNTCOUNT_0, EVNT_HANDLER_BUSY, 31, 1)
+    FIELD(GEVNTCOUNT_0, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTCOUNT_0, EVNTCOUNT, 0, 16)
+REG32(GEVNTADRLO_1, 0x310)
+REG32(GEVNTADRHI_1, 0x314)
+REG32(GEVNTSIZ_1, 0x318)
+    FIELD(GEVNTSIZ_1, EVNTINTRPTMASK, 31, 1)
+    FIELD(GEVNTSIZ_1, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTSIZ_1, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_1, 0x31c)
+    FIELD(GEVNTCOUNT_1, EVNT_HANDLER_BUSY, 31, 1)
+    FIELD(GEVNTCOUNT_1, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTCOUNT_1, EVNTCOUNT, 0, 16)
+REG32(GEVNTADRLO_2, 0x320)
+REG32(GEVNTADRHI_2, 0x324)
+REG32(GEVNTSIZ_2, 0x328)
+    FIELD(GEVNTSIZ_2, EVNTINTRPTMASK, 31, 1)
+    FIELD(GEVNTSIZ_2, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTSIZ_2, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_2, 0x32c)
+    FIELD(GEVNTCOUNT_2, EVNT_HANDLER_BUSY, 31, 1)
+    FIELD(GEVNTCOUNT_2, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTCOUNT_2, EVNTCOUNT, 0, 16)
+REG32(GEVNTADRLO_3, 0x330)
+REG32(GEVNTADRHI_3, 0x334)
+REG32(GEVNTSIZ_3, 0x338)
+    FIELD(GEVNTSIZ_3, EVNTINTRPTMASK, 31, 1)
+    FIELD(GEVNTSIZ_3, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTSIZ_3, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_3, 0x33c)
+    FIELD(GEVNTCOUNT_3, EVNT_HANDLER_BUSY, 31, 1)
+    FIELD(GEVNTCOUNT_3, RESERVED_30_16, 16, 15)
+    FIELD(GEVNTCOUNT_3, EVNTCOUNT, 0, 16)
+REG32(GHWPARAMS8, 0x500)
+REG32(GTXFIFOPRIDEV, 0x510)
+    FIELD(GTXFIFOPRIDEV, RESERVED_31_N, 6, 26)
+    FIELD(GTXFIFOPRIDEV, GTXFIFOPRIDEV, 0, 6)
+REG32(GTXFIFOPRIHST, 0x518)
+    FIELD(GTXFIFOPRIHST, RESERVED_31_16, 3, 29)
+    FIELD(GTXFIFOPRIHST, GTXFIFOPRIHST, 0, 3)
+REG32(GRXFIFOPRIHST, 0x51c)
+    FIELD(GRXFIFOPRIHST, RESERVED_31_16, 3, 29)
+    FIELD(GRXFIFOPRIHST, GRXFIFOPRIHST, 0, 3)
+REG32(GDMAHLRATIO, 0x524)
+    FIELD(GDMAHLRATIO, RESERVED_31_13, 13, 19)
+    FIELD(GDMAHLRATIO, HSTRXFIFO, 8, 5)
+    FIELD(GDMAHLRATIO, RESERVED_7_5, 5, 3)
+    FIELD(GDMAHLRATIO, HSTTXFIFO, 0, 5)
+REG32(GFLADJ, 0x530)
+    FIELD(GFLADJ, GFLADJ_REFCLK_240MHZDECR_PLS1, 31, 1)
+    FIELD(GFLADJ, GFLADJ_REFCLK_240MHZ_DECR, 24, 7)
+    FIELD(GFLADJ, GFLADJ_REFCLK_LPM_SEL, 23, 1)
+    FIELD(GFLADJ, RESERVED_22, 22, 1)
+    FIELD(GFLADJ, GFLADJ_REFCLK_FLADJ, 8, 14)
+    FIELD(GFLADJ, GFLADJ_30MHZ_SDBND_SEL, 7, 1)
+    FIELD(GFLADJ, GFLADJ_30MHZ, 0, 6)
+
+#define DWC3_GLOBAL_OFFSET 0xC100
+static void reset_csr(USBDWC3 * s)
+{
+    int i = 0;
+    /*
+     * We reset all CSR regs except GCTL, GUCTL, GSTS, GSNPSID, GGPIO, GUID,
+     * GUSB2PHYCFGn registers and GUSB3PIPECTLn registers. We will skip PHY
+     * register as we don't implement them.
+     */
+    for (i = 0; i < USB_DWC3_R_MAX; i++) {
+        switch (i) {
+        case R_GCTL:
+            break;
+        case R_GSTS:
+            break;
+        case R_GSNPSID:
+            break;
+        case R_GGPIO:
+            break;
+        case R_GUID:
+            break;
+        case R_GUCTL:
+            break;
+        case R_GHWPARAMS0...R_GHWPARAMS7:
+            break;
+        case R_GHWPARAMS8:
+            break;
+        default:
+            register_reset(&s->regs_info[i]);
+            break;
+        }
+    }
+
+    xhci_sysbus_reset(DEVICE(&s->sysbus_xhci));
+}
+
+static void usb_dwc3_gctl_postw(RegisterInfo *reg, uint64_t val64)
+{
+    USBDWC3 *s = USB_DWC3(reg->opaque);
+
+    if (ARRAY_FIELD_EX32(s->regs, GCTL, CORESOFTRESET)) {
+        reset_csr(s);
+    }
+}
+
+static void usb_dwc3_guid_postw(RegisterInfo *reg, uint64_t val64)
+{
+    USBDWC3 *s = USB_DWC3(reg->opaque);
+
+    s->regs[R_GUID] = s->cfg.dwc_usb3_user;
+}
+
+static const RegisterAccessInfo usb_dwc3_regs_info[] = {
+    {   .name = "GSBUSCFG0",  .addr = A_GSBUSCFG0,
+        .ro = 0xf300,
+        .unimp = 0xffffffff,
+    },{ .name = "GSBUSCFG1",  .addr = A_GSBUSCFG1,
+        .reset = 0x300,
+        .ro = 0xffffe0ff,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXTHRCFG",  .addr = A_GTXTHRCFG,
+        .ro = 0xd000ffff,
+        .unimp = 0xffffffff,
+    },{ .name = "GRXTHRCFG",  .addr = A_GRXTHRCFG,
+        .ro = 0xd007e000,
+        .unimp = 0xffffffff,
+    },{ .name = "GCTL",  .addr = A_GCTL,
+        .reset = 0x30c13004, .post_write = usb_dwc3_gctl_postw,
+    },{ .name = "GPMSTS",  .addr = A_GPMSTS,
+        .ro = 0xfffffff,
+        .unimp = 0xffffffff,
+    },{ .name = "GSTS",  .addr = A_GSTS,
+        .reset = 0x7e800000,
+        .ro = 0xffffffcf,
+        .w1c = 0x30,
+        .unimp = 0xffffffff,
+    },{ .name = "GUCTL1",  .addr = A_GUCTL1,
+        .reset = 0x198a,
+        .ro = 0x7800,
+        .unimp = 0xffffffff,
+    },{ .name = "GSNPSID",  .addr = A_GSNPSID,
+        .reset = 0x5533330a,
+        .ro = 0xffffffff,
+    },{ .name = "GGPIO",  .addr = A_GGPIO,
+        .ro = 0xffff,
+        .unimp = 0xffffffff,
+    },{ .name = "GUID",  .addr = A_GUID,
+        .reset = 0x12345678, .post_write = usb_dwc3_guid_postw,
+    },{ .name = "GUCTL",  .addr = A_GUCTL,
+        .reset = 0x0c808010,
+        .ro = 0x1c8000,
+        .unimp = 0xffffffff,
+    },{ .name = "GBUSERRADDRLO",  .addr = A_GBUSERRADDRLO,
+        .ro = 0xffffffff,
+    },{ .name = "GBUSERRADDRHI",  .addr = A_GBUSERRADDRHI,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS0",  .addr = A_GHWPARAMS0,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS1",  .addr = A_GHWPARAMS1,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS2",  .addr = A_GHWPARAMS2,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS3",  .addr = A_GHWPARAMS3,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS4",  .addr = A_GHWPARAMS4,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS5",  .addr = A_GHWPARAMS5,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS6",  .addr = A_GHWPARAMS6,
+        .ro = 0xffffffff,
+    },{ .name = "GHWPARAMS7",  .addr = A_GHWPARAMS7,
+        .ro = 0xffffffff,
+    },{ .name = "GDBGFIFOSPACE",  .addr = A_GDBGFIFOSPACE,
+        .reset = 0xa0000,
+        .ro = 0xfffffe00,
+        .unimp = 0xffffffff,
+    },{ .name = "GUCTL2",  .addr = A_GUCTL2,
+        .reset = 0x40d,
+        .ro = 0x2000,
+        .unimp = 0xffffffff,
+    },{ .name = "GUSB2PHYCFG",  .addr = A_GUSB2PHYCFG,
+        .reset = 0x40102410,
+        .ro = 0x1e014030,
+        .unimp = 0xffffffff,
+    },{ .name = "GUSB2I2CCTL",  .addr = A_GUSB2I2CCTL,
+        .ro = 0xffffffff,
+        .unimp = 0xffffffff,
+    },{ .name = "GUSB2PHYACC_ULPI",  .addr = A_GUSB2PHYACC_ULPI,
+        .ro = 0xfd000000,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOSIZ0",  .addr = A_GTXFIFOSIZ0,
+        .reset = 0x2c7000a,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOSIZ1",  .addr = A_GTXFIFOSIZ1,
+        .reset = 0x2d10103,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOSIZ2",  .addr = A_GTXFIFOSIZ2,
+        .reset = 0x3d40103,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOSIZ3",  .addr = A_GTXFIFOSIZ3,
+        .reset = 0x4d70083,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOSIZ4",  .addr = A_GTXFIFOSIZ4,
+        .reset = 0x55a0083,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOSIZ5",  .addr = A_GTXFIFOSIZ5,
+        .reset = 0x5dd0083,
+        .unimp = 0xffffffff,
+    },{ .name = "GRXFIFOSIZ0",  .addr = A_GRXFIFOSIZ0,
+        .reset = 0x1c20105,
+        .unimp = 0xffffffff,
+    },{ .name = "GRXFIFOSIZ1",  .addr = A_GRXFIFOSIZ1,
+        .reset = 0x2c70000,
+        .unimp = 0xffffffff,
+    },{ .name = "GRXFIFOSIZ2",  .addr = A_GRXFIFOSIZ2,
+        .reset = 0x2c70000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRLO_0",  .addr = A_GEVNTADRLO_0,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRHI_0",  .addr = A_GEVNTADRHI_0,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTSIZ_0",  .addr = A_GEVNTSIZ_0,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTCOUNT_0",  .addr = A_GEVNTCOUNT_0,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRLO_1",  .addr = A_GEVNTADRLO_1,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRHI_1",  .addr = A_GEVNTADRHI_1,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTSIZ_1",  .addr = A_GEVNTSIZ_1,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTCOUNT_1",  .addr = A_GEVNTCOUNT_1,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRLO_2",  .addr = A_GEVNTADRLO_2,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRHI_2",  .addr = A_GEVNTADRHI_2,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTSIZ_2",  .addr = A_GEVNTSIZ_2,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTCOUNT_2",  .addr = A_GEVNTCOUNT_2,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRLO_3",  .addr = A_GEVNTADRLO_3,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTADRHI_3",  .addr = A_GEVNTADRHI_3,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTSIZ_3",  .addr = A_GEVNTSIZ_3,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GEVNTCOUNT_3",  .addr = A_GEVNTCOUNT_3,
+        .ro = 0x7fff0000,
+        .unimp = 0xffffffff,
+    },{ .name = "GHWPARAMS8",  .addr = A_GHWPARAMS8,
+        .ro = 0xffffffff,
+    },{ .name = "GTXFIFOPRIDEV",  .addr = A_GTXFIFOPRIDEV,
+        .ro = 0xffffffc0,
+        .unimp = 0xffffffff,
+    },{ .name = "GTXFIFOPRIHST",  .addr = A_GTXFIFOPRIHST,
+        .ro = 0xfffffff8,
+        .unimp = 0xffffffff,
+    },{ .name = "GRXFIFOPRIHST",  .addr = A_GRXFIFOPRIHST,
+        .ro = 0xfffffff8,
+        .unimp = 0xffffffff,
+    },{ .name = "GDMAHLRATIO",  .addr = A_GDMAHLRATIO,
+        .ro = 0xffffe0e0,
+        .unimp = 0xffffffff,
+    },{ .name = "GFLADJ",  .addr = A_GFLADJ,
+        .reset = 0xc83f020,
+        .rsvd = 0x40,
+        .ro = 0x400040,
+        .unimp = 0xffffffff,
+    }
+};
+
+static void usb_dwc3_reset(DeviceState *dev)
+{
+    USBDWC3 *s = USB_DWC3(dev);
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+        switch (i) {
+        case R_GHWPARAMS0...R_GHWPARAMS7:
+            break;
+        case R_GHWPARAMS8:
+            break;
+        default:
+            register_reset(&s->regs_info[i]);
+        };
+    }
+
+    xhci_sysbus_reset(DEVICE(&s->sysbus_xhci));
+}
+
+static const MemoryRegionOps usb_dwc3_ops = {
+    .read = register_read_memory,
+    .write = register_write_memory,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void usb_dwc3_realize(DeviceState *dev, Error **errp)
+{
+    USBDWC3 *s = USB_DWC3(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *err = NULL;
+
+    sysbus_realize(SYS_BUS_DEVICE(&s->sysbus_xhci), &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    memory_region_add_subregion(&s->iomem, 0,
+         sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sysbus_xhci), 0));
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    /*
+     * Device Configuration
+     */
+    s->regs[R_GHWPARAMS0] = 0x40204048 | s->cfg.mode;
+    s->regs[R_GHWPARAMS1] = 0x222493b;
+    s->regs[R_GHWPARAMS2] = 0x12345678;
+    s->regs[R_GHWPARAMS3] = 0x618c088;
+    s->regs[R_GHWPARAMS4] = 0x47822004;
+    s->regs[R_GHWPARAMS5] = 0x4202088;
+    s->regs[R_GHWPARAMS6] = 0x7850c20;
+    s->regs[R_GHWPARAMS7] = 0x0;
+    s->regs[R_GHWPARAMS8] = 0x478;
+}
+
+static void usb_dwc3_init(Object *obj)
+{
+    USBDWC3 *s = USB_DWC3(obj);
+    RegisterInfoArray *reg_array;
+
+    memory_region_init(&s->iomem, obj, TYPE_USB_DWC3, DWC3_SIZE);
+    reg_array =
+        register_init_block32(DEVICE(obj), usb_dwc3_regs_info,
+                              ARRAY_SIZE(usb_dwc3_regs_info),
+                              s->regs_info, s->regs,
+                              &usb_dwc3_ops,
+                              USB_DWC3_ERR_DEBUG,
+                              USB_DWC3_R_MAX * 4);
+    memory_region_add_subregion(&s->iomem,
+                                DWC3_GLOBAL_OFFSET,
+                                &reg_array->mem);
+    object_initialize_child(obj, "dwc3-xhci", &s->sysbus_xhci,
+                            TYPE_XHCI_SYSBUS);
+    qdev_alias_all_properties(DEVICE(&s->sysbus_xhci), obj);
+
+    s->cfg.mode = HOST_MODE;
+}
+
+static const VMStateDescription vmstate_usb_dwc3 = {
+    .name = "usb-dwc3",
+    .version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, USBDWC3, USB_DWC3_R_MAX),
+        VMSTATE_UINT8(cfg.mode, USBDWC3),
+        VMSTATE_UINT32(cfg.dwc_usb3_user, USBDWC3),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property usb_dwc3_properties[] = {
+    DEFINE_PROP_UINT32("DWC_USB3_USERID", USBDWC3, cfg.dwc_usb3_user,
+                       0x12345678),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_dwc3_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = usb_dwc3_reset;
+    dc->realize = usb_dwc3_realize;
+    dc->vmsd = &vmstate_usb_dwc3;
+    device_class_set_props(dc, usb_dwc3_properties);
+}
+
+static const TypeInfo usb_dwc3_info = {
+    .name          = TYPE_USB_DWC3,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(USBDWC3),
+    .class_init    = usb_dwc3_class_init,
+    .instance_init = usb_dwc3_init,
+};
+
+static void usb_dwc3_register_types(void)
+{
+    type_register_static(&usb_dwc3_info);
+}
+
+type_init(usb_dwc3_register_types)
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index 934e4fa675..f46c6b6655 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -26,10 +26,13 @@ softmmu_ss.add(when: 'CONFIG_USB_XHCI_SYSBUS', if_true: files('hcd-xhci-sysbus.c
 softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c'))
 softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c'))
 softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c'))
+softmmu_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c'))
 
 softmmu_ss.add(when: 'CONFIG_TUSB6010', if_true: files('tusb6010.c'))
 softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('chipidea.c'))
 softmmu_ss.add(when: 'CONFIG_IMX_USBPHY', if_true: files('imx-usb-phy.c'))
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2-ctrl-regs.c'))
+specific_ss.add(when: 'CONFIG_XLNX_USB_SUBSYS', if_true: files('xlnx-usb-subsystem.c'))
 
 # emulated usb devices
 softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hub.c'))
diff --git a/hw/usb/xlnx-usb-subsystem.c b/hw/usb/xlnx-usb-subsystem.c
new file mode 100644
index 0000000000..568257370c
--- /dev/null
+++ b/hw/usb/xlnx-usb-subsystem.c
@@ -0,0 +1,94 @@
+/*
+ * QEMU model of the Xilinx usb subsystem
+ *
+ * Copyright (c) 2020 Xilinx Inc. Sai Pavan Boddu <sai.pava.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/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/usb/xlnx-usb-subsystem.h"
+
+static void versal_usb2_realize(DeviceState *dev, Error **errp)
+{
+    VersalUsb2 *s = VERSAL_USB2(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *err = NULL;
+
+    sysbus_realize(SYS_BUS_DEVICE(&s->dwc3), &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_realize(SYS_BUS_DEVICE(&s->usb2Ctrl), &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_init_mmio(sbd, &s->dwc3_mr);
+    sysbus_init_mmio(sbd, &s->usb2Ctrl_mr);
+    qdev_pass_gpios(DEVICE(&s->dwc3.sysbus_xhci), dev, SYSBUS_DEVICE_GPIO_IRQ);
+}
+
+static void versal_usb2_init(Object *obj)
+{
+    VersalUsb2 *s = VERSAL_USB2(obj);
+
+    object_initialize_child(obj, "versal.dwc3", &s->dwc3,
+                            TYPE_USB_DWC3);
+    object_initialize_child(obj, "versal.usb2-ctrl", &s->usb2Ctrl,
+                            TYPE_XILINX_VERSAL_USB2_CTRL_REGS);
+    memory_region_init_alias(&s->dwc3_mr, obj, "versal.dwc3_alias",
+                             &s->dwc3.iomem, 0, DWC3_SIZE);
+    memory_region_init_alias(&s->usb2Ctrl_mr, obj, "versal.usb2Ctrl_alias",
+                             &s->usb2Ctrl.iomem, 0, USB2_REGS_R_MAX * 4);
+    qdev_alias_all_properties(DEVICE(&s->dwc3), obj);
+    qdev_alias_all_properties(DEVICE(&s->dwc3.sysbus_xhci), obj);
+    object_property_add_alias(obj, "dma", OBJECT(&s->dwc3.sysbus_xhci), "dma");
+}
+
+static void versal_usb2_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = versal_usb2_realize;
+}
+
+static const TypeInfo versal_usb2_info = {
+    .name          = TYPE_XILINX_VERSAL_USB2,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VersalUsb2),
+    .class_init    = versal_usb2_class_init,
+    .instance_init = versal_usb2_init,
+};
+
+static void versal_usb_types(void)
+{
+    type_register_static(&versal_usb2_info);
+}
+
+type_init(versal_usb_types)
diff --git a/hw/usb/xlnx-versal-usb2-ctrl-regs.c b/hw/usb/xlnx-versal-usb2-ctrl-regs.c
new file mode 100644
index 0000000000..9eaa59ebb8
--- /dev/null
+++ b/hw/usb/xlnx-versal-usb2-ctrl-regs.c
@@ -0,0 +1,229 @@
+/*
+ * QEMU model of the VersalUsb2CtrlRegs Register control/Status block for
+ * USB2.0 controller
+ *
+ * This module should control phy_reset, permanent device plugs, frame length
+ * time adjust & setting of coherency paths. None of which are emulated in
+ * present model.
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@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/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
+#include "hw/usb/xlnx-versal-usb2-ctrl-regs.h"
+
+#ifndef XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG
+#define XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG 0
+#endif
+
+REG32(BUS_FILTER, 0x30)
+    FIELD(BUS_FILTER, BYPASS, 0, 4)
+REG32(PORT, 0x34)
+    FIELD(PORT, HOST_SMI_BAR_WR, 4, 1)
+    FIELD(PORT, HOST_SMI_PCI_CMD_REG_WR, 3, 1)
+    FIELD(PORT, HOST_MSI_ENABLE, 2, 1)
+    FIELD(PORT, PWR_CTRL_PRSNT, 1, 1)
+    FIELD(PORT, HUB_PERM_ATTACH, 0, 1)
+REG32(JITTER_ADJUST, 0x38)
+    FIELD(JITTER_ADJUST, FLADJ, 0, 6)
+REG32(BIGENDIAN, 0x40)
+    FIELD(BIGENDIAN, ENDIAN_GS, 0, 1)
+REG32(COHERENCY, 0x44)
+    FIELD(COHERENCY, USB_COHERENCY, 0, 1)
+REG32(XHC_BME, 0x48)
+    FIELD(XHC_BME, XHC_BME, 0, 1)
+REG32(REG_CTRL, 0x60)
+    FIELD(REG_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x64)
+    FIELD(IR_STATUS, HOST_SYS_ERR, 1, 1)
+    FIELD(IR_STATUS, ADDR_DEC_ERR, 0, 1)
+REG32(IR_MASK, 0x68)
+    FIELD(IR_MASK, HOST_SYS_ERR, 1, 1)
+    FIELD(IR_MASK, ADDR_DEC_ERR, 0, 1)
+REG32(IR_ENABLE, 0x6c)
+    FIELD(IR_ENABLE, HOST_SYS_ERR, 1, 1)
+    FIELD(IR_ENABLE, ADDR_DEC_ERR, 0, 1)
+REG32(IR_DISABLE, 0x70)
+    FIELD(IR_DISABLE, HOST_SYS_ERR, 1, 1)
+    FIELD(IR_DISABLE, ADDR_DEC_ERR, 0, 1)
+REG32(USB3, 0x78)
+
+static void ir_update_irq(VersalUsb2CtrlRegs *s)
+{
+    bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
+    qemu_set_irq(s->irq_ir, pending);
+}
+
+static void ir_status_postw(RegisterInfo *reg, uint64_t val64)
+{
+    VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
+    /*
+     * TODO: This should also clear USBSTS.HSE field in USB XHCI register.
+     * May be combine both the modules.
+     */
+    ir_update_irq(s);
+}
+
+static uint64_t ir_enable_prew(RegisterInfo *reg, uint64_t val64)
+{
+    VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
+    uint32_t val = val64;
+
+    s->regs[R_IR_MASK] &= ~val;
+    ir_update_irq(s);
+    return 0;
+}
+
+static uint64_t ir_disable_prew(RegisterInfo *reg, uint64_t val64)
+{
+    VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
+    uint32_t val = val64;
+
+    s->regs[R_IR_MASK] |= val;
+    ir_update_irq(s);
+    return 0;
+}
+
+static const RegisterAccessInfo usb2_ctrl_regs_regs_info[] = {
+    {   .name = "BUS_FILTER",  .addr = A_BUS_FILTER,
+        .rsvd = 0xfffffff0,
+    },{ .name = "PORT",  .addr = A_PORT,
+        .rsvd = 0xffffffe0,
+    },{ .name = "JITTER_ADJUST",  .addr = A_JITTER_ADJUST,
+        .reset = 0x20,
+        .rsvd = 0xffffffc0,
+    },{ .name = "BIGENDIAN",  .addr = A_BIGENDIAN,
+        .rsvd = 0xfffffffe,
+    },{ .name = "COHERENCY",  .addr = A_COHERENCY,
+        .rsvd = 0xfffffffe,
+    },{ .name = "XHC_BME",  .addr = A_XHC_BME,
+        .reset = 0x1,
+        .rsvd = 0xfffffffe,
+    },{ .name = "REG_CTRL",  .addr = A_REG_CTRL,
+        .rsvd = 0xfffffffe,
+    },{ .name = "IR_STATUS",  .addr = A_IR_STATUS,
+        .rsvd = 0xfffffffc,
+        .w1c = 0x3,
+        .post_write = ir_status_postw,
+    },{ .name = "IR_MASK",  .addr = A_IR_MASK,
+        .reset = 0x3,
+        .rsvd = 0xfffffffc,
+        .ro = 0x3,
+    },{ .name = "IR_ENABLE",  .addr = A_IR_ENABLE,
+        .rsvd = 0xfffffffc,
+        .pre_write = ir_enable_prew,
+    },{ .name = "IR_DISABLE",  .addr = A_IR_DISABLE,
+        .rsvd = 0xfffffffc,
+        .pre_write = ir_disable_prew,
+    },{ .name = "USB3",  .addr = A_USB3,
+    }
+};
+
+static void usb2_ctrl_regs_reset_init(Object *obj, ResetType type)
+{
+    VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+        register_reset(&s->regs_info[i]);
+    }
+}
+
+static void usb2_ctrl_regs_reset_hold(Object *obj)
+{
+    VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
+
+    ir_update_irq(s);
+}
+
+static const MemoryRegionOps usb2_ctrl_regs_ops = {
+    .read = register_read_memory,
+    .write = register_write_memory,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void usb2_ctrl_regs_init(Object *obj)
+{
+    VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RegisterInfoArray *reg_array;
+
+    memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
+                       USB2_REGS_R_MAX * 4);
+    reg_array =
+        register_init_block32(DEVICE(obj), usb2_ctrl_regs_regs_info,
+                              ARRAY_SIZE(usb2_ctrl_regs_regs_info),
+                              s->regs_info, s->regs,
+                              &usb2_ctrl_regs_ops,
+                              XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG,
+                              USB2_REGS_R_MAX * 4);
+    memory_region_add_subregion(&s->iomem,
+                                0x0,
+                                &reg_array->mem);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq_ir);
+}
+
+static const VMStateDescription vmstate_usb2_ctrl_regs = {
+    .name = TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, VersalUsb2CtrlRegs, USB2_REGS_R_MAX),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void usb2_ctrl_regs_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.enter = usb2_ctrl_regs_reset_init;
+    rc->phases.hold  = usb2_ctrl_regs_reset_hold;
+    dc->vmsd = &vmstate_usb2_ctrl_regs;
+}
+
+static const TypeInfo usb2_ctrl_regs_info = {
+    .name          = TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VersalUsb2CtrlRegs),
+    .class_init    = usb2_ctrl_regs_class_init,
+    .instance_init = usb2_ctrl_regs_init,
+};
+
+static void usb2_ctrl_regs_register_types(void)
+{
+    type_register_static(&usb2_ctrl_regs_info);
+}
+
+type_init(usb2_ctrl_regs_register_types)
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 8ce8e63b56..2b76885afd 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -21,6 +21,7 @@
 #include "hw/net/cadence_gem.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
+#include "hw/usb/xlnx-usb-subsystem.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -59,6 +60,7 @@ struct Versal {
             PL011State uart[XLNX_VERSAL_NR_UARTS];
             CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
             XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
+            VersalUsb2 usb;
         } iou;
     } lpd;
 
@@ -88,6 +90,7 @@ struct Versal {
 
 #define VERSAL_UART0_IRQ_0         18
 #define VERSAL_UART1_IRQ_0         19
+#define VERSAL_USB0_IRQ_0          22
 #define VERSAL_GEM0_IRQ_0          56
 #define VERSAL_GEM0_WAKE_IRQ_0     57
 #define VERSAL_GEM1_IRQ_0          58
@@ -125,6 +128,12 @@ struct Versal {
 #define MM_OCM                      0xfffc0000U
 #define MM_OCM_SIZE                 0x40000
 
+#define MM_USB2_CTRL_REGS           0xFF9D0000
+#define MM_USB2_CTRL_REGS_SIZE      0x10000
+
+#define MM_USB_0                    0xFE200000
+#define MM_USB_0_SIZE               0x10000
+
 #define MM_TOP_DDR                  0x0
 #define MM_TOP_DDR_SIZE             0x80000000U
 #define MM_TOP_DDR_2                0x800000000ULL
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 6fdff3dced..8e8436831d 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -330,7 +330,6 @@ static int glue(load_elf, SZ)(const char *name, int fd,
     uint64_t addr, low = (uint64_t)-1, high = 0;
     GMappedFile *mapped_file = NULL;
     uint8_t *data = NULL;
-    char label[128];
     int ret = ELF_LOAD_FAILED;
 
     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
@@ -544,7 +543,9 @@ static int glue(load_elf, SZ)(const char *name, int fd,
              */
             if (mem_size != 0) {
                 if (load_rom) {
-                    snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
+                    g_autofree char *label =
+                        g_strdup_printf("%s ELF program header segment %d",
+                                        name, i);
 
                     /*
                      * rom_add_elf_program() takes its own reference to
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
new file mode 100644
index 0000000000..7c804d536d
--- /dev/null
+++ b/include/hw/usb/hcd-dwc3.h
@@ -0,0 +1,55 @@
+/*
+ * QEMU model of the USB DWC3 host controller emulation.
+ *
+ * Copyright (c) 2020 Xilinx Inc.
+ *
+ * Written by Vikram Garhwal<fnu.vikram@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.
+ */
+#ifndef HCD_DWC3_H
+#define HCD_DWC3_H
+
+#include "hw/usb/hcd-xhci.h"
+#include "hw/usb/hcd-xhci-sysbus.h"
+
+#define TYPE_USB_DWC3 "usb_dwc3"
+
+#define USB_DWC3(obj) \
+     OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
+
+#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
+#define DWC3_SIZE 0x10000
+
+typedef struct USBDWC3 {
+    SysBusDevice parent_obj;
+    MemoryRegion iomem;
+    XHCISysbusState sysbus_xhci;
+
+    uint32_t regs[USB_DWC3_R_MAX];
+    RegisterInfo regs_info[USB_DWC3_R_MAX];
+
+    struct {
+        uint8_t     mode;
+        uint32_t    dwc_usb3_user;
+    } cfg;
+
+} USBDWC3;
+
+#endif
diff --git a/include/hw/usb/xlnx-usb-subsystem.h b/include/hw/usb/xlnx-usb-subsystem.h
new file mode 100644
index 0000000000..739bef7f45
--- /dev/null
+++ b/include/hw/usb/xlnx-usb-subsystem.h
@@ -0,0 +1,45 @@
+/*
+ * QEMU model of the Xilinx usb subsystem
+ *
+ * Copyright (c) 2020 Xilinx Inc. 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.
+ */
+
+#ifndef _XLNX_VERSAL_USB_SUBSYSTEM_H_
+#define _XLNX_VERSAL_USB_SUBSYSTEM_H_
+
+#include "hw/usb/xlnx-versal-usb2-ctrl-regs.h"
+#include "hw/usb/hcd-dwc3.h"
+
+#define TYPE_XILINX_VERSAL_USB2 "xlnx.versal-usb2"
+
+#define VERSAL_USB2(obj) \
+     OBJECT_CHECK(VersalUsb2, (obj), TYPE_XILINX_VERSAL_USB2)
+
+typedef struct VersalUsb2 {
+    SysBusDevice parent_obj;
+    MemoryRegion dwc3_mr;
+    MemoryRegion usb2Ctrl_mr;
+
+    VersalUsb2CtrlRegs usb2Ctrl;
+    USBDWC3 dwc3;
+} VersalUsb2;
+
+#endif
diff --git a/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h b/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h
new file mode 100644
index 0000000000..975a717627
--- /dev/null
+++ b/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h
@@ -0,0 +1,45 @@
+/*
+ * QEMU model of the VersalUsb2CtrlRegs Register control/Status block for
+ * USB2.0 controller
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@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.
+ */
+
+#ifndef _XLNX_USB2_REGS_H_
+#define _XLNX_USB2_REGS_H_
+
+#define TYPE_XILINX_VERSAL_USB2_CTRL_REGS "xlnx.versal-usb2-ctrl-regs"
+
+#define XILINX_VERSAL_USB2_CTRL_REGS(obj) \
+     OBJECT_CHECK(VersalUsb2CtrlRegs, (obj), TYPE_XILINX_VERSAL_USB2_CTRL_REGS)
+
+#define USB2_REGS_R_MAX ((0x78 / 4) + 1)
+
+typedef struct VersalUsb2CtrlRegs {
+    SysBusDevice parent_obj;
+    MemoryRegion iomem;
+    qemu_irq irq_ir;
+
+    uint32_t regs[USB2_REGS_R_MAX];
+    RegisterInfo regs_info[USB2_REGS_R_MAX];
+} VersalUsb2CtrlRegs;
+
+#endif
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 7146fbe219..cbf3896ce6 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3278,7 +3278,6 @@ static void qemu_machine_creation_done(void)
     qemu_run_machine_init_done_notifiers();
 
     if (rom_check_and_register_reset() != 0) {
-        error_report("rom check and register reset failed");
         exit(1);
     }
 
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index 8f7011fcb9..58688e1623 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -64,6 +64,26 @@ static void nios2_cpu_reset(DeviceState *dev)
 #endif
 }
 
+#ifndef CONFIG_USER_ONLY
+static void nios2_cpu_set_irq(void *opaque, int irq, int level)
+{
+    Nios2CPU *cpu = opaque;
+    CPUNios2State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+
+    env->regs[CR_IPENDING] = deposit32(env->regs[CR_IPENDING], irq, 1, !!level);
+
+    env->irq_pending = env->regs[CR_IPENDING] & env->regs[CR_IENABLE];
+
+    if (env->irq_pending && (env->regs[CR_STATUS] & CR_STATUS_PIE)) {
+        env->irq_pending = 0;
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+    } else if (!env->irq_pending) {
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+    }
+}
+#endif
+
 static void nios2_cpu_initfn(Object *obj)
 {
     Nios2CPU *cpu = NIOS2_CPU(obj);
@@ -72,6 +92,15 @@ static void nios2_cpu_initfn(Object *obj)
 
 #if !defined(CONFIG_USER_ONLY)
     mmu_init(&cpu->env);
+
+    /*
+     * These interrupt lines model the IIC (internal interrupt
+     * controller). QEMU does not currently support the EIC
+     * (external interrupt controller) -- if we did it would be
+     * a separate device in hw/intc with a custom interface to
+     * the CPU, and boards using it would not wire up these IRQ lines.
+     */
+    qdev_init_gpio_in_named(DEVICE(cpu), nios2_cpu_set_irq, "IRQ", 32);
 #endif
 }
 
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 86bbe1d867..2ab82fdc71 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -201,9 +201,6 @@ void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
                                    MMUAccessType access_type,
                                    int mmu_idx, uintptr_t retaddr);
 
-qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu);
-void nios2_check_interrupts(CPUNios2State *env);
-
 void do_nios2_semihosting(CPUNios2State *env);
 
 #define CPU_RESOLVING_TYPE TYPE_NIOS2_CPU
diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c
index a60730faac..a59003855a 100644
--- a/target/nios2/op_helper.c
+++ b/target/nios2/op_helper.c
@@ -36,6 +36,15 @@ void helper_mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v)
     mmu_write(env, rn, v);
 }
 
+static void nios2_check_interrupts(CPUNios2State *env)
+{
+    if (env->irq_pending &&
+        (env->regs[CR_STATUS] & CR_STATUS_PIE)) {
+        env->irq_pending = 0;
+        cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HARD);
+    }
+}
+
 void helper_check_interrupts(CPUNios2State *env)
 {
     qemu_mutex_lock_iothread();
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 5528c0918f..b0bdfbe4fe 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -65,6 +65,34 @@ static void openrisc_cpu_reset(DeviceState *dev)
 #endif
 }
 
+#ifndef CONFIG_USER_ONLY
+static void openrisc_cpu_set_irq(void *opaque, int irq, int level)
+{
+    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
+    CPUState *cs = CPU(cpu);
+    uint32_t irq_bit;
+
+    if (irq > 31 || irq < 0) {
+        return;
+    }
+
+    irq_bit = 1U << irq;
+
+    if (level) {
+        cpu->env.picsr |= irq_bit;
+    } else {
+        cpu->env.picsr &= ~irq_bit;
+    }
+
+    if (cpu->env.picsr & cpu->env.picmr) {
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        cpu->env.picsr = 0;
+    }
+}
+#endif
+
 static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -88,6 +116,10 @@ static void openrisc_cpu_initfn(Object *obj)
     OpenRISCCPU *cpu = OPENRISC_CPU(obj);
 
     cpu_set_cpustate_pointers(cpu);
+
+#ifndef CONFIG_USER_ONLY
+    qdev_init_gpio_in_named(DEVICE(cpu), openrisc_cpu_set_irq, "IRQ", NR_IRQS);
+#endif
 }
 
 /* CPU models */
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index bd42faf144..82cbaeb4f8 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -293,7 +293,6 @@ typedef struct CPUOpenRISCState {
     uint32_t picmr;         /* Interrupt mask register */
     uint32_t picsr;         /* Interrupt contrl register*/
 #endif
-    void *irq[32];          /* Interrupt irq input */
 } CPUOpenRISCState;
 
 /**