2 * QEMU PowerPC PowerNV Proxy PHB model
4 * Copyright (c) 2022, IBM Corporation.
6 * This code is licensed under the GPL version 2 or later. See the
7 * COPYING file in the top-level directory.
10 #include "qemu/osdep.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"
23 * Set the QOM parent of an object child. If the device state
24 * associated with the child has an id, use it as QOM id. Otherwise
25 * use object_typename[index] as QOM id.
27 static void pnv_parent_qom_fixup(Object
*parent
, Object
*child
, int index
)
29 g_autofree
char *default_id
=
30 g_strdup_printf("%s[%d]", object_get_typename(child
), index
);
31 const char *dev_id
= DEVICE(child
)->id
;
33 if (child
->parent
== parent
) {
38 object_unparent(child
);
39 object_property_add_child(parent
, dev_id
? dev_id
: default_id
, child
);
43 static void pnv_parent_bus_fixup(DeviceState
*parent
, DeviceState
*child
,
46 BusState
*parent_bus
= qdev_get_parent_bus(parent
);
48 if (!qdev_set_parent_bus(child
, parent_bus
, errp
)) {
54 * Attach a root port device.
56 * 'index' will be used both as a PCIE slot value and to calculate
57 * QOM id. 'chip_id' is going to be used as PCIE chassis for the
60 static void pnv_phb_attach_root_port(PCIHostState
*pci
)
62 PCIDevice
*root
= pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT
);
63 const char *dev_id
= DEVICE(root
)->id
;
64 g_autofree
char *default_id
= NULL
;
67 index
= object_property_get_int(OBJECT(pci
->bus
), "phb-id", &error_fatal
);
68 default_id
= g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT
, index
);
70 object_property_add_child(OBJECT(pci
->bus
), dev_id
? dev_id
: default_id
,
73 pci_realize_and_unref(root
, pci
->bus
, &error_fatal
);
77 * User created devices won't have the initial setup that default
78 * devices have. This setup consists of assigning a parent device
79 * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent
82 static bool pnv_phb_user_device_init(PnvPHB
*phb
, Error
**errp
)
84 PnvMachineState
*pnv
= PNV_MACHINE(qdev_get_machine());
85 PnvChip
*chip
= pnv_get_chip(pnv
, phb
->chip_id
);
86 Object
*parent
= NULL
;
89 error_setg(errp
, "invalid chip id: %d", phb
->chip_id
);
93 parent
= pnv_chip_add_phb(chip
, phb
, errp
);
99 * Reparent user created devices to the chip to build
100 * correctly the device tree. pnv_xscom_dt() needs every
101 * PHB to be a child of the chip to build the DT correctly.
103 pnv_parent_qom_fixup(parent
, OBJECT(phb
), phb
->phb_id
);
104 pnv_parent_bus_fixup(DEVICE(chip
), DEVICE(phb
), errp
);
109 static void pnv_phb_realize(DeviceState
*dev
, Error
**errp
)
111 PnvPHB
*phb
= PNV_PHB(dev
);
112 PCIHostState
*pci
= PCI_HOST_BRIDGE(dev
);
113 g_autofree
char *phb_typename
= NULL
;
116 error_setg(errp
, "version not specified");
120 switch (phb
->version
) {
122 phb_typename
= g_strdup(TYPE_PNV_PHB3
);
125 phb_typename
= g_strdup(TYPE_PNV_PHB4
);
128 phb_typename
= g_strdup(TYPE_PNV_PHB5
);
131 g_assert_not_reached();
134 phb
->backend
= object_new(phb_typename
);
135 object_property_add_child(OBJECT(dev
), "phb-backend", phb
->backend
);
137 /* Passthrough child device properties to the proxy device */
138 object_property_set_uint(phb
->backend
, "index", phb
->phb_id
, errp
);
139 object_property_set_uint(phb
->backend
, "chip-id", phb
->chip_id
, errp
);
140 object_property_set_link(phb
->backend
, "phb-base", OBJECT(phb
), errp
);
143 * Handle user created devices. User devices will not have a
144 * pointer to a chip (PHB3) and a PEC (PHB4/5).
146 if (!phb
->chip
&& !phb
->pec
) {
147 if (!pnv_phb_user_device_init(phb
, errp
)) {
152 if (phb
->version
== 3) {
153 object_property_set_link(phb
->backend
, "chip",
154 OBJECT(phb
->chip
), errp
);
156 object_property_set_link(phb
->backend
, "pec", OBJECT(phb
->pec
), errp
);
159 if (!qdev_realize(DEVICE(phb
->backend
), NULL
, errp
)) {
163 if (phb
->version
== 3) {
164 pnv_phb3_bus_init(dev
, PNV_PHB3(phb
->backend
));
166 pnv_phb4_bus_init(dev
, PNV_PHB4(phb
->backend
));
169 pnv_phb_attach_root_port(pci
);
172 static const char *pnv_phb_root_bus_path(PCIHostState
*host_bridge
,
175 PnvPHB
*phb
= PNV_PHB(host_bridge
);
177 snprintf(phb
->bus_path
, sizeof(phb
->bus_path
), "00%02x:%02x",
178 phb
->chip_id
, phb
->phb_id
);
179 return phb
->bus_path
;
182 static Property pnv_phb_properties
[] = {
183 DEFINE_PROP_UINT32("index", PnvPHB
, phb_id
, 0),
184 DEFINE_PROP_UINT32("chip-id", PnvPHB
, chip_id
, 0),
185 DEFINE_PROP_UINT32("version", PnvPHB
, version
, 0),
187 DEFINE_PROP_LINK("chip", PnvPHB
, chip
, TYPE_PNV_CHIP
, PnvChip
*),
189 DEFINE_PROP_LINK("pec", PnvPHB
, pec
, TYPE_PNV_PHB4_PEC
,
192 DEFINE_PROP_END_OF_LIST(),
195 static void pnv_phb_class_init(ObjectClass
*klass
, void *data
)
197 PCIHostBridgeClass
*hc
= PCI_HOST_BRIDGE_CLASS(klass
);
198 DeviceClass
*dc
= DEVICE_CLASS(klass
);
200 hc
->root_bus_path
= pnv_phb_root_bus_path
;
201 dc
->realize
= pnv_phb_realize
;
202 device_class_set_props(dc
, pnv_phb_properties
);
203 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
204 dc
->user_creatable
= false;
207 static void pnv_phb_root_port_reset(DeviceState
*dev
)
209 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_GET_CLASS(dev
);
210 PnvPHBRootPort
*phb_rp
= PNV_PHB_ROOT_PORT(dev
);
211 PCIDevice
*d
= PCI_DEVICE(dev
);
212 uint8_t *conf
= d
->config
;
214 rpc
->parent_reset(dev
);
216 if (phb_rp
->version
== 3) {
220 /* PHB4 and later requires these extra reset steps */
221 pci_byte_test_and_set_mask(conf
+ PCI_IO_BASE
,
222 PCI_IO_RANGE_MASK
& 0xff);
223 pci_byte_test_and_clear_mask(conf
+ PCI_IO_LIMIT
,
224 PCI_IO_RANGE_MASK
& 0xff);
225 pci_set_word(conf
+ PCI_MEMORY_BASE
, 0);
226 pci_set_word(conf
+ PCI_MEMORY_LIMIT
, 0xfff0);
227 pci_set_word(conf
+ PCI_PREF_MEMORY_BASE
, 0x1);
228 pci_set_word(conf
+ PCI_PREF_MEMORY_LIMIT
, 0xfff1);
229 pci_set_long(conf
+ PCI_PREF_BASE_UPPER32
, 0x1); /* Hack */
230 pci_set_long(conf
+ PCI_PREF_LIMIT_UPPER32
, 0xffffffff);
231 pci_config_set_interrupt_pin(conf
, 0);
234 static void pnv_phb_root_port_realize(DeviceState
*dev
, Error
**errp
)
236 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_GET_CLASS(dev
);
237 PnvPHBRootPort
*phb_rp
= PNV_PHB_ROOT_PORT(dev
);
238 PCIBus
*bus
= PCI_BUS(qdev_get_parent_bus(dev
));
239 PCIDevice
*pci
= PCI_DEVICE(dev
);
240 uint16_t device_id
= 0;
241 Error
*local_err
= NULL
;
244 chip_id
= object_property_get_int(OBJECT(bus
), "chip-id", &error_fatal
);
245 index
= object_property_get_int(OBJECT(bus
), "phb-id", &error_fatal
);
247 /* Set unique chassis/slot values for the root port */
248 qdev_prop_set_uint8(dev
, "chassis", chip_id
);
249 qdev_prop_set_uint16(dev
, "slot", index
);
251 rpc
->parent_realize(dev
, &local_err
);
253 error_propagate(errp
, local_err
);
257 switch (phb_rp
->version
) {
259 device_id
= PNV_PHB3_DEVICE_ID
;
262 device_id
= PNV_PHB4_DEVICE_ID
;
265 device_id
= PNV_PHB5_DEVICE_ID
;
268 g_assert_not_reached();
271 pci_config_set_device_id(pci
->config
, device_id
);
272 pci_config_set_interrupt_pin(pci
->config
, 0);
275 static Property pnv_phb_root_port_properties
[] = {
276 DEFINE_PROP_UINT32("version", PnvPHBRootPort
, version
, 0),
278 DEFINE_PROP_END_OF_LIST(),
281 static void pnv_phb_root_port_class_init(ObjectClass
*klass
, void *data
)
283 DeviceClass
*dc
= DEVICE_CLASS(klass
);
284 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
285 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_CLASS(klass
);
287 dc
->desc
= "IBM PHB PCIE Root Port";
289 device_class_set_props(dc
, pnv_phb_root_port_properties
);
290 device_class_set_parent_realize(dc
, pnv_phb_root_port_realize
,
291 &rpc
->parent_realize
);
292 device_class_set_parent_reset(dc
, pnv_phb_root_port_reset
,
294 dc
->reset
= &pnv_phb_root_port_reset
;
295 dc
->user_creatable
= false;
297 k
->vendor_id
= PCI_VENDOR_ID_IBM
;
298 /* device_id will be written during realize() */
302 rpc
->exp_offset
= 0x48;
303 rpc
->aer_offset
= 0x100;
306 static const TypeInfo pnv_phb_type_info
= {
307 .name
= TYPE_PNV_PHB
,
308 .parent
= TYPE_PCIE_HOST_BRIDGE
,
309 .instance_size
= sizeof(PnvPHB
),
310 .class_init
= pnv_phb_class_init
,
313 static const TypeInfo pnv_phb_root_port_info
= {
314 .name
= TYPE_PNV_PHB_ROOT_PORT
,
315 .parent
= TYPE_PCIE_ROOT_PORT
,
316 .instance_size
= sizeof(PnvPHBRootPort
),
317 .class_init
= pnv_phb_root_port_class_init
,
320 static void pnv_phb_register_types(void)
322 type_register_static(&pnv_phb_type_info
);
323 type_register_static(&pnv_phb_root_port_info
);
326 type_init(pnv_phb_register_types
)