target-arm queue:

* gdbstub: Correct misparsing of vCont C/S requests
  * openrisc: Move pic_cpu code into CPU object proper
  * nios2: Move IIC code into CPU object proper
  * Improve reporting of ROM overlap errors
  * xlnx-versal: Add USB support
  * hw/misc/zynq_slcr: Avoid #DIV/0! error
  * Numonyx: Fix dummy cycles and check for SPI mode on cmds
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl/YwVIZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3lOpD/9FjasMvZqYeanyNlv+4Swk
 4MFeYouIzXKSFu9tj5eDTHzN1TJl5iSwhkIcr9NBqxppuv2eqzxfWWMEfCZ06pxz
 BR2HoSlSLUih8cKpu40cQg0TTMEOGEOV9RAHtt8vSGE0FesoiXG2ORUPcxm3NxbN
 l9XZ1x3Yb5ZLqVZViFjlZ5gXnTzJ//uPEzbl7N9+pa0mXDKvmvwAl19DLmF6N2Jj
 D+gmrLGeEbkJ358RGO/VF7r/1bOkrhwKrb8MzeqFRmjIqaOGbGqs/71+amiSjS8n
 hC1HKf6KQOLrklMVaYg1pRxHLbHpQR+haeeX4Xt9jxx8EUrwXojlyaD8p4V9Hcu8
 L5haTIBhPrnTkUfHZYL0qYkqRpzbNq97oX2Gmk967FfsZME5fxNa3kS6zM0GkIBx
 YKghaZtFInAFODUbG1hHdUc+WbvfQDhj/mBQ6wWw669vYpoab/3nfVq8YVoupVM/
 RntcqpBfqtGgPzuJ2dJEEsm6QlK4SZaGlmPkz542OzcHxw3SgeqkbIuDW/CtNI+b
 c5PgX0C2S2AnFAAHURnsXdqt6+O01FZqOU7SCLjmwrBrpDG69lum+JLCqXFe9iMW
 XgrTrxyPIcz5+Bv63AqKcm6rpcQs5ekwmLLEjT0OJtr+5ef9MeRil0aChj1j4i+2
 H/82yKR4JWW1egEvTJhskQ==
 =lHZA
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20201215' into staging

target-arm queue:
 * gdbstub: Correct misparsing of vCont C/S requests
 * openrisc: Move pic_cpu code into CPU object proper
 * nios2: Move IIC code into CPU object proper
 * Improve reporting of ROM overlap errors
 * xlnx-versal: Add USB support
 * hw/misc/zynq_slcr: Avoid #DIV/0! error
 * Numonyx: Fix dummy cycles and check for SPI mode on cmds

# gpg: Signature made Tue 15 Dec 2020 13:59:46 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20201215:
  hw/block/m25p80: Fix Numonyx fast read dummy cycle count
  hw/block/m25p80: Check SPI mode before running some Numonyx commands
  hw/block/m25p80: Fix when VCFG XIP bit is set for Numonyx
  hw/block/m25p80: Make Numonyx config field names more accurate
  hw/misc/zynq_slcr: Avoid #DIV/0! error
  arm: xlnx-versal: Connect usb to virt-versal
  usb: xlnx-usb-subsystem: Add xilinx usb subsystem
  usb: Add DWC3 model
  usb: Add versal-usb2-ctrl-regs module
  elf_ops.h: Be more verbose with ROM blob names
  elf_ops.h: Don't truncate name of the ROM blobs we create
  hw/core/loader.c: Improve reporting of ROM overlap errors
  hw/core/loader.c: Track last-seen ROM in rom_check_and_register_reset()
  target/nios2: Use deposit32() to update ipending register
  target/nios2: Move nios2_check_interrupts() into target/nios2
  target/nios2: Move IIC code into CPU object proper
  target/openrisc: Move pic_cpu code into CPU object proper
  hw/openrisc/openrisc_sim: Abstract out "get IRQ x of CPU y"
  hw/openrisc/openrisc_sim: Use IRQ splitter when connecting IRQ to multiple CPUs
  gdbstub: Correct misparsing of vCont C/S requests

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-12-15 16:58:27 +00:00
commit 657ee88ef3
32 changed files with 1557 additions and 304 deletions

View File

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

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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:
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:
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:
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,6 +1130,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
break;
case JEDEC_READ:
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];
@ -1046,6 +1142,10 @@ static void decode_new_cmd(Flash *s, uint32_t value)
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:

View File

@ -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();
}
addr = rom->addr;
addr += rom->romsize;
as = rom->as;
rom_print_one_overlap_error(last_rom, rom);
/* Keep going through the list so we report all overlaps */
}
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;

View File

@ -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'))

View File

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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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'))

View File

@ -3,3 +3,4 @@ config OR1K_SIM
select SERIAL
select OPENCORES_ETH
select OMPIC
select SPLIT_IRQ

View File

@ -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}

View File

@ -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);
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++) {
sysbus_connect_irq(s, 0, cpu_irqs[i][irq_pin]);
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,

View File

@ -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];
}
}

View File

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

689
hw/usb/hcd-dwc3.c Normal file
View File

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

View File

@ -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'))

View File

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

View File

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

View File

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

View File

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

55
include/hw/usb/hcd-dwc3.h Normal file
View File

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

View File

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

View File

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

View File

@ -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);
}

View File

@ -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
}

View File

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

View File

@ -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();

View File

@ -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 */

View File

@ -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;
/**