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