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"
20892c3ad0SDaniel Henrique Barboza #include "sysemu/sysemu.h"
21e4e6db52SDaniel Henrique Barboza
22ba47c3a4SDaniel Henrique Barboza
23ba47c3a4SDaniel Henrique Barboza /*
243466bb50SDaniel Henrique Barboza * Set the QOM parent and parent bus of an object child. If the device
253466bb50SDaniel Henrique Barboza * state associated with the child has an id, use it as QOM id.
263466bb50SDaniel Henrique Barboza * Otherwise use object_typename[index] as QOM id.
273466bb50SDaniel Henrique Barboza *
28f1c0cff8SMichael Tokarev * This helper does both operations at the same time because setting
293466bb50SDaniel Henrique Barboza * a new QOM child will erase the bus parent of the device. This happens
303466bb50SDaniel Henrique Barboza * because object_unparent() will call object_property_del_child(),
313466bb50SDaniel Henrique Barboza * which in turn calls the property release callback prop->release if
323466bb50SDaniel Henrique Barboza * it's defined. In our case this callback is set to
333466bb50SDaniel Henrique Barboza * object_finalize_child_property(), which was assigned during the
343466bb50SDaniel Henrique Barboza * first object_property_add_child() call. This callback will end up
353466bb50SDaniel Henrique Barboza * calling device_unparent(), and this function removes the device
363466bb50SDaniel Henrique Barboza * from its parent bus.
373466bb50SDaniel Henrique Barboza *
383466bb50SDaniel Henrique Barboza * The QOM and parent bus to be set aren´t necessarily related, so
393466bb50SDaniel Henrique Barboza * let's receive both as arguments.
40ba47c3a4SDaniel Henrique Barboza */
pnv_parent_fixup(Object * parent,BusState * parent_bus,Object * child,int index,Error ** errp)413466bb50SDaniel Henrique Barboza static bool pnv_parent_fixup(Object *parent, BusState *parent_bus,
423466bb50SDaniel Henrique Barboza Object *child, int index,
433466bb50SDaniel Henrique Barboza Error **errp)
44ba47c3a4SDaniel Henrique Barboza {
45ba47c3a4SDaniel Henrique Barboza g_autofree char *default_id =
46ba47c3a4SDaniel Henrique Barboza g_strdup_printf("%s[%d]", object_get_typename(child), index);
47ba47c3a4SDaniel Henrique Barboza const char *dev_id = DEVICE(child)->id;
48ba47c3a4SDaniel Henrique Barboza
49ba47c3a4SDaniel Henrique Barboza if (child->parent == parent) {
503466bb50SDaniel Henrique Barboza return true;
51ba47c3a4SDaniel Henrique Barboza }
52ba47c3a4SDaniel Henrique Barboza
53ba47c3a4SDaniel Henrique Barboza object_ref(child);
54ba47c3a4SDaniel Henrique Barboza object_unparent(child);
55ba47c3a4SDaniel Henrique Barboza object_property_add_child(parent, dev_id ? dev_id : default_id, child);
56ba47c3a4SDaniel Henrique Barboza object_unref(child);
573466bb50SDaniel Henrique Barboza
583466bb50SDaniel Henrique Barboza if (!qdev_set_parent_bus(DEVICE(child), parent_bus, errp)) {
593466bb50SDaniel Henrique Barboza return false;
60ba47c3a4SDaniel Henrique Barboza }
61ba47c3a4SDaniel Henrique Barboza
623466bb50SDaniel Henrique Barboza return true;
63ba47c3a4SDaniel Henrique Barboza }
64ba47c3a4SDaniel Henrique Barboza
pnv_phb_user_get_parent(PnvChip * chip,PnvPHB * phb,Error ** errp)65ddf0676fSFrederic Barrat static Object *pnv_phb_user_get_parent(PnvChip *chip, PnvPHB *phb, Error **errp)
66ddf0676fSFrederic Barrat {
67ddf0676fSFrederic Barrat if (phb->version == 3) {
68ddf0676fSFrederic Barrat return OBJECT(pnv_chip_add_phb(chip, phb));
69ddf0676fSFrederic Barrat } else {
70ddf0676fSFrederic Barrat return OBJECT(pnv_pec_add_phb(chip, phb, errp));
71ddf0676fSFrederic Barrat }
72ddf0676fSFrederic Barrat }
73ddf0676fSFrederic Barrat
74e5ea9436SDaniel Henrique Barboza /*
75ba47c3a4SDaniel Henrique Barboza * User created devices won't have the initial setup that default
76ba47c3a4SDaniel Henrique Barboza * devices have. This setup consists of assigning a parent device
77ba47c3a4SDaniel Henrique Barboza * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent
78ba47c3a4SDaniel Henrique Barboza * of the PHB.
79ba47c3a4SDaniel Henrique Barboza */
pnv_phb_user_device_init(PnvPHB * phb,Error ** errp)80ba47c3a4SDaniel Henrique Barboza static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp)
81ba47c3a4SDaniel Henrique Barboza {
82ba47c3a4SDaniel Henrique Barboza PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
83ba47c3a4SDaniel Henrique Barboza PnvChip *chip = pnv_get_chip(pnv, phb->chip_id);
84ba47c3a4SDaniel Henrique Barboza Object *parent = NULL;
85ba47c3a4SDaniel Henrique Barboza
86ba47c3a4SDaniel Henrique Barboza if (!chip) {
87ba47c3a4SDaniel Henrique Barboza error_setg(errp, "invalid chip id: %d", phb->chip_id);
88ba47c3a4SDaniel Henrique Barboza return false;
89ba47c3a4SDaniel Henrique Barboza }
90ba47c3a4SDaniel Henrique Barboza
91ddf0676fSFrederic Barrat parent = pnv_phb_user_get_parent(chip, phb, errp);
92ba47c3a4SDaniel Henrique Barboza if (!parent) {
93ba47c3a4SDaniel Henrique Barboza return false;
94ba47c3a4SDaniel Henrique Barboza }
95ba47c3a4SDaniel Henrique Barboza
96ba47c3a4SDaniel Henrique Barboza /*
97ba47c3a4SDaniel Henrique Barboza * Reparent user created devices to the chip to build
98ba47c3a4SDaniel Henrique Barboza * correctly the device tree. pnv_xscom_dt() needs every
99ba47c3a4SDaniel Henrique Barboza * PHB to be a child of the chip to build the DT correctly.
100ba47c3a4SDaniel Henrique Barboza */
1013466bb50SDaniel Henrique Barboza if (!pnv_parent_fixup(parent, qdev_get_parent_bus(DEVICE(chip)),
1023466bb50SDaniel Henrique Barboza OBJECT(phb), phb->phb_id, errp)) {
1033466bb50SDaniel Henrique Barboza return false;
1043466bb50SDaniel Henrique Barboza }
105ba47c3a4SDaniel Henrique Barboza
106ba47c3a4SDaniel Henrique Barboza return true;
107ba47c3a4SDaniel Henrique Barboza }
108ba47c3a4SDaniel Henrique Barboza
pnv_phb_realize(DeviceState * dev,Error ** errp)109e4e6db52SDaniel Henrique Barboza static void pnv_phb_realize(DeviceState *dev, Error **errp)
110e4e6db52SDaniel Henrique Barboza {
111e4e6db52SDaniel Henrique Barboza PnvPHB *phb = PNV_PHB(dev);
112e4e6db52SDaniel Henrique Barboza PCIHostState *pci = PCI_HOST_BRIDGE(dev);
113e4e6db52SDaniel Henrique Barboza g_autofree char *phb_typename = NULL;
114e4e6db52SDaniel Henrique Barboza
115e4e6db52SDaniel Henrique Barboza if (!phb->version) {
116e4e6db52SDaniel Henrique Barboza error_setg(errp, "version not specified");
117e4e6db52SDaniel Henrique Barboza return;
118e4e6db52SDaniel Henrique Barboza }
119e4e6db52SDaniel Henrique Barboza
120e4e6db52SDaniel Henrique Barboza switch (phb->version) {
121e4e6db52SDaniel Henrique Barboza case 3:
122e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB3);
123e4e6db52SDaniel Henrique Barboza break;
124e4e6db52SDaniel Henrique Barboza case 4:
125e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB4);
126e4e6db52SDaniel Henrique Barboza break;
127e4e6db52SDaniel Henrique Barboza case 5:
128e4e6db52SDaniel Henrique Barboza phb_typename = g_strdup(TYPE_PNV_PHB5);
129e4e6db52SDaniel Henrique Barboza break;
130e4e6db52SDaniel Henrique Barboza default:
131e4e6db52SDaniel Henrique Barboza g_assert_not_reached();
132e4e6db52SDaniel Henrique Barboza }
133e4e6db52SDaniel Henrique Barboza
134e4e6db52SDaniel Henrique Barboza phb->backend = object_new(phb_typename);
135e4e6db52SDaniel Henrique Barboza object_property_add_child(OBJECT(dev), "phb-backend", phb->backend);
136e4e6db52SDaniel Henrique Barboza
137e4e6db52SDaniel Henrique Barboza /* Passthrough child device properties to the proxy device */
138e4e6db52SDaniel Henrique Barboza object_property_set_uint(phb->backend, "index", phb->phb_id, errp);
139e4e6db52SDaniel Henrique Barboza object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp);
140e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp);
141e4e6db52SDaniel Henrique Barboza
142ba47c3a4SDaniel Henrique Barboza /*
143ba47c3a4SDaniel Henrique Barboza * Handle user created devices. User devices will not have a
144ba47c3a4SDaniel Henrique Barboza * pointer to a chip (PHB3) and a PEC (PHB4/5).
145ba47c3a4SDaniel Henrique Barboza */
146ba47c3a4SDaniel Henrique Barboza if (!phb->chip && !phb->pec) {
147ba47c3a4SDaniel Henrique Barboza if (!pnv_phb_user_device_init(phb, errp)) {
148ba47c3a4SDaniel Henrique Barboza return;
149ba47c3a4SDaniel Henrique Barboza }
150ba47c3a4SDaniel Henrique Barboza }
151ba47c3a4SDaniel Henrique Barboza
152e4e6db52SDaniel Henrique Barboza if (phb->version == 3) {
153e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "chip",
154e4e6db52SDaniel Henrique Barboza OBJECT(phb->chip), errp);
155e4e6db52SDaniel Henrique Barboza } else {
156e4e6db52SDaniel Henrique Barboza object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp);
157e4e6db52SDaniel Henrique Barboza }
158e4e6db52SDaniel Henrique Barboza
159e4e6db52SDaniel Henrique Barboza if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) {
160e4e6db52SDaniel Henrique Barboza return;
161e4e6db52SDaniel Henrique Barboza }
162e4e6db52SDaniel Henrique Barboza
163e4e6db52SDaniel Henrique Barboza if (phb->version == 3) {
164e4e6db52SDaniel Henrique Barboza pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend));
165fe5bfd4bSDaniel Henrique Barboza } else {
166fe5bfd4bSDaniel Henrique Barboza pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
167e4e6db52SDaniel Henrique Barboza }
168e4e6db52SDaniel Henrique Barboza
1696a1e1ce2SDaniel Henrique Barboza if (defaults_enabled()) {
1706a1e1ce2SDaniel Henrique Barboza PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
171892c3ad0SDaniel Henrique Barboza
1726a1e1ce2SDaniel Henrique Barboza pci_realize_and_unref(root, pci->bus, errp);
1736a1e1ce2SDaniel Henrique Barboza }
174e4e6db52SDaniel Henrique Barboza }
175e4e6db52SDaniel Henrique Barboza
pnv_phb_root_bus_path(PCIHostState * host_bridge,PCIBus * rootbus)176e4e6db52SDaniel Henrique Barboza static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,
177e4e6db52SDaniel Henrique Barboza PCIBus *rootbus)
178e4e6db52SDaniel Henrique Barboza {
179e4e6db52SDaniel Henrique Barboza PnvPHB *phb = PNV_PHB(host_bridge);
180e4e6db52SDaniel Henrique Barboza
181e4e6db52SDaniel Henrique Barboza snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x",
182e4e6db52SDaniel Henrique Barboza phb->chip_id, phb->phb_id);
183e4e6db52SDaniel Henrique Barboza return phb->bus_path;
184e4e6db52SDaniel Henrique Barboza }
185e4e6db52SDaniel Henrique Barboza
186e4e6db52SDaniel Henrique Barboza static Property pnv_phb_properties[] = {
187e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0),
188e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0),
189e4e6db52SDaniel Henrique Barboza DEFINE_PROP_UINT32("version", PnvPHB, version, 0),
190e4e6db52SDaniel Henrique Barboza
191e4e6db52SDaniel Henrique Barboza DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *),
192e4e6db52SDaniel Henrique Barboza
193e4e6db52SDaniel Henrique Barboza DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC,
194e4e6db52SDaniel Henrique Barboza PnvPhb4PecState *),
195e4e6db52SDaniel Henrique Barboza
196e4e6db52SDaniel Henrique Barboza DEFINE_PROP_END_OF_LIST(),
197e4e6db52SDaniel Henrique Barboza };
198e4e6db52SDaniel Henrique Barboza
pnv_phb_class_init(ObjectClass * klass,void * data)199e4e6db52SDaniel Henrique Barboza static void pnv_phb_class_init(ObjectClass *klass, void *data)
200e4e6db52SDaniel Henrique Barboza {
201e4e6db52SDaniel Henrique Barboza PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
202e4e6db52SDaniel Henrique Barboza DeviceClass *dc = DEVICE_CLASS(klass);
203e4e6db52SDaniel Henrique Barboza
204e4e6db52SDaniel Henrique Barboza hc->root_bus_path = pnv_phb_root_bus_path;
205e4e6db52SDaniel Henrique Barboza dc->realize = pnv_phb_realize;
206e4e6db52SDaniel Henrique Barboza device_class_set_props(dc, pnv_phb_properties);
207e4e6db52SDaniel Henrique Barboza set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
208892c3ad0SDaniel Henrique Barboza dc->user_creatable = true;
209e4e6db52SDaniel Henrique Barboza }
210e4e6db52SDaniel Henrique Barboza
pnv_phb_root_port_reset_hold(Object * obj,ResetType type)211*ad80e367SPeter Maydell static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
212e4e6db52SDaniel Henrique Barboza {
213f4c636b0SPeter Maydell PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
214f4c636b0SPeter Maydell PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(obj);
215f4c636b0SPeter Maydell PCIDevice *d = PCI_DEVICE(obj);
2165ba76b61SDaniel Henrique Barboza uint8_t *conf = d->config;
2175ba76b61SDaniel Henrique Barboza
218f4c636b0SPeter Maydell if (rpc->parent_phases.hold) {
219*ad80e367SPeter Maydell rpc->parent_phases.hold(obj, type);
220f4c636b0SPeter Maydell }
2215ba76b61SDaniel Henrique Barboza
2225ba76b61SDaniel Henrique Barboza if (phb_rp->version == 3) {
2235ba76b61SDaniel Henrique Barboza return;
2245ba76b61SDaniel Henrique Barboza }
2255ba76b61SDaniel Henrique Barboza
2265ba76b61SDaniel Henrique Barboza /* PHB4 and later requires these extra reset steps */
2275ba76b61SDaniel Henrique Barboza pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
2285ba76b61SDaniel Henrique Barboza PCI_IO_RANGE_MASK & 0xff);
2295ba76b61SDaniel Henrique Barboza pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
2305ba76b61SDaniel Henrique Barboza PCI_IO_RANGE_MASK & 0xff);
2315ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_MEMORY_BASE, 0);
2325ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
2335ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
2345ba76b61SDaniel Henrique Barboza pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
2355ba76b61SDaniel Henrique Barboza pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
2365ba76b61SDaniel Henrique Barboza pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
2375ba76b61SDaniel Henrique Barboza pci_config_set_interrupt_pin(conf, 0);
2385ba76b61SDaniel Henrique Barboza }
2395ba76b61SDaniel Henrique Barboza
pnv_phb_root_port_realize(DeviceState * dev,Error ** errp)2405ba76b61SDaniel Henrique Barboza static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)
2415ba76b61SDaniel Henrique Barboza {
2425ba76b61SDaniel Henrique Barboza PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
2435ba76b61SDaniel Henrique Barboza PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
244c2f3f78aSDaniel Henrique Barboza PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev));
2455ba76b61SDaniel Henrique Barboza PCIDevice *pci = PCI_DEVICE(dev);
2465ba76b61SDaniel Henrique Barboza uint16_t device_id = 0;
2475ba76b61SDaniel Henrique Barboza Error *local_err = NULL;
248c2f3f78aSDaniel Henrique Barboza int chip_id, index;
249c2f3f78aSDaniel Henrique Barboza
2506a1e1ce2SDaniel Henrique Barboza /*
2516a1e1ce2SDaniel Henrique Barboza * 'index' will be used both as a PCIE slot value and to calculate
2526a1e1ce2SDaniel Henrique Barboza * QOM id. 'chip_id' is going to be used as PCIE chassis for the
2536a1e1ce2SDaniel Henrique Barboza * root port.
2546a1e1ce2SDaniel Henrique Barboza */
255ec565134SThomas Huth chip_id = object_property_get_int(OBJECT(bus), "chip-id", &local_err);
256ec565134SThomas Huth if (local_err) {
257ec565134SThomas Huth error_propagate(errp, local_err);
258ec565134SThomas Huth return;
259ec565134SThomas Huth }
260ec565134SThomas Huth index = object_property_get_int(OBJECT(bus), "phb-id", &local_err);
261ec565134SThomas Huth if (local_err) {
262ec565134SThomas Huth error_propagate(errp, local_err);
263ec565134SThomas Huth return;
264ec565134SThomas Huth }
265c2f3f78aSDaniel Henrique Barboza
266c2f3f78aSDaniel Henrique Barboza /* Set unique chassis/slot values for the root port */
267c2f3f78aSDaniel Henrique Barboza qdev_prop_set_uint8(dev, "chassis", chip_id);
268c2f3f78aSDaniel Henrique Barboza qdev_prop_set_uint16(dev, "slot", index);
2695ba76b61SDaniel Henrique Barboza
2706a1e1ce2SDaniel Henrique Barboza /*
2716a1e1ce2SDaniel Henrique Barboza * User created root ports are QOM parented to one of
2726a1e1ce2SDaniel Henrique Barboza * the peripheral containers but it's already at the right
2736a1e1ce2SDaniel Henrique Barboza * parent bus. Change the QOM parent to be the same as the
2746a1e1ce2SDaniel Henrique Barboza * parent bus it's already assigned to.
2756a1e1ce2SDaniel Henrique Barboza */
2766a1e1ce2SDaniel Henrique Barboza if (!pnv_parent_fixup(OBJECT(bus), BUS(bus), OBJECT(dev),
2776a1e1ce2SDaniel Henrique Barboza index, errp)) {
2786a1e1ce2SDaniel Henrique Barboza return;
2796a1e1ce2SDaniel Henrique Barboza }
2806a1e1ce2SDaniel Henrique Barboza
2815ba76b61SDaniel Henrique Barboza rpc->parent_realize(dev, &local_err);
2825ba76b61SDaniel Henrique Barboza if (local_err) {
2835ba76b61SDaniel Henrique Barboza error_propagate(errp, local_err);
2845ba76b61SDaniel Henrique Barboza return;
2855ba76b61SDaniel Henrique Barboza }
2865ba76b61SDaniel Henrique Barboza
2875ba76b61SDaniel Henrique Barboza switch (phb_rp->version) {
2885ba76b61SDaniel Henrique Barboza case 3:
2895ba76b61SDaniel Henrique Barboza device_id = PNV_PHB3_DEVICE_ID;
2905ba76b61SDaniel Henrique Barboza break;
2915ba76b61SDaniel Henrique Barboza case 4:
2925ba76b61SDaniel Henrique Barboza device_id = PNV_PHB4_DEVICE_ID;
2935ba76b61SDaniel Henrique Barboza break;
2945ba76b61SDaniel Henrique Barboza case 5:
2955ba76b61SDaniel Henrique Barboza device_id = PNV_PHB5_DEVICE_ID;
2965ba76b61SDaniel Henrique Barboza break;
2975ba76b61SDaniel Henrique Barboza default:
2985ba76b61SDaniel Henrique Barboza g_assert_not_reached();
2995ba76b61SDaniel Henrique Barboza }
3005ba76b61SDaniel Henrique Barboza
3015ba76b61SDaniel Henrique Barboza pci_config_set_device_id(pci->config, device_id);
3025ba76b61SDaniel Henrique Barboza pci_config_set_interrupt_pin(pci->config, 0);
3035ba76b61SDaniel Henrique Barboza }
3045ba76b61SDaniel Henrique Barboza
3055ba76b61SDaniel Henrique Barboza static Property pnv_phb_root_port_properties[] = {
3065ba76b61SDaniel Henrique Barboza DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0),
3075ba76b61SDaniel Henrique Barboza
3085ba76b61SDaniel Henrique Barboza DEFINE_PROP_END_OF_LIST(),
3095ba76b61SDaniel Henrique Barboza };
3105ba76b61SDaniel Henrique Barboza
pnv_phb_root_port_class_init(ObjectClass * klass,void * data)3115ba76b61SDaniel Henrique Barboza static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data)
3125ba76b61SDaniel Henrique Barboza {
3135ba76b61SDaniel Henrique Barboza DeviceClass *dc = DEVICE_CLASS(klass);
314f4c636b0SPeter Maydell ResettableClass *rc = RESETTABLE_CLASS(klass);
3155ba76b61SDaniel Henrique Barboza PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
3165ba76b61SDaniel Henrique Barboza PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
3175ba76b61SDaniel Henrique Barboza
3185ba76b61SDaniel Henrique Barboza dc->desc = "IBM PHB PCIE Root Port";
3195ba76b61SDaniel Henrique Barboza
3205ba76b61SDaniel Henrique Barboza device_class_set_props(dc, pnv_phb_root_port_properties);
3215ba76b61SDaniel Henrique Barboza device_class_set_parent_realize(dc, pnv_phb_root_port_realize,
3225ba76b61SDaniel Henrique Barboza &rpc->parent_realize);
323f4c636b0SPeter Maydell resettable_class_set_parent_phases(rc, NULL, pnv_phb_root_port_reset_hold,
324f4c636b0SPeter Maydell NULL, &rpc->parent_phases);
325892c3ad0SDaniel Henrique Barboza dc->user_creatable = true;
3265ba76b61SDaniel Henrique Barboza
3275ba76b61SDaniel Henrique Barboza k->vendor_id = PCI_VENDOR_ID_IBM;
3285ba76b61SDaniel Henrique Barboza /* device_id will be written during realize() */
3295ba76b61SDaniel Henrique Barboza k->device_id = 0;
3305ba76b61SDaniel Henrique Barboza k->revision = 0;
3315ba76b61SDaniel Henrique Barboza
3325ba76b61SDaniel Henrique Barboza rpc->exp_offset = 0x48;
3335ba76b61SDaniel Henrique Barboza rpc->aer_offset = 0x100;
3345ba76b61SDaniel Henrique Barboza }
3355ba76b61SDaniel Henrique Barboza
336e4e6db52SDaniel Henrique Barboza static const TypeInfo pnv_phb_type_info = {
337e4e6db52SDaniel Henrique Barboza .name = TYPE_PNV_PHB,
338e4e6db52SDaniel Henrique Barboza .parent = TYPE_PCIE_HOST_BRIDGE,
339e4e6db52SDaniel Henrique Barboza .instance_size = sizeof(PnvPHB),
340e4e6db52SDaniel Henrique Barboza .class_init = pnv_phb_class_init,
341e4e6db52SDaniel Henrique Barboza };
342e4e6db52SDaniel Henrique Barboza
3435ba76b61SDaniel Henrique Barboza static const TypeInfo pnv_phb_root_port_info = {
3445ba76b61SDaniel Henrique Barboza .name = TYPE_PNV_PHB_ROOT_PORT,
3455ba76b61SDaniel Henrique Barboza .parent = TYPE_PCIE_ROOT_PORT,
3465ba76b61SDaniel Henrique Barboza .instance_size = sizeof(PnvPHBRootPort),
3475ba76b61SDaniel Henrique Barboza .class_init = pnv_phb_root_port_class_init,
3485ba76b61SDaniel Henrique Barboza };
3495ba76b61SDaniel Henrique Barboza
pnv_phb_register_types(void)3505ba76b61SDaniel Henrique Barboza static void pnv_phb_register_types(void)
3515ba76b61SDaniel Henrique Barboza {
352e4e6db52SDaniel Henrique Barboza type_register_static(&pnv_phb_type_info);
3535ba76b61SDaniel Henrique Barboza type_register_static(&pnv_phb_root_port_info);
354e4e6db52SDaniel Henrique Barboza }
3555ba76b61SDaniel Henrique Barboza
3565ba76b61SDaniel Henrique Barboza type_init(pnv_phb_register_types)
357