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"
20 #include "sysemu/sysemu.h"
24 * Set the QOM parent and parent bus of an object child. If the device
25 * state associated with the child has an id, use it as QOM id.
26 * Otherwise use object_typename[index] as QOM id.
28 * This helper does both operations at the same time because setting
29 * a new QOM child will erase the bus parent of the device. This happens
30 * because object_unparent() will call object_property_del_child(),
31 * which in turn calls the property release callback prop->release if
32 * it's defined. In our case this callback is set to
33 * object_finalize_child_property(), which was assigned during the
34 * first object_property_add_child() call. This callback will end up
35 * calling device_unparent(), and this function removes the device
36 * from its parent bus.
38 * The QOM and parent bus to be set arenĀ“t necessarily related, so
39 * let's receive both as arguments.
41 static bool pnv_parent_fixup(Object
*parent
, BusState
*parent_bus
,
42 Object
*child
, int index
,
45 g_autofree
char *default_id
=
46 g_strdup_printf("%s[%d]", object_get_typename(child
), index
);
47 const char *dev_id
= DEVICE(child
)->id
;
49 if (child
->parent
== parent
) {
54 object_unparent(child
);
55 object_property_add_child(parent
, dev_id
? dev_id
: default_id
, child
);
58 if (!qdev_set_parent_bus(DEVICE(child
), parent_bus
, errp
)) {
65 static Object
*pnv_phb_user_get_parent(PnvChip
*chip
, PnvPHB
*phb
, Error
**errp
)
67 if (phb
->version
== 3) {
68 return OBJECT(pnv_chip_add_phb(chip
, phb
));
70 return OBJECT(pnv_pec_add_phb(chip
, phb
, errp
));
75 * User created devices won't have the initial setup that default
76 * devices have. This setup consists of assigning a parent device
77 * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent
80 static bool pnv_phb_user_device_init(PnvPHB
*phb
, Error
**errp
)
82 PnvMachineState
*pnv
= PNV_MACHINE(qdev_get_machine());
83 PnvChip
*chip
= pnv_get_chip(pnv
, phb
->chip_id
);
84 Object
*parent
= NULL
;
87 error_setg(errp
, "invalid chip id: %d", phb
->chip_id
);
91 parent
= pnv_phb_user_get_parent(chip
, phb
, errp
);
97 * Reparent user created devices to the chip to build
98 * correctly the device tree. pnv_xscom_dt() needs every
99 * PHB to be a child of the chip to build the DT correctly.
101 if (!pnv_parent_fixup(parent
, qdev_get_parent_bus(DEVICE(chip
)),
102 OBJECT(phb
), phb
->phb_id
, 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 if (defaults_enabled()) {
170 PCIDevice
*root
= pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT
);
172 pci_realize_and_unref(root
, pci
->bus
, errp
);
176 static const char *pnv_phb_root_bus_path(PCIHostState
*host_bridge
,
179 PnvPHB
*phb
= PNV_PHB(host_bridge
);
181 snprintf(phb
->bus_path
, sizeof(phb
->bus_path
), "00%02x:%02x",
182 phb
->chip_id
, phb
->phb_id
);
183 return phb
->bus_path
;
186 static Property pnv_phb_properties
[] = {
187 DEFINE_PROP_UINT32("index", PnvPHB
, phb_id
, 0),
188 DEFINE_PROP_UINT32("chip-id", PnvPHB
, chip_id
, 0),
189 DEFINE_PROP_UINT32("version", PnvPHB
, version
, 0),
191 DEFINE_PROP_LINK("chip", PnvPHB
, chip
, TYPE_PNV_CHIP
, PnvChip
*),
193 DEFINE_PROP_LINK("pec", PnvPHB
, pec
, TYPE_PNV_PHB4_PEC
,
196 DEFINE_PROP_END_OF_LIST(),
199 static void pnv_phb_class_init(ObjectClass
*klass
, void *data
)
201 PCIHostBridgeClass
*hc
= PCI_HOST_BRIDGE_CLASS(klass
);
202 DeviceClass
*dc
= DEVICE_CLASS(klass
);
204 hc
->root_bus_path
= pnv_phb_root_bus_path
;
205 dc
->realize
= pnv_phb_realize
;
206 device_class_set_props(dc
, pnv_phb_properties
);
207 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
208 dc
->user_creatable
= true;
211 static void pnv_phb_root_port_reset_hold(Object
*obj
)
213 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_GET_CLASS(obj
);
214 PnvPHBRootPort
*phb_rp
= PNV_PHB_ROOT_PORT(obj
);
215 PCIDevice
*d
= PCI_DEVICE(obj
);
216 uint8_t *conf
= d
->config
;
218 if (rpc
->parent_phases
.hold
) {
219 rpc
->parent_phases
.hold(obj
);
222 if (phb_rp
->version
== 3) {
226 /* PHB4 and later requires these extra reset steps */
227 pci_byte_test_and_set_mask(conf
+ PCI_IO_BASE
,
228 PCI_IO_RANGE_MASK
& 0xff);
229 pci_byte_test_and_clear_mask(conf
+ PCI_IO_LIMIT
,
230 PCI_IO_RANGE_MASK
& 0xff);
231 pci_set_word(conf
+ PCI_MEMORY_BASE
, 0);
232 pci_set_word(conf
+ PCI_MEMORY_LIMIT
, 0xfff0);
233 pci_set_word(conf
+ PCI_PREF_MEMORY_BASE
, 0x1);
234 pci_set_word(conf
+ PCI_PREF_MEMORY_LIMIT
, 0xfff1);
235 pci_set_long(conf
+ PCI_PREF_BASE_UPPER32
, 0x1); /* Hack */
236 pci_set_long(conf
+ PCI_PREF_LIMIT_UPPER32
, 0xffffffff);
237 pci_config_set_interrupt_pin(conf
, 0);
240 static void pnv_phb_root_port_realize(DeviceState
*dev
, Error
**errp
)
242 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_GET_CLASS(dev
);
243 PnvPHBRootPort
*phb_rp
= PNV_PHB_ROOT_PORT(dev
);
244 PCIBus
*bus
= PCI_BUS(qdev_get_parent_bus(dev
));
245 PCIDevice
*pci
= PCI_DEVICE(dev
);
246 uint16_t device_id
= 0;
247 Error
*local_err
= NULL
;
251 * 'index' will be used both as a PCIE slot value and to calculate
252 * QOM id. 'chip_id' is going to be used as PCIE chassis for the
255 chip_id
= object_property_get_int(OBJECT(bus
), "chip-id", &local_err
);
257 error_propagate(errp
, local_err
);
260 index
= object_property_get_int(OBJECT(bus
), "phb-id", &local_err
);
262 error_propagate(errp
, local_err
);
266 /* Set unique chassis/slot values for the root port */
267 qdev_prop_set_uint8(dev
, "chassis", chip_id
);
268 qdev_prop_set_uint16(dev
, "slot", index
);
271 * User created root ports are QOM parented to one of
272 * the peripheral containers but it's already at the right
273 * parent bus. Change the QOM parent to be the same as the
274 * parent bus it's already assigned to.
276 if (!pnv_parent_fixup(OBJECT(bus
), BUS(bus
), OBJECT(dev
),
281 rpc
->parent_realize(dev
, &local_err
);
283 error_propagate(errp
, local_err
);
287 switch (phb_rp
->version
) {
289 device_id
= PNV_PHB3_DEVICE_ID
;
292 device_id
= PNV_PHB4_DEVICE_ID
;
295 device_id
= PNV_PHB5_DEVICE_ID
;
298 g_assert_not_reached();
301 pci_config_set_device_id(pci
->config
, device_id
);
302 pci_config_set_interrupt_pin(pci
->config
, 0);
305 static Property pnv_phb_root_port_properties
[] = {
306 DEFINE_PROP_UINT32("version", PnvPHBRootPort
, version
, 0),
308 DEFINE_PROP_END_OF_LIST(),
311 static void pnv_phb_root_port_class_init(ObjectClass
*klass
, void *data
)
313 DeviceClass
*dc
= DEVICE_CLASS(klass
);
314 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
315 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
316 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_CLASS(klass
);
318 dc
->desc
= "IBM PHB PCIE Root Port";
320 device_class_set_props(dc
, pnv_phb_root_port_properties
);
321 device_class_set_parent_realize(dc
, pnv_phb_root_port_realize
,
322 &rpc
->parent_realize
);
323 resettable_class_set_parent_phases(rc
, NULL
, pnv_phb_root_port_reset_hold
,
324 NULL
, &rpc
->parent_phases
);
325 dc
->user_creatable
= true;
327 k
->vendor_id
= PCI_VENDOR_ID_IBM
;
328 /* device_id will be written during realize() */
332 rpc
->exp_offset
= 0x48;
333 rpc
->aer_offset
= 0x100;
336 static const TypeInfo pnv_phb_type_info
= {
337 .name
= TYPE_PNV_PHB
,
338 .parent
= TYPE_PCIE_HOST_BRIDGE
,
339 .instance_size
= sizeof(PnvPHB
),
340 .class_init
= pnv_phb_class_init
,
343 static const TypeInfo pnv_phb_root_port_info
= {
344 .name
= TYPE_PNV_PHB_ROOT_PORT
,
345 .parent
= TYPE_PCIE_ROOT_PORT
,
346 .instance_size
= sizeof(PnvPHBRootPort
),
347 .class_init
= pnv_phb_root_port_class_init
,
350 static void pnv_phb_register_types(void)
352 type_register_static(&pnv_phb_type_info
);
353 type_register_static(&pnv_phb_root_port_info
);
356 type_init(pnv_phb_register_types
)