@@ -35,6 +35,8 @@
#include "trace.h"
#include "dma.h"
#include "sysemu.h"
+#include "hw/sysbus.h"
+#include "exec-memory.h"
#define EHCI_DEBUG 0
@@ -450,6 +452,11 @@ typedef struct EHCIPCIState {
EHCIState ehci;
} EHCIPCIState;
+typedef struct EHCISysBusState {
+ SysBusDevice busdev;
+ EHCIState ehci;
+} EHCISysBusState;
+
#define SET_LAST_RUN_CLOCK(s) \
(s)->last_run_ns = qemu_get_clock_ns(vm_clock);
@@ -2544,6 +2551,7 @@ static const MemoryRegionOps ehci_mmio_port_ops = {
};
static int usb_ehci_pci_initfn(PCIDevice *dev);
+static int usb_ehci_sysbus_initfn(SysBusDevice *dev);
static USBPortOps ehci_port_ops = {
.attach = ehci_attach,
@@ -2650,11 +2658,26 @@ static const VMStateDescription vmstate_ehci_pci = {
}
};
+static const VMStateDescription vmstate_ehci_sysbus = {
+ .name = "ehci-sysbus",
+ .version_id = 2,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static Property ehci_pci_properties[] = {
DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128),
DEFINE_PROP_END_OF_LIST(),
};
+static Property ehci_sysbus_properties[] = {
+ DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
typedef struct EHCIInfo {
uint16_t capabase;
uint16_t opregbase;
@@ -2665,6 +2688,11 @@ typedef struct EHCIPCIClass {
EHCIInfo ehci;
} EHCIPCIClass;
+typedef struct EHCISysBusClass {
+ SysBusDeviceClass sdc;
+ EHCIInfo ehci;
+} EHCISysBusClass;
+
static void ehci_pci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -2681,6 +2709,18 @@ static void ehci_pci_class_init(ObjectClass *klass, void *data)
dc->props = ehci_pci_properties;
}
+static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ EHCISysBusClass *k = (EHCISysBusClass *)klass;
+ EHCISysBusClass *template = data;
+
+ k->sdc.init = usb_ehci_sysbus_initfn;
+ k->ehci = template->ehci;
+ dc->vmsd = &vmstate_ehci_sysbus;
+ dc->props = ehci_sysbus_properties;
+}
+
static TypeInfo ehci_info[] = {
{
.name = "usb-ehci",
@@ -2708,6 +2748,16 @@ static TypeInfo ehci_info[] = {
.ehci.capabase = 0x0,
.ehci.opregbase = 0x20,
} }
+ }, {
+ .name = "xlnx,ps7-usb",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(EHCISysBusState),
+ .class_init = ehci_sysbus_class_init,
+ .class_size = sizeof(EHCISysBusClass),
+ .class_data = (EHCISysBusClass[]) {{
+ .ehci.capabase = 0x100,
+ .ehci.opregbase = 0x140,
+ } }
},
};
@@ -2761,6 +2811,21 @@ static void usb_ehci_initfn(EHCIState *s, DeviceState *dev, EHCIInfo *ei)
&s->mem_ports);
}
+static int usb_ehci_sysbus_initfn(SysBusDevice *dev)
+{
+ EHCISysBusState *i = FROM_SYSBUS(EHCISysBusState, dev);
+ EHCISysBusClass *c = (EHCISysBusClass *)object_get_class(OBJECT(dev));
+ EHCIState *s = &i->ehci;
+
+ s->dma = &dma_context_memory;
+
+ usb_ehci_initfn(s, DEVICE(dev), &c->ehci);
+ sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(dev, &s->mem);
+
+ return 0;
+}
+
static int usb_ehci_pci_initfn(PCIDevice *dev)
{
EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev);
Add QOM class definition helpers for sysbus attached EHCI implementations and added Xilinx Zynq USB implementation. Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> --- changed from v2: Squashed Xilinx zynq Defintion into this patch. Otherwise complie fails due to werror and unsued ehci_sysbus_class_init fn. Duplicated state struct (as EHCISysBusState) - no more union. changed from v1: Dont create a QOM definition for Sysbus EHCI, rather just add all the bits and pieces. (Multiple) sysbus EHCI defs can be created by adding to the type_info[] table. Use dma_context_memory for sysbus DMA (PMM review) hw/usb/hcd-ehci.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 65 insertions(+), 0 deletions(-)