2 * Xilinx PCIe host controller emulation.
4 * Copyright (c) 2016 Imagination Technologies
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 <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "qemu/module.h"
22 #include "qemu/units.h"
23 #include "qapi/error.h"
24 #include "hw/pci/pci_bridge.h"
25 #include "hw/qdev-properties.h"
27 #include "hw/pci-host/xilinx-pcie.h"
30 /* Interrupt Decode Register */
31 ROOTCFG_INTDEC
= 0x138,
33 /* Interrupt Mask Register */
34 ROOTCFG_INTMASK
= 0x13c,
35 /* INTx Interrupt Received */
36 #define ROOTCFG_INTMASK_INTX (1 << 16)
37 /* MSI Interrupt Received */
38 #define ROOTCFG_INTMASK_MSI (1 << 17)
40 /* PHY Status/Control Register */
43 #define ROOTCFG_PSCR_LINK_UP (1 << 11)
45 /* Root Port Status/Control Register */
46 ROOTCFG_RPSCR
= 0x148,
48 #define ROOTCFG_RPSCR_BRIDGEEN (1 << 0)
49 /* Interrupt FIFO Not Empty */
50 #define ROOTCFG_RPSCR_INTNEMPTY (1 << 18)
51 /* Interrupt FIFO Overflow */
52 #define ROOTCFG_RPSCR_INTOVF (1 << 19)
54 /* Root Port Interrupt FIFO Read Register 1 */
55 ROOTCFG_RPIFR1
= 0x158,
56 #define ROOTCFG_RPIFR1_INT_LANE_SHIFT 27
57 #define ROOTCFG_RPIFR1_INT_ASSERT_SHIFT 29
58 #define ROOTCFG_RPIFR1_INT_VALID_SHIFT 31
59 /* Root Port Interrupt FIFO Read Register 2 */
60 ROOTCFG_RPIFR2
= 0x15c,
63 static void xilinx_pcie_update_intr(XilinxPCIEHost
*s
,
64 uint32_t set
, uint32_t clear
)
71 if (s
->intr_fifo_r
!= s
->intr_fifo_w
) {
72 s
->intr
|= ROOTCFG_INTMASK_INTX
;
75 level
= !!(s
->intr
& s
->intr_mask
);
76 qemu_set_irq(s
->irq
, level
);
79 static void xilinx_pcie_queue_intr(XilinxPCIEHost
*s
,
80 uint32_t fifo_reg1
, uint32_t fifo_reg2
)
85 new_w
= (s
->intr_fifo_w
+ 1) % ARRAY_SIZE(s
->intr_fifo
);
86 if (new_w
== s
->intr_fifo_r
) {
87 s
->rpscr
|= ROOTCFG_RPSCR_INTOVF
;
91 intr
= &s
->intr_fifo
[s
->intr_fifo_w
];
92 s
->intr_fifo_w
= new_w
;
94 intr
->fifo_reg1
= fifo_reg1
;
95 intr
->fifo_reg2
= fifo_reg2
;
97 xilinx_pcie_update_intr(s
, ROOTCFG_INTMASK_INTX
, 0);
100 static void xilinx_pcie_set_irq(void *opaque
, int irq_num
, int level
)
102 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(opaque
);
104 xilinx_pcie_queue_intr(s
,
105 (irq_num
<< ROOTCFG_RPIFR1_INT_LANE_SHIFT
) |
106 (level
<< ROOTCFG_RPIFR1_INT_ASSERT_SHIFT
) |
107 (1 << ROOTCFG_RPIFR1_INT_VALID_SHIFT
),
111 static void xilinx_pcie_host_realize(DeviceState
*dev
, Error
**errp
)
113 PCIHostState
*pci
= PCI_HOST_BRIDGE(dev
);
114 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(dev
);
115 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
116 PCIExpressHost
*pex
= PCIE_HOST_BRIDGE(dev
);
118 snprintf(s
->name
, sizeof(s
->name
), "pcie%u", s
->bus_nr
);
120 /* PCI configuration space */
121 pcie_host_mmcfg_init(pex
, s
->cfg_size
);
124 memory_region_init(&s
->mmio
, OBJECT(s
), "mmio", UINT64_MAX
);
125 memory_region_set_enabled(&s
->mmio
, false);
127 /* dummy PCI I/O region (not visible to the CPU) */
128 memory_region_init(&s
->io
, OBJECT(s
), "io", 16);
131 qdev_init_gpio_out_named(dev
, &s
->irq
, "interrupt_out", 1);
133 sysbus_init_mmio(sbd
, &pex
->mmio
);
134 sysbus_init_mmio(sbd
, &s
->mmio
);
136 pci
->bus
= pci_register_root_bus(dev
, s
->name
, xilinx_pcie_set_irq
,
137 pci_swizzle_map_irq_fn
, s
, &s
->mmio
,
138 &s
->io
, 0, 4, TYPE_PCIE_BUS
);
140 qdev_realize(DEVICE(&s
->root
), BUS(pci
->bus
), &error_fatal
);
143 static const char *xilinx_pcie_host_root_bus_path(PCIHostState
*host_bridge
,
149 static void xilinx_pcie_host_init(Object
*obj
)
151 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(obj
);
152 XilinxPCIERoot
*root
= &s
->root
;
154 object_initialize_child(obj
, "root", root
, TYPE_XILINX_PCIE_ROOT
);
155 qdev_prop_set_int32(DEVICE(root
), "addr", PCI_DEVFN(0, 0));
156 qdev_prop_set_bit(DEVICE(root
), "multifunction", false);
159 static Property xilinx_pcie_host_props
[] = {
160 DEFINE_PROP_UINT32("bus_nr", XilinxPCIEHost
, bus_nr
, 0),
161 DEFINE_PROP_SIZE("cfg_base", XilinxPCIEHost
, cfg_base
, 0),
162 DEFINE_PROP_SIZE("cfg_size", XilinxPCIEHost
, cfg_size
, 32 * MiB
),
163 DEFINE_PROP_SIZE("mmio_base", XilinxPCIEHost
, mmio_base
, 0),
164 DEFINE_PROP_SIZE("mmio_size", XilinxPCIEHost
, mmio_size
, 1 * MiB
),
165 DEFINE_PROP_BOOL("link_up", XilinxPCIEHost
, link_up
, true),
166 DEFINE_PROP_END_OF_LIST(),
169 static void xilinx_pcie_host_class_init(ObjectClass
*klass
, void *data
)
171 DeviceClass
*dc
= DEVICE_CLASS(klass
);
172 PCIHostBridgeClass
*hc
= PCI_HOST_BRIDGE_CLASS(klass
);
174 hc
->root_bus_path
= xilinx_pcie_host_root_bus_path
;
175 dc
->realize
= xilinx_pcie_host_realize
;
176 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
178 device_class_set_props(dc
, xilinx_pcie_host_props
);
181 static const TypeInfo xilinx_pcie_host_info
= {
182 .name
= TYPE_XILINX_PCIE_HOST
,
183 .parent
= TYPE_PCIE_HOST_BRIDGE
,
184 .instance_size
= sizeof(XilinxPCIEHost
),
185 .instance_init
= xilinx_pcie_host_init
,
186 .class_init
= xilinx_pcie_host_class_init
,
189 static uint32_t xilinx_pcie_root_config_read(PCIDevice
*d
,
190 uint32_t address
, int len
)
192 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(OBJECT(d
)->parent
);
199 case ROOTCFG_INTMASK
:
203 val
= s
->link_up
? ROOTCFG_PSCR_LINK_UP
: 0;
206 if (s
->intr_fifo_r
!= s
->intr_fifo_w
) {
207 s
->rpscr
&= ~ROOTCFG_RPSCR_INTNEMPTY
;
209 s
->rpscr
|= ROOTCFG_RPSCR_INTNEMPTY
;
214 if (s
->intr_fifo_w
== s
->intr_fifo_r
) {
218 val
= s
->intr_fifo
[s
->intr_fifo_r
].fifo_reg1
;
222 if (s
->intr_fifo_w
== s
->intr_fifo_r
) {
226 val
= s
->intr_fifo
[s
->intr_fifo_r
].fifo_reg2
;
230 val
= pci_default_read_config(d
, address
, len
);
236 static void xilinx_pcie_root_config_write(PCIDevice
*d
, uint32_t address
,
237 uint32_t val
, int len
)
239 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(OBJECT(d
)->parent
);
242 xilinx_pcie_update_intr(s
, 0, val
);
244 case ROOTCFG_INTMASK
:
246 xilinx_pcie_update_intr(s
, 0, 0);
249 s
->rpscr
&= ~ROOTCFG_RPSCR_BRIDGEEN
;
250 s
->rpscr
|= val
& ROOTCFG_RPSCR_BRIDGEEN
;
251 memory_region_set_enabled(&s
->mmio
, val
& ROOTCFG_RPSCR_BRIDGEEN
);
253 if (val
& ROOTCFG_INTMASK_INTX
) {
254 s
->rpscr
&= ~ROOTCFG_INTMASK_INTX
;
259 if (s
->intr_fifo_w
== s
->intr_fifo_r
) {
263 s
->intr_fifo_r
= (s
->intr_fifo_r
+ 1) % ARRAY_SIZE(s
->intr_fifo
);
267 pci_default_write_config(d
, address
, val
, len
);
272 static void xilinx_pcie_root_realize(PCIDevice
*pci_dev
, Error
**errp
)
274 BusState
*bus
= qdev_get_parent_bus(DEVICE(pci_dev
));
275 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(bus
->parent
);
277 pci_set_word(pci_dev
->config
+ PCI_COMMAND
,
278 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
);
279 pci_set_word(pci_dev
->config
+ PCI_MEMORY_BASE
, s
->mmio_base
>> 16);
280 pci_set_word(pci_dev
->config
+ PCI_MEMORY_LIMIT
,
281 ((s
->mmio_base
+ s
->mmio_size
- 1) >> 16) & 0xfff0);
283 pci_bridge_initfn(pci_dev
, TYPE_PCI_BUS
);
285 if (pcie_endpoint_cap_v1_init(pci_dev
, 0x80) < 0) {
286 error_setg(errp
, "Failed to initialize PCIe capability");
290 static void xilinx_pcie_root_class_init(ObjectClass
*klass
, void *data
)
292 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
293 DeviceClass
*dc
= DEVICE_CLASS(klass
);
295 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
296 dc
->desc
= "Xilinx AXI-PCIe Host Bridge";
297 k
->vendor_id
= PCI_VENDOR_ID_XILINX
;
298 k
->device_id
= 0x7021;
300 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
302 k
->realize
= xilinx_pcie_root_realize
;
303 k
->exit
= pci_bridge_exitfn
;
304 dc
->reset
= pci_bridge_reset
;
305 k
->config_read
= xilinx_pcie_root_config_read
;
306 k
->config_write
= xilinx_pcie_root_config_write
;
308 * PCI-facing part of the host bridge, not usable without the
309 * host-facing part, which can't be device_add'ed, yet.
311 dc
->user_creatable
= false;
314 static const TypeInfo xilinx_pcie_root_info
= {
315 .name
= TYPE_XILINX_PCIE_ROOT
,
316 .parent
= TYPE_PCI_BRIDGE
,
317 .instance_size
= sizeof(XilinxPCIERoot
),
318 .class_init
= xilinx_pcie_root_class_init
,
319 .interfaces
= (InterfaceInfo
[]) {
320 { INTERFACE_PCIE_DEVICE
},
325 static void xilinx_pcie_register(void)
327 type_register_static(&xilinx_pcie_root_info
);
328 type_register_static(&xilinx_pcie_host_info
);
331 type_init(xilinx_pcie_register
)