1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "qemu/osdep.h"
23#include "migration/vmstate.h"
24#include "hw/qdev-properties.h"
25#include "hw/pci/pci_ids.h"
26#include "hw/pci/msi.h"
27#include "hw/pci/pcie.h"
28#include "hw/pci/pcie_port.h"
29#include "qapi/error.h"
30
31#define PCI_DEVICE_ID_EPORT 0xd022
32#define PCI_DEVICE_ID_REV 0x1
33#define EP_EXP_OFFSET 0x60
34#define EP_AER_OFFSET 0x100
35
36static void xlnx_write_config(PCIDevice *d,
37 uint32_t address, uint32_t val, int len)
38{
39 uint32_t root_cmd =
40 pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
41 uint16_t slt_ctl, slt_sta;
42
43 pcie_cap_slot_get(d, &slt_ctl, &slt_sta);
44
45 pci_bridge_write_config(d, address, val, len);
46 pcie_cap_slot_write_config(d, slt_ctl, slt_sta, address, val, len);
47 pcie_aer_write_config(d, address, val, len);
48 pcie_aer_root_write_config(d, address, val, len, root_cmd);
49}
50
51static void xlnx_reset(DeviceState *qdev)
52{
53 PCIDevice *d = PCI_DEVICE(qdev);
54
55 pcie_cap_root_reset(d);
56 pcie_cap_deverr_reset(d);
57 pcie_cap_slot_reset(d);
58 pcie_cap_arifwd_reset(d);
59 pcie_aer_root_reset(d);
60 pci_bridge_reset(qdev);
61 pci_bridge_disable_base_limit(d);
62}
63
64static void xlnx_realize(PCIDevice *d, Error **errp)
65{
66 PCIEPort *p = PCIE_PORT(d);
67 PCIESlot *s = PCIE_SLOT(d);
68 int rc;
69
70 pci_config_set_interrupt_pin(d->config, 1);
71 pci_bridge_initfn(d, TYPE_PCIE_BUS);
72 pcie_port_init_reg(d);
73
74 rc = pcie_cap_init(d, EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port,
75 errp);
76 if (rc < 0) {
77 goto err_bridge;
78 }
79
80 pcie_cap_arifwd_init(d);
81 pcie_cap_deverr_init(d);
82 pcie_cap_slot_init(d, s);
83 pcie_chassis_create(s->chassis);
84 rc = pcie_chassis_add_slot(s);
85 if (rc < 0) {
86 goto err_pcie_cap;
87 }
88 pcie_cap_root_init(d);
89 rc = pcie_aer_init(d, PCI_ERR_VER, EP_AER_OFFSET, PCI_ERR_SIZEOF, errp);
90 if (rc < 0) {
91 goto err;
92 }
93
94 return;
95err:
96 pcie_chassis_del_slot(s);
97err_pcie_cap:
98 pcie_cap_exit(d);
99err_bridge:
100 pci_bridge_exitfn(d);
101}
102
103static void xlnx_exitfn(PCIDevice *d)
104{
105 PCIESlot *s = PCIE_SLOT(d);
106
107 pcie_aer_exit(d);
108 pcie_chassis_del_slot(s);
109 pcie_cap_exit(d);
110 pci_bridge_exitfn(d);
111}
112
113static Property xlnx_props[] = {
114 DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
115 QEMU_PCIE_SLTCAP_PCP_BITNR, true),
116 DEFINE_PROP_END_OF_LIST()
117};
118
119static const VMStateDescription vmstate_xlnx = {
120 .name = "xlnx-pcie-rp",
121 .version_id = 1,
122 .minimum_version_id = 1,
123 .post_load = pcie_cap_slot_post_load,
124 .fields = (VMStateField[]) {
125 VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
126 VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
127 PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
128 VMSTATE_END_OF_LIST()
129 }
130};
131
132static void xlnx_class_init(ObjectClass *klass, void *data)
133{
134 DeviceClass *dc = DEVICE_CLASS(klass);
135 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
136
137 k->is_bridge = 1;
138 k->config_write = xlnx_write_config;
139 k->realize = xlnx_realize;
140 k->exit = xlnx_exitfn;
141 k->vendor_id = PCI_VENDOR_ID_XILINX;
142 k->device_id = PCI_DEVICE_ID_EPORT;
143 k->revision = PCI_DEVICE_ID_REV;
144 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
145 dc->desc = "Xilinx PCIe Root Port";
146 dc->reset = xlnx_reset;
147 dc->vmsd = &vmstate_xlnx;
148 device_class_set_props(dc, xlnx_props);
149}
150
151static const TypeInfo xlnx_info = {
152 .name = "xlnx-pcie-rp",
153 .parent = TYPE_PCIE_SLOT,
154 .class_init = xlnx_class_init,
155 .interfaces = (InterfaceInfo[]) {
156 { INTERFACE_PCIE_DEVICE },
157 { },
158 },
159
160};
161
162static void xlnx_register_types(void)
163{
164 type_register_static(&xlnx_info);
165}
166
167type_init(xlnx_register_types)
168