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"
22 static void pnv_phb_realize(DeviceState
*dev
, Error
**errp
)
24 PnvPHB
*phb
= PNV_PHB(dev
);
25 PCIHostState
*pci
= PCI_HOST_BRIDGE(dev
);
26 g_autofree
char *phb_typename
= NULL
;
29 error_setg(errp
, "version not specified");
33 switch (phb
->version
) {
35 phb_typename
= g_strdup(TYPE_PNV_PHB3
);
38 phb_typename
= g_strdup(TYPE_PNV_PHB4
);
41 phb_typename
= g_strdup(TYPE_PNV_PHB5
);
44 g_assert_not_reached();
47 phb
->backend
= object_new(phb_typename
);
48 object_property_add_child(OBJECT(dev
), "phb-backend", phb
->backend
);
50 /* Passthrough child device properties to the proxy device */
51 object_property_set_uint(phb
->backend
, "index", phb
->phb_id
, errp
);
52 object_property_set_uint(phb
->backend
, "chip-id", phb
->chip_id
, errp
);
53 object_property_set_link(phb
->backend
, "phb-base", OBJECT(phb
), errp
);
55 if (phb
->version
== 3) {
56 object_property_set_link(phb
->backend
, "chip",
57 OBJECT(phb
->chip
), errp
);
59 object_property_set_link(phb
->backend
, "pec", OBJECT(phb
->pec
), errp
);
62 if (!qdev_realize(DEVICE(phb
->backend
), NULL
, errp
)) {
66 if (phb
->version
== 3) {
67 pnv_phb3_bus_init(dev
, PNV_PHB3(phb
->backend
));
69 pnv_phb4_bus_init(dev
, PNV_PHB4(phb
->backend
));
72 pnv_phb_attach_root_port(pci
, phb
->phb_id
, phb
->chip_id
);
75 static const char *pnv_phb_root_bus_path(PCIHostState
*host_bridge
,
78 PnvPHB
*phb
= PNV_PHB(host_bridge
);
80 snprintf(phb
->bus_path
, sizeof(phb
->bus_path
), "00%02x:%02x",
81 phb
->chip_id
, phb
->phb_id
);
85 static Property pnv_phb_properties
[] = {
86 DEFINE_PROP_UINT32("index", PnvPHB
, phb_id
, 0),
87 DEFINE_PROP_UINT32("chip-id", PnvPHB
, chip_id
, 0),
88 DEFINE_PROP_UINT32("version", PnvPHB
, version
, 0),
90 DEFINE_PROP_LINK("chip", PnvPHB
, chip
, TYPE_PNV_CHIP
, PnvChip
*),
92 DEFINE_PROP_LINK("pec", PnvPHB
, pec
, TYPE_PNV_PHB4_PEC
,
95 DEFINE_PROP_END_OF_LIST(),
98 static void pnv_phb_class_init(ObjectClass
*klass
, void *data
)
100 PCIHostBridgeClass
*hc
= PCI_HOST_BRIDGE_CLASS(klass
);
101 DeviceClass
*dc
= DEVICE_CLASS(klass
);
103 hc
->root_bus_path
= pnv_phb_root_bus_path
;
104 dc
->realize
= pnv_phb_realize
;
105 device_class_set_props(dc
, pnv_phb_properties
);
106 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
107 dc
->user_creatable
= false;
110 static void pnv_phb_root_port_reset(DeviceState
*dev
)
112 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_GET_CLASS(dev
);
113 PnvPHBRootPort
*phb_rp
= PNV_PHB_ROOT_PORT(dev
);
114 PCIDevice
*d
= PCI_DEVICE(dev
);
115 uint8_t *conf
= d
->config
;
117 rpc
->parent_reset(dev
);
119 if (phb_rp
->version
== 3) {
123 /* PHB4 and later requires these extra reset steps */
124 pci_byte_test_and_set_mask(conf
+ PCI_IO_BASE
,
125 PCI_IO_RANGE_MASK
& 0xff);
126 pci_byte_test_and_clear_mask(conf
+ PCI_IO_LIMIT
,
127 PCI_IO_RANGE_MASK
& 0xff);
128 pci_set_word(conf
+ PCI_MEMORY_BASE
, 0);
129 pci_set_word(conf
+ PCI_MEMORY_LIMIT
, 0xfff0);
130 pci_set_word(conf
+ PCI_PREF_MEMORY_BASE
, 0x1);
131 pci_set_word(conf
+ PCI_PREF_MEMORY_LIMIT
, 0xfff1);
132 pci_set_long(conf
+ PCI_PREF_BASE_UPPER32
, 0x1); /* Hack */
133 pci_set_long(conf
+ PCI_PREF_LIMIT_UPPER32
, 0xffffffff);
134 pci_config_set_interrupt_pin(conf
, 0);
137 static void pnv_phb_root_port_realize(DeviceState
*dev
, Error
**errp
)
139 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_GET_CLASS(dev
);
140 PnvPHBRootPort
*phb_rp
= PNV_PHB_ROOT_PORT(dev
);
141 PCIDevice
*pci
= PCI_DEVICE(dev
);
142 uint16_t device_id
= 0;
143 Error
*local_err
= NULL
;
145 rpc
->parent_realize(dev
, &local_err
);
147 error_propagate(errp
, local_err
);
151 switch (phb_rp
->version
) {
153 device_id
= PNV_PHB3_DEVICE_ID
;
156 device_id
= PNV_PHB4_DEVICE_ID
;
159 device_id
= PNV_PHB5_DEVICE_ID
;
162 g_assert_not_reached();
165 pci_config_set_device_id(pci
->config
, device_id
);
166 pci_config_set_interrupt_pin(pci
->config
, 0);
169 static Property pnv_phb_root_port_properties
[] = {
170 DEFINE_PROP_UINT32("version", PnvPHBRootPort
, version
, 0),
172 DEFINE_PROP_END_OF_LIST(),
175 static void pnv_phb_root_port_class_init(ObjectClass
*klass
, void *data
)
177 DeviceClass
*dc
= DEVICE_CLASS(klass
);
178 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
179 PCIERootPortClass
*rpc
= PCIE_ROOT_PORT_CLASS(klass
);
181 dc
->desc
= "IBM PHB PCIE Root Port";
183 device_class_set_props(dc
, pnv_phb_root_port_properties
);
184 device_class_set_parent_realize(dc
, pnv_phb_root_port_realize
,
185 &rpc
->parent_realize
);
186 device_class_set_parent_reset(dc
, pnv_phb_root_port_reset
,
188 dc
->reset
= &pnv_phb_root_port_reset
;
189 dc
->user_creatable
= false;
191 k
->vendor_id
= PCI_VENDOR_ID_IBM
;
192 /* device_id will be written during realize() */
196 rpc
->exp_offset
= 0x48;
197 rpc
->aer_offset
= 0x100;
200 static const TypeInfo pnv_phb_type_info
= {
201 .name
= TYPE_PNV_PHB
,
202 .parent
= TYPE_PCIE_HOST_BRIDGE
,
203 .instance_size
= sizeof(PnvPHB
),
204 .class_init
= pnv_phb_class_init
,
207 static const TypeInfo pnv_phb_root_port_info
= {
208 .name
= TYPE_PNV_PHB_ROOT_PORT
,
209 .parent
= TYPE_PCIE_ROOT_PORT
,
210 .instance_size
= sizeof(PnvPHBRootPort
),
211 .class_init
= pnv_phb_root_port_class_init
,
214 static void pnv_phb_register_types(void)
216 type_register_static(&pnv_phb_type_info
);
217 type_register_static(&pnv_phb_root_port_info
);
220 type_init(pnv_phb_register_types
)