1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "qapi/error.h"
23#include "hw/pci/msi.h"
24#include "hw/pci/pci_bridge.h"
25#include "hw/pci/pci_host.h"
26#include "hw/pci/pcie_port.h"
27#include "hw/pci-host/designware.h"
28
29#define DESIGNWARE_PCIE_PORT_LINK_CONTROL 0x710
30#define DESIGNWARE_PCIE_PHY_DEBUG_R1 0x72C
31#define DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP BIT(4)
32#define DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
33#define DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE BIT(17)
34#define DESIGNWARE_PCIE_MSI_ADDR_LO 0x820
35#define DESIGNWARE_PCIE_MSI_ADDR_HI 0x824
36#define DESIGNWARE_PCIE_MSI_INTR0_ENABLE 0x828
37#define DESIGNWARE_PCIE_MSI_INTR0_MASK 0x82C
38#define DESIGNWARE_PCIE_MSI_INTR0_STATUS 0x830
39#define DESIGNWARE_PCIE_ATU_VIEWPORT 0x900
40#define DESIGNWARE_PCIE_ATU_REGION_INBOUND BIT(31)
41#define DESIGNWARE_PCIE_ATU_CR1 0x904
42#define DESIGNWARE_PCIE_ATU_TYPE_MEM (0x0 << 0)
43#define DESIGNWARE_PCIE_ATU_CR2 0x908
44#define DESIGNWARE_PCIE_ATU_ENABLE BIT(31)
45#define DESIGNWARE_PCIE_ATU_LOWER_BASE 0x90C
46#define DESIGNWARE_PCIE_ATU_UPPER_BASE 0x910
47#define DESIGNWARE_PCIE_ATU_LIMIT 0x914
48#define DESIGNWARE_PCIE_ATU_LOWER_TARGET 0x918
49#define DESIGNWARE_PCIE_ATU_BUS(x) (((x) >> 24) & 0xff)
50#define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
51#define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
52
53static DesignwarePCIEHost *
54designware_pcie_root_to_host(DesignwarePCIERoot *root)
55{
56 BusState *bus = qdev_get_parent_bus(DEVICE(root));
57 return DESIGNWARE_PCIE_HOST(bus->parent);
58}
59
60static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
61 uint64_t val, unsigned len)
62{
63 DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque);
64 DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
65
66 root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
67
68 if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
69 qemu_set_irq(host->pci.irqs[0], 1);
70 }
71}
72
73static const MemoryRegionOps designware_pci_host_msi_ops = {
74 .write = designware_pcie_root_msi_write,
75 .endianness = DEVICE_LITTLE_ENDIAN,
76 .valid = {
77 .min_access_size = 4,
78 .max_access_size = 4,
79 },
80};
81
82static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot *root)
83
84{
85 MemoryRegion *mem = &root->msi.iomem;
86 const uint64_t base = root->msi.base;
87 const bool enable = root->msi.intr[0].enable;
88
89 memory_region_set_address(mem, base);
90 memory_region_set_enabled(mem, enable);
91}
92
93static DesignwarePCIEViewport *
94designware_pcie_root_get_current_viewport(DesignwarePCIERoot *root)
95{
96 const unsigned int idx = root->atu_viewport & 0xF;
97 const unsigned int dir =
98 !!(root->atu_viewport & DESIGNWARE_PCIE_ATU_REGION_INBOUND);
99 return &root->viewports[dir][idx];
100}
101
102static uint32_t
103designware_pcie_root_config_read(PCIDevice *d, uint32_t address, int len)
104{
105 DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
106 DesignwarePCIEViewport *viewport =
107 designware_pcie_root_get_current_viewport(root);
108
109 uint32_t val;
110
111 switch (address) {
112 case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
113
114
115
116
117
118 val = 0xDEADBEEF;
119 break;
120
121 case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
122
123
124
125
126
127 val = DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE;
128 break;
129
130 case DESIGNWARE_PCIE_MSI_ADDR_LO:
131 val = root->msi.base;
132 break;
133
134 case DESIGNWARE_PCIE_MSI_ADDR_HI:
135 val = root->msi.base >> 32;
136 break;
137
138 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
139 val = root->msi.intr[0].enable;
140 break;
141
142 case DESIGNWARE_PCIE_MSI_INTR0_MASK:
143 val = root->msi.intr[0].mask;
144 break;
145
146 case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
147 val = root->msi.intr[0].status;
148 break;
149
150 case DESIGNWARE_PCIE_PHY_DEBUG_R1:
151 val = DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
152 break;
153
154 case DESIGNWARE_PCIE_ATU_VIEWPORT:
155 val = root->atu_viewport;
156 break;
157
158 case DESIGNWARE_PCIE_ATU_LOWER_BASE:
159 val = viewport->base;
160 break;
161
162 case DESIGNWARE_PCIE_ATU_UPPER_BASE:
163 val = viewport->base >> 32;
164 break;
165
166 case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
167 val = viewport->target;
168 break;
169
170 case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
171 val = viewport->target >> 32;
172 break;
173
174 case DESIGNWARE_PCIE_ATU_LIMIT:
175 val = viewport->limit;
176 break;
177
178 case DESIGNWARE_PCIE_ATU_CR1:
179 case DESIGNWARE_PCIE_ATU_CR2:
180 val = viewport->cr[(address - DESIGNWARE_PCIE_ATU_CR1) /
181 sizeof(uint32_t)];
182 break;
183
184 default:
185 val = pci_default_read_config(d, address, len);
186 break;
187 }
188
189 return val;
190}
191
192static uint64_t designware_pcie_root_data_access(void *opaque, hwaddr addr,
193 uint64_t *val, unsigned len)
194{
195 DesignwarePCIEViewport *viewport = opaque;
196 DesignwarePCIERoot *root = viewport->root;
197
198 const uint8_t busnum = DESIGNWARE_PCIE_ATU_BUS(viewport->target);
199 const uint8_t devfn = DESIGNWARE_PCIE_ATU_DEVFN(viewport->target);
200 PCIBus *pcibus = pci_get_bus(PCI_DEVICE(root));
201 PCIDevice *pcidev = pci_find_device(pcibus, busnum, devfn);
202
203 if (pcidev) {
204 addr &= pci_config_size(pcidev) - 1;
205
206 if (val) {
207 pci_host_config_write_common(pcidev, addr,
208 pci_config_size(pcidev),
209 *val, len);
210 } else {
211 return pci_host_config_read_common(pcidev, addr,
212 pci_config_size(pcidev),
213 len);
214 }
215 }
216
217 return UINT64_MAX;
218}
219
220static uint64_t designware_pcie_root_data_read(void *opaque, hwaddr addr,
221 unsigned len)
222{
223 return designware_pcie_root_data_access(opaque, addr, NULL, len);
224}
225
226static void designware_pcie_root_data_write(void *opaque, hwaddr addr,
227 uint64_t val, unsigned len)
228{
229 designware_pcie_root_data_access(opaque, addr, &val, len);
230}
231
232static const MemoryRegionOps designware_pci_host_conf_ops = {
233 .read = designware_pcie_root_data_read,
234 .write = designware_pcie_root_data_write,
235 .endianness = DEVICE_LITTLE_ENDIAN,
236 .valid = {
237 .min_access_size = 1,
238 .max_access_size = 4,
239 },
240};
241
242static void designware_pcie_update_viewport(DesignwarePCIERoot *root,
243 DesignwarePCIEViewport *viewport)
244{
245 const uint64_t target = viewport->target;
246 const uint64_t base = viewport->base;
247 const uint64_t size = (uint64_t)viewport->limit - base + 1;
248 const bool enabled = viewport->cr[1] & DESIGNWARE_PCIE_ATU_ENABLE;
249
250 MemoryRegion *current, *other;
251
252 if (viewport->cr[0] == DESIGNWARE_PCIE_ATU_TYPE_MEM) {
253 current = &viewport->mem;
254 other = &viewport->cfg;
255 memory_region_set_alias_offset(current, target);
256 } else {
257 current = &viewport->cfg;
258 other = &viewport->mem;
259 }
260
261
262
263
264
265
266 memory_region_set_enabled(other, false);
267 if (enabled) {
268 memory_region_set_size(current, size);
269 memory_region_set_address(current, base);
270 }
271 memory_region_set_enabled(current, enabled);
272}
273
274static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
275 uint32_t val, int len)
276{
277 DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
278 DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
279 DesignwarePCIEViewport *viewport =
280 designware_pcie_root_get_current_viewport(root);
281
282 switch (address) {
283 case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
284 case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
285 case DESIGNWARE_PCIE_PHY_DEBUG_R1:
286
287 break;
288
289 case DESIGNWARE_PCIE_MSI_ADDR_LO:
290 root->msi.base &= 0xFFFFFFFF00000000ULL;
291 root->msi.base |= val;
292 break;
293
294 case DESIGNWARE_PCIE_MSI_ADDR_HI:
295 root->msi.base &= 0x00000000FFFFFFFFULL;
296 root->msi.base |= (uint64_t)val << 32;
297 break;
298
299 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: {
300 const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val;
301
302 root->msi.intr[0].enable = val;
303
304 if (update_msi_mapping) {
305 designware_pcie_root_update_msi_mapping(root);
306 }
307 break;
308 }
309
310 case DESIGNWARE_PCIE_MSI_INTR0_MASK:
311 root->msi.intr[0].mask = val;
312 break;
313
314 case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
315 root->msi.intr[0].status ^= val;
316 if (!root->msi.intr[0].status) {
317 qemu_set_irq(host->pci.irqs[0], 0);
318 }
319 break;
320
321 case DESIGNWARE_PCIE_ATU_VIEWPORT:
322 root->atu_viewport = val;
323 break;
324
325 case DESIGNWARE_PCIE_ATU_LOWER_BASE:
326 viewport->base &= 0xFFFFFFFF00000000ULL;
327 viewport->base |= val;
328 break;
329
330 case DESIGNWARE_PCIE_ATU_UPPER_BASE:
331 viewport->base &= 0x00000000FFFFFFFFULL;
332 viewport->base |= (uint64_t)val << 32;
333 break;
334
335 case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
336 viewport->target &= 0xFFFFFFFF00000000ULL;
337 viewport->target |= val;
338 break;
339
340 case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
341 viewport->target &= 0x00000000FFFFFFFFULL;
342 viewport->target |= val;
343 break;
344
345 case DESIGNWARE_PCIE_ATU_LIMIT:
346 viewport->limit = val;
347 break;
348
349 case DESIGNWARE_PCIE_ATU_CR1:
350 viewport->cr[0] = val;
351 break;
352 case DESIGNWARE_PCIE_ATU_CR2:
353 viewport->cr[1] = val;
354 designware_pcie_update_viewport(root, viewport);
355 break;
356
357 default:
358 pci_bridge_write_config(d, address, val, len);
359 break;
360 }
361}
362
363static char *designware_pcie_viewport_name(const char *direction,
364 unsigned int i,
365 const char *type)
366{
367 return g_strdup_printf("PCI %s Viewport %u [%s]",
368 direction, i, type);
369}
370
371static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
372{
373 DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev);
374 DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
375 MemoryRegion *address_space = &host->pci.memory;
376 PCIBridge *br = PCI_BRIDGE(dev);
377 DesignwarePCIEViewport *viewport;
378
379
380
381
382 const hwaddr dummy_offset = 0;
383 const uint64_t dummy_size = 4;
384 size_t i;
385
386 br->bus_name = "dw-pcie";
387
388 pci_set_word(dev->config + PCI_COMMAND,
389 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
390
391 pci_config_set_interrupt_pin(dev->config, 1);
392 pci_bridge_initfn(dev, TYPE_PCIE_BUS);
393
394 pcie_port_init_reg(dev);
395
396 pcie_cap_init(dev, 0x70, PCI_EXP_TYPE_ROOT_PORT,
397 0, &error_fatal);
398
399 msi_nonbroken = true;
400 msi_init(dev, 0x50, 32, true, true, &error_fatal);
401
402 for (i = 0; i < DESIGNWARE_PCIE_NUM_VIEWPORTS; i++) {
403 MemoryRegion *source, *destination, *mem;
404 const char *direction;
405 char *name;
406
407 viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][i];
408 viewport->inbound = true;
409 viewport->base = 0x0000000000000000ULL;
410 viewport->target = 0x0000000000000000ULL;
411 viewport->limit = UINT32_MAX;
412 viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
413
414 source = &host->pci.address_space_root;
415 destination = get_system_memory();
416 direction = "Inbound";
417
418
419
420
421
422 mem = &viewport->mem;
423 name = designware_pcie_viewport_name(direction, i, "MEM");
424 memory_region_init_alias(mem, OBJECT(root), name, destination,
425 dummy_offset, dummy_size);
426 memory_region_add_subregion_overlap(source, dummy_offset, mem, -1);
427 memory_region_set_enabled(mem, false);
428 g_free(name);
429
430 viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_OUTBOUND][i];
431 viewport->root = root;
432 viewport->inbound = false;
433 viewport->base = 0x0000000000000000ULL;
434 viewport->target = 0x0000000000000000ULL;
435 viewport->limit = UINT32_MAX;
436 viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
437
438 destination = &host->pci.memory;
439 direction = "Outbound";
440 source = get_system_memory();
441
442
443
444
445
446 mem = &viewport->mem;
447 name = designware_pcie_viewport_name(direction, i, "MEM");
448 memory_region_init_alias(mem, OBJECT(root), name, destination,
449 dummy_offset, dummy_size);
450 memory_region_add_subregion(source, dummy_offset, mem);
451 memory_region_set_enabled(mem, false);
452 g_free(name);
453
454
455
456
457
458 mem = &viewport->cfg;
459 name = designware_pcie_viewport_name(direction, i, "CFG");
460 memory_region_init_io(&viewport->cfg, OBJECT(root),
461 &designware_pci_host_conf_ops,
462 viewport, name, dummy_size);
463 memory_region_add_subregion(source, dummy_offset, mem);
464 memory_region_set_enabled(mem, false);
465 g_free(name);
466 }
467
468
469
470
471
472
473
474
475
476
477 viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][0];
478 viewport->cr[1] = DESIGNWARE_PCIE_ATU_ENABLE;
479 designware_pcie_update_viewport(root, viewport);
480
481 memory_region_init_io(&root->msi.iomem, OBJECT(root),
482 &designware_pci_host_msi_ops,
483 root, "pcie-msi", 0x4);
484
485
486
487
488
489
490 memory_region_add_subregion(address_space, dummy_offset, &root->msi.iomem);
491 memory_region_set_enabled(&root->msi.iomem, false);
492}
493
494static void designware_pcie_set_irq(void *opaque, int irq_num, int level)
495{
496 DesignwarePCIEHost *host = DESIGNWARE_PCIE_HOST(opaque);
497
498 qemu_set_irq(host->pci.irqs[irq_num], level);
499}
500
501static const char *
502designware_pcie_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus)
503{
504 return "0000:00";
505}
506
507static const VMStateDescription vmstate_designware_pcie_msi_bank = {
508 .name = "designware-pcie-msi-bank",
509 .version_id = 1,
510 .minimum_version_id = 1,
511 .fields = (VMStateField[]) {
512 VMSTATE_UINT32(enable, DesignwarePCIEMSIBank),
513 VMSTATE_UINT32(mask, DesignwarePCIEMSIBank),
514 VMSTATE_UINT32(status, DesignwarePCIEMSIBank),
515 VMSTATE_END_OF_LIST()
516 }
517};
518
519static const VMStateDescription vmstate_designware_pcie_msi = {
520 .name = "designware-pcie-msi",
521 .version_id = 1,
522 .minimum_version_id = 1,
523 .fields = (VMStateField[]) {
524 VMSTATE_UINT64(base, DesignwarePCIEMSI),
525 VMSTATE_STRUCT_ARRAY(intr,
526 DesignwarePCIEMSI,
527 DESIGNWARE_PCIE_NUM_MSI_BANKS,
528 1,
529 vmstate_designware_pcie_msi_bank,
530 DesignwarePCIEMSIBank),
531 VMSTATE_END_OF_LIST()
532 }
533};
534
535static const VMStateDescription vmstate_designware_pcie_viewport = {
536 .name = "designware-pcie-viewport",
537 .version_id = 1,
538 .minimum_version_id = 1,
539 .fields = (VMStateField[]) {
540 VMSTATE_UINT64(base, DesignwarePCIEViewport),
541 VMSTATE_UINT64(target, DesignwarePCIEViewport),
542 VMSTATE_UINT32(limit, DesignwarePCIEViewport),
543 VMSTATE_UINT32_ARRAY(cr, DesignwarePCIEViewport, 2),
544 VMSTATE_END_OF_LIST()
545 }
546};
547
548static const VMStateDescription vmstate_designware_pcie_root = {
549 .name = "designware-pcie-root",
550 .version_id = 1,
551 .minimum_version_id = 1,
552 .fields = (VMStateField[]) {
553 VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
554 VMSTATE_UINT32(atu_viewport, DesignwarePCIERoot),
555 VMSTATE_STRUCT_2DARRAY(viewports,
556 DesignwarePCIERoot,
557 2,
558 DESIGNWARE_PCIE_NUM_VIEWPORTS,
559 1,
560 vmstate_designware_pcie_viewport,
561 DesignwarePCIEViewport),
562 VMSTATE_STRUCT(msi,
563 DesignwarePCIERoot,
564 1,
565 vmstate_designware_pcie_msi,
566 DesignwarePCIEMSI),
567 VMSTATE_END_OF_LIST()
568 }
569};
570
571static void designware_pcie_root_class_init(ObjectClass *klass, void *data)
572{
573 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
574 DeviceClass *dc = DEVICE_CLASS(klass);
575
576 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
577
578 k->vendor_id = PCI_VENDOR_ID_SYNOPSYS;
579 k->device_id = 0xABCD;
580 k->revision = 0;
581 k->class_id = PCI_CLASS_BRIDGE_PCI;
582 k->is_bridge = true;
583 k->exit = pci_bridge_exitfn;
584 k->realize = designware_pcie_root_realize;
585 k->config_read = designware_pcie_root_config_read;
586 k->config_write = designware_pcie_root_config_write;
587
588 dc->reset = pci_bridge_reset;
589
590
591
592
593 dc->user_creatable = false;
594 dc->vmsd = &vmstate_designware_pcie_root;
595}
596
597static uint64_t designware_pcie_host_mmio_read(void *opaque, hwaddr addr,
598 unsigned int size)
599{
600 PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
601 PCIDevice *device = pci_find_device(pci->bus, 0, 0);
602
603 return pci_host_config_read_common(device,
604 addr,
605 pci_config_size(device),
606 size);
607}
608
609static void designware_pcie_host_mmio_write(void *opaque, hwaddr addr,
610 uint64_t val, unsigned int size)
611{
612 PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
613 PCIDevice *device = pci_find_device(pci->bus, 0, 0);
614
615 return pci_host_config_write_common(device,
616 addr,
617 pci_config_size(device),
618 val, size);
619}
620
621static const MemoryRegionOps designware_pci_mmio_ops = {
622 .read = designware_pcie_host_mmio_read,
623 .write = designware_pcie_host_mmio_write,
624 .endianness = DEVICE_LITTLE_ENDIAN,
625 .impl = {
626
627
628
629
630
631
632 .min_access_size = 4,
633 .max_access_size = 4,
634 .unaligned = false,
635 },
636};
637
638static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
639 int devfn)
640{
641 DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque);
642
643 return &s->pci.address_space;
644}
645
646static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
647{
648 PCIHostState *pci = PCI_HOST_BRIDGE(dev);
649 DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(dev);
650 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
651 size_t i;
652
653 for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
654 sysbus_init_irq(sbd, &s->pci.irqs[i]);
655 }
656
657 memory_region_init_io(&s->mmio,
658 OBJECT(s),
659 &designware_pci_mmio_ops,
660 s,
661 "pcie.reg", 4 * 1024);
662 sysbus_init_mmio(sbd, &s->mmio);
663
664 memory_region_init(&s->pci.io, OBJECT(s), "pcie-pio", 16);
665 memory_region_init(&s->pci.memory, OBJECT(s),
666 "pcie-bus-memory",
667 UINT64_MAX);
668
669 pci->bus = pci_register_root_bus(dev, "pcie",
670 designware_pcie_set_irq,
671 pci_swizzle_map_irq_fn,
672 s,
673 &s->pci.memory,
674 &s->pci.io,
675 0, 4,
676 TYPE_PCIE_BUS);
677
678 memory_region_init(&s->pci.address_space_root,
679 OBJECT(s),
680 "pcie-bus-address-space-root",
681 UINT64_MAX);
682 memory_region_add_subregion(&s->pci.address_space_root,
683 0x0, &s->pci.memory);
684 address_space_init(&s->pci.address_space,
685 &s->pci.address_space_root,
686 "pcie-bus-address-space");
687 pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s);
688
689 qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
690 qdev_init_nofail(DEVICE(&s->root));
691}
692
693static const VMStateDescription vmstate_designware_pcie_host = {
694 .name = "designware-pcie-host",
695 .version_id = 1,
696 .minimum_version_id = 1,
697 .fields = (VMStateField[]) {
698 VMSTATE_STRUCT(root,
699 DesignwarePCIEHost,
700 1,
701 vmstate_designware_pcie_root,
702 DesignwarePCIERoot),
703 VMSTATE_END_OF_LIST()
704 }
705};
706
707static void designware_pcie_host_class_init(ObjectClass *klass, void *data)
708{
709 DeviceClass *dc = DEVICE_CLASS(klass);
710 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
711
712 hc->root_bus_path = designware_pcie_host_root_bus_path;
713 dc->realize = designware_pcie_host_realize;
714 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
715 dc->fw_name = "pci";
716 dc->vmsd = &vmstate_designware_pcie_host;
717}
718
719static void designware_pcie_host_init(Object *obj)
720{
721 DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj);
722 DesignwarePCIERoot *root = &s->root;
723
724 object_initialize(root, sizeof(*root), TYPE_DESIGNWARE_PCIE_ROOT);
725 object_property_add_child(obj, "root", OBJECT(root), NULL);
726 qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
727 qdev_prop_set_bit(DEVICE(root), "multifunction", false);
728}
729
730static const TypeInfo designware_pcie_root_info = {
731 .name = TYPE_DESIGNWARE_PCIE_ROOT,
732 .parent = TYPE_PCI_BRIDGE,
733 .instance_size = sizeof(DesignwarePCIERoot),
734 .class_init = designware_pcie_root_class_init,
735 .interfaces = (InterfaceInfo[]) {
736 { INTERFACE_PCIE_DEVICE },
737 { }
738 },
739};
740
741static const TypeInfo designware_pcie_host_info = {
742 .name = TYPE_DESIGNWARE_PCIE_HOST,
743 .parent = TYPE_PCI_HOST_BRIDGE,
744 .instance_size = sizeof(DesignwarePCIEHost),
745 .instance_init = designware_pcie_host_init,
746 .class_init = designware_pcie_host_class_init,
747};
748
749static void designware_pcie_register(void)
750{
751 type_register_static(&designware_pcie_root_info);
752 type_register_static(&designware_pcie_host_info);
753}
754type_init(designware_pcie_register)
755