1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "hw/sysbus.h"
28#include "sysemu/sysemu.h"
29#include "qemu/log.h"
30#include "hw/pci/pci.h"
31#include "exec/memory.h"
32#include "exec/address-spaces.h"
33
34#include "hw/fdt_generic_util.h"
35
36#define XILINX_AXI_PCIE_DEBUG 1
37
38#ifndef XILINX_AXI_PCIE_DEBUG
39#define XILINX_AXI_PCIE_DEBUG 0
40#endif
41#define DB_PRINT(fmt, args...) do {\
42 if (XILINX_AXI_PCIE_DEBUG) {\
43 fprintf(stderr, "XILINX_AXI_PCIE: %s:" fmt, __func__, ## args);\
44 } \
45} while (0);
46
47#define R_ADDR_TO_IDX(x) (((x) - 0x130) / 4)
48
49#define R_BR_INFO R_ADDR_TO_IDX(0x130)
50#define R_BR_SCR R_ADDR_TO_IDX(0x134)
51#define R_IDR R_ADDR_TO_IDX(0x138)
52#define R_IMR R_ADDR_TO_IDX(0x13c)
53#define R_BUS_LOC R_ADDR_TO_IDX(0x140)
54#define R_PHY_SCR R_ADDR_TO_IDX(0x144)
55#define R_RP_MSI_1 R_ADDR_TO_IDX(0x14c)
56#define R_RP_MSI_2 R_ADDR_TO_IDX(0x150)
57#define R_RP_ERR_FIFO R_ADDR_TO_IDX(0x154)
58#define R_RP_INT_FIFO1 R_ADDR_TO_IDX(0x158)
59#define R_RP_INT_FIFO2 R_ADDR_TO_IDX(0x15c)
60
61#define R_MAX ((0x160 - 0x130)/4)
62
63
64
65
66
67typedef struct XilinxAXIPCIERegInfo {
68 const char *name;
69 uint32_t ro;
70 uint32_t wtc;
71 uint32_t reset;
72 int width;
73} XilinxAXIPCIERegInfo;
74
75static const XilinxAXIPCIERegInfo xilinx_axi_pcie_reg_info[] = {
76 [R_BR_INFO] = {.name = "BRIDGE INFO", .width = 19, .reset = 0x70007,
77 .ro = ~0 },
78 [R_BR_SCR] = {.name = "BRIDGE STATUS CONTROL", .width = 18,
79 .ro = 0x0FEFF },
80 [R_IDR] = {.name = "INTERRUPT DECODE", .width = 29,
81 .wtc = 0x1FF30FEF, .ro = 0xCF010 },
82 [R_IMR] = {.name = "INTERRUPT MASK", .width = 29,
83 .ro = 0xCF010 },
84 [R_BUS_LOC] = {.name = "BUS LOCATION", .width = 24 },
85 [R_PHY_SCR] = {.name = "PHY STATUS CONTROL", .width = 22,
86 .ro = 0xFFFF, .reset = 0x800 },
87 [R_RP_MSI_1] = {.name = "ROOT PORT MSI BASE 1", .width = 32 },
88 [R_RP_MSI_2] = {.name = "ROOT PORT MSI BASE 2", .width = 32 },
89 [R_MAX] = {.name = NULL }
90};
91
92#define MAX_AXI_TO_PCI_BARS 6
93#define MAX_PCI_TO_AXI_BARS 3
94
95typedef struct XilinxACIPCIEMapping {
96 hwaddr src;
97 hwaddr dst;
98 hwaddr size;
99 uint8_t size2;
100} XilinxACIPCIEMapping;
101
102typedef struct XilinxAXIPCIE {
103 SysBusDevice busdev;
104 PCIBus *pci_bus;
105
106 MemoryRegion container;
107 MemoryRegion config;
108 MemoryRegion mmio;
109 MemoryRegion pci_space;
110
111 MemoryRegion axi_to_pci_bar[MAX_AXI_TO_PCI_BARS];
112 MemoryRegion pci_to_axi_bar[MAX_PCI_TO_AXI_BARS];
113
114 PCIBus *bus;
115
116 qemu_irq irq;
117 int irqline;
118
119 uint32_t regs[R_MAX];
120} XilinxAXIPCIE;
121
122static inline void xilinx_axi_pcie_update_irq(XilinxAXIPCIE *s)
123{
124 int new_irqline = !!(s->regs[R_IDR] & s->regs[R_IMR]);
125
126 if (new_irqline != s->irqline) {
127 DB_PRINT("irq state: %d\n", new_irqline);
128 qemu_set_irq(s->irq, new_irqline);
129 s->irqline = new_irqline;
130 }
131}
132
133static void xilinx_axi_pcie_do_reset(XilinxAXIPCIE *s)
134{
135 int i;
136 memset(s->regs, 0, sizeof(s->regs));
137
138 for (i = 0; i < ARRAY_SIZE(s->regs); ++i) {
139 if (xilinx_axi_pcie_reg_info[i].name) {
140 s->regs[i] = xilinx_axi_pcie_reg_info[i].reset;
141 }
142 }
143
144 xilinx_axi_pcie_update_irq(s);
145}
146
147static void xilinx_axi_pcie_reset(DeviceState *d)
148{
149
150 xilinx_axi_pcie_do_reset((XilinxAXIPCIE *)d);
151}
152
153static inline void xilinx_axi_pcie_check_reg_access(hwaddr offset, uint32_t val,
154 bool rnw)
155{
156 if (!xilinx_axi_pcie_reg_info[offset >> 2].name) {
157 qemu_log_mask(LOG_UNIMP, "Xilinx AXI PCIE: %s offset %x\n",
158 rnw ? "read from" : "write to", (unsigned)offset);
159 DB_PRINT("Unimplemented %s offset %x\n",
160 rnw ? "read from" : "write to", (unsigned)offset);
161 } else {
162 DB_PRINT("%s %s [%#02x] %s %#08x\n", rnw ? "read" : "write",
163 xilinx_axi_pcie_reg_info[offset >> 2].name, (unsigned) offset,
164 rnw ? "->" : "<-", val);
165 }
166}
167
168static uint64_t xilinx_axi_pcie_config_read(void *opaque, hwaddr offset,
169 unsigned int size)
170{
171 XilinxAXIPCIE *s = opaque;
172 PCIDevice *pci_dev = pci_find_device(s->pci_bus, 0, 0);
173 uint64_t ret = pci_dev ? pci_dev->config_read(pci_dev, offset, size) : 0;
174
175 DB_PRINT("PCI config read device :%s offset: %x data: %x size: %d\n",
176 pci_dev ? object_get_canonical_path(OBJECT(pci_dev)) : "(none)",
177 (unsigned)offset, (unsigned)ret, size);
178
179 return ret;
180}
181
182static void xilinx_axi_pcie_config_write(void *opaque, hwaddr offset,
183 uint64_t value, unsigned int size)
184{
185 XilinxAXIPCIE *s = opaque;
186 PCIDevice *pci_dev = pci_find_device(s->pci_bus, 0, 0);
187
188 DB_PRINT("PCI config write device :%s offset: %x data: %x size: %d\n",
189 pci_dev ? object_get_canonical_path(OBJECT(pci_dev)) : "(none)",
190 (unsigned)offset, (unsigned)value, size);
191
192 if (pci_dev) {
193 pci_dev->config_write(pci_dev, offset, value, size);
194 }
195}
196
197static const MemoryRegionOps xilinx_axi_pcie_config_ops = {
198 .read = xilinx_axi_pcie_config_read,
199 .write = xilinx_axi_pcie_config_write,
200 .endianness = DEVICE_NATIVE_ENDIAN,
201 .valid = {
202 .min_access_size = 1,
203 .max_access_size = 4
204 }
205};
206
207static uint64_t xilinx_axi_pcie_read(void *opaque, hwaddr offset,
208 unsigned int size)
209{
210 XilinxAXIPCIE *s = opaque;
211 uint32_t ret = s->regs[offset >> 2];
212
213 xilinx_axi_pcie_check_reg_access(offset, ret, true);
214 return ret;
215}
216
217static void xilinx_axi_pcie_write(void *opaque, hwaddr offset, uint64_t value,
218 unsigned int size)
219{
220 XilinxAXIPCIE *s = opaque;
221 const XilinxAXIPCIERegInfo *info = &xilinx_axi_pcie_reg_info[offset >> 2];
222 uint32_t new_value = value;
223 uint32_t ro_mask;
224
225 xilinx_axi_pcie_check_reg_access(offset, value, false);
226 if (!info->name) {
227 return;
228 }
229
230 offset >>= 2;
231 assert(!(info->wtc & info->ro));
232
233 ro_mask = info->ro | info->wtc | ~((1ull << info->width) - 1);
234 new_value &= ~ro_mask;
235 new_value |= ro_mask & s->regs[offset];
236
237 new_value &= ~(value & info->wtc);
238 s->regs[offset] = new_value;
239
240 xilinx_axi_pcie_update_irq(s);
241}
242
243static const MemoryRegionOps xilinx_axi_pcie_ops = {
244 .read = xilinx_axi_pcie_read,
245 .write = xilinx_axi_pcie_write,
246 .endianness = DEVICE_NATIVE_ENDIAN,
247 .valid = {
248 .min_access_size = 4,
249 .max_access_size = 4
250 }
251};
252
253static int xilinx_axi_pcie_init(SysBusDevice *dev)
254{
255#if 0
256 XilinxAXIPCIE *s = (XilinxAXIPCIE *)dev;
257
258 DB_PRINT("\n");
259
260
261 memory_region_init(&s->pci_space, OBJECT(dev), "xilinx-pci-bar", 1ull << 32);
262 s->pci_bus = pci_register_bus(DEVICE(dev), "xilinx-pci",
263 NULL, NULL, s->irq,
264 &s->pci_space, get_system_io(),
265 0 , 1, TYPE_PCI_BUS);
266
267
268
269 memory_region_init_io(&s->config, OBJECT(dev), &razwi_unimp_ops, s,
270 "xilinx-axi_pcie_bar", 0x10000000);
271 memory_region_add_subregion(get_system_memory(), 0x70000000,
272 &s->axi_to_pci_bar[0]);
273
274 memory_region_init_alias(&s->pci_to_axi_bar[0], OBJECT(dev), "bar", get_system_memory(),
275 0x50000000, 0x10000000);
276 memory_region_add_subregion(&s->pci_space, 0x50000000,
277 &s->pci_to_axi_bar[0]);
278
279 sysbus_init_irq(dev, &s->irq);
280 memory_region_init(&s->container, OBJECT(dev), "a9mp-priv-container", 16 << 20);
281 memory_region_init_io(&s->mmio, OBJECT(dev), &xilinx_axi_pcie_ops, s,
282 "xilinx-axi_pcie_mmio", R_MAX * 4);
283 memory_region_add_subregion(&s->container, 0x130, &s->mmio);
284
285 memory_region_init_io(&s->config, OBJECT(dev), &xilinx_axi_pcie_config_ops, s,
286 "xilinx-axi_pcie_mmio", 0x130);
287 memory_region_add_subregion(&s->container, 0, &s->config);
288
289 sysbus_init_mmio(dev, &s->container);
290
291 s->irqline = -1;
292#endif
293 return 0;
294}
295
296static const VMStateDescription vmstate_xilinx_axi_pcie = {
297 .name = "xlnx.axi-pcie",
298 .version_id = 1,
299 .minimum_version_id = 1,
300 .minimum_version_id_old = 1,
301 .fields = (VMStateField[]) {
302 VMSTATE_UINT32_ARRAY(regs, XilinxAXIPCIE, R_MAX),
303 VMSTATE_END_OF_LIST()
304 }
305};
306
307static Property xilinx_axi_pcie_properties[] = {
308 DEFINE_PROP_END_OF_LIST(),
309};
310
311static void xilinx_axi_pcie_class_init(ObjectClass *klass, void *data)
312{
313 DeviceClass *dc = DEVICE_CLASS(klass);
314 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
315
316 k->init = xilinx_axi_pcie_init;
317 dc->reset = xilinx_axi_pcie_reset;
318 dc->props = xilinx_axi_pcie_properties;
319 dc->vmsd = &vmstate_xilinx_axi_pcie;
320}
321
322static TypeInfo xilinx_axi_pcie_info = {
323 .name = "xlnx.axi-pcie",
324 .parent = TYPE_SYS_BUS_DEVICE,
325 .instance_size = sizeof(XilinxAXIPCIE),
326 .class_init = xilinx_axi_pcie_class_init,
327};
328
329static void xilinx_axi_pcie_register_types(void)
330{
331 type_register_static(&xilinx_axi_pcie_info);
332}
333
334type_init(xilinx_axi_pcie_register_types)
335