1*e4e6db52SDaniel Henrique Barboza /* 2*e4e6db52SDaniel Henrique Barboza * QEMU PowerPC PowerNV Proxy PHB model 3*e4e6db52SDaniel Henrique Barboza * 4*e4e6db52SDaniel Henrique Barboza * Copyright (c) 2022, IBM Corporation. 5*e4e6db52SDaniel Henrique Barboza * 6*e4e6db52SDaniel Henrique Barboza * This code is licensed under the GPL version 2 or later. See the 7*e4e6db52SDaniel Henrique Barboza * COPYING file in the top-level directory. 8*e4e6db52SDaniel Henrique Barboza */ 9*e4e6db52SDaniel Henrique Barboza 10*e4e6db52SDaniel Henrique Barboza #include "qemu/osdep.h" 11*e4e6db52SDaniel Henrique Barboza #include "qemu/log.h" 12*e4e6db52SDaniel Henrique Barboza #include "qapi/visitor.h" 13*e4e6db52SDaniel Henrique Barboza #include "qapi/error.h" 14*e4e6db52SDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h" 15*e4e6db52SDaniel Henrique Barboza #include "hw/pci-host/pnv_phb3.h" 16*e4e6db52SDaniel Henrique Barboza #include "hw/pci-host/pnv_phb4.h" 17*e4e6db52SDaniel Henrique Barboza #include "hw/ppc/pnv.h" 18*e4e6db52SDaniel Henrique Barboza #include "hw/qdev-properties.h" 19*e4e6db52SDaniel Henrique Barboza #include "qom/object.h" 20*e4e6db52SDaniel Henrique Barboza 21*e4e6db52SDaniel Henrique Barboza 22*e4e6db52SDaniel Henrique Barboza static void pnv_phb_realize(DeviceState *dev, Error **errp) 23*e4e6db52SDaniel Henrique Barboza { 24*e4e6db52SDaniel Henrique Barboza PnvPHB *phb = PNV_PHB(dev); 25*e4e6db52SDaniel Henrique Barboza PCIHostState *pci = PCI_HOST_BRIDGE(dev); 26*e4e6db52SDaniel Henrique Barboza g_autofree char *phb_typename = NULL; 27*e4e6db52SDaniel Henrique Barboza g_autofree char *phb_rootport_typename = NULL; 28*e4e6db52SDaniel Henrique Barboza 29*e4e6db52SDaniel Henrique Barboza if (!phb->version) { 30*e4e6db52SDaniel Henrique Barboza error_setg(errp, "version not specified"); 31*e4e6db52SDaniel Henrique Barboza return; 32*e4e6db52SDaniel Henrique Barboza } 33*e4e6db52SDaniel Henrique Barboza 34*e4e6db52SDaniel Henrique Barboza switch (phb->version) { 35*e4e6db52SDaniel Henrique Barboza case 3: 36*e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB3); 37*e4e6db52SDaniel Henrique Barboza phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT); 38*e4e6db52SDaniel Henrique Barboza break; 39*e4e6db52SDaniel Henrique Barboza case 4: 40*e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB4); 41*e4e6db52SDaniel Henrique Barboza phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT); 42*e4e6db52SDaniel Henrique Barboza break; 43*e4e6db52SDaniel Henrique Barboza case 5: 44*e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB5); 45*e4e6db52SDaniel Henrique Barboza phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT); 46*e4e6db52SDaniel Henrique Barboza break; 47*e4e6db52SDaniel Henrique Barboza default: 48*e4e6db52SDaniel Henrique Barboza g_assert_not_reached(); 49*e4e6db52SDaniel Henrique Barboza } 50*e4e6db52SDaniel Henrique Barboza 51*e4e6db52SDaniel Henrique Barboza phb->backend = object_new(phb_typename); 52*e4e6db52SDaniel Henrique Barboza object_property_add_child(OBJECT(dev), "phb-backend", phb->backend); 53*e4e6db52SDaniel Henrique Barboza 54*e4e6db52SDaniel Henrique Barboza /* Passthrough child device properties to the proxy device */ 55*e4e6db52SDaniel Henrique Barboza object_property_set_uint(phb->backend, "index", phb->phb_id, errp); 56*e4e6db52SDaniel Henrique Barboza object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); 57*e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); 58*e4e6db52SDaniel Henrique Barboza 59*e4e6db52SDaniel Henrique Barboza if (phb->version == 3) { 60*e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "chip", 61*e4e6db52SDaniel Henrique Barboza OBJECT(phb->chip), errp); 62*e4e6db52SDaniel Henrique Barboza } else { 63*e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp); 64*e4e6db52SDaniel Henrique Barboza } 65*e4e6db52SDaniel Henrique Barboza 66*e4e6db52SDaniel Henrique Barboza if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) { 67*e4e6db52SDaniel Henrique Barboza return; 68*e4e6db52SDaniel Henrique Barboza } 69*e4e6db52SDaniel Henrique Barboza 70*e4e6db52SDaniel Henrique Barboza if (phb->version == 3) { 71*e4e6db52SDaniel Henrique Barboza pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); 72*e4e6db52SDaniel Henrique Barboza } 73*e4e6db52SDaniel Henrique Barboza 74*e4e6db52SDaniel Henrique Barboza pnv_phb_attach_root_port(pci, phb_rootport_typename, 75*e4e6db52SDaniel Henrique Barboza phb->phb_id, phb->chip_id); 76*e4e6db52SDaniel Henrique Barboza } 77*e4e6db52SDaniel Henrique Barboza 78*e4e6db52SDaniel Henrique Barboza static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, 79*e4e6db52SDaniel Henrique Barboza PCIBus *rootbus) 80*e4e6db52SDaniel Henrique Barboza { 81*e4e6db52SDaniel Henrique Barboza PnvPHB *phb = PNV_PHB(host_bridge); 82*e4e6db52SDaniel Henrique Barboza 83*e4e6db52SDaniel Henrique Barboza snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", 84*e4e6db52SDaniel Henrique Barboza phb->chip_id, phb->phb_id); 85*e4e6db52SDaniel Henrique Barboza return phb->bus_path; 86*e4e6db52SDaniel Henrique Barboza } 87*e4e6db52SDaniel Henrique Barboza 88*e4e6db52SDaniel Henrique Barboza static Property pnv_phb_properties[] = { 89*e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0), 90*e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0), 91*e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("version", PnvPHB, version, 0), 92*e4e6db52SDaniel Henrique Barboza 93*e4e6db52SDaniel Henrique Barboza DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *), 94*e4e6db52SDaniel Henrique Barboza 95*e4e6db52SDaniel Henrique Barboza DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC, 96*e4e6db52SDaniel Henrique Barboza PnvPhb4PecState *), 97*e4e6db52SDaniel Henrique Barboza 98*e4e6db52SDaniel Henrique Barboza DEFINE_PROP_END_OF_LIST(), 99*e4e6db52SDaniel Henrique Barboza }; 100*e4e6db52SDaniel Henrique Barboza 101*e4e6db52SDaniel Henrique Barboza static void pnv_phb_class_init(ObjectClass *klass, void *data) 102*e4e6db52SDaniel Henrique Barboza { 103*e4e6db52SDaniel Henrique Barboza PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); 104*e4e6db52SDaniel Henrique Barboza DeviceClass *dc = DEVICE_CLASS(klass); 105*e4e6db52SDaniel Henrique Barboza 106*e4e6db52SDaniel Henrique Barboza hc->root_bus_path = pnv_phb_root_bus_path; 107*e4e6db52SDaniel Henrique Barboza dc->realize = pnv_phb_realize; 108*e4e6db52SDaniel Henrique Barboza device_class_set_props(dc, pnv_phb_properties); 109*e4e6db52SDaniel Henrique Barboza set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 110*e4e6db52SDaniel Henrique Barboza dc->user_creatable = false; 111*e4e6db52SDaniel Henrique Barboza } 112*e4e6db52SDaniel Henrique Barboza 113*e4e6db52SDaniel Henrique Barboza static void pnv_phb_register_type(void) 114*e4e6db52SDaniel Henrique Barboza { 115*e4e6db52SDaniel Henrique Barboza static const TypeInfo pnv_phb_type_info = { 116*e4e6db52SDaniel Henrique Barboza .name = TYPE_PNV_PHB, 117*e4e6db52SDaniel Henrique Barboza .parent = TYPE_PCIE_HOST_BRIDGE, 118*e4e6db52SDaniel Henrique Barboza .instance_size = sizeof(PnvPHB), 119*e4e6db52SDaniel Henrique Barboza .class_init = pnv_phb_class_init, 120*e4e6db52SDaniel Henrique Barboza }; 121*e4e6db52SDaniel Henrique Barboza 122*e4e6db52SDaniel Henrique Barboza type_register_static(&pnv_phb_type_info); 123*e4e6db52SDaniel Henrique Barboza } 124*e4e6db52SDaniel Henrique Barboza type_init(pnv_phb_register_type) 125