pci: Add support for Designware IP block
[qemu.git] / hw / pci-host / designware.c
blob29ea3137980d28d284f01129ef00de7340676c4e
1 /*
2 * Copyright (c) 2018, Impinj, Inc.
4 * Designware PCIe IP block emulation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/>.
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"
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
53 static DesignwarePCIEHost *
54 designware_pcie_root_to_host(DesignwarePCIERoot *root)
56 BusState *bus = qdev_get_parent_bus(DEVICE(root));
57 return DESIGNWARE_PCIE_HOST(bus->parent);
60 static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
61 uint64_t val, unsigned len)
63 DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque);
64 DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
66 root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
68 if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
69 qemu_set_irq(host->pci.irqs[0], 1);
73 static 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,
82 static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot *root)
85 MemoryRegion *mem = &root->msi.iomem;
86 const uint64_t base = root->msi.base;
87 const bool enable = root->msi.intr[0].enable;
89 memory_region_set_address(mem, base);
90 memory_region_set_enabled(mem, enable);
93 static DesignwarePCIEViewport *
94 designware_pcie_root_get_current_viewport(DesignwarePCIERoot *root)
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];
102 static uint32_t
103 designware_pcie_root_config_read(PCIDevice *d, uint32_t address, int len)
105 DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
106 DesignwarePCIEViewport *viewport =
107 designware_pcie_root_get_current_viewport(root);
109 uint32_t val;
111 switch (address) {
112 case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
114 * Linux guest uses this register only to configure number of
115 * PCIE lane (which in our case is irrelevant) and doesn't
116 * really care about the value it reads from this register
118 val = 0xDEADBEEF;
119 break;
121 case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
123 * To make sure that any code in guest waiting for speed
124 * change does not time out we always report
125 * PORT_LOGIC_SPEED_CHANGE as set
127 val = DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE;
128 break;
130 case DESIGNWARE_PCIE_MSI_ADDR_LO:
131 val = root->msi.base;
132 break;
134 case DESIGNWARE_PCIE_MSI_ADDR_HI:
135 val = root->msi.base >> 32;
136 break;
138 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
139 val = root->msi.intr[0].enable;
140 break;
142 case DESIGNWARE_PCIE_MSI_INTR0_MASK:
143 val = root->msi.intr[0].mask;
144 break;
146 case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
147 val = root->msi.intr[0].status;
148 break;
150 case DESIGNWARE_PCIE_PHY_DEBUG_R1:
151 val = DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
152 break;
154 case DESIGNWARE_PCIE_ATU_VIEWPORT:
155 val = root->atu_viewport;
156 break;
158 case DESIGNWARE_PCIE_ATU_LOWER_BASE:
159 val = viewport->base;
160 break;
162 case DESIGNWARE_PCIE_ATU_UPPER_BASE:
163 val = viewport->base >> 32;
164 break;
166 case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
167 val = viewport->target;
168 break;
170 case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
171 val = viewport->target >> 32;
172 break;
174 case DESIGNWARE_PCIE_ATU_LIMIT:
175 val = viewport->limit;
176 break;
178 case DESIGNWARE_PCIE_ATU_CR1:
179 case DESIGNWARE_PCIE_ATU_CR2: /* FALLTHROUGH */
180 val = viewport->cr[(address - DESIGNWARE_PCIE_ATU_CR1) /
181 sizeof(uint32_t)];
182 break;
184 default:
185 val = pci_default_read_config(d, address, len);
186 break;
189 return val;
192 static uint64_t designware_pcie_root_data_access(void *opaque, hwaddr addr,
193 uint64_t *val, unsigned len)
195 DesignwarePCIEViewport *viewport = opaque;
196 DesignwarePCIERoot *root = viewport->root;
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);
203 if (pcidev) {
204 addr &= pci_config_size(pcidev) - 1;
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);
217 return UINT64_MAX;
220 static uint64_t designware_pcie_root_data_read(void *opaque, hwaddr addr,
221 unsigned len)
223 return designware_pcie_root_data_access(opaque, addr, NULL, len);
226 static void designware_pcie_root_data_write(void *opaque, hwaddr addr,
227 uint64_t val, unsigned len)
229 designware_pcie_root_data_access(opaque, addr, &val, len);
232 static 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,
242 static void designware_pcie_update_viewport(DesignwarePCIERoot *root,
243 DesignwarePCIEViewport *viewport)
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;
250 MemoryRegion *current, *other;
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;
262 * An outbound viewport can be reconfigure from being MEM to CFG,
263 * to account for that we disable the "other" memory region that
264 * becomes unused due to that fact.
266 memory_region_set_enabled(other, false);
267 if (enabled) {
268 memory_region_set_size(current, size);
269 memory_region_set_address(current, base);
271 memory_region_set_enabled(current, enabled);
274 static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
275 uint32_t val, int len)
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);
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 /* No-op */
287 break;
289 case DESIGNWARE_PCIE_MSI_ADDR_LO:
290 root->msi.base &= 0xFFFFFFFF00000000ULL;
291 root->msi.base |= val;
292 break;
294 case DESIGNWARE_PCIE_MSI_ADDR_HI:
295 root->msi.base &= 0x00000000FFFFFFFFULL;
296 root->msi.base |= (uint64_t)val << 32;
297 break;
299 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: {
300 const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val;
302 root->msi.intr[0].enable = val;
304 if (update_msi_mapping) {
305 designware_pcie_root_update_msi_mapping(root);
307 break;
310 case DESIGNWARE_PCIE_MSI_INTR0_MASK:
311 root->msi.intr[0].mask = val;
312 break;
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);
319 break;
321 case DESIGNWARE_PCIE_ATU_VIEWPORT:
322 root->atu_viewport = val;
323 break;
325 case DESIGNWARE_PCIE_ATU_LOWER_BASE:
326 viewport->base &= 0xFFFFFFFF00000000ULL;
327 viewport->base |= val;
328 break;
330 case DESIGNWARE_PCIE_ATU_UPPER_BASE:
331 viewport->base &= 0x00000000FFFFFFFFULL;
332 viewport->base |= (uint64_t)val << 32;
333 break;
335 case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
336 viewport->target &= 0xFFFFFFFF00000000ULL;
337 viewport->target |= val;
338 break;
340 case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
341 viewport->target &= 0x00000000FFFFFFFFULL;
342 viewport->target |= val;
343 break;
345 case DESIGNWARE_PCIE_ATU_LIMIT:
346 viewport->limit = val;
347 break;
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;
357 default:
358 pci_bridge_write_config(d, address, val, len);
359 break;
363 static char *designware_pcie_viewport_name(const char *direction,
364 unsigned int i,
365 const char *type)
367 return g_strdup_printf("PCI %s Viewport %u [%s]",
368 direction, i, type);
371 static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
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;
379 * Dummy values used for initial configuration of MemoryRegions
380 * that belong to a given viewport
382 const hwaddr dummy_offset = 0;
383 const uint64_t dummy_size = 4;
384 size_t i;
386 br->bus_name = "dw-pcie";
388 pci_set_word(dev->config + PCI_COMMAND,
389 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
391 pci_config_set_interrupt_pin(dev->config, 1);
392 pci_bridge_initfn(dev, TYPE_PCIE_BUS);
394 pcie_port_init_reg(dev);
396 pcie_cap_init(dev, 0x70, PCI_EXP_TYPE_ROOT_PORT,
397 0, &error_fatal);
399 msi_nonbroken = true;
400 msi_init(dev, 0x50, 32, true, true, &error_fatal);
402 for (i = 0; i < DESIGNWARE_PCIE_NUM_VIEWPORTS; i++) {
403 MemoryRegion *source, *destination, *mem;
404 const char *direction;
405 char *name;
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;
414 source = &host->pci.address_space_root;
415 destination = get_system_memory();
416 direction = "Inbound";
419 * Configure MemoryRegion implementing PCI -> CPU memory
420 * access
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);
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;
438 destination = &host->pci.memory;
439 direction = "Outbound";
440 source = get_system_memory();
443 * Configure MemoryRegion implementing CPU -> PCI memory
444 * access
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);
455 * Configure MemoryRegion implementing access to configuration
456 * space
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);
469 * If no inbound iATU windows are configured, HW defaults to
470 * letting inbound TLPs to pass in. We emulate that by exlicitly
471 * configuring first inbound window to cover all of target's
472 * address space.
474 * NOTE: This will not work correctly for the case when first
475 * configured inbound window is window 0
477 viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][0];
478 viewport->cr[1] = DESIGNWARE_PCIE_ATU_ENABLE;
479 designware_pcie_update_viewport(root, viewport);
481 memory_region_init_io(&root->msi.iomem, OBJECT(root),
482 &designware_pci_host_msi_ops,
483 root, "pcie-msi", 0x4);
485 * We initially place MSI interrupt I/O region a adress 0 and
486 * disable it. It'll be later moved to correct offset and enabled
487 * in designware_pcie_root_update_msi_mapping() as a part of
488 * initialization done by guest OS
490 memory_region_add_subregion(address_space, dummy_offset, &root->msi.iomem);
491 memory_region_set_enabled(&root->msi.iomem, false);
494 static void designware_pcie_set_irq(void *opaque, int irq_num, int level)
496 DesignwarePCIEHost *host = DESIGNWARE_PCIE_HOST(opaque);
498 qemu_set_irq(host->pci.irqs[irq_num], level);
501 static const char *
502 designware_pcie_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus)
504 return "0000:00";
507 static 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()
519 static 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,
529 vmstate_designware_pcie_msi_bank,
530 DesignwarePCIEMSIBank),
531 VMSTATE_END_OF_LIST()
535 static 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()
548 static 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,
558 DESIGNWARE_PCIE_NUM_VIEWPORTS,
560 vmstate_designware_pcie_viewport,
561 DesignwarePCIEViewport),
562 VMSTATE_STRUCT(msi,
563 DesignwarePCIERoot,
565 vmstate_designware_pcie_msi,
566 DesignwarePCIEMSI),
567 VMSTATE_END_OF_LIST()
571 static void designware_pcie_root_class_init(ObjectClass *klass, void *data)
573 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
574 DeviceClass *dc = DEVICE_CLASS(klass);
576 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
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;
588 dc->reset = pci_bridge_reset;
590 * PCI-facing part of the host bridge, not usable without the
591 * host-facing part, which can't be device_add'ed, yet.
593 dc->user_creatable = false;
594 dc->vmsd = &vmstate_designware_pcie_root;
597 static uint64_t designware_pcie_host_mmio_read(void *opaque, hwaddr addr,
598 unsigned int size)
600 PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
601 PCIDevice *device = pci_find_device(pci->bus, 0, 0);
603 return pci_host_config_read_common(device,
604 addr,
605 pci_config_size(device),
606 size);
609 static void designware_pcie_host_mmio_write(void *opaque, hwaddr addr,
610 uint64_t val, unsigned int size)
612 PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
613 PCIDevice *device = pci_find_device(pci->bus, 0, 0);
615 return pci_host_config_write_common(device,
616 addr,
617 pci_config_size(device),
618 val, size);
621 static 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 = {
627 * Our device would not work correctly if the guest was doing
628 * unaligned access. This might not be a limitation on the real
629 * device but in practice there is no reason for a guest to access
630 * this device unaligned.
632 .min_access_size = 4,
633 .max_access_size = 4,
634 .unaligned = false,
638 static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
639 int devfn)
641 DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque);
643 return &s->pci.address_space;
646 static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
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;
653 for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
654 sysbus_init_irq(sbd, &s->pci.irqs[i]);
657 memory_region_init_io(&s->mmio,
658 OBJECT(s),
659 &designware_pci_mmio_ops,
661 "pcie.reg", 4 * 1024);
662 sysbus_init_mmio(sbd, &s->mmio);
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);
669 pci->bus = pci_register_root_bus(dev, "pcie",
670 designware_pcie_set_irq,
671 pci_swizzle_map_irq_fn,
673 &s->pci.memory,
674 &s->pci.io,
675 0, 4,
676 TYPE_PCIE_BUS);
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);
689 qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
690 qdev_init_nofail(DEVICE(&s->root));
693 static 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,
701 vmstate_designware_pcie_root,
702 DesignwarePCIERoot),
703 VMSTATE_END_OF_LIST()
707 static void designware_pcie_host_class_init(ObjectClass *klass, void *data)
709 DeviceClass *dc = DEVICE_CLASS(klass);
710 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
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;
719 static void designware_pcie_host_init(Object *obj)
721 DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj);
722 DesignwarePCIERoot *root = &s->root;
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);
730 static 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 },
741 static 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,
749 static void designware_pcie_register(void)
751 type_register_static(&designware_pcie_root_info);
752 type_register_static(&designware_pcie_host_info);
754 type_init(designware_pcie_register)