123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /*
- * QEMU USB EHCI Emulation
- *
- * 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 program; if not, see <http://www.gnu.org/licenses/>.
- */
- #include "qemu/osdep.h"
- #include "hw/qdev-properties.h"
- #include "hw/usb/hcd-ehci.h"
- #include "migration/vmstate.h"
- static const VMStateDescription vmstate_ehci_sysbus = {
- .name = "ehci-sysbus",
- .version_id = 2,
- .minimum_version_id = 1,
- .fields = (const VMStateField[]) {
- VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState),
- VMSTATE_END_OF_LIST()
- }
- };
- static const Property ehci_sysbus_properties[] = {
- DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
- DEFINE_PROP_BOOL("companion-enable", EHCISysBusState, ehci.companion_enable,
- false),
- };
- static void usb_ehci_sysbus_realize(DeviceState *dev, Error **errp)
- {
- SysBusDevice *d = SYS_BUS_DEVICE(dev);
- EHCISysBusState *i = SYS_BUS_EHCI(dev);
- EHCIState *s = &i->ehci;
- usb_ehci_realize(s, dev, errp);
- sysbus_init_irq(d, &s->irq);
- }
- static void usb_ehci_sysbus_reset(DeviceState *dev)
- {
- SysBusDevice *d = SYS_BUS_DEVICE(dev);
- EHCISysBusState *i = SYS_BUS_EHCI(d);
- EHCIState *s = &i->ehci;
- ehci_reset(s);
- }
- static void ehci_sysbus_init(Object *obj)
- {
- SysBusDevice *d = SYS_BUS_DEVICE(obj);
- EHCISysBusState *i = SYS_BUS_EHCI(obj);
- SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(obj);
- EHCIState *s = &i->ehci;
- s->capsbase = sec->capsbase;
- s->opregbase = sec->opregbase;
- s->portscbase = sec->portscbase;
- s->portnr = sec->portnr;
- s->as = &address_space_memory;
- usb_ehci_init(s, DEVICE(obj));
- sysbus_init_mmio(d, &s->mem);
- }
- static void ehci_sysbus_finalize(Object *obj)
- {
- EHCISysBusState *i = SYS_BUS_EHCI(obj);
- EHCIState *s = &i->ehci;
- usb_ehci_finalize(s);
- }
- static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
- {
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
- sec->portscbase = 0x44;
- sec->portnr = EHCI_PORTS;
- dc->realize = usb_ehci_sysbus_realize;
- dc->vmsd = &vmstate_ehci_sysbus;
- device_class_set_props(dc, ehci_sysbus_properties);
- device_class_set_legacy_reset(dc, usb_ehci_sysbus_reset);
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static void ehci_platform_class_init(ObjectClass *oc, void *data)
- {
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x0;
- sec->opregbase = 0x20;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
- {
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x0;
- sec->opregbase = 0x10;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
- {
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x0;
- sec->opregbase = 0x10;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data)
- {
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x0;
- sec->opregbase = 0x10;
- sec->portscbase = 0x44;
- sec->portnr = 1;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
- {
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x100;
- sec->opregbase = 0x140;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static void ehci_ppc4xx_init(Object *o)
- {
- EHCISysBusState *s = SYS_BUS_EHCI(o);
- s->ehci.companion_enable = true;
- }
- static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
- {
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x0;
- sec->opregbase = 0x10;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- /*
- * 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, OBJECT(f), &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);
- DeviceClass *dc = DEVICE_CLASS(oc);
- sec->capsbase = 0x0;
- sec->opregbase = 0x10;
- sec->portscbase = 0x20;
- sec->portnr = 1;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- }
- static const TypeInfo ehci_sysbus_types[] = {
- {
- .name = TYPE_SYS_BUS_EHCI,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(EHCISysBusState),
- .instance_init = ehci_sysbus_init,
- .instance_finalize = ehci_sysbus_finalize,
- .abstract = true,
- .class_init = ehci_sysbus_class_init,
- .class_size = sizeof(SysBusEHCIClass),
- },
- {
- .name = TYPE_PLATFORM_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .class_init = ehci_platform_class_init,
- },
- {
- .name = TYPE_EXYNOS4210_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .class_init = ehci_exynos4210_class_init,
- },
- {
- .name = TYPE_AW_H3_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .class_init = ehci_aw_h3_class_init,
- },
- {
- .name = TYPE_NPCM7XX_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .class_init = ehci_npcm7xx_class_init,
- },
- {
- .name = TYPE_TEGRA2_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .class_init = ehci_tegra2_class_init,
- },
- {
- .name = TYPE_PPC4xx_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .class_init = ehci_ppc4xx_class_init,
- .instance_init = ehci_ppc4xx_init,
- },
- {
- .name = TYPE_FUSBH200_EHCI,
- .parent = TYPE_SYS_BUS_EHCI,
- .instance_size = sizeof(FUSBH200EHCIState),
- .instance_init = fusbh200_ehci_init,
- .class_init = fusbh200_ehci_class_init,
- },
- };
- DEFINE_TYPES(ehci_sysbus_types)
|