1*83698261SGuenter Roeck /* 2*83698261SGuenter Roeck * QEMU USB UHCI Emulation 3*83698261SGuenter Roeck * Copyright (c) 2006 Openedhand Ltd. 4*83698261SGuenter Roeck * Copyright (c) 2010 CodeSourcery 5*83698261SGuenter Roeck * Copyright (c) 2024 Red Hat, Inc. 6*83698261SGuenter Roeck * 7*83698261SGuenter Roeck * This library is free software; you can redistribute it and/or 8*83698261SGuenter Roeck * modify it under the terms of the GNU Lesser General Public 9*83698261SGuenter Roeck * License as published by the Free Software Foundation; either 10*83698261SGuenter Roeck * version 2.1 of the License, or (at your option) any later version. 11*83698261SGuenter Roeck * 12*83698261SGuenter Roeck * This library is distributed in the hope that it will be useful, 13*83698261SGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*83698261SGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*83698261SGuenter Roeck * Lesser General Public License for more details. 16*83698261SGuenter Roeck * 17*83698261SGuenter Roeck * You should have received a copy of the GNU Lesser General Public 18*83698261SGuenter Roeck * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19*83698261SGuenter Roeck */ 20*83698261SGuenter Roeck 21*83698261SGuenter Roeck #include "qemu/osdep.h" 22*83698261SGuenter Roeck #include "hw/irq.h" 23*83698261SGuenter Roeck #include "qapi/error.h" 24*83698261SGuenter Roeck #include "qemu/module.h" 25*83698261SGuenter Roeck #include "qemu/timer.h" 26*83698261SGuenter Roeck #include "hw/usb.h" 27*83698261SGuenter Roeck #include "migration/vmstate.h" 28*83698261SGuenter Roeck #include "hw/sysbus.h" 29*83698261SGuenter Roeck #include "hw/qdev-dma.h" 30*83698261SGuenter Roeck #include "hw/qdev-properties.h" 31*83698261SGuenter Roeck #include "trace.h" 32*83698261SGuenter Roeck #include "hcd-uhci.h" 33*83698261SGuenter Roeck #include "hcd-uhci-sysbus.h" 34*83698261SGuenter Roeck 35*83698261SGuenter Roeck static void uhci_sysbus_reset(UHCIState *uhci) 36*83698261SGuenter Roeck { 37*83698261SGuenter Roeck uhci_state_reset(uhci); 38*83698261SGuenter Roeck } 39*83698261SGuenter Roeck 40*83698261SGuenter Roeck static void uhci_sysbus_realize(DeviceState *dev, Error **errp) 41*83698261SGuenter Roeck { 42*83698261SGuenter Roeck UHCISysBusState *s = SYSBUS_UHCI(dev); 43*83698261SGuenter Roeck UHCIState *uhci = &s->uhci; 44*83698261SGuenter Roeck SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 45*83698261SGuenter Roeck Error *err = NULL; 46*83698261SGuenter Roeck 47*83698261SGuenter Roeck uhci->masterbus = s->masterbus; 48*83698261SGuenter Roeck uhci->firstport = s->firstport; 49*83698261SGuenter Roeck uhci->maxframes = s->maxframes; 50*83698261SGuenter Roeck uhci->frame_bandwidth = s->frame_bandwidth; 51*83698261SGuenter Roeck uhci->as = &address_space_memory; 52*83698261SGuenter Roeck uhci->uhci_reset = uhci_sysbus_reset; 53*83698261SGuenter Roeck 54*83698261SGuenter Roeck usb_uhci_init(uhci, dev, &err); 55*83698261SGuenter Roeck 56*83698261SGuenter Roeck if (err) { 57*83698261SGuenter Roeck error_propagate(errp, err); 58*83698261SGuenter Roeck return; 59*83698261SGuenter Roeck } 60*83698261SGuenter Roeck sysbus_init_irq(sbd, &uhci->irq); 61*83698261SGuenter Roeck sysbus_init_mmio(sbd, &uhci->mem); 62*83698261SGuenter Roeck } 63*83698261SGuenter Roeck 64*83698261SGuenter Roeck static void uhci_sysbus_reset_sysbus(DeviceState *dev) 65*83698261SGuenter Roeck { 66*83698261SGuenter Roeck UHCISysBusState *s = SYSBUS_UHCI(dev); 67*83698261SGuenter Roeck UHCIState *uhci = &s->uhci; 68*83698261SGuenter Roeck 69*83698261SGuenter Roeck uhci_sysbus_reset(uhci); 70*83698261SGuenter Roeck } 71*83698261SGuenter Roeck 72*83698261SGuenter Roeck static Property uhci_sysbus_properties[] = { 73*83698261SGuenter Roeck DEFINE_PROP_STRING("masterbus", UHCISysBusState, masterbus), 74*83698261SGuenter Roeck DEFINE_PROP_UINT32("firstport", UHCISysBusState, firstport, 0), 75*83698261SGuenter Roeck DEFINE_PROP_UINT32("bandwidth", UHCISysBusState, frame_bandwidth, 1280), 76*83698261SGuenter Roeck DEFINE_PROP_UINT32("maxframes", UHCISysBusState, maxframes, 128), 77*83698261SGuenter Roeck DEFINE_PROP_END_OF_LIST(), 78*83698261SGuenter Roeck }; 79*83698261SGuenter Roeck 80*83698261SGuenter Roeck static void uhci_sysbus_class_init(ObjectClass *klass, void *data) 81*83698261SGuenter Roeck { 82*83698261SGuenter Roeck DeviceClass *dc = DEVICE_CLASS(klass); 83*83698261SGuenter Roeck 84*83698261SGuenter Roeck dc->realize = uhci_sysbus_realize; 85*83698261SGuenter Roeck set_bit(DEVICE_CATEGORY_USB, dc->categories); 86*83698261SGuenter Roeck dc->desc = "UHCI USB Controller"; 87*83698261SGuenter Roeck device_class_set_props(dc, uhci_sysbus_properties); 88*83698261SGuenter Roeck device_class_set_legacy_reset(dc, uhci_sysbus_reset_sysbus); 89*83698261SGuenter Roeck } 90*83698261SGuenter Roeck 91*83698261SGuenter Roeck static const TypeInfo uhci_sysbus_types[] = { 92*83698261SGuenter Roeck { 93*83698261SGuenter Roeck .name = TYPE_SYSBUS_UHCI, 94*83698261SGuenter Roeck .parent = TYPE_SYS_BUS_DEVICE, 95*83698261SGuenter Roeck .instance_size = sizeof(UHCISysBusState), 96*83698261SGuenter Roeck .class_init = uhci_sysbus_class_init, 97*83698261SGuenter Roeck }, 98*83698261SGuenter Roeck }; 99*83698261SGuenter Roeck 100*83698261SGuenter Roeck DEFINE_TYPES(uhci_sysbus_types); 101