1c0907c9eSPaolo Bonzini /* 2c0907c9eSPaolo Bonzini * QEMU Grackle PCI host (heathrow OldWorld PowerMac) 3c0907c9eSPaolo Bonzini * 4c0907c9eSPaolo Bonzini * Copyright (c) 2006-2007 Fabrice Bellard 5c0907c9eSPaolo Bonzini * Copyright (c) 2007 Jocelyn Mayer 6c0907c9eSPaolo Bonzini * 7c0907c9eSPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 8c0907c9eSPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 9c0907c9eSPaolo Bonzini * in the Software without restriction, including without limitation the rights 10c0907c9eSPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11c0907c9eSPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 12c0907c9eSPaolo Bonzini * furnished to do so, subject to the following conditions: 13c0907c9eSPaolo Bonzini * 14c0907c9eSPaolo Bonzini * The above copyright notice and this permission notice shall be included in 15c0907c9eSPaolo Bonzini * all copies or substantial portions of the Software. 16c0907c9eSPaolo Bonzini * 17c0907c9eSPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18c0907c9eSPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19c0907c9eSPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20c0907c9eSPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21c0907c9eSPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22c0907c9eSPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23c0907c9eSPaolo Bonzini * THE SOFTWARE. 24c0907c9eSPaolo Bonzini */ 25c0907c9eSPaolo Bonzini 260d75590dSPeter Maydell #include "qemu/osdep.h" 27c0907c9eSPaolo Bonzini #include "hw/pci/pci_host.h" 28c0907c9eSPaolo Bonzini #include "hw/ppc/mac.h" 29a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 30c0907c9eSPaolo Bonzini #include "hw/pci/pci.h" 3164552b6bSMarkus Armbruster #include "hw/irq.h" 32b0318ec1SMark Cave-Ayland #include "qapi/error.h" 330b8fa32fSMarkus Armbruster #include "qemu/module.h" 34b728fbbcSMark Cave-Ayland #include "trace.h" 35db1015e9SEduardo Habkost #include "qom/object.h" 36c0907c9eSPaolo Bonzini 378063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(GrackleState, GRACKLE_PCI_HOST_BRIDGE) 38c0907c9eSPaolo Bonzini 39db1015e9SEduardo Habkost struct GrackleState { 40c0907c9eSPaolo Bonzini PCIHostState parent_obj; 41c0907c9eSPaolo Bonzini 42ac43eb2eSMark Cave-Ayland uint32_t ofw_addr; 43b0318ec1SMark Cave-Ayland qemu_irq irqs[4]; 44c0907c9eSPaolo Bonzini MemoryRegion pci_mmio; 45c0907c9eSPaolo Bonzini MemoryRegion pci_hole; 46a94e5f99SMark Cave-Ayland MemoryRegion pci_io; 47db1015e9SEduardo Habkost }; 48c0907c9eSPaolo Bonzini 49c0907c9eSPaolo Bonzini /* Don't know if this matches real hardware, but it agrees with OHW. */ 50c0907c9eSPaolo Bonzini static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num) 51c0907c9eSPaolo Bonzini { 52c0907c9eSPaolo Bonzini return (irq_num + (pci_dev->devfn >> 3)) & 3; 53c0907c9eSPaolo Bonzini } 54c0907c9eSPaolo Bonzini 55c0907c9eSPaolo Bonzini static void pci_grackle_set_irq(void *opaque, int irq_num, int level) 56c0907c9eSPaolo Bonzini { 57b0318ec1SMark Cave-Ayland GrackleState *s = opaque; 58c0907c9eSPaolo Bonzini 59b728fbbcSMark Cave-Ayland trace_grackle_set_irq(irq_num, level); 60b0318ec1SMark Cave-Ayland qemu_set_irq(s->irqs[irq_num], level); 61c0907c9eSPaolo Bonzini } 62c0907c9eSPaolo Bonzini 63b0318ec1SMark Cave-Ayland static void grackle_realize(DeviceState *dev, Error **errp) 64c0907c9eSPaolo Bonzini { 65b0318ec1SMark Cave-Ayland GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(dev); 66b0318ec1SMark Cave-Ayland PCIHostState *phb = PCI_HOST_BRIDGE(dev); 67c0907c9eSPaolo Bonzini 68b0318ec1SMark Cave-Ayland phb->bus = pci_register_root_bus(dev, NULL, 69b0318ec1SMark Cave-Ayland pci_grackle_set_irq, 70b0318ec1SMark Cave-Ayland pci_grackle_map_irq, 71b0318ec1SMark Cave-Ayland s, 72b0318ec1SMark Cave-Ayland &s->pci_mmio, 73a94e5f99SMark Cave-Ayland &s->pci_io, 74b0318ec1SMark Cave-Ayland 0, 4, TYPE_PCI_BUS); 75c0907c9eSPaolo Bonzini 76b0318ec1SMark Cave-Ayland pci_create_simple(phb->bus, 0, "grackle"); 77c0907c9eSPaolo Bonzini } 78c0907c9eSPaolo Bonzini 79b0318ec1SMark Cave-Ayland static void grackle_init(Object *obj) 80b0318ec1SMark Cave-Ayland { 81b0318ec1SMark Cave-Ayland GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(obj); 82b0318ec1SMark Cave-Ayland SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 83b0318ec1SMark Cave-Ayland PCIHostState *phb = PCI_HOST_BRIDGE(obj); 84b0318ec1SMark Cave-Ayland 85b0318ec1SMark Cave-Ayland memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); 86a94e5f99SMark Cave-Ayland memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj, 87a94e5f99SMark Cave-Ayland "pci-isa-mmio", 0x00200000); 88a94e5f99SMark Cave-Ayland 89b0318ec1SMark Cave-Ayland memory_region_init_alias(&s->pci_hole, OBJECT(s), "pci-hole", &s->pci_mmio, 90b0318ec1SMark Cave-Ayland 0x80000000ULL, 0x7e000000ULL); 91b0318ec1SMark Cave-Ayland 92b0318ec1SMark Cave-Ayland memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops, 93b0318ec1SMark Cave-Ayland DEVICE(obj), "pci-conf-idx", 0x1000); 94b0318ec1SMark Cave-Ayland memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, 95b0318ec1SMark Cave-Ayland DEVICE(obj), "pci-data-idx", 0x1000); 96b0318ec1SMark Cave-Ayland 97b0318ec1SMark Cave-Ayland sysbus_init_mmio(sbd, &phb->conf_mem); 98b0318ec1SMark Cave-Ayland sysbus_init_mmio(sbd, &phb->data_mem); 99a773e64aSMark Cave-Ayland sysbus_init_mmio(sbd, &s->pci_hole); 100a94e5f99SMark Cave-Ayland sysbus_init_mmio(sbd, &s->pci_io); 101*b950914dSMark Cave-Ayland 102*b950914dSMark Cave-Ayland qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); 103b0318ec1SMark Cave-Ayland } 104b0318ec1SMark Cave-Ayland 105b0318ec1SMark Cave-Ayland static void grackle_pci_realize(PCIDevice *d, Error **errp) 106c0907c9eSPaolo Bonzini { 107c0907c9eSPaolo Bonzini d->config[0x09] = 0x01; 108c0907c9eSPaolo Bonzini } 109c0907c9eSPaolo Bonzini 110c0907c9eSPaolo Bonzini static void grackle_pci_class_init(ObjectClass *klass, void *data) 111c0907c9eSPaolo Bonzini { 112c0907c9eSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 113b0318ec1SMark Cave-Ayland PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 114c0907c9eSPaolo Bonzini 115b0318ec1SMark Cave-Ayland k->realize = grackle_pci_realize; 116c0907c9eSPaolo Bonzini k->vendor_id = PCI_VENDOR_ID_MOTOROLA; 117c0907c9eSPaolo Bonzini k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; 118c0907c9eSPaolo Bonzini k->revision = 0x00; 119c0907c9eSPaolo Bonzini k->class_id = PCI_CLASS_BRIDGE_HOST; 12008c58f92SMarkus Armbruster /* 12108c58f92SMarkus Armbruster * PCI-facing part of the host bridge, not usable without the 12208c58f92SMarkus Armbruster * host-facing part, which can't be device_add'ed, yet. 12308c58f92SMarkus Armbruster */ 124e90f2a8cSEduardo Habkost dc->user_creatable = false; 125c0907c9eSPaolo Bonzini } 126c0907c9eSPaolo Bonzini 127c0907c9eSPaolo Bonzini static const TypeInfo grackle_pci_info = { 128c0907c9eSPaolo Bonzini .name = "grackle", 129c0907c9eSPaolo Bonzini .parent = TYPE_PCI_DEVICE, 130c0907c9eSPaolo Bonzini .instance_size = sizeof(PCIDevice), 131c0907c9eSPaolo Bonzini .class_init = grackle_pci_class_init, 132fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) { 133fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 134fd3b02c8SEduardo Habkost { }, 135fd3b02c8SEduardo Habkost }, 136c0907c9eSPaolo Bonzini }; 137c0907c9eSPaolo Bonzini 138ac43eb2eSMark Cave-Ayland static char *grackle_ofw_unit_address(const SysBusDevice *dev) 139ac43eb2eSMark Cave-Ayland { 140ac43eb2eSMark Cave-Ayland GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(dev); 141ac43eb2eSMark Cave-Ayland 142ac43eb2eSMark Cave-Ayland return g_strdup_printf("%x", s->ofw_addr); 143ac43eb2eSMark Cave-Ayland } 144ac43eb2eSMark Cave-Ayland 145ac43eb2eSMark Cave-Ayland static Property grackle_properties[] = { 146ac43eb2eSMark Cave-Ayland DEFINE_PROP_UINT32("ofw-addr", GrackleState, ofw_addr, -1), 147ac43eb2eSMark Cave-Ayland DEFINE_PROP_END_OF_LIST() 148ac43eb2eSMark Cave-Ayland }; 149ac43eb2eSMark Cave-Ayland 150b0318ec1SMark Cave-Ayland static void grackle_class_init(ObjectClass *klass, void *data) 151c0907c9eSPaolo Bonzini { 152e1624435SLaurent Vivier DeviceClass *dc = DEVICE_CLASS(klass); 153ac43eb2eSMark Cave-Ayland SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 154c0907c9eSPaolo Bonzini 155b0318ec1SMark Cave-Ayland dc->realize = grackle_realize; 1564f67d30bSMarc-André Lureau device_class_set_props(dc, grackle_properties); 157e1624435SLaurent Vivier set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 158ac43eb2eSMark Cave-Ayland dc->fw_name = "pci"; 159ac43eb2eSMark Cave-Ayland sbc->explicit_ofw_unit_address = grackle_ofw_unit_address; 160c0907c9eSPaolo Bonzini } 161c0907c9eSPaolo Bonzini 162b0318ec1SMark Cave-Ayland static const TypeInfo grackle_host_info = { 163c0907c9eSPaolo Bonzini .name = TYPE_GRACKLE_PCI_HOST_BRIDGE, 164c0907c9eSPaolo Bonzini .parent = TYPE_PCI_HOST_BRIDGE, 165c0907c9eSPaolo Bonzini .instance_size = sizeof(GrackleState), 166b0318ec1SMark Cave-Ayland .instance_init = grackle_init, 167b0318ec1SMark Cave-Ayland .class_init = grackle_class_init, 168c0907c9eSPaolo Bonzini }; 169c0907c9eSPaolo Bonzini 170c0907c9eSPaolo Bonzini static void grackle_register_types(void) 171c0907c9eSPaolo Bonzini { 172c0907c9eSPaolo Bonzini type_register_static(&grackle_pci_info); 173b0318ec1SMark Cave-Ayland type_register_static(&grackle_host_info); 174c0907c9eSPaolo Bonzini } 175c0907c9eSPaolo Bonzini 176c0907c9eSPaolo Bonzini type_init(grackle_register_types) 177