xref: /openbmc/qemu/hw/pci-host/pnv_phb.c (revision e5ea94360eba4818467283a259d8d681f0da799f)
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  * Attach a root port device.
23  *
24  * 'index' will be used both as a PCIE slot value and to calculate
25  * QOM id. 'chip_id' is going to be used as PCIE chassis for the
26  * root port.
27  */
28 static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id)
29 {
30     PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
31     g_autofree char *default_id = g_strdup_printf("%s[%d]",
32                                                   TYPE_PNV_PHB_ROOT_PORT,
33                                                   index);
34     const char *dev_id = DEVICE(root)->id;
35 
36     object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
37                               OBJECT(root));
38 
39     /* Set unique chassis/slot values for the root port */
40     qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id);
41     qdev_prop_set_uint16(DEVICE(root), "slot", index);
42 
43     pci_realize_and_unref(root, pci->bus, &error_fatal);
44 }
45 
46 static void pnv_phb_realize(DeviceState *dev, Error **errp)
47 {
48     PnvPHB *phb = PNV_PHB(dev);
49     PCIHostState *pci = PCI_HOST_BRIDGE(dev);
50     g_autofree char *phb_typename = NULL;
51 
52     if (!phb->version) {
53         error_setg(errp, "version not specified");
54         return;
55     }
56 
57     switch (phb->version) {
58     case 3:
59         phb_typename = g_strdup(TYPE_PNV_PHB3);
60         break;
61     case 4:
62         phb_typename = g_strdup(TYPE_PNV_PHB4);
63         break;
64     case 5:
65         phb_typename = g_strdup(TYPE_PNV_PHB5);
66         break;
67     default:
68         g_assert_not_reached();
69     }
70 
71     phb->backend = object_new(phb_typename);
72     object_property_add_child(OBJECT(dev), "phb-backend", phb->backend);
73 
74     /* Passthrough child device properties to the proxy device */
75     object_property_set_uint(phb->backend, "index", phb->phb_id, errp);
76     object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp);
77     object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp);
78 
79     if (phb->version == 3) {
80         object_property_set_link(phb->backend, "chip",
81                                  OBJECT(phb->chip), errp);
82     } else {
83         object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp);
84     }
85 
86     if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) {
87         return;
88     }
89 
90     if (phb->version == 3) {
91         pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend));
92     } else {
93         pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
94     }
95 
96     pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id);
97 }
98 
99 static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,
100                                          PCIBus *rootbus)
101 {
102     PnvPHB *phb = PNV_PHB(host_bridge);
103 
104     snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x",
105              phb->chip_id, phb->phb_id);
106     return phb->bus_path;
107 }
108 
109 static Property pnv_phb_properties[] = {
110     DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0),
111     DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0),
112     DEFINE_PROP_UINT32("version", PnvPHB, version, 0),
113 
114     DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *),
115 
116     DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC,
117                      PnvPhb4PecState *),
118 
119     DEFINE_PROP_END_OF_LIST(),
120 };
121 
122 static void pnv_phb_class_init(ObjectClass *klass, void *data)
123 {
124     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
125     DeviceClass *dc = DEVICE_CLASS(klass);
126 
127     hc->root_bus_path = pnv_phb_root_bus_path;
128     dc->realize = pnv_phb_realize;
129     device_class_set_props(dc, pnv_phb_properties);
130     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
131     dc->user_creatable = false;
132 }
133 
134 static void pnv_phb_root_port_reset(DeviceState *dev)
135 {
136     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
137     PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
138     PCIDevice *d = PCI_DEVICE(dev);
139     uint8_t *conf = d->config;
140 
141     rpc->parent_reset(dev);
142 
143     if (phb_rp->version == 3) {
144         return;
145     }
146 
147     /* PHB4 and later requires these extra reset steps */
148     pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
149                                PCI_IO_RANGE_MASK & 0xff);
150     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
151                                  PCI_IO_RANGE_MASK & 0xff);
152     pci_set_word(conf + PCI_MEMORY_BASE, 0);
153     pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
154     pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
155     pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
156     pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
157     pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
158     pci_config_set_interrupt_pin(conf, 0);
159 }
160 
161 static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)
162 {
163     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
164     PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
165     PCIDevice *pci = PCI_DEVICE(dev);
166     uint16_t device_id = 0;
167     Error *local_err = NULL;
168 
169     rpc->parent_realize(dev, &local_err);
170     if (local_err) {
171         error_propagate(errp, local_err);
172         return;
173     }
174 
175     switch (phb_rp->version) {
176     case 3:
177         device_id = PNV_PHB3_DEVICE_ID;
178         break;
179     case 4:
180         device_id = PNV_PHB4_DEVICE_ID;
181         break;
182     case 5:
183         device_id = PNV_PHB5_DEVICE_ID;
184         break;
185     default:
186         g_assert_not_reached();
187     }
188 
189     pci_config_set_device_id(pci->config, device_id);
190     pci_config_set_interrupt_pin(pci->config, 0);
191 }
192 
193 static Property pnv_phb_root_port_properties[] = {
194     DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0),
195 
196     DEFINE_PROP_END_OF_LIST(),
197 };
198 
199 static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data)
200 {
201     DeviceClass *dc = DEVICE_CLASS(klass);
202     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
203     PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
204 
205     dc->desc     = "IBM PHB PCIE Root Port";
206 
207     device_class_set_props(dc, pnv_phb_root_port_properties);
208     device_class_set_parent_realize(dc, pnv_phb_root_port_realize,
209                                     &rpc->parent_realize);
210     device_class_set_parent_reset(dc, pnv_phb_root_port_reset,
211                                   &rpc->parent_reset);
212     dc->reset = &pnv_phb_root_port_reset;
213     dc->user_creatable = false;
214 
215     k->vendor_id = PCI_VENDOR_ID_IBM;
216     /* device_id will be written during realize() */
217     k->device_id = 0;
218     k->revision  = 0;
219 
220     rpc->exp_offset = 0x48;
221     rpc->aer_offset = 0x100;
222 }
223 
224 static const TypeInfo pnv_phb_type_info = {
225     .name          = TYPE_PNV_PHB,
226     .parent        = TYPE_PCIE_HOST_BRIDGE,
227     .instance_size = sizeof(PnvPHB),
228     .class_init    = pnv_phb_class_init,
229 };
230 
231 static const TypeInfo pnv_phb_root_port_info = {
232     .name          = TYPE_PNV_PHB_ROOT_PORT,
233     .parent        = TYPE_PCIE_ROOT_PORT,
234     .instance_size = sizeof(PnvPHBRootPort),
235     .class_init    = pnv_phb_root_port_class_init,
236 };
237 
238 static void pnv_phb_register_types(void)
239 {
240     type_register_static(&pnv_phb_type_info);
241     type_register_static(&pnv_phb_root_port_info);
242 }
243 
244 type_init(pnv_phb_register_types)
245