usb/hcd-ehci: Add Faraday FUSBH200 support

Add Faraday FUSBH200 support, which is slightly different from EHCI spec.
(Or maybe simply a bad/wrong implementation...)

Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Kuo-Jung Su 2013-06-06 15:41:13 +02:00 committed by Gerd Hoffmann
parent cc8d6a8481
commit 4e3d8b4b37
2 changed files with 87 additions and 0 deletions

View File

@ -124,12 +124,87 @@ static const TypeInfo ehci_tegra2_type_info = {
.class_init = ehci_tegra2_class_init,
};
/*
* Faraday FUSBH200 USB 2.0 EHCI
*/
/**
* FUSBH200EHCIRegs:
* @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register
* @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register
*/
enum FUSBH200EHCIRegs {
FUSBH200_REG_EOF_ASTR = 0x34,
FUSBH200_REG_BMCSR = 0x40,
};
static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size)
{
EHCIState *s = opaque;
hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr;
switch (off) {
case FUSBH200_REG_EOF_ASTR:
return 0x00000041;
case FUSBH200_REG_BMCSR:
/* High-Speed, VBUS valid, interrupt level-high active */
return (2 << 9) | (1 << 8) | (1 << 3);
}
return 0;
}
static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
}
static const MemoryRegionOps fusbh200_ehci_mmio_ops = {
.read = fusbh200_ehci_read,
.write = fusbh200_ehci_write,
.valid.min_access_size = 4,
.valid.max_access_size = 4,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void fusbh200_ehci_init(Object *obj)
{
EHCISysBusState *i = SYS_BUS_EHCI(obj);
FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
EHCIState *s = &i->ehci;
memory_region_init_io(&f->mem_vendor, &fusbh200_ehci_mmio_ops, s,
"fusbh200", 0x4c);
memory_region_add_subregion(&s->mem,
s->opregbase + s->portscbase + 4 * s->portnr,
&f->mem_vendor);
}
static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
{
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
sec->capsbase = 0x0;
sec->opregbase = 0x10;
sec->portscbase = 0x20;
sec->portnr = 1;
}
static const TypeInfo ehci_fusbh200_type_info = {
.name = TYPE_FUSBH200_EHCI,
.parent = TYPE_SYS_BUS_EHCI,
.instance_size = sizeof(FUSBH200EHCIState),
.instance_init = fusbh200_ehci_init,
.class_init = fusbh200_ehci_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_tegra2_type_info);
type_register_static(&ehci_fusbh200_type_info);
}
type_init(ehci_sysbus_register_types)

View File

@ -338,6 +338,7 @@ typedef struct EHCIPCIState {
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
#define SYS_BUS_EHCI(obj) \
OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI)
@ -365,4 +366,15 @@ typedef struct SysBusEHCIClass {
uint16_t portnr;
} SysBusEHCIClass;
#define FUSBH200_EHCI(obj) \
OBJECT_CHECK(FUSBH200EHCIState, (obj), TYPE_FUSBH200_EHCI)
typedef struct FUSBH200EHCIState {
/*< private >*/
EHCISysBusState parent_obj;
/*< public >*/
MemoryRegion mem_vendor;
} FUSBH200EHCIState;
#endif