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 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 "hw/pci/pci_bridge.h"
22 #include "hw/pci-host/xilinx-pcie.h"
25 /* Interrupt Decode Register */
26 ROOTCFG_INTDEC
= 0x138,
28 /* Interrupt Mask Register */
29 ROOTCFG_INTMASK
= 0x13c,
30 /* INTx Interrupt Received */
31 #define ROOTCFG_INTMASK_INTX (1 << 16)
32 /* MSI Interrupt Received */
33 #define ROOTCFG_INTMASK_MSI (1 << 17)
35 /* PHY Status/Control Register */
38 #define ROOTCFG_PSCR_LINK_UP (1 << 11)
40 /* Root Port Status/Control Register */
41 ROOTCFG_RPSCR
= 0x148,
43 #define ROOTCFG_RPSCR_BRIDGEEN (1 << 0)
44 /* Interrupt FIFO Not Empty */
45 #define ROOTCFG_RPSCR_INTNEMPTY (1 << 18)
46 /* Interrupt FIFO Overflow */
47 #define ROOTCFG_RPSCR_INTOVF (1 << 19)
49 /* Root Port Interrupt FIFO Read Register 1 */
50 ROOTCFG_RPIFR1
= 0x158,
51 #define ROOTCFG_RPIFR1_INT_LANE_SHIFT 27
52 #define ROOTCFG_RPIFR1_INT_ASSERT_SHIFT 29
53 #define ROOTCFG_RPIFR1_INT_VALID_SHIFT 31
54 /* Root Port Interrupt FIFO Read Register 2 */
55 ROOTCFG_RPIFR2
= 0x15c,
58 static void xilinx_pcie_update_intr(XilinxPCIEHost
*s
,
59 uint32_t set
, uint32_t clear
)
66 if (s
->intr_fifo_r
!= s
->intr_fifo_w
) {
67 s
->intr
|= ROOTCFG_INTMASK_INTX
;
70 level
= !!(s
->intr
& s
->intr_mask
);
71 qemu_set_irq(s
->irq
, level
);
74 static void xilinx_pcie_queue_intr(XilinxPCIEHost
*s
,
75 uint32_t fifo_reg1
, uint32_t fifo_reg2
)
80 new_w
= (s
->intr_fifo_w
+ 1) % ARRAY_SIZE(s
->intr_fifo
);
81 if (new_w
== s
->intr_fifo_r
) {
82 s
->rpscr
|= ROOTCFG_RPSCR_INTOVF
;
86 intr
= &s
->intr_fifo
[s
->intr_fifo_w
];
87 s
->intr_fifo_w
= new_w
;
89 intr
->fifo_reg1
= fifo_reg1
;
90 intr
->fifo_reg2
= fifo_reg2
;
92 xilinx_pcie_update_intr(s
, ROOTCFG_INTMASK_INTX
, 0);
95 static void xilinx_pcie_set_irq(void *opaque
, int irq_num
, int level
)
97 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(opaque
);
99 xilinx_pcie_queue_intr(s
,
100 (irq_num
<< ROOTCFG_RPIFR1_INT_LANE_SHIFT
) |
101 (level
<< ROOTCFG_RPIFR1_INT_ASSERT_SHIFT
) |
102 (1 << ROOTCFG_RPIFR1_INT_VALID_SHIFT
),
106 static void xilinx_pcie_host_realize(DeviceState
*dev
, Error
**errp
)
108 PCIHostState
*pci
= PCI_HOST_BRIDGE(dev
);
109 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(dev
);
110 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
111 PCIExpressHost
*pex
= PCIE_HOST_BRIDGE(dev
);
113 snprintf(s
->name
, sizeof(s
->name
), "pcie%u", s
->bus_nr
);
115 /* PCI configuration space */
116 pcie_host_mmcfg_init(pex
, s
->cfg_size
);
119 memory_region_init(&s
->mmio
, OBJECT(s
), "mmio", UINT64_MAX
);
120 memory_region_set_enabled(&s
->mmio
, false);
122 /* dummy I/O region */
123 memory_region_init_ram(&s
->io
, OBJECT(s
), "io", 16, NULL
);
124 memory_region_set_enabled(&s
->io
, false);
127 qdev_init_gpio_out_named(dev
, &s
->irq
, "interrupt_out", 1);
129 sysbus_init_mmio(sbd
, &pex
->mmio
);
130 sysbus_init_mmio(sbd
, &s
->mmio
);
132 pci
->bus
= pci_register_bus(dev
, s
->name
, xilinx_pcie_set_irq
,
133 pci_swizzle_map_irq_fn
, s
, &s
->mmio
,
134 &s
->io
, 0, 4, TYPE_PCIE_BUS
);
136 qdev_set_parent_bus(DEVICE(&s
->root
), BUS(pci
->bus
));
137 qdev_init_nofail(DEVICE(&s
->root
));
140 static const char *xilinx_pcie_host_root_bus_path(PCIHostState
*host_bridge
,
146 static void xilinx_pcie_host_init(Object
*obj
)
148 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(obj
);
149 XilinxPCIERoot
*root
= &s
->root
;
151 object_initialize(root
, sizeof(*root
), TYPE_XILINX_PCIE_ROOT
);
152 object_property_add_child(obj
, "root", OBJECT(root
), NULL
);
153 qdev_prop_set_uint32(DEVICE(root
), "addr", PCI_DEVFN(0, 0));
154 qdev_prop_set_bit(DEVICE(root
), "multifunction", false);
157 static Property xilinx_pcie_host_props
[] = {
158 DEFINE_PROP_UINT32("bus_nr", XilinxPCIEHost
, bus_nr
, 0),
159 DEFINE_PROP_SIZE("cfg_base", XilinxPCIEHost
, cfg_base
, 0),
160 DEFINE_PROP_SIZE("cfg_size", XilinxPCIEHost
, cfg_size
, 32 << 20),
161 DEFINE_PROP_SIZE("mmio_base", XilinxPCIEHost
, mmio_base
, 0),
162 DEFINE_PROP_SIZE("mmio_size", XilinxPCIEHost
, mmio_size
, 1 << 20),
163 DEFINE_PROP_BOOL("link_up", XilinxPCIEHost
, link_up
, true),
164 DEFINE_PROP_END_OF_LIST(),
167 static void xilinx_pcie_host_class_init(ObjectClass
*klass
, void *data
)
169 DeviceClass
*dc
= DEVICE_CLASS(klass
);
170 PCIHostBridgeClass
*hc
= PCI_HOST_BRIDGE_CLASS(klass
);
172 hc
->root_bus_path
= xilinx_pcie_host_root_bus_path
;
173 dc
->realize
= xilinx_pcie_host_realize
;
174 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
176 dc
->props
= xilinx_pcie_host_props
;
179 static const TypeInfo xilinx_pcie_host_info
= {
180 .name
= TYPE_XILINX_PCIE_HOST
,
181 .parent
= TYPE_PCIE_HOST_BRIDGE
,
182 .instance_size
= sizeof(XilinxPCIEHost
),
183 .instance_init
= xilinx_pcie_host_init
,
184 .class_init
= xilinx_pcie_host_class_init
,
187 static uint32_t xilinx_pcie_root_config_read(PCIDevice
*d
,
188 uint32_t address
, int len
)
190 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(OBJECT(d
)->parent
);
197 case ROOTCFG_INTMASK
:
201 val
= s
->link_up
? ROOTCFG_PSCR_LINK_UP
: 0;
204 if (s
->intr_fifo_r
!= s
->intr_fifo_w
) {
205 s
->rpscr
&= ~ROOTCFG_RPSCR_INTNEMPTY
;
207 s
->rpscr
|= ROOTCFG_RPSCR_INTNEMPTY
;
212 if (s
->intr_fifo_w
== s
->intr_fifo_r
) {
216 val
= s
->intr_fifo
[s
->intr_fifo_r
].fifo_reg1
;
220 if (s
->intr_fifo_w
== s
->intr_fifo_r
) {
224 val
= s
->intr_fifo
[s
->intr_fifo_r
].fifo_reg2
;
228 val
= pci_default_read_config(d
, address
, len
);
234 static void xilinx_pcie_root_config_write(PCIDevice
*d
, uint32_t address
,
235 uint32_t val
, int len
)
237 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(OBJECT(d
)->parent
);
240 xilinx_pcie_update_intr(s
, 0, val
);
242 case ROOTCFG_INTMASK
:
244 xilinx_pcie_update_intr(s
, 0, 0);
247 s
->rpscr
&= ~ROOTCFG_RPSCR_BRIDGEEN
;
248 s
->rpscr
|= val
& ROOTCFG_RPSCR_BRIDGEEN
;
249 memory_region_set_enabled(&s
->mmio
, val
& ROOTCFG_RPSCR_BRIDGEEN
);
251 if (val
& ROOTCFG_INTMASK_INTX
) {
252 s
->rpscr
&= ~ROOTCFG_INTMASK_INTX
;
257 if (s
->intr_fifo_w
== s
->intr_fifo_r
) {
261 s
->intr_fifo_r
= (s
->intr_fifo_r
+ 1) % ARRAY_SIZE(s
->intr_fifo
);
265 pci_default_write_config(d
, address
, val
, len
);
270 static int xilinx_pcie_root_init(PCIDevice
*dev
)
272 BusState
*bus
= qdev_get_parent_bus(DEVICE(dev
));
273 XilinxPCIEHost
*s
= XILINX_PCIE_HOST(bus
->parent
);
275 pci_set_word(dev
->config
+ PCI_COMMAND
,
276 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
);
277 pci_set_word(dev
->config
+ PCI_MEMORY_BASE
, s
->mmio_base
>> 16);
278 pci_set_word(dev
->config
+ PCI_MEMORY_LIMIT
,
279 ((s
->mmio_base
+ s
->mmio_size
- 1) >> 16) & 0xfff0);
281 pci_bridge_initfn(dev
, TYPE_PCI_BUS
);
283 if (pcie_endpoint_cap_v1_init(dev
, 0x80) < 0) {
284 hw_error("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
;
301 k
->is_express
= true;
303 k
->init
= xilinx_pcie_root_init
;
304 k
->exit
= pci_bridge_exitfn
;
305 dc
->reset
= pci_bridge_reset
;
306 k
->config_read
= xilinx_pcie_root_config_read
;
307 k
->config_write
= xilinx_pcie_root_config_write
;
309 * PCI-facing part of the host bridge, not usable without the
310 * host-facing part, which can't be device_add'ed, yet.
312 dc
->user_creatable
= false;
315 static const TypeInfo xilinx_pcie_root_info
= {
316 .name
= TYPE_XILINX_PCIE_ROOT
,
317 .parent
= TYPE_PCI_BRIDGE
,
318 .instance_size
= sizeof(XilinxPCIERoot
),
319 .class_init
= xilinx_pcie_root_class_init
,
322 static void xilinx_pcie_register(void)
324 type_register_static(&xilinx_pcie_root_info
);
325 type_register_static(&xilinx_pcie_host_info
);
328 type_init(xilinx_pcie_register
)