1e4e6db52SDaniel Henrique Barboza /* 2e4e6db52SDaniel Henrique Barboza * QEMU PowerPC PowerNV Proxy PHB model 3e4e6db52SDaniel Henrique Barboza * 4e4e6db52SDaniel Henrique Barboza * Copyright (c) 2022, IBM Corporation. 5e4e6db52SDaniel Henrique Barboza * 6e4e6db52SDaniel Henrique Barboza * This code is licensed under the GPL version 2 or later. See the 7e4e6db52SDaniel Henrique Barboza * COPYING file in the top-level directory. 8e4e6db52SDaniel Henrique Barboza */ 9e4e6db52SDaniel Henrique Barboza 10e4e6db52SDaniel Henrique Barboza #include "qemu/osdep.h" 11e4e6db52SDaniel Henrique Barboza #include "qemu/log.h" 12e4e6db52SDaniel Henrique Barboza #include "qapi/visitor.h" 13e4e6db52SDaniel Henrique Barboza #include "qapi/error.h" 14e4e6db52SDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h" 15e4e6db52SDaniel Henrique Barboza #include "hw/pci-host/pnv_phb3.h" 16e4e6db52SDaniel Henrique Barboza #include "hw/pci-host/pnv_phb4.h" 17e4e6db52SDaniel Henrique Barboza #include "hw/ppc/pnv.h" 18e4e6db52SDaniel Henrique Barboza #include "hw/qdev-properties.h" 19e4e6db52SDaniel Henrique Barboza #include "qom/object.h" 20*32cad1ffSPhilippe Mathieu-Daudé #include "system/system.h" 21e4e6db52SDaniel Henrique Barboza 22ba47c3a4SDaniel Henrique Barboza 23ba47c3a4SDaniel Henrique Barboza /* 243466bb50SDaniel Henrique Barboza * Set the QOM parent and parent bus of an object child. If the device 253466bb50SDaniel Henrique Barboza * state associated with the child has an id, use it as QOM id. 263466bb50SDaniel Henrique Barboza * Otherwise use object_typename[index] as QOM id. 273466bb50SDaniel Henrique Barboza * 28f1c0cff8SMichael Tokarev * This helper does both operations at the same time because setting 293466bb50SDaniel Henrique Barboza * a new QOM child will erase the bus parent of the device. This happens 303466bb50SDaniel Henrique Barboza * because object_unparent() will call object_property_del_child(), 313466bb50SDaniel Henrique Barboza * which in turn calls the property release callback prop->release if 323466bb50SDaniel Henrique Barboza * it's defined. In our case this callback is set to 333466bb50SDaniel Henrique Barboza * object_finalize_child_property(), which was assigned during the 343466bb50SDaniel Henrique Barboza * first object_property_add_child() call. This callback will end up 353466bb50SDaniel Henrique Barboza * calling device_unparent(), and this function removes the device 363466bb50SDaniel Henrique Barboza * from its parent bus. 373466bb50SDaniel Henrique Barboza * 383466bb50SDaniel Henrique Barboza * The QOM and parent bus to be set aren´t necessarily related, so 393466bb50SDaniel Henrique Barboza * let's receive both as arguments. 40ba47c3a4SDaniel Henrique Barboza */ 413466bb50SDaniel Henrique Barboza static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, 423466bb50SDaniel Henrique Barboza Object *child, int index, 433466bb50SDaniel Henrique Barboza Error **errp) 44ba47c3a4SDaniel Henrique Barboza { 45ba47c3a4SDaniel Henrique Barboza g_autofree char *default_id = 46ba47c3a4SDaniel Henrique Barboza g_strdup_printf("%s[%d]", object_get_typename(child), index); 47ba47c3a4SDaniel Henrique Barboza const char *dev_id = DEVICE(child)->id; 48ba47c3a4SDaniel Henrique Barboza 49ba47c3a4SDaniel Henrique Barboza if (child->parent == parent) { 503466bb50SDaniel Henrique Barboza return true; 51ba47c3a4SDaniel Henrique Barboza } 52ba47c3a4SDaniel Henrique Barboza 53ba47c3a4SDaniel Henrique Barboza object_ref(child); 54ba47c3a4SDaniel Henrique Barboza object_unparent(child); 55ba47c3a4SDaniel Henrique Barboza object_property_add_child(parent, dev_id ? dev_id : default_id, child); 56ba47c3a4SDaniel Henrique Barboza object_unref(child); 573466bb50SDaniel Henrique Barboza 583466bb50SDaniel Henrique Barboza if (!qdev_set_parent_bus(DEVICE(child), parent_bus, errp)) { 593466bb50SDaniel Henrique Barboza return false; 60ba47c3a4SDaniel Henrique Barboza } 61ba47c3a4SDaniel Henrique Barboza 623466bb50SDaniel Henrique Barboza return true; 63ba47c3a4SDaniel Henrique Barboza } 64ba47c3a4SDaniel Henrique Barboza 65ddf0676fSFrederic Barrat static Object *pnv_phb_user_get_parent(PnvChip *chip, PnvPHB *phb, Error **errp) 66ddf0676fSFrederic Barrat { 67ddf0676fSFrederic Barrat if (phb->version == 3) { 68ddf0676fSFrederic Barrat return OBJECT(pnv_chip_add_phb(chip, phb)); 69ddf0676fSFrederic Barrat } else { 70ddf0676fSFrederic Barrat return OBJECT(pnv_pec_add_phb(chip, phb, errp)); 71ddf0676fSFrederic Barrat } 72ddf0676fSFrederic Barrat } 73ddf0676fSFrederic Barrat 74e5ea9436SDaniel Henrique Barboza /* 75ba47c3a4SDaniel Henrique Barboza * User created devices won't have the initial setup that default 76ba47c3a4SDaniel Henrique Barboza * devices have. This setup consists of assigning a parent device 77ba47c3a4SDaniel Henrique Barboza * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent 78ba47c3a4SDaniel Henrique Barboza * of the PHB. 79ba47c3a4SDaniel Henrique Barboza */ 80ba47c3a4SDaniel Henrique Barboza static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) 81ba47c3a4SDaniel Henrique Barboza { 82ba47c3a4SDaniel Henrique Barboza PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 83ba47c3a4SDaniel Henrique Barboza PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); 84ba47c3a4SDaniel Henrique Barboza Object *parent = NULL; 85ba47c3a4SDaniel Henrique Barboza 86ba47c3a4SDaniel Henrique Barboza if (!chip) { 87ba47c3a4SDaniel Henrique Barboza error_setg(errp, "invalid chip id: %d", phb->chip_id); 88ba47c3a4SDaniel Henrique Barboza return false; 89ba47c3a4SDaniel Henrique Barboza } 90ba47c3a4SDaniel Henrique Barboza 91ddf0676fSFrederic Barrat parent = pnv_phb_user_get_parent(chip, phb, errp); 92ba47c3a4SDaniel Henrique Barboza if (!parent) { 93ba47c3a4SDaniel Henrique Barboza return false; 94ba47c3a4SDaniel Henrique Barboza } 95ba47c3a4SDaniel Henrique Barboza 96ba47c3a4SDaniel Henrique Barboza /* 97ba47c3a4SDaniel Henrique Barboza * Reparent user created devices to the chip to build 98ba47c3a4SDaniel Henrique Barboza * correctly the device tree. pnv_xscom_dt() needs every 99ba47c3a4SDaniel Henrique Barboza * PHB to be a child of the chip to build the DT correctly. 100ba47c3a4SDaniel Henrique Barboza */ 1013466bb50SDaniel Henrique Barboza if (!pnv_parent_fixup(parent, qdev_get_parent_bus(DEVICE(chip)), 1023466bb50SDaniel Henrique Barboza OBJECT(phb), phb->phb_id, errp)) { 1033466bb50SDaniel Henrique Barboza return false; 1043466bb50SDaniel Henrique Barboza } 105ba47c3a4SDaniel Henrique Barboza 106ba47c3a4SDaniel Henrique Barboza return true; 107ba47c3a4SDaniel Henrique Barboza } 108ba47c3a4SDaniel Henrique Barboza 109e4e6db52SDaniel Henrique Barboza static void pnv_phb_realize(DeviceState *dev, Error **errp) 110e4e6db52SDaniel Henrique Barboza { 111e4e6db52SDaniel Henrique Barboza PnvPHB *phb = PNV_PHB(dev); 112e4e6db52SDaniel Henrique Barboza PCIHostState *pci = PCI_HOST_BRIDGE(dev); 113e4e6db52SDaniel Henrique Barboza g_autofree char *phb_typename = NULL; 114e4e6db52SDaniel Henrique Barboza 115e4e6db52SDaniel Henrique Barboza if (!phb->version) { 116e4e6db52SDaniel Henrique Barboza error_setg(errp, "version not specified"); 117e4e6db52SDaniel Henrique Barboza return; 118e4e6db52SDaniel Henrique Barboza } 119e4e6db52SDaniel Henrique Barboza 120e4e6db52SDaniel Henrique Barboza switch (phb->version) { 121e4e6db52SDaniel Henrique Barboza case 3: 122e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB3); 123e4e6db52SDaniel Henrique Barboza break; 124e4e6db52SDaniel Henrique Barboza case 4: 125e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB4); 126e4e6db52SDaniel Henrique Barboza break; 127e4e6db52SDaniel Henrique Barboza case 5: 128e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB5); 129e4e6db52SDaniel Henrique Barboza break; 130e4e6db52SDaniel Henrique Barboza default: 131e4e6db52SDaniel Henrique Barboza g_assert_not_reached(); 132e4e6db52SDaniel Henrique Barboza } 133e4e6db52SDaniel Henrique Barboza 134e4e6db52SDaniel Henrique Barboza phb->backend = object_new(phb_typename); 135e4e6db52SDaniel Henrique Barboza object_property_add_child(OBJECT(dev), "phb-backend", phb->backend); 136e4e6db52SDaniel Henrique Barboza 137e4e6db52SDaniel Henrique Barboza /* Passthrough child device properties to the proxy device */ 138e4e6db52SDaniel Henrique Barboza object_property_set_uint(phb->backend, "index", phb->phb_id, errp); 139e4e6db52SDaniel Henrique Barboza object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); 140e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); 141e4e6db52SDaniel Henrique Barboza 142ba47c3a4SDaniel Henrique Barboza /* 143ba47c3a4SDaniel Henrique Barboza * Handle user created devices. User devices will not have a 144ba47c3a4SDaniel Henrique Barboza * pointer to a chip (PHB3) and a PEC (PHB4/5). 145ba47c3a4SDaniel Henrique Barboza */ 146ba47c3a4SDaniel Henrique Barboza if (!phb->chip && !phb->pec) { 147ba47c3a4SDaniel Henrique Barboza if (!pnv_phb_user_device_init(phb, errp)) { 148ba47c3a4SDaniel Henrique Barboza return; 149ba47c3a4SDaniel Henrique Barboza } 150ba47c3a4SDaniel Henrique Barboza } 151ba47c3a4SDaniel Henrique Barboza 152e4e6db52SDaniel Henrique Barboza if (phb->version == 3) { 153e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "chip", 154e4e6db52SDaniel Henrique Barboza OBJECT(phb->chip), errp); 155e4e6db52SDaniel Henrique Barboza } else { 156e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp); 157e4e6db52SDaniel Henrique Barboza } 158e4e6db52SDaniel Henrique Barboza 159e4e6db52SDaniel Henrique Barboza if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) { 160e4e6db52SDaniel Henrique Barboza return; 161e4e6db52SDaniel Henrique Barboza } 162e4e6db52SDaniel Henrique Barboza 163e4e6db52SDaniel Henrique Barboza if (phb->version == 3) { 164e4e6db52SDaniel Henrique Barboza pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); 165fe5bfd4bSDaniel Henrique Barboza } else { 166fe5bfd4bSDaniel Henrique Barboza pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); 167e4e6db52SDaniel Henrique Barboza } 168e4e6db52SDaniel Henrique Barboza 1696a1e1ce2SDaniel Henrique Barboza if (defaults_enabled()) { 1706a1e1ce2SDaniel Henrique Barboza PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); 171892c3ad0SDaniel Henrique Barboza 1726a1e1ce2SDaniel Henrique Barboza pci_realize_and_unref(root, pci->bus, errp); 1736a1e1ce2SDaniel Henrique Barboza } 174e4e6db52SDaniel Henrique Barboza } 175e4e6db52SDaniel Henrique Barboza 176e4e6db52SDaniel Henrique Barboza static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, 177e4e6db52SDaniel Henrique Barboza PCIBus *rootbus) 178e4e6db52SDaniel Henrique Barboza { 179e4e6db52SDaniel Henrique Barboza PnvPHB *phb = PNV_PHB(host_bridge); 180e4e6db52SDaniel Henrique Barboza 181e4e6db52SDaniel Henrique Barboza snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", 182e4e6db52SDaniel Henrique Barboza phb->chip_id, phb->phb_id); 183e4e6db52SDaniel Henrique Barboza return phb->bus_path; 184e4e6db52SDaniel Henrique Barboza } 185e4e6db52SDaniel Henrique Barboza 186909a5c0aSRichard Henderson static const Property pnv_phb_properties[] = { 187e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0), 188e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0), 189e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("version", PnvPHB, version, 0), 190e4e6db52SDaniel Henrique Barboza 191e4e6db52SDaniel Henrique Barboza DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *), 192e4e6db52SDaniel Henrique Barboza 193e4e6db52SDaniel Henrique Barboza DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC, 194e4e6db52SDaniel Henrique Barboza PnvPhb4PecState *), 195e4e6db52SDaniel Henrique Barboza 196e4e6db52SDaniel Henrique Barboza DEFINE_PROP_END_OF_LIST(), 197e4e6db52SDaniel Henrique Barboza }; 198e4e6db52SDaniel Henrique Barboza 199e4e6db52SDaniel Henrique Barboza static void pnv_phb_class_init(ObjectClass *klass, void *data) 200e4e6db52SDaniel Henrique Barboza { 201e4e6db52SDaniel Henrique Barboza PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); 202e4e6db52SDaniel Henrique Barboza DeviceClass *dc = DEVICE_CLASS(klass); 203e4e6db52SDaniel Henrique Barboza 204e4e6db52SDaniel Henrique Barboza hc->root_bus_path = pnv_phb_root_bus_path; 205e4e6db52SDaniel Henrique Barboza dc->realize = pnv_phb_realize; 206e4e6db52SDaniel Henrique Barboza device_class_set_props(dc, pnv_phb_properties); 207e4e6db52SDaniel Henrique Barboza set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 208892c3ad0SDaniel Henrique Barboza dc->user_creatable = true; 209e4e6db52SDaniel Henrique Barboza } 210e4e6db52SDaniel Henrique Barboza 211ad80e367SPeter Maydell static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type) 212e4e6db52SDaniel Henrique Barboza { 213f4c636b0SPeter Maydell PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj); 214f4c636b0SPeter Maydell PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(obj); 215f4c636b0SPeter Maydell PCIDevice *d = PCI_DEVICE(obj); 2165ba76b61SDaniel Henrique Barboza uint8_t *conf = d->config; 2175ba76b61SDaniel Henrique Barboza 218f4c636b0SPeter Maydell if (rpc->parent_phases.hold) { 219ad80e367SPeter Maydell rpc->parent_phases.hold(obj, type); 220f4c636b0SPeter Maydell } 2215ba76b61SDaniel Henrique Barboza 2225ba76b61SDaniel Henrique Barboza if (phb_rp->version == 3) { 2235ba76b61SDaniel Henrique Barboza return; 2245ba76b61SDaniel Henrique Barboza } 2255ba76b61SDaniel Henrique Barboza 2265ba76b61SDaniel Henrique Barboza /* PHB4 and later requires these extra reset steps */ 2275ba76b61SDaniel Henrique Barboza pci_byte_test_and_set_mask(conf + PCI_IO_BASE, 2285ba76b61SDaniel Henrique Barboza PCI_IO_RANGE_MASK & 0xff); 2295ba76b61SDaniel Henrique Barboza pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, 2305ba76b61SDaniel Henrique Barboza PCI_IO_RANGE_MASK & 0xff); 2315ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_MEMORY_BASE, 0); 2325ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); 2335ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); 2345ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); 2355ba76b61SDaniel Henrique Barboza pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ 2365ba76b61SDaniel Henrique Barboza pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); 2375ba76b61SDaniel Henrique Barboza pci_config_set_interrupt_pin(conf, 0); 2385ba76b61SDaniel Henrique Barboza } 2395ba76b61SDaniel Henrique Barboza 2405ba76b61SDaniel Henrique Barboza static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) 2415ba76b61SDaniel Henrique Barboza { 2425ba76b61SDaniel Henrique Barboza PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); 2435ba76b61SDaniel Henrique Barboza PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); 244c2f3f78aSDaniel Henrique Barboza PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev)); 2455ba76b61SDaniel Henrique Barboza PCIDevice *pci = PCI_DEVICE(dev); 2465ba76b61SDaniel Henrique Barboza uint16_t device_id = 0; 2475ba76b61SDaniel Henrique Barboza Error *local_err = NULL; 248c2f3f78aSDaniel Henrique Barboza int chip_id, index; 249c2f3f78aSDaniel Henrique Barboza 2506a1e1ce2SDaniel Henrique Barboza /* 2516a1e1ce2SDaniel Henrique Barboza * 'index' will be used both as a PCIE slot value and to calculate 2526a1e1ce2SDaniel Henrique Barboza * QOM id. 'chip_id' is going to be used as PCIE chassis for the 2536a1e1ce2SDaniel Henrique Barboza * root port. 2546a1e1ce2SDaniel Henrique Barboza */ 255ec565134SThomas Huth chip_id = object_property_get_int(OBJECT(bus), "chip-id", &local_err); 256ec565134SThomas Huth if (local_err) { 257ec565134SThomas Huth error_propagate(errp, local_err); 258ec565134SThomas Huth return; 259ec565134SThomas Huth } 260ec565134SThomas Huth index = object_property_get_int(OBJECT(bus), "phb-id", &local_err); 261ec565134SThomas Huth if (local_err) { 262ec565134SThomas Huth error_propagate(errp, local_err); 263ec565134SThomas Huth return; 264ec565134SThomas Huth } 265c2f3f78aSDaniel Henrique Barboza 266c2f3f78aSDaniel Henrique Barboza /* Set unique chassis/slot values for the root port */ 267c2f3f78aSDaniel Henrique Barboza qdev_prop_set_uint8(dev, "chassis", chip_id); 268c2f3f78aSDaniel Henrique Barboza qdev_prop_set_uint16(dev, "slot", index); 2695ba76b61SDaniel Henrique Barboza 2706a1e1ce2SDaniel Henrique Barboza /* 2716a1e1ce2SDaniel Henrique Barboza * User created root ports are QOM parented to one of 2726a1e1ce2SDaniel Henrique Barboza * the peripheral containers but it's already at the right 2736a1e1ce2SDaniel Henrique Barboza * parent bus. Change the QOM parent to be the same as the 2746a1e1ce2SDaniel Henrique Barboza * parent bus it's already assigned to. 2756a1e1ce2SDaniel Henrique Barboza */ 2766a1e1ce2SDaniel Henrique Barboza if (!pnv_parent_fixup(OBJECT(bus), BUS(bus), OBJECT(dev), 2776a1e1ce2SDaniel Henrique Barboza index, errp)) { 2786a1e1ce2SDaniel Henrique Barboza return; 2796a1e1ce2SDaniel Henrique Barboza } 2806a1e1ce2SDaniel Henrique Barboza 2815ba76b61SDaniel Henrique Barboza rpc->parent_realize(dev, &local_err); 2825ba76b61SDaniel Henrique Barboza if (local_err) { 2835ba76b61SDaniel Henrique Barboza error_propagate(errp, local_err); 2845ba76b61SDaniel Henrique Barboza return; 2855ba76b61SDaniel Henrique Barboza } 2865ba76b61SDaniel Henrique Barboza 2875ba76b61SDaniel Henrique Barboza switch (phb_rp->version) { 2885ba76b61SDaniel Henrique Barboza case 3: 2895ba76b61SDaniel Henrique Barboza device_id = PNV_PHB3_DEVICE_ID; 2905ba76b61SDaniel Henrique Barboza break; 2915ba76b61SDaniel Henrique Barboza case 4: 2925ba76b61SDaniel Henrique Barboza device_id = PNV_PHB4_DEVICE_ID; 2935ba76b61SDaniel Henrique Barboza break; 2945ba76b61SDaniel Henrique Barboza case 5: 2955ba76b61SDaniel Henrique Barboza device_id = PNV_PHB5_DEVICE_ID; 2965ba76b61SDaniel Henrique Barboza break; 2975ba76b61SDaniel Henrique Barboza default: 2985ba76b61SDaniel Henrique Barboza g_assert_not_reached(); 2995ba76b61SDaniel Henrique Barboza } 3005ba76b61SDaniel Henrique Barboza 3015ba76b61SDaniel Henrique Barboza pci_config_set_device_id(pci->config, device_id); 3025ba76b61SDaniel Henrique Barboza pci_config_set_interrupt_pin(pci->config, 0); 3035ba76b61SDaniel Henrique Barboza } 3045ba76b61SDaniel Henrique Barboza 305909a5c0aSRichard Henderson static const Property pnv_phb_root_port_properties[] = { 3065ba76b61SDaniel Henrique Barboza DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0), 3075ba76b61SDaniel Henrique Barboza 3085ba76b61SDaniel Henrique Barboza DEFINE_PROP_END_OF_LIST(), 3095ba76b61SDaniel Henrique Barboza }; 3105ba76b61SDaniel Henrique Barboza 3115ba76b61SDaniel Henrique Barboza static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data) 3125ba76b61SDaniel Henrique Barboza { 3135ba76b61SDaniel Henrique Barboza DeviceClass *dc = DEVICE_CLASS(klass); 314f4c636b0SPeter Maydell ResettableClass *rc = RESETTABLE_CLASS(klass); 3155ba76b61SDaniel Henrique Barboza PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 3165ba76b61SDaniel Henrique Barboza PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); 3175ba76b61SDaniel Henrique Barboza 3185ba76b61SDaniel Henrique Barboza dc->desc = "IBM PHB PCIE Root Port"; 3195ba76b61SDaniel Henrique Barboza 3205ba76b61SDaniel Henrique Barboza device_class_set_props(dc, pnv_phb_root_port_properties); 3215ba76b61SDaniel Henrique Barboza device_class_set_parent_realize(dc, pnv_phb_root_port_realize, 3225ba76b61SDaniel Henrique Barboza &rpc->parent_realize); 323f4c636b0SPeter Maydell resettable_class_set_parent_phases(rc, NULL, pnv_phb_root_port_reset_hold, 324f4c636b0SPeter Maydell NULL, &rpc->parent_phases); 325892c3ad0SDaniel Henrique Barboza dc->user_creatable = true; 3265ba76b61SDaniel Henrique Barboza 3275ba76b61SDaniel Henrique Barboza k->vendor_id = PCI_VENDOR_ID_IBM; 3285ba76b61SDaniel Henrique Barboza /* device_id will be written during realize() */ 3295ba76b61SDaniel Henrique Barboza k->device_id = 0; 3305ba76b61SDaniel Henrique Barboza k->revision = 0; 3315ba76b61SDaniel Henrique Barboza 3325ba76b61SDaniel Henrique Barboza rpc->exp_offset = 0x48; 3335ba76b61SDaniel Henrique Barboza rpc->aer_offset = 0x100; 3345ba76b61SDaniel Henrique Barboza } 3355ba76b61SDaniel Henrique Barboza 336e4e6db52SDaniel Henrique Barboza static const TypeInfo pnv_phb_type_info = { 337e4e6db52SDaniel Henrique Barboza .name = TYPE_PNV_PHB, 338e4e6db52SDaniel Henrique Barboza .parent = TYPE_PCIE_HOST_BRIDGE, 339e4e6db52SDaniel Henrique Barboza .instance_size = sizeof(PnvPHB), 340e4e6db52SDaniel Henrique Barboza .class_init = pnv_phb_class_init, 341e4e6db52SDaniel Henrique Barboza }; 342e4e6db52SDaniel Henrique Barboza 3435ba76b61SDaniel Henrique Barboza static const TypeInfo pnv_phb_root_port_info = { 3445ba76b61SDaniel Henrique Barboza .name = TYPE_PNV_PHB_ROOT_PORT, 3455ba76b61SDaniel Henrique Barboza .parent = TYPE_PCIE_ROOT_PORT, 3465ba76b61SDaniel Henrique Barboza .instance_size = sizeof(PnvPHBRootPort), 3475ba76b61SDaniel Henrique Barboza .class_init = pnv_phb_root_port_class_init, 3485ba76b61SDaniel Henrique Barboza }; 3495ba76b61SDaniel Henrique Barboza 3505ba76b61SDaniel Henrique Barboza static void pnv_phb_register_types(void) 3515ba76b61SDaniel Henrique Barboza { 352e4e6db52SDaniel Henrique Barboza type_register_static(&pnv_phb_type_info); 3535ba76b61SDaniel Henrique Barboza type_register_static(&pnv_phb_root_port_info); 354e4e6db52SDaniel Henrique Barboza } 3555ba76b61SDaniel Henrique Barboza 3565ba76b61SDaniel Henrique Barboza type_init(pnv_phb_register_types) 357