1 /* 2 * USB xHCI controller for system-bus interface 3 * Based on hcd-echi-sysbus.c 4 5 * SPDX-FileCopyrightText: 2020 Xilinx 6 * SPDX-FileContributor: Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 #include "qemu/osdep.h" 11 #include "hw/qdev-properties.h" 12 #include "migration/vmstate.h" 13 #include "trace.h" 14 #include "qapi/error.h" 15 #include "hcd-xhci-sysbus.h" 16 #include "hw/irq.h" 17 18 static void xhci_sysbus_intr_raise(XHCIState *xhci, int n, bool level) 19 { 20 XHCISysbusState *s = container_of(xhci, XHCISysbusState, xhci); 21 22 qemu_set_irq(s->irq[n], level); 23 } 24 25 void xhci_sysbus_reset(DeviceState *dev) 26 { 27 XHCISysbusState *s = XHCI_SYSBUS(dev); 28 29 device_legacy_reset(DEVICE(&s->xhci)); 30 } 31 32 static void xhci_sysbus_realize(DeviceState *dev, Error **errp) 33 { 34 XHCISysbusState *s = XHCI_SYSBUS(dev); 35 Error *err = NULL; 36 37 object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL); 38 object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err); 39 if (err) { 40 error_propagate(errp, err); 41 return; 42 } 43 s->irq = g_new0(qemu_irq, s->xhci.numintrs); 44 qdev_init_gpio_out_named(dev, s->irq, SYSBUS_DEVICE_GPIO_IRQ, 45 s->xhci.numintrs); 46 if (s->xhci.dma_mr) { 47 s->xhci.as = g_malloc0(sizeof(AddressSpace)); 48 address_space_init(s->xhci.as, s->xhci.dma_mr, NULL); 49 } else { 50 s->xhci.as = &address_space_memory; 51 } 52 53 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->xhci.mem); 54 } 55 56 static void xhci_sysbus_instance_init(Object *obj) 57 { 58 XHCISysbusState *s = XHCI_SYSBUS(obj); 59 60 object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI); 61 qdev_alias_all_properties(DEVICE(&s->xhci), obj); 62 63 object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, 64 (Object **)&s->xhci.dma_mr, 65 qdev_prop_allow_set_link_before_realize, 66 OBJ_PROP_LINK_STRONG); 67 s->xhci.intr_update = NULL; 68 s->xhci.intr_raise = xhci_sysbus_intr_raise; 69 } 70 71 static Property xhci_sysbus_props[] = { 72 DEFINE_PROP_UINT32("intrs", XHCISysbusState, xhci.numintrs, MAXINTRS), 73 DEFINE_PROP_UINT32("slots", XHCISysbusState, xhci.numslots, MAXSLOTS), 74 DEFINE_PROP_END_OF_LIST(), 75 }; 76 77 static const VMStateDescription vmstate_xhci_sysbus = { 78 .name = "xhci-sysbus", 79 .version_id = 1, 80 .fields = (VMStateField[]) { 81 VMSTATE_STRUCT(xhci, XHCISysbusState, 1, vmstate_xhci, XHCIState), 82 VMSTATE_END_OF_LIST() 83 } 84 }; 85 86 static void xhci_sysbus_class_init(ObjectClass *klass, void *data) 87 { 88 DeviceClass *dc = DEVICE_CLASS(klass); 89 90 dc->reset = xhci_sysbus_reset; 91 dc->realize = xhci_sysbus_realize; 92 dc->vmsd = &vmstate_xhci_sysbus; 93 device_class_set_props(dc, xhci_sysbus_props); 94 } 95 96 static const TypeInfo xhci_sysbus_info = { 97 .name = TYPE_XHCI_SYSBUS, 98 .parent = TYPE_SYS_BUS_DEVICE, 99 .instance_size = sizeof(XHCISysbusState), 100 .class_init = xhci_sysbus_class_init, 101 .instance_init = xhci_sysbus_instance_init 102 }; 103 104 static void xhci_sysbus_register_types(void) 105 { 106 type_register_static(&xhci_sysbus_info); 107 } 108 109 type_init(xhci_sysbus_register_types); 110