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