From: Kuo-Jung Su <dant...@faraday-tech.com> Faraday FUSBH200 is a one-port host controller for USB 2.0, which is fully compliant with the USB 2.0 specification and the Enhanced Host Controller Interface (EHCI) specification. This host controller supports the HS/FS/LS transactions, Isochronous/Interrupt/Control/Bulk transfers, and split/preamble transaction for the hub. Without intervening by the software, this host controller can deal with the transaction-based data structure to offload the CPU and automatically transmit and receive the data on the USB bus.
The native system bus of FUSBH200 is a PVCI 32-bit bus interface. However, by using the wrappers, FUSBH200 can also support the AMBA AHB 32-bit bus or RISC 8051 bus. The transceiver interface is UTMI+ level 3, which supports the HS/FS/LS device and HS/FS hub. Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com> --- .gitignore | 1 + hw/usb/hcd-ehci-sysbus.c | 23 +++++++++++++++++++++ hw/usb/hcd-ehci.c | 51 ++++++++++++++++++++++++++++++++++++++-------- hw/usb/hcd-ehci.h | 14 +++++++------ 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 53fe9c3..0fd6a51 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ fsdev/virtfs-proxy-helper.pod .gdbinit *.a *.aux +*.bak *.cp *.dvi *.exe diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index b68a66a..b1147f3 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -40,6 +40,8 @@ static int usb_ehci_sysbus_initfn(SysBusDevice *dev) s->capsbase = sec->capsbase; s->opregbase = sec->opregbase; + s->portscbase = sec->portscbase; + s->portnr = sec->portnr; s->dma = &dma_context_memory; usb_ehci_initfn(s, DEVICE(dev)); @@ -73,6 +75,8 @@ static void ehci_xlnx_class_init(ObjectClass *oc, void *data) sec->capsbase = 0x100; sec->opregbase = 0x140; + sec->portscbase = 0x44; + sec->portnr = NB_PORTS; } static const TypeInfo ehci_xlnx_type_info = { @@ -87,6 +91,8 @@ static void ehci_exynos4210_class_init(ObjectClass *oc, void *data) sec->capsbase = 0x0; sec->opregbase = 0x10; + sec->portscbase = 0x44; + sec->portnr = NB_PORTS; } static const TypeInfo ehci_exynos4210_type_info = { @@ -95,11 +101,28 @@ static const TypeInfo ehci_exynos4210_type_info = { .class_init = ehci_exynos4210_class_init, }; +static void ehci_faraday_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); + + sec->capsbase = 0x00; + sec->opregbase = 0x10; + sec->portscbase = 0x20; + sec->portnr = 1; +} + +static const TypeInfo ehci_faraday_type_info = { + .name = TYPE_FARADAY_EHCI, + .parent = TYPE_SYS_BUS_EHCI, + .class_init = ehci_faraday_class_init, +}; + static void ehci_sysbus_register_types(void) { type_register_static(&ehci_type_info); type_register_static(&ehci_xlnx_type_info); type_register_static(&ehci_exynos4210_type_info); + type_register_static(&ehci_faraday_type_info); } type_init(ehci_sysbus_register_types) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 7040659..6e42086 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -10,7 +10,8 @@ * * EHCI project was started by Mark Burkley, with contributions by * Niels de Vos. David S. Ahern continued working on it. Kevin Wolf, - * Jan Kiszka and Vincent Palatin contributed bugfixes. + * Jan Kiszka and Vincent Palatin contributed bugfixes. Kuo-Jung Su + * contributed Faraday extension. * * * This library is free software; you can redistribute it and/or @@ -988,7 +989,7 @@ static uint64_t ehci_port_read(void *ptr, hwaddr addr, uint32_t val; val = s->portsc[addr >> 2]; - trace_usb_ehci_portsc_read(addr + PORTSC_BEGIN, addr >> 2, val); + trace_usb_ehci_portsc_read(addr + s->portscbase, addr >> 2, val); return val; } @@ -1029,7 +1030,7 @@ static void ehci_port_write(void *ptr, hwaddr addr, uint32_t old = *portsc; USBDevice *dev = s->ports[port].dev; - trace_usb_ehci_portsc_write(addr + PORTSC_BEGIN, addr >> 2, val); + trace_usb_ehci_portsc_write(addr + s->portscbase, addr >> 2, val); /* Clear rwc bits */ *portsc &= ~(val & PORTSC_RWC_MASK); @@ -1062,7 +1063,7 @@ static void ehci_port_write(void *ptr, hwaddr addr, *portsc &= ~PORTSC_RO_MASK; *portsc |= val; - trace_usb_ehci_portsc_change(addr + PORTSC_BEGIN, addr >> 2, *portsc, old); + trace_usb_ehci_portsc_change(addr + s->portscbase, addr >> 2, *portsc, old); } static void ehci_opreg_write(void *ptr, hwaddr addr, @@ -2501,6 +2502,35 @@ const VMStateDescription vmstate_ehci = { } }; +static uint64_t +ehci_faraday_read(void *ptr, hwaddr addr, unsigned size) +{ + hwaddr off = 0x34 + addr; + + switch (off) { + case 0x34: /* fusbh200: EOF/Async. Sleep Timer Register */ + return 0x00000041; + case 0x40: /* fusbh200: Bus Monitor Control/Status Register */ + /* High-Speed, VBUS valid, interrupt level-high active */ + return (2 << 9) | (1 << 8) | (1 << 3); + } + + return 0; +} + +static void +ehci_faraday_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) +{ +} + +static const MemoryRegionOps ehci_mmio_faraday_ops = { + .read = ehci_faraday_read, + .write = ehci_faraday_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + void usb_ehci_initfn(EHCIState *s, DeviceState *dev) { int i; @@ -2510,7 +2540,7 @@ void usb_ehci_initfn(EHCIState *s, DeviceState *dev) s->caps[0x01] = 0x00; s->caps[0x02] = 0x00; s->caps[0x03] = 0x01; /* HC version */ - s->caps[0x04] = NB_PORTS; /* Number of downstream ports */ + s->caps[0x04] = s->portnr; /* Number of downstream ports */ s->caps[0x05] = 0x00; /* No companion ports at present */ s->caps[0x06] = 0x00; s->caps[0x07] = 0x00; @@ -2538,14 +2568,19 @@ void usb_ehci_initfn(EHCIState *s, DeviceState *dev) memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s, "capabilities", CAPA_SIZE); memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s, - "operational", PORTSC_BEGIN); + "operational", s->portscbase); memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s, - "ports", PORTSC_END - PORTSC_BEGIN); + "ports", 4 * s->portnr); + memory_region_init_io(&s->mem_faraday, &ehci_mmio_faraday_ops, s, + "faraday", 0x4c); memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps); memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg); - memory_region_add_subregion(&s->mem, s->opregbase + PORTSC_BEGIN, + memory_region_add_subregion(&s->mem, s->opregbase + s->portscbase, &s->mem_ports); + memory_region_add_subregion(&s->mem, + s->opregbase + s->portscbase + 4 * s->portnr, + &s->mem_faraday); } /* diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index e95bb7e..2849e81 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -40,11 +40,7 @@ #define MMIO_SIZE 0x1000 #define CAPA_SIZE 0x10 -#define PORTSC 0x0044 -#define PORTSC_BEGIN PORTSC -#define PORTSC_END (PORTSC + 4 * NB_PORTS) - -#define NB_PORTS 6 /* Number of downstream ports */ +#define NB_PORTS 6 /* Max. number of downstream ports */ typedef struct EHCIPacket EHCIPacket; typedef struct EHCIQueue EHCIQueue; @@ -265,9 +261,12 @@ struct EHCIState { MemoryRegion mem_caps; MemoryRegion mem_opreg; MemoryRegion mem_ports; + MemoryRegion mem_faraday; int companion_count; uint16_t capsbase; uint16_t opregbase; + uint16_t portscbase; + uint16_t portnr; /* properties */ uint32_t maxframes; @@ -278,7 +277,7 @@ struct EHCIState { */ uint8_t caps[CAPA_SIZE]; union { - uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)]; + uint32_t opreg[0x44/sizeof(uint32_t)]; struct { uint32_t usbcmd; uint32_t usbsts; @@ -338,6 +337,7 @@ typedef struct EHCIPCIState { #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb" +#define TYPE_FARADAY_EHCI "faraday-ehci-usb" #define SYS_BUS_EHCI(obj) \ OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI) @@ -361,6 +361,8 @@ typedef struct SysBusEHCIClass { uint16_t capsbase; uint16_t opregbase; + uint16_t portscbase; + uint16_t portnr; } SysBusEHCIClass; #endif -- 1.7.9.5