qemu/hw/usb/hcd-ehci-sysbus.c
<<
>>
Prefs
   1/*
   2 * QEMU USB EHCI Emulation
   3 *
   4 * This library is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU Lesser General Public
   6 * License as published by the Free Software Foundation; either
   7 * version 2.1 of the License, or (at your option) any later version.
   8 *
   9 * This library is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12 * Lesser General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU Lesser General Public License
  15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#include "qemu/osdep.h"
  19#include "hw/qdev-properties.h"
  20#include "hw/usb/hcd-ehci.h"
  21#include "migration/vmstate.h"
  22#include "qemu/module.h"
  23
  24static const VMStateDescription vmstate_ehci_sysbus = {
  25    .name        = "ehci-sysbus",
  26    .version_id  = 2,
  27    .minimum_version_id  = 1,
  28    .fields = (VMStateField[]) {
  29        VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState),
  30        VMSTATE_END_OF_LIST()
  31    }
  32};
  33
  34static Property ehci_sysbus_properties[] = {
  35    DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
  36    DEFINE_PROP_END_OF_LIST(),
  37};
  38
  39static void usb_ehci_sysbus_realize(DeviceState *dev, Error **errp)
  40{
  41    SysBusDevice *d = SYS_BUS_DEVICE(dev);
  42    EHCISysBusState *i = SYS_BUS_EHCI(dev);
  43    EHCIState *s = &i->ehci;
  44
  45    usb_ehci_realize(s, dev, errp);
  46    sysbus_init_irq(d, &s->irq);
  47}
  48
  49static void usb_ehci_sysbus_reset(DeviceState *dev)
  50{
  51    SysBusDevice *d = SYS_BUS_DEVICE(dev);
  52    EHCISysBusState *i = SYS_BUS_EHCI(d);
  53    EHCIState *s = &i->ehci;
  54
  55    ehci_reset(s);
  56}
  57
  58static void ehci_sysbus_init(Object *obj)
  59{
  60    SysBusDevice *d = SYS_BUS_DEVICE(obj);
  61    EHCISysBusState *i = SYS_BUS_EHCI(obj);
  62    SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(obj);
  63    EHCIState *s = &i->ehci;
  64
  65    s->capsbase = sec->capsbase;
  66    s->opregbase = sec->opregbase;
  67    s->portscbase = sec->portscbase;
  68    s->portnr = sec->portnr;
  69    s->as = &address_space_memory;
  70
  71    usb_ehci_init(s, DEVICE(obj));
  72    sysbus_init_mmio(d, &s->mem);
  73}
  74
  75static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
  76{
  77    DeviceClass *dc = DEVICE_CLASS(klass);
  78    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
  79
  80    sec->portscbase = 0x44;
  81    sec->portnr = NB_PORTS;
  82
  83    dc->realize = usb_ehci_sysbus_realize;
  84    dc->vmsd = &vmstate_ehci_sysbus;
  85    dc->props = ehci_sysbus_properties;
  86    dc->reset = usb_ehci_sysbus_reset;
  87    set_bit(DEVICE_CATEGORY_USB, dc->categories);
  88}
  89
  90static const TypeInfo ehci_type_info = {
  91    .name          = TYPE_SYS_BUS_EHCI,
  92    .parent        = TYPE_SYS_BUS_DEVICE,
  93    .instance_size = sizeof(EHCISysBusState),
  94    .instance_init = ehci_sysbus_init,
  95    .abstract      = true,
  96    .class_init    = ehci_sysbus_class_init,
  97    .class_size    = sizeof(SysBusEHCIClass),
  98};
  99
 100static void ehci_platform_class_init(ObjectClass *oc, void *data)
 101{
 102    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
 103    DeviceClass *dc = DEVICE_CLASS(oc);
 104
 105    sec->capsbase = 0x0;
 106    sec->opregbase = 0x20;
 107    set_bit(DEVICE_CATEGORY_USB, dc->categories);
 108}
 109
 110static const TypeInfo ehci_platform_type_info = {
 111    .name          = TYPE_PLATFORM_EHCI,
 112    .parent        = TYPE_SYS_BUS_EHCI,
 113    .class_init    = ehci_platform_class_init,
 114};
 115
 116static void ehci_xlnx_class_init(ObjectClass *oc, void *data)
 117{
 118    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
 119    DeviceClass *dc = DEVICE_CLASS(oc);
 120
 121    set_bit(DEVICE_CATEGORY_USB, dc->categories);
 122    sec->capsbase = 0x100;
 123    sec->opregbase = 0x140;
 124}
 125
 126static const TypeInfo ehci_xlnx_type_info = {
 127    .name          = "xlnx,ps7-usb",
 128    .parent        = TYPE_SYS_BUS_EHCI,
 129    .class_init    = ehci_xlnx_class_init,
 130};
 131
 132static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
 133{
 134    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
 135    DeviceClass *dc = DEVICE_CLASS(oc);
 136
 137    sec->capsbase = 0x0;
 138    sec->opregbase = 0x10;
 139    set_bit(DEVICE_CATEGORY_USB, dc->categories);
 140}
 141
 142static const TypeInfo ehci_exynos4210_type_info = {
 143    .name          = TYPE_EXYNOS4210_EHCI,
 144    .parent        = TYPE_SYS_BUS_EHCI,
 145    .class_init    = ehci_exynos4210_class_init,
 146};
 147
 148static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
 149{
 150    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
 151    DeviceClass *dc = DEVICE_CLASS(oc);
 152
 153    sec->capsbase = 0x100;
 154    sec->opregbase = 0x140;
 155    set_bit(DEVICE_CATEGORY_USB, dc->categories);
 156}
 157
 158static const TypeInfo ehci_tegra2_type_info = {
 159    .name          = TYPE_TEGRA2_EHCI,
 160    .parent        = TYPE_SYS_BUS_EHCI,
 161    .class_init    = ehci_tegra2_class_init,
 162};
 163
 164static void ehci_ppc4xx_init(Object *o)
 165{
 166    EHCISysBusState *s = SYS_BUS_EHCI(o);
 167
 168    s->ehci.companion_enable = true;
 169}
 170
 171static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
 172{
 173    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
 174    DeviceClass *dc = DEVICE_CLASS(oc);
 175
 176    sec->capsbase = 0x0;
 177    sec->opregbase = 0x10;
 178    set_bit(DEVICE_CATEGORY_USB, dc->categories);
 179}
 180
 181static const TypeInfo ehci_ppc4xx_type_info = {
 182    .name          = TYPE_PPC4xx_EHCI,
 183    .parent        = TYPE_SYS_BUS_EHCI,
 184    .class_init    = ehci_ppc4xx_class_init,
 185    .instance_init = ehci_ppc4xx_init,
 186};
 187
 188/*
 189 * Faraday FUSBH200 USB 2.0 EHCI
 190 */
 191
 192/**
 193 * FUSBH200EHCIRegs:
 194 * @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register
 195 * @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register
 196 */
 197enum FUSBH200EHCIRegs {
 198    FUSBH200_REG_EOF_ASTR = 0x34,
 199    FUSBH200_REG_BMCSR    = 0x40,
 200};
 201
 202static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size)
 203{
 204    EHCIState *s = opaque;
 205    hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr;
 206
 207    switch (off) {
 208    case FUSBH200_REG_EOF_ASTR:
 209        return 0x00000041;
 210    case FUSBH200_REG_BMCSR:
 211        /* High-Speed, VBUS valid, interrupt level-high active */
 212        return (2 << 9) | (1 << 8) | (1 << 3);
 213    }
 214
 215    return 0;
 216}
 217
 218static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val,
 219                                unsigned size)
 220{
 221}
 222
 223static const MemoryRegionOps fusbh200_ehci_mmio_ops = {
 224    .read = fusbh200_ehci_read,
 225    .write = fusbh200_ehci_write,
 226    .valid.min_access_size = 4,
 227    .valid.max_access_size = 4,
 228    .endianness = DEVICE_LITTLE_ENDIAN,
 229};
 230
 231static void fusbh200_ehci_init(Object *obj)
 232{
 233    EHCISysBusState *i = SYS_BUS_EHCI(obj);
 234    FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
 235    EHCIState *s = &i->ehci;
 236
 237    memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s,
 238                          "fusbh200", 0x4c);
 239    memory_region_add_subregion(&s->mem,
 240                                s->opregbase + s->portscbase + 4 * s->portnr,
 241                                &f->mem_vendor);
 242}
 243
 244static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
 245{
 246    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
 247    DeviceClass *dc = DEVICE_CLASS(oc);
 248
 249    sec->capsbase = 0x0;
 250    sec->opregbase = 0x10;
 251    sec->portscbase = 0x20;
 252    sec->portnr = 1;
 253    set_bit(DEVICE_CATEGORY_USB, dc->categories);
 254}
 255
 256static const TypeInfo ehci_fusbh200_type_info = {
 257    .name          = TYPE_FUSBH200_EHCI,
 258    .parent        = TYPE_SYS_BUS_EHCI,
 259    .instance_size = sizeof(FUSBH200EHCIState),
 260    .instance_init = fusbh200_ehci_init,
 261    .class_init    = fusbh200_ehci_class_init,
 262};
 263
 264static void ehci_sysbus_register_types(void)
 265{
 266    type_register_static(&ehci_type_info);
 267    type_register_static(&ehci_platform_type_info);
 268    type_register_static(&ehci_xlnx_type_info);
 269    type_register_static(&ehci_exynos4210_type_info);
 270    type_register_static(&ehci_tegra2_type_info);
 271    type_register_static(&ehci_ppc4xx_type_info);
 272    type_register_static(&ehci_fusbh200_type_info);
 273}
 274
 275type_init(ehci_sysbus_register_types)
 276