xref: /openbmc/qemu/hw/usb/hcd-uhci-sysbus.c (revision 83698261)
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