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.1 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 "qemu/module.h"
25 #include "hw/pci/msi.h"
26 #include "hw/pci/pci_bridge.h"
27 #include "hw/pci/pci_host.h"
28 #include "hw/pci/pcie_port.h"
29 #include "hw/qdev-properties.h"
30 #include "migration/vmstate.h"
32 #include "hw/pci-host/designware.h"
34 #define DESIGNWARE_PCIE_PORT_LINK_CONTROL 0x710
35 #define DESIGNWARE_PCIE_PHY_DEBUG_R1 0x72C
36 #define DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP BIT(4)
37 #define DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
38 #define DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE BIT(17)
39 #define DESIGNWARE_PCIE_MSI_ADDR_LO 0x820
40 #define DESIGNWARE_PCIE_MSI_ADDR_HI 0x824
41 #define DESIGNWARE_PCIE_MSI_INTR0_ENABLE 0x828
42 #define DESIGNWARE_PCIE_MSI_INTR0_MASK 0x82C
43 #define DESIGNWARE_PCIE_MSI_INTR0_STATUS 0x830
44 #define DESIGNWARE_PCIE_ATU_VIEWPORT 0x900
45 #define DESIGNWARE_PCIE_ATU_REGION_INBOUND BIT(31)
46 #define DESIGNWARE_PCIE_ATU_CR1 0x904
47 #define DESIGNWARE_PCIE_ATU_TYPE_MEM (0x0 << 0)
48 #define DESIGNWARE_PCIE_ATU_CR2 0x908
49 #define DESIGNWARE_PCIE_ATU_ENABLE BIT(31)
50 #define DESIGNWARE_PCIE_ATU_LOWER_BASE 0x90C
51 #define DESIGNWARE_PCIE_ATU_UPPER_BASE 0x910
52 #define DESIGNWARE_PCIE_ATU_LIMIT 0x914
53 #define DESIGNWARE_PCIE_ATU_LOWER_TARGET 0x918
54 #define DESIGNWARE_PCIE_ATU_BUS(x) (((x) >> 24) & 0xff)
55 #define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
56 #define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
58 #define DESIGNWARE_PCIE_IRQ_MSI 3
60 static DesignwarePCIEHost
*
61 designware_pcie_root_to_host(DesignwarePCIERoot
*root
)
63 BusState
*bus
= qdev_get_parent_bus(DEVICE(root
));
64 return DESIGNWARE_PCIE_HOST(bus
->parent
);
67 static uint64_t designware_pcie_root_msi_read(void *opaque
, hwaddr addr
,
71 * Attempts to read from the MSI address are undefined in
72 * the PCI specifications. For this hardware, the datasheet
73 * specifies that a read from the magic address is simply not
74 * intercepted by the MSI controller, and will go out to the
75 * AHB/AXI bus like any other PCI-device-initiated DMA read.
76 * This is not trivial to implement in QEMU, so since
77 * well-behaved guests won't ever ask a PCI device to DMA from
78 * this address we just log the missing functionality.
80 qemu_log_mask(LOG_UNIMP
, "%s not implemented\n", __func__
);
84 static void designware_pcie_root_msi_write(void *opaque
, hwaddr addr
,
85 uint64_t val
, unsigned len
)
87 DesignwarePCIERoot
*root
= DESIGNWARE_PCIE_ROOT(opaque
);
88 DesignwarePCIEHost
*host
= designware_pcie_root_to_host(root
);
90 root
->msi
.intr
[0].status
|= BIT(val
) & root
->msi
.intr
[0].enable
;
92 if (root
->msi
.intr
[0].status
& ~root
->msi
.intr
[0].mask
) {
93 qemu_set_irq(host
->pci
.irqs
[DESIGNWARE_PCIE_IRQ_MSI
], 1);
97 static const MemoryRegionOps designware_pci_host_msi_ops
= {
98 .read
= designware_pcie_root_msi_read
,
99 .write
= designware_pcie_root_msi_write
,
100 .endianness
= DEVICE_LITTLE_ENDIAN
,
102 .min_access_size
= 4,
103 .max_access_size
= 4,
107 static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot
*root
)
110 MemoryRegion
*mem
= &root
->msi
.iomem
;
111 const uint64_t base
= root
->msi
.base
;
112 const bool enable
= root
->msi
.intr
[0].enable
;
114 memory_region_set_address(mem
, base
);
115 memory_region_set_enabled(mem
, enable
);
118 static DesignwarePCIEViewport
*
119 designware_pcie_root_get_current_viewport(DesignwarePCIERoot
*root
)
121 const unsigned int idx
= root
->atu_viewport
& 0xF;
122 const unsigned int dir
=
123 !!(root
->atu_viewport
& DESIGNWARE_PCIE_ATU_REGION_INBOUND
);
124 return &root
->viewports
[dir
][idx
];
128 designware_pcie_root_config_read(PCIDevice
*d
, uint32_t address
, int len
)
130 DesignwarePCIERoot
*root
= DESIGNWARE_PCIE_ROOT(d
);
131 DesignwarePCIEViewport
*viewport
=
132 designware_pcie_root_get_current_viewport(root
);
137 case DESIGNWARE_PCIE_PORT_LINK_CONTROL
:
139 * Linux guest uses this register only to configure number of
140 * PCIE lane (which in our case is irrelevant) and doesn't
141 * really care about the value it reads from this register
146 case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL
:
148 * To make sure that any code in guest waiting for speed
149 * change does not time out we always report
150 * PORT_LOGIC_SPEED_CHANGE as set
152 val
= DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE
;
155 case DESIGNWARE_PCIE_MSI_ADDR_LO
:
156 val
= root
->msi
.base
;
159 case DESIGNWARE_PCIE_MSI_ADDR_HI
:
160 val
= root
->msi
.base
>> 32;
163 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE
:
164 val
= root
->msi
.intr
[0].enable
;
167 case DESIGNWARE_PCIE_MSI_INTR0_MASK
:
168 val
= root
->msi
.intr
[0].mask
;
171 case DESIGNWARE_PCIE_MSI_INTR0_STATUS
:
172 val
= root
->msi
.intr
[0].status
;
175 case DESIGNWARE_PCIE_PHY_DEBUG_R1
:
176 val
= DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP
;
179 case DESIGNWARE_PCIE_ATU_VIEWPORT
:
180 val
= root
->atu_viewport
;
183 case DESIGNWARE_PCIE_ATU_LOWER_BASE
:
184 val
= viewport
->base
;
187 case DESIGNWARE_PCIE_ATU_UPPER_BASE
:
188 val
= viewport
->base
>> 32;
191 case DESIGNWARE_PCIE_ATU_LOWER_TARGET
:
192 val
= viewport
->target
;
195 case DESIGNWARE_PCIE_ATU_UPPER_TARGET
:
196 val
= viewport
->target
>> 32;
199 case DESIGNWARE_PCIE_ATU_LIMIT
:
200 val
= viewport
->limit
;
203 case DESIGNWARE_PCIE_ATU_CR1
:
204 case DESIGNWARE_PCIE_ATU_CR2
:
205 val
= viewport
->cr
[(address
- DESIGNWARE_PCIE_ATU_CR1
) /
210 val
= pci_default_read_config(d
, address
, len
);
217 static uint64_t designware_pcie_root_data_access(void *opaque
, hwaddr addr
,
218 uint64_t *val
, unsigned len
)
220 DesignwarePCIEViewport
*viewport
= opaque
;
221 DesignwarePCIERoot
*root
= viewport
->root
;
223 const uint8_t busnum
= DESIGNWARE_PCIE_ATU_BUS(viewport
->target
);
224 const uint8_t devfn
= DESIGNWARE_PCIE_ATU_DEVFN(viewport
->target
);
225 PCIBus
*pcibus
= pci_get_bus(PCI_DEVICE(root
));
226 PCIDevice
*pcidev
= pci_find_device(pcibus
, busnum
, devfn
);
229 addr
&= pci_config_size(pcidev
) - 1;
232 pci_host_config_write_common(pcidev
, addr
,
233 pci_config_size(pcidev
),
236 return pci_host_config_read_common(pcidev
, addr
,
237 pci_config_size(pcidev
),
245 static uint64_t designware_pcie_root_data_read(void *opaque
, hwaddr addr
,
248 return designware_pcie_root_data_access(opaque
, addr
, NULL
, len
);
251 static void designware_pcie_root_data_write(void *opaque
, hwaddr addr
,
252 uint64_t val
, unsigned len
)
254 designware_pcie_root_data_access(opaque
, addr
, &val
, len
);
257 static const MemoryRegionOps designware_pci_host_conf_ops
= {
258 .read
= designware_pcie_root_data_read
,
259 .write
= designware_pcie_root_data_write
,
260 .endianness
= DEVICE_LITTLE_ENDIAN
,
262 .min_access_size
= 1,
263 .max_access_size
= 4,
267 static void designware_pcie_update_viewport(DesignwarePCIERoot
*root
,
268 DesignwarePCIEViewport
*viewport
)
270 const uint64_t target
= viewport
->target
;
271 const uint64_t base
= viewport
->base
;
272 const uint64_t size
= (uint64_t)viewport
->limit
- base
+ 1;
273 const bool enabled
= viewport
->cr
[1] & DESIGNWARE_PCIE_ATU_ENABLE
;
275 MemoryRegion
*current
, *other
;
277 if (viewport
->cr
[0] == DESIGNWARE_PCIE_ATU_TYPE_MEM
) {
278 current
= &viewport
->mem
;
279 other
= &viewport
->cfg
;
280 memory_region_set_alias_offset(current
, target
);
282 current
= &viewport
->cfg
;
283 other
= &viewport
->mem
;
287 * An outbound viewport can be reconfigure from being MEM to CFG,
288 * to account for that we disable the "other" memory region that
289 * becomes unused due to that fact.
291 memory_region_set_enabled(other
, false);
293 memory_region_set_size(current
, size
);
294 memory_region_set_address(current
, base
);
296 memory_region_set_enabled(current
, enabled
);
299 static void designware_pcie_root_config_write(PCIDevice
*d
, uint32_t address
,
300 uint32_t val
, int len
)
302 DesignwarePCIERoot
*root
= DESIGNWARE_PCIE_ROOT(d
);
303 DesignwarePCIEHost
*host
= designware_pcie_root_to_host(root
);
304 DesignwarePCIEViewport
*viewport
=
305 designware_pcie_root_get_current_viewport(root
);
308 case DESIGNWARE_PCIE_PORT_LINK_CONTROL
:
309 case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL
:
310 case DESIGNWARE_PCIE_PHY_DEBUG_R1
:
314 case DESIGNWARE_PCIE_MSI_ADDR_LO
:
315 root
->msi
.base
&= 0xFFFFFFFF00000000ULL
;
316 root
->msi
.base
|= val
;
317 designware_pcie_root_update_msi_mapping(root
);
320 case DESIGNWARE_PCIE_MSI_ADDR_HI
:
321 root
->msi
.base
&= 0x00000000FFFFFFFFULL
;
322 root
->msi
.base
|= (uint64_t)val
<< 32;
323 designware_pcie_root_update_msi_mapping(root
);
326 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE
:
327 root
->msi
.intr
[0].enable
= val
;
328 designware_pcie_root_update_msi_mapping(root
);
331 case DESIGNWARE_PCIE_MSI_INTR0_MASK
:
332 root
->msi
.intr
[0].mask
= val
;
335 case DESIGNWARE_PCIE_MSI_INTR0_STATUS
:
336 root
->msi
.intr
[0].status
^= val
;
337 if (!root
->msi
.intr
[0].status
) {
338 qemu_set_irq(host
->pci
.irqs
[DESIGNWARE_PCIE_IRQ_MSI
], 0);
342 case DESIGNWARE_PCIE_ATU_VIEWPORT
:
343 val
&= DESIGNWARE_PCIE_ATU_REGION_INBOUND
|
344 (DESIGNWARE_PCIE_NUM_VIEWPORTS
- 1);
345 root
->atu_viewport
= val
;
348 case DESIGNWARE_PCIE_ATU_LOWER_BASE
:
349 viewport
->base
&= 0xFFFFFFFF00000000ULL
;
350 viewport
->base
|= val
;
353 case DESIGNWARE_PCIE_ATU_UPPER_BASE
:
354 viewport
->base
&= 0x00000000FFFFFFFFULL
;
355 viewport
->base
|= (uint64_t)val
<< 32;
358 case DESIGNWARE_PCIE_ATU_LOWER_TARGET
:
359 viewport
->target
&= 0xFFFFFFFF00000000ULL
;
360 viewport
->target
|= val
;
363 case DESIGNWARE_PCIE_ATU_UPPER_TARGET
:
364 viewport
->target
&= 0x00000000FFFFFFFFULL
;
365 viewport
->target
|= val
;
368 case DESIGNWARE_PCIE_ATU_LIMIT
:
369 viewport
->limit
= val
;
372 case DESIGNWARE_PCIE_ATU_CR1
:
373 viewport
->cr
[0] = val
;
375 case DESIGNWARE_PCIE_ATU_CR2
:
376 viewport
->cr
[1] = val
;
377 designware_pcie_update_viewport(root
, viewport
);
381 pci_bridge_write_config(d
, address
, val
, len
);
386 static char *designware_pcie_viewport_name(const char *direction
,
390 return g_strdup_printf("PCI %s Viewport %u [%s]",
394 static void designware_pcie_root_realize(PCIDevice
*dev
, Error
**errp
)
396 DesignwarePCIERoot
*root
= DESIGNWARE_PCIE_ROOT(dev
);
397 DesignwarePCIEHost
*host
= designware_pcie_root_to_host(root
);
398 MemoryRegion
*address_space
= &host
->pci
.memory
;
399 PCIBridge
*br
= PCI_BRIDGE(dev
);
400 DesignwarePCIEViewport
*viewport
;
402 * Dummy values used for initial configuration of MemoryRegions
403 * that belong to a given viewport
405 const hwaddr dummy_offset
= 0;
406 const uint64_t dummy_size
= 4;
409 br
->bus_name
= "dw-pcie";
411 pci_set_word(dev
->config
+ PCI_COMMAND
,
412 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
);
414 pci_config_set_interrupt_pin(dev
->config
, 1);
415 pci_bridge_initfn(dev
, TYPE_PCIE_BUS
);
417 pcie_port_init_reg(dev
);
419 pcie_cap_init(dev
, 0x70, PCI_EXP_TYPE_ROOT_PORT
,
422 msi_nonbroken
= true;
423 msi_init(dev
, 0x50, 32, true, true, &error_fatal
);
425 for (i
= 0; i
< DESIGNWARE_PCIE_NUM_VIEWPORTS
; i
++) {
426 MemoryRegion
*source
, *destination
, *mem
;
427 const char *direction
;
430 viewport
= &root
->viewports
[DESIGNWARE_PCIE_VIEWPORT_INBOUND
][i
];
431 viewport
->inbound
= true;
432 viewport
->base
= 0x0000000000000000ULL
;
433 viewport
->target
= 0x0000000000000000ULL
;
434 viewport
->limit
= UINT32_MAX
;
435 viewport
->cr
[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM
;
437 source
= &host
->pci
.address_space_root
;
438 destination
= get_system_memory();
439 direction
= "Inbound";
442 * Configure MemoryRegion implementing PCI -> CPU memory
445 mem
= &viewport
->mem
;
446 name
= designware_pcie_viewport_name(direction
, i
, "MEM");
447 memory_region_init_alias(mem
, OBJECT(root
), name
, destination
,
448 dummy_offset
, dummy_size
);
449 memory_region_add_subregion_overlap(source
, dummy_offset
, mem
, -1);
450 memory_region_set_enabled(mem
, false);
453 viewport
= &root
->viewports
[DESIGNWARE_PCIE_VIEWPORT_OUTBOUND
][i
];
454 viewport
->root
= root
;
455 viewport
->inbound
= false;
456 viewport
->base
= 0x0000000000000000ULL
;
457 viewport
->target
= 0x0000000000000000ULL
;
458 viewport
->limit
= UINT32_MAX
;
459 viewport
->cr
[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM
;
461 destination
= &host
->pci
.memory
;
462 direction
= "Outbound";
463 source
= get_system_memory();
466 * Configure MemoryRegion implementing CPU -> PCI memory
469 mem
= &viewport
->mem
;
470 name
= designware_pcie_viewport_name(direction
, i
, "MEM");
471 memory_region_init_alias(mem
, OBJECT(root
), name
, destination
,
472 dummy_offset
, dummy_size
);
473 memory_region_add_subregion(source
, dummy_offset
, mem
);
474 memory_region_set_enabled(mem
, false);
478 * Configure MemoryRegion implementing access to configuration
481 mem
= &viewport
->cfg
;
482 name
= designware_pcie_viewport_name(direction
, i
, "CFG");
483 memory_region_init_io(&viewport
->cfg
, OBJECT(root
),
484 &designware_pci_host_conf_ops
,
485 viewport
, name
, dummy_size
);
486 memory_region_add_subregion(source
, dummy_offset
, mem
);
487 memory_region_set_enabled(mem
, false);
492 * If no inbound iATU windows are configured, HW defaults to
493 * letting inbound TLPs to pass in. We emulate that by explicitly
494 * configuring first inbound window to cover all of target's
497 * NOTE: This will not work correctly for the case when first
498 * configured inbound window is window 0
500 viewport
= &root
->viewports
[DESIGNWARE_PCIE_VIEWPORT_INBOUND
][0];
501 viewport
->cr
[1] = DESIGNWARE_PCIE_ATU_ENABLE
;
502 designware_pcie_update_viewport(root
, viewport
);
504 memory_region_init_io(&root
->msi
.iomem
, OBJECT(root
),
505 &designware_pci_host_msi_ops
,
506 root
, "pcie-msi", 0x4);
508 * We initially place MSI interrupt I/O region at address 0 and
509 * disable it. It'll be later moved to correct offset and enabled
510 * in designware_pcie_root_update_msi_mapping() as a part of
511 * initialization done by guest OS
513 memory_region_add_subregion(address_space
, dummy_offset
, &root
->msi
.iomem
);
514 memory_region_set_enabled(&root
->msi
.iomem
, false);
517 static void designware_pcie_set_irq(void *opaque
, int irq_num
, int level
)
519 DesignwarePCIEHost
*host
= DESIGNWARE_PCIE_HOST(opaque
);
521 qemu_set_irq(host
->pci
.irqs
[irq_num
], level
);
525 designware_pcie_host_root_bus_path(PCIHostState
*host_bridge
, PCIBus
*rootbus
)
530 static const VMStateDescription vmstate_designware_pcie_msi_bank
= {
531 .name
= "designware-pcie-msi-bank",
533 .minimum_version_id
= 1,
534 .fields
= (const VMStateField
[]) {
535 VMSTATE_UINT32(enable
, DesignwarePCIEMSIBank
),
536 VMSTATE_UINT32(mask
, DesignwarePCIEMSIBank
),
537 VMSTATE_UINT32(status
, DesignwarePCIEMSIBank
),
538 VMSTATE_END_OF_LIST()
542 static const VMStateDescription vmstate_designware_pcie_msi
= {
543 .name
= "designware-pcie-msi",
545 .minimum_version_id
= 1,
546 .fields
= (const VMStateField
[]) {
547 VMSTATE_UINT64(base
, DesignwarePCIEMSI
),
548 VMSTATE_STRUCT_ARRAY(intr
,
550 DESIGNWARE_PCIE_NUM_MSI_BANKS
,
552 vmstate_designware_pcie_msi_bank
,
553 DesignwarePCIEMSIBank
),
554 VMSTATE_END_OF_LIST()
558 static const VMStateDescription vmstate_designware_pcie_viewport
= {
559 .name
= "designware-pcie-viewport",
561 .minimum_version_id
= 1,
562 .fields
= (const VMStateField
[]) {
563 VMSTATE_UINT64(base
, DesignwarePCIEViewport
),
564 VMSTATE_UINT64(target
, DesignwarePCIEViewport
),
565 VMSTATE_UINT32(limit
, DesignwarePCIEViewport
),
566 VMSTATE_UINT32_ARRAY(cr
, DesignwarePCIEViewport
, 2),
567 VMSTATE_END_OF_LIST()
571 static const VMStateDescription vmstate_designware_pcie_root
= {
572 .name
= "designware-pcie-root",
574 .minimum_version_id
= 1,
575 .fields
= (const VMStateField
[]) {
576 VMSTATE_PCI_DEVICE(parent_obj
, PCIBridge
),
577 VMSTATE_UINT32(atu_viewport
, DesignwarePCIERoot
),
578 VMSTATE_STRUCT_2DARRAY(viewports
,
581 DESIGNWARE_PCIE_NUM_VIEWPORTS
,
583 vmstate_designware_pcie_viewport
,
584 DesignwarePCIEViewport
),
588 vmstate_designware_pcie_msi
,
590 VMSTATE_END_OF_LIST()
594 static void designware_pcie_root_class_init(ObjectClass
*klass
, void *data
)
596 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
597 DeviceClass
*dc
= DEVICE_CLASS(klass
);
599 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
601 k
->vendor_id
= PCI_VENDOR_ID_SYNOPSYS
;
602 k
->device_id
= 0xABCD;
604 k
->class_id
= PCI_CLASS_BRIDGE_PCI
;
605 k
->exit
= pci_bridge_exitfn
;
606 k
->realize
= designware_pcie_root_realize
;
607 k
->config_read
= designware_pcie_root_config_read
;
608 k
->config_write
= designware_pcie_root_config_write
;
610 dc
->reset
= pci_bridge_reset
;
612 * PCI-facing part of the host bridge, not usable without the
613 * host-facing part, which can't be device_add'ed, yet.
615 dc
->user_creatable
= false;
616 dc
->vmsd
= &vmstate_designware_pcie_root
;
619 static uint64_t designware_pcie_host_mmio_read(void *opaque
, hwaddr addr
,
622 PCIHostState
*pci
= PCI_HOST_BRIDGE(opaque
);
623 PCIDevice
*device
= pci_find_device(pci
->bus
, 0, 0);
625 return pci_host_config_read_common(device
,
627 pci_config_size(device
),
631 static void designware_pcie_host_mmio_write(void *opaque
, hwaddr addr
,
632 uint64_t val
, unsigned int size
)
634 PCIHostState
*pci
= PCI_HOST_BRIDGE(opaque
);
635 PCIDevice
*device
= pci_find_device(pci
->bus
, 0, 0);
637 return pci_host_config_write_common(device
,
639 pci_config_size(device
),
643 static const MemoryRegionOps designware_pci_mmio_ops
= {
644 .read
= designware_pcie_host_mmio_read
,
645 .write
= designware_pcie_host_mmio_write
,
646 .endianness
= DEVICE_LITTLE_ENDIAN
,
649 * Our device would not work correctly if the guest was doing
650 * unaligned access. This might not be a limitation on the real
651 * device but in practice there is no reason for a guest to access
652 * this device unaligned.
654 .min_access_size
= 4,
655 .max_access_size
= 4,
660 static AddressSpace
*designware_pcie_host_set_iommu(PCIBus
*bus
, void *opaque
,
663 DesignwarePCIEHost
*s
= DESIGNWARE_PCIE_HOST(opaque
);
665 return &s
->pci
.address_space
;
668 static const PCIIOMMUOps designware_iommu_ops
= {
669 .get_address_space
= designware_pcie_host_set_iommu
,
672 static void designware_pcie_host_realize(DeviceState
*dev
, Error
**errp
)
674 PCIHostState
*pci
= PCI_HOST_BRIDGE(dev
);
675 DesignwarePCIEHost
*s
= DESIGNWARE_PCIE_HOST(dev
);
676 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
679 for (i
= 0; i
< ARRAY_SIZE(s
->pci
.irqs
); i
++) {
680 sysbus_init_irq(sbd
, &s
->pci
.irqs
[i
]);
683 memory_region_init_io(&s
->mmio
,
685 &designware_pci_mmio_ops
,
687 "pcie.reg", 4 * 1024);
688 sysbus_init_mmio(sbd
, &s
->mmio
);
690 memory_region_init(&s
->pci
.io
, OBJECT(s
), "pcie-pio", 16);
691 memory_region_init(&s
->pci
.memory
, OBJECT(s
),
695 pci
->bus
= pci_register_root_bus(dev
, "pcie",
696 designware_pcie_set_irq
,
697 pci_swizzle_map_irq_fn
,
703 pci
->bus
->flags
|= PCI_BUS_EXTENDED_CONFIG_SPACE
;
705 memory_region_init(&s
->pci
.address_space_root
,
707 "pcie-bus-address-space-root",
709 memory_region_add_subregion(&s
->pci
.address_space_root
,
710 0x0, &s
->pci
.memory
);
711 address_space_init(&s
->pci
.address_space
,
712 &s
->pci
.address_space_root
,
713 "pcie-bus-address-space");
714 pci_setup_iommu(pci
->bus
, &designware_iommu_ops
, s
);
716 qdev_realize(DEVICE(&s
->root
), BUS(pci
->bus
), &error_fatal
);
719 static const VMStateDescription vmstate_designware_pcie_host
= {
720 .name
= "designware-pcie-host",
722 .minimum_version_id
= 1,
723 .fields
= (const VMStateField
[]) {
727 vmstate_designware_pcie_root
,
729 VMSTATE_END_OF_LIST()
733 static void designware_pcie_host_class_init(ObjectClass
*klass
, void *data
)
735 DeviceClass
*dc
= DEVICE_CLASS(klass
);
736 PCIHostBridgeClass
*hc
= PCI_HOST_BRIDGE_CLASS(klass
);
738 hc
->root_bus_path
= designware_pcie_host_root_bus_path
;
739 dc
->realize
= designware_pcie_host_realize
;
740 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
742 dc
->vmsd
= &vmstate_designware_pcie_host
;
745 static void designware_pcie_host_init(Object
*obj
)
747 DesignwarePCIEHost
*s
= DESIGNWARE_PCIE_HOST(obj
);
748 DesignwarePCIERoot
*root
= &s
->root
;
750 object_initialize_child(obj
, "root", root
, TYPE_DESIGNWARE_PCIE_ROOT
);
751 qdev_prop_set_int32(DEVICE(root
), "addr", PCI_DEVFN(0, 0));
752 qdev_prop_set_bit(DEVICE(root
), "multifunction", false);
755 static const TypeInfo designware_pcie_root_info
= {
756 .name
= TYPE_DESIGNWARE_PCIE_ROOT
,
757 .parent
= TYPE_PCI_BRIDGE
,
758 .instance_size
= sizeof(DesignwarePCIERoot
),
759 .class_init
= designware_pcie_root_class_init
,
760 .interfaces
= (InterfaceInfo
[]) {
761 { INTERFACE_PCIE_DEVICE
},
766 static const TypeInfo designware_pcie_host_info
= {
767 .name
= TYPE_DESIGNWARE_PCIE_HOST
,
768 .parent
= TYPE_PCI_HOST_BRIDGE
,
769 .instance_size
= sizeof(DesignwarePCIEHost
),
770 .instance_init
= designware_pcie_host_init
,
771 .class_init
= designware_pcie_host_class_init
,
774 static void designware_pcie_register(void)
776 type_register_static(&designware_pcie_root_info
);
777 type_register_static(&designware_pcie_host_info
);
779 type_init(designware_pcie_register
)