Add QOM class definition helpers for sysbus attached EHCI implementations and added Xilinx Zynq USB implementation.
Signed-off-by: Peter Crosthwaite <peter.crosthwa...@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(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index df224b2..7948146 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -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); -- 1.7.0.4