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" 31b0318ec1SMark Cave-Ayland #include "hw/intc/heathrow_pic.h" 3264552b6bSMarkus Armbruster #include "hw/irq.h" 33b0318ec1SMark Cave-Ayland #include "qapi/error.h" 340b8fa32fSMarkus Armbruster #include "qemu/module.h" 35b728fbbcSMark Cave-Ayland #include "trace.h" 36c0907c9eSPaolo Bonzini 37c0907c9eSPaolo Bonzini #define GRACKLE_PCI_HOST_BRIDGE(obj) \ 38c0907c9eSPaolo Bonzini OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE) 39c0907c9eSPaolo Bonzini 40c0907c9eSPaolo Bonzini typedef struct GrackleState { 41c0907c9eSPaolo Bonzini PCIHostState parent_obj; 42c0907c9eSPaolo Bonzini 43ac43eb2eSMark Cave-Ayland uint32_t ofw_addr; 44b0318ec1SMark Cave-Ayland HeathrowState *pic; 45b0318ec1SMark Cave-Ayland qemu_irq irqs[4]; 46c0907c9eSPaolo Bonzini MemoryRegion pci_mmio; 47c0907c9eSPaolo Bonzini MemoryRegion pci_hole; 48a94e5f99SMark Cave-Ayland MemoryRegion pci_io; 49c0907c9eSPaolo Bonzini } GrackleState; 50c0907c9eSPaolo Bonzini 51c0907c9eSPaolo Bonzini /* Don't know if this matches real hardware, but it agrees with OHW. */ 52c0907c9eSPaolo Bonzini static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num) 53c0907c9eSPaolo Bonzini { 54c0907c9eSPaolo Bonzini return (irq_num + (pci_dev->devfn >> 3)) & 3; 55c0907c9eSPaolo Bonzini } 56c0907c9eSPaolo Bonzini 57c0907c9eSPaolo Bonzini static void pci_grackle_set_irq(void *opaque, int irq_num, int level) 58c0907c9eSPaolo Bonzini { 59b0318ec1SMark Cave-Ayland GrackleState *s = opaque; 60c0907c9eSPaolo Bonzini 61b728fbbcSMark Cave-Ayland trace_grackle_set_irq(irq_num, level); 62b0318ec1SMark Cave-Ayland qemu_set_irq(s->irqs[irq_num], level); 63c0907c9eSPaolo Bonzini } 64c0907c9eSPaolo Bonzini 65b0318ec1SMark Cave-Ayland static void grackle_init_irqs(GrackleState *s) 66b0318ec1SMark Cave-Ayland { 67b0318ec1SMark Cave-Ayland int i; 68b0318ec1SMark Cave-Ayland 69b0318ec1SMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(s->irqs); i++) { 70b0318ec1SMark Cave-Ayland s->irqs[i] = qdev_get_gpio_in(DEVICE(s->pic), 0x15 + i); 71b0318ec1SMark Cave-Ayland } 72b0318ec1SMark Cave-Ayland } 73b0318ec1SMark Cave-Ayland 74b0318ec1SMark Cave-Ayland static void grackle_realize(DeviceState *dev, Error **errp) 75c0907c9eSPaolo Bonzini { 76b0318ec1SMark Cave-Ayland GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(dev); 77b0318ec1SMark Cave-Ayland PCIHostState *phb = PCI_HOST_BRIDGE(dev); 78c0907c9eSPaolo Bonzini 79b0318ec1SMark Cave-Ayland phb->bus = pci_register_root_bus(dev, NULL, 80b0318ec1SMark Cave-Ayland pci_grackle_set_irq, 81b0318ec1SMark Cave-Ayland pci_grackle_map_irq, 82b0318ec1SMark Cave-Ayland s, 83b0318ec1SMark Cave-Ayland &s->pci_mmio, 84a94e5f99SMark Cave-Ayland &s->pci_io, 85b0318ec1SMark Cave-Ayland 0, 4, TYPE_PCI_BUS); 86c0907c9eSPaolo Bonzini 87b0318ec1SMark Cave-Ayland pci_create_simple(phb->bus, 0, "grackle"); 88b0318ec1SMark Cave-Ayland grackle_init_irqs(s); 89c0907c9eSPaolo Bonzini } 90c0907c9eSPaolo Bonzini 91b0318ec1SMark Cave-Ayland static void grackle_init(Object *obj) 92b0318ec1SMark Cave-Ayland { 93b0318ec1SMark Cave-Ayland GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(obj); 94b0318ec1SMark Cave-Ayland SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 95b0318ec1SMark Cave-Ayland PCIHostState *phb = PCI_HOST_BRIDGE(obj); 96b0318ec1SMark Cave-Ayland 97b0318ec1SMark Cave-Ayland memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); 98a94e5f99SMark Cave-Ayland memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj, 99a94e5f99SMark Cave-Ayland "pci-isa-mmio", 0x00200000); 100a94e5f99SMark Cave-Ayland 101b0318ec1SMark Cave-Ayland memory_region_init_alias(&s->pci_hole, OBJECT(s), "pci-hole", &s->pci_mmio, 102b0318ec1SMark Cave-Ayland 0x80000000ULL, 0x7e000000ULL); 103b0318ec1SMark Cave-Ayland 104b0318ec1SMark Cave-Ayland memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops, 105b0318ec1SMark Cave-Ayland DEVICE(obj), "pci-conf-idx", 0x1000); 106b0318ec1SMark Cave-Ayland memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, 107b0318ec1SMark Cave-Ayland DEVICE(obj), "pci-data-idx", 0x1000); 108b0318ec1SMark Cave-Ayland 109b0318ec1SMark Cave-Ayland object_property_add_link(obj, "pic", TYPE_HEATHROW, 110b0318ec1SMark Cave-Ayland (Object **) &s->pic, 111b0318ec1SMark Cave-Ayland qdev_prop_allow_set_link_before_realize, 112b0318ec1SMark Cave-Ayland 0, NULL); 113b0318ec1SMark Cave-Ayland 114b0318ec1SMark Cave-Ayland sysbus_init_mmio(sbd, &phb->conf_mem); 115b0318ec1SMark Cave-Ayland sysbus_init_mmio(sbd, &phb->data_mem); 116a773e64aSMark Cave-Ayland sysbus_init_mmio(sbd, &s->pci_hole); 117a94e5f99SMark Cave-Ayland sysbus_init_mmio(sbd, &s->pci_io); 118b0318ec1SMark Cave-Ayland } 119b0318ec1SMark Cave-Ayland 120b0318ec1SMark Cave-Ayland static void grackle_pci_realize(PCIDevice *d, Error **errp) 121c0907c9eSPaolo Bonzini { 122c0907c9eSPaolo Bonzini d->config[0x09] = 0x01; 123c0907c9eSPaolo Bonzini } 124c0907c9eSPaolo Bonzini 125c0907c9eSPaolo Bonzini static void grackle_pci_class_init(ObjectClass *klass, void *data) 126c0907c9eSPaolo Bonzini { 127c0907c9eSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 128b0318ec1SMark Cave-Ayland PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 129c0907c9eSPaolo Bonzini 130b0318ec1SMark Cave-Ayland k->realize = grackle_pci_realize; 131c0907c9eSPaolo Bonzini k->vendor_id = PCI_VENDOR_ID_MOTOROLA; 132c0907c9eSPaolo Bonzini k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; 133c0907c9eSPaolo Bonzini k->revision = 0x00; 134c0907c9eSPaolo Bonzini k->class_id = PCI_CLASS_BRIDGE_HOST; 13508c58f92SMarkus Armbruster /* 13608c58f92SMarkus Armbruster * PCI-facing part of the host bridge, not usable without the 13708c58f92SMarkus Armbruster * host-facing part, which can't be device_add'ed, yet. 13808c58f92SMarkus Armbruster */ 139e90f2a8cSEduardo Habkost dc->user_creatable = false; 140c0907c9eSPaolo Bonzini } 141c0907c9eSPaolo Bonzini 142c0907c9eSPaolo Bonzini static const TypeInfo grackle_pci_info = { 143c0907c9eSPaolo Bonzini .name = "grackle", 144c0907c9eSPaolo Bonzini .parent = TYPE_PCI_DEVICE, 145c0907c9eSPaolo Bonzini .instance_size = sizeof(PCIDevice), 146c0907c9eSPaolo Bonzini .class_init = grackle_pci_class_init, 147fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) { 148fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 149fd3b02c8SEduardo Habkost { }, 150fd3b02c8SEduardo Habkost }, 151c0907c9eSPaolo Bonzini }; 152c0907c9eSPaolo Bonzini 153ac43eb2eSMark Cave-Ayland static char *grackle_ofw_unit_address(const SysBusDevice *dev) 154ac43eb2eSMark Cave-Ayland { 155ac43eb2eSMark Cave-Ayland GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(dev); 156ac43eb2eSMark Cave-Ayland 157ac43eb2eSMark Cave-Ayland return g_strdup_printf("%x", s->ofw_addr); 158ac43eb2eSMark Cave-Ayland } 159ac43eb2eSMark Cave-Ayland 160ac43eb2eSMark Cave-Ayland static Property grackle_properties[] = { 161ac43eb2eSMark Cave-Ayland DEFINE_PROP_UINT32("ofw-addr", GrackleState, ofw_addr, -1), 162ac43eb2eSMark Cave-Ayland DEFINE_PROP_END_OF_LIST() 163ac43eb2eSMark Cave-Ayland }; 164ac43eb2eSMark Cave-Ayland 165b0318ec1SMark Cave-Ayland static void grackle_class_init(ObjectClass *klass, void *data) 166c0907c9eSPaolo Bonzini { 167e1624435SLaurent Vivier DeviceClass *dc = DEVICE_CLASS(klass); 168ac43eb2eSMark Cave-Ayland SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 169c0907c9eSPaolo Bonzini 170b0318ec1SMark Cave-Ayland dc->realize = grackle_realize; 171*4f67d30bSMarc-André Lureau device_class_set_props(dc, grackle_properties); 172e1624435SLaurent Vivier set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 173ac43eb2eSMark Cave-Ayland dc->fw_name = "pci"; 174ac43eb2eSMark Cave-Ayland sbc->explicit_ofw_unit_address = grackle_ofw_unit_address; 175c0907c9eSPaolo Bonzini } 176c0907c9eSPaolo Bonzini 177b0318ec1SMark Cave-Ayland static const TypeInfo grackle_host_info = { 178c0907c9eSPaolo Bonzini .name = TYPE_GRACKLE_PCI_HOST_BRIDGE, 179c0907c9eSPaolo Bonzini .parent = TYPE_PCI_HOST_BRIDGE, 180c0907c9eSPaolo Bonzini .instance_size = sizeof(GrackleState), 181b0318ec1SMark Cave-Ayland .instance_init = grackle_init, 182b0318ec1SMark Cave-Ayland .class_init = grackle_class_init, 183c0907c9eSPaolo Bonzini }; 184c0907c9eSPaolo Bonzini 185c0907c9eSPaolo Bonzini static void grackle_register_types(void) 186c0907c9eSPaolo Bonzini { 187c0907c9eSPaolo Bonzini type_register_static(&grackle_pci_info); 188b0318ec1SMark Cave-Ayland type_register_static(&grackle_host_info); 189c0907c9eSPaolo Bonzini } 190c0907c9eSPaolo Bonzini 191c0907c9eSPaolo Bonzini type_init(grackle_register_types) 192