xref: /qemu/hw/pci-host/pnv_phb.c (revision fe5bfd4bb816faa1b3fa8c3c23165cdbadfa5c91)
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"
20e4e6db52SDaniel Henrique Barboza 
21e4e6db52SDaniel Henrique Barboza 
22e4e6db52SDaniel Henrique Barboza static void pnv_phb_realize(DeviceState *dev, Error **errp)
23e4e6db52SDaniel Henrique Barboza {
24e4e6db52SDaniel Henrique Barboza     PnvPHB *phb = PNV_PHB(dev);
25e4e6db52SDaniel Henrique Barboza     PCIHostState *pci = PCI_HOST_BRIDGE(dev);
26e4e6db52SDaniel Henrique Barboza     g_autofree char *phb_typename = NULL;
27e4e6db52SDaniel Henrique Barboza     g_autofree char *phb_rootport_typename = NULL;
28e4e6db52SDaniel Henrique Barboza 
29e4e6db52SDaniel Henrique Barboza     if (!phb->version) {
30e4e6db52SDaniel Henrique Barboza         error_setg(errp, "version not specified");
31e4e6db52SDaniel Henrique Barboza         return;
32e4e6db52SDaniel Henrique Barboza     }
33e4e6db52SDaniel Henrique Barboza 
34e4e6db52SDaniel Henrique Barboza     switch (phb->version) {
35e4e6db52SDaniel Henrique Barboza     case 3:
36e4e6db52SDaniel Henrique Barboza         phb_typename = g_strdup(TYPE_PNV_PHB3);
37e4e6db52SDaniel Henrique Barboza         phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT);
38e4e6db52SDaniel Henrique Barboza         break;
39e4e6db52SDaniel Henrique Barboza     case 4:
40e4e6db52SDaniel Henrique Barboza         phb_typename = g_strdup(TYPE_PNV_PHB4);
41e4e6db52SDaniel Henrique Barboza         phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT);
42e4e6db52SDaniel Henrique Barboza         break;
43e4e6db52SDaniel Henrique Barboza     case 5:
44e4e6db52SDaniel Henrique Barboza         phb_typename = g_strdup(TYPE_PNV_PHB5);
45e4e6db52SDaniel Henrique Barboza         phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT);
46e4e6db52SDaniel Henrique Barboza         break;
47e4e6db52SDaniel Henrique Barboza     default:
48e4e6db52SDaniel Henrique Barboza         g_assert_not_reached();
49e4e6db52SDaniel Henrique Barboza     }
50e4e6db52SDaniel Henrique Barboza 
51e4e6db52SDaniel Henrique Barboza     phb->backend = object_new(phb_typename);
52e4e6db52SDaniel Henrique Barboza     object_property_add_child(OBJECT(dev), "phb-backend", phb->backend);
53e4e6db52SDaniel Henrique Barboza 
54e4e6db52SDaniel Henrique Barboza     /* Passthrough child device properties to the proxy device */
55e4e6db52SDaniel Henrique Barboza     object_property_set_uint(phb->backend, "index", phb->phb_id, errp);
56e4e6db52SDaniel Henrique Barboza     object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp);
57e4e6db52SDaniel Henrique Barboza     object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp);
58e4e6db52SDaniel Henrique Barboza 
59e4e6db52SDaniel Henrique Barboza     if (phb->version == 3) {
60e4e6db52SDaniel Henrique Barboza         object_property_set_link(phb->backend, "chip",
61e4e6db52SDaniel Henrique Barboza                                  OBJECT(phb->chip), errp);
62e4e6db52SDaniel Henrique Barboza     } else {
63e4e6db52SDaniel Henrique Barboza         object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp);
64e4e6db52SDaniel Henrique Barboza     }
65e4e6db52SDaniel Henrique Barboza 
66e4e6db52SDaniel Henrique Barboza     if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) {
67e4e6db52SDaniel Henrique Barboza         return;
68e4e6db52SDaniel Henrique Barboza     }
69e4e6db52SDaniel Henrique Barboza 
70e4e6db52SDaniel Henrique Barboza     if (phb->version == 3) {
71e4e6db52SDaniel Henrique Barboza         pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend));
72*fe5bfd4bSDaniel Henrique Barboza     } else {
73*fe5bfd4bSDaniel Henrique Barboza         pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
74e4e6db52SDaniel Henrique Barboza     }
75e4e6db52SDaniel Henrique Barboza 
76e4e6db52SDaniel Henrique Barboza     pnv_phb_attach_root_port(pci, phb_rootport_typename,
77e4e6db52SDaniel Henrique Barboza                              phb->phb_id, phb->chip_id);
78e4e6db52SDaniel Henrique Barboza }
79e4e6db52SDaniel Henrique Barboza 
80e4e6db52SDaniel Henrique Barboza static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,
81e4e6db52SDaniel Henrique Barboza                                          PCIBus *rootbus)
82e4e6db52SDaniel Henrique Barboza {
83e4e6db52SDaniel Henrique Barboza     PnvPHB *phb = PNV_PHB(host_bridge);
84e4e6db52SDaniel Henrique Barboza 
85e4e6db52SDaniel Henrique Barboza     snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x",
86e4e6db52SDaniel Henrique Barboza              phb->chip_id, phb->phb_id);
87e4e6db52SDaniel Henrique Barboza     return phb->bus_path;
88e4e6db52SDaniel Henrique Barboza }
89e4e6db52SDaniel Henrique Barboza 
90e4e6db52SDaniel Henrique Barboza static Property pnv_phb_properties[] = {
91e4e6db52SDaniel Henrique Barboza     DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0),
92e4e6db52SDaniel Henrique Barboza     DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0),
93e4e6db52SDaniel Henrique Barboza     DEFINE_PROP_UINT32("version", PnvPHB, version, 0),
94e4e6db52SDaniel Henrique Barboza 
95e4e6db52SDaniel Henrique Barboza     DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *),
96e4e6db52SDaniel Henrique Barboza 
97e4e6db52SDaniel Henrique Barboza     DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC,
98e4e6db52SDaniel Henrique Barboza                      PnvPhb4PecState *),
99e4e6db52SDaniel Henrique Barboza 
100e4e6db52SDaniel Henrique Barboza     DEFINE_PROP_END_OF_LIST(),
101e4e6db52SDaniel Henrique Barboza };
102e4e6db52SDaniel Henrique Barboza 
103e4e6db52SDaniel Henrique Barboza static void pnv_phb_class_init(ObjectClass *klass, void *data)
104e4e6db52SDaniel Henrique Barboza {
105e4e6db52SDaniel Henrique Barboza     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
106e4e6db52SDaniel Henrique Barboza     DeviceClass *dc = DEVICE_CLASS(klass);
107e4e6db52SDaniel Henrique Barboza 
108e4e6db52SDaniel Henrique Barboza     hc->root_bus_path = pnv_phb_root_bus_path;
109e4e6db52SDaniel Henrique Barboza     dc->realize = pnv_phb_realize;
110e4e6db52SDaniel Henrique Barboza     device_class_set_props(dc, pnv_phb_properties);
111e4e6db52SDaniel Henrique Barboza     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
112e4e6db52SDaniel Henrique Barboza     dc->user_creatable = false;
113e4e6db52SDaniel Henrique Barboza }
114e4e6db52SDaniel Henrique Barboza 
115e4e6db52SDaniel Henrique Barboza static void pnv_phb_register_type(void)
116e4e6db52SDaniel Henrique Barboza {
117e4e6db52SDaniel Henrique Barboza     static const TypeInfo pnv_phb_type_info = {
118e4e6db52SDaniel Henrique Barboza         .name          = TYPE_PNV_PHB,
119e4e6db52SDaniel Henrique Barboza         .parent        = TYPE_PCIE_HOST_BRIDGE,
120e4e6db52SDaniel Henrique Barboza         .instance_size = sizeof(PnvPHB),
121e4e6db52SDaniel Henrique Barboza         .class_init    = pnv_phb_class_init,
122e4e6db52SDaniel Henrique Barboza     };
123e4e6db52SDaniel Henrique Barboza 
124e4e6db52SDaniel Henrique Barboza     type_register_static(&pnv_phb_type_info);
125e4e6db52SDaniel Henrique Barboza }
126e4e6db52SDaniel Henrique Barboza type_init(pnv_phb_register_type)
127