1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2017 Cadence
3 // Cadence PCIe host controller driver.
4 // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
6 #include <linux/kernel.h>
7 #include <linux/of_address.h>
8 #include <linux/of_pci.h>
9 #include <linux/platform_device.h>
10 #include <linux/pm_runtime.h>
12 #include "pcie-cadence.h"
15 * struct cdns_pcie_rc - private data for this PCIe Root Complex driver
16 * @pcie: Cadence PCIe controller
17 * @dev: pointer to PCIe device
18 * @cfg_res: start/end offsets in the physical system memory to map PCI
19 * configuration space accesses
20 * @bus_range: first/last buses behind the PCIe host controller
21 * @cfg_base: IO mapped window to access the PCI configuration space of a
22 * single function at a time
23 * @max_regions: maximum number of regions supported by the hardware
24 * @no_bar_nbits: Number of bits to keep for inbound (PCIe -> CPU) address
25 * translation (nbits sets into the "no BAR match" register)
26 * @vendor_id: PCI vendor ID
27 * @device_id: PCI device ID
30 struct cdns_pcie pcie
;
32 struct resource
*cfg_res
;
33 struct resource
*bus_range
;
34 void __iomem
*cfg_base
;
41 static void __iomem
*cdns_pci_map_bus(struct pci_bus
*bus
, unsigned int devfn
,
44 struct pci_host_bridge
*bridge
= pci_find_host_bridge(bus
);
45 struct cdns_pcie_rc
*rc
= pci_host_bridge_priv(bridge
);
46 struct cdns_pcie
*pcie
= &rc
->pcie
;
47 unsigned int busn
= bus
->number
;
50 if (busn
== rc
->bus_range
->start
) {
52 * Only the root port (devfn == 0) is connected to this bus.
53 * All other PCI devices are behind some bridge hence on another
59 return pcie
->reg_base
+ (where
& 0xfff);
62 /* Update Output registers for AXI region 0. */
63 addr0
= CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
64 CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn
) |
65 CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(busn
);
66 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(0), addr0
);
68 /* Configuration Type 0 or Type 1 access. */
69 desc0
= CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID
|
70 CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
72 * The bus number was already set once for all in desc1 by
73 * cdns_pcie_host_init_address_translation().
75 if (busn
== rc
->bus_range
->start
+ 1)
76 desc0
|= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0
;
78 desc0
|= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1
;
79 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0
);
81 return rc
->cfg_base
+ (where
& 0xfff);
84 static struct pci_ops cdns_pcie_host_ops
= {
85 .map_bus
= cdns_pci_map_bus
,
86 .read
= pci_generic_config_read
,
87 .write
= pci_generic_config_write
,
90 static const struct of_device_id cdns_pcie_host_of_match
[] = {
91 { .compatible
= "cdns,cdns-pcie-host" },
96 static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc
*rc
)
98 struct cdns_pcie
*pcie
= &rc
->pcie
;
102 * Set the root complex BAR configuration register:
103 * - disable both BAR0 and BAR1.
104 * - enable Prefetchable Memory Base and Limit registers in type 1
105 * config space (64 bits).
106 * - enable IO Base and Limit registers in type 1 config
109 ctrl
= CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED
;
110 value
= CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl
) |
111 CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl
) |
112 CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE
|
113 CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS
|
114 CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE
|
115 CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS
;
116 cdns_pcie_writel(pcie
, CDNS_PCIE_LM_RC_BAR_CFG
, value
);
118 /* Set root port configuration space */
119 if (rc
->vendor_id
!= 0xffff)
120 cdns_pcie_rp_writew(pcie
, PCI_VENDOR_ID
, rc
->vendor_id
);
121 if (rc
->device_id
!= 0xffff)
122 cdns_pcie_rp_writew(pcie
, PCI_DEVICE_ID
, rc
->device_id
);
124 cdns_pcie_rp_writeb(pcie
, PCI_CLASS_REVISION
, 0);
125 cdns_pcie_rp_writeb(pcie
, PCI_CLASS_PROG
, 0);
126 cdns_pcie_rp_writew(pcie
, PCI_CLASS_DEVICE
, PCI_CLASS_BRIDGE_PCI
);
131 static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc
*rc
)
133 struct cdns_pcie
*pcie
= &rc
->pcie
;
134 struct resource
*cfg_res
= rc
->cfg_res
;
135 struct resource
*mem_res
= pcie
->mem_res
;
136 struct resource
*bus_range
= rc
->bus_range
;
137 struct device
*dev
= rc
->dev
;
138 struct device_node
*np
= dev
->of_node
;
139 struct of_pci_range_parser parser
;
140 struct of_pci_range range
;
141 u32 addr0
, addr1
, desc1
;
146 * Reserve region 0 for PCI configure space accesses:
147 * OB_REGION_PCI_ADDR0 and OB_REGION_DESC0 are updated dynamically by
148 * cdns_pci_map_bus(), other region registers are set here once for all.
150 addr1
= 0; /* Should be programmed to zero. */
151 desc1
= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(bus_range
->start
);
152 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1
);
153 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1
);
155 cpu_addr
= cfg_res
->start
- mem_res
->start
;
156 addr0
= CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) |
157 (lower_32_bits(cpu_addr
) & GENMASK(31, 8));
158 addr1
= upper_32_bits(cpu_addr
);
159 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(0), addr0
);
160 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(0), addr1
);
162 err
= of_pci_range_parser_init(&parser
, np
);
167 for_each_of_pci_range(&parser
, &range
) {
170 if (r
>= rc
->max_regions
)
173 if ((range
.flags
& IORESOURCE_TYPE_BITS
) == IORESOURCE_MEM
)
175 else if ((range
.flags
& IORESOURCE_TYPE_BITS
) == IORESOURCE_IO
)
180 cdns_pcie_set_outbound_region(pcie
, 0, r
, is_io
,
188 * Set Root Port no BAR match Inbound Translation registers:
189 * needed for MSI and DMA.
190 * Root Port BAR0 and BAR1 are disabled, hence no need to set their
191 * inbound translation registers.
193 addr0
= CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(rc
->no_bar_nbits
);
195 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(RP_NO_BAR
), addr0
);
196 cdns_pcie_writel(pcie
, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(RP_NO_BAR
), addr1
);
201 static int cdns_pcie_host_init(struct device
*dev
,
202 struct list_head
*resources
,
203 struct cdns_pcie_rc
*rc
)
205 struct resource
*bus_range
= NULL
;
208 /* Parse our PCI ranges and request their resources */
209 err
= pci_parse_request_of_pci_ranges(dev
, resources
, &bus_range
);
213 rc
->bus_range
= bus_range
;
214 rc
->pcie
.bus
= bus_range
->start
;
216 err
= cdns_pcie_host_init_root_port(rc
);
220 err
= cdns_pcie_host_init_address_translation(rc
);
227 pci_free_resource_list(resources
);
231 static int cdns_pcie_host_probe(struct platform_device
*pdev
)
234 struct device
*dev
= &pdev
->dev
;
235 struct device_node
*np
= dev
->of_node
;
236 struct pci_host_bridge
*bridge
;
237 struct list_head resources
;
238 struct cdns_pcie_rc
*rc
;
239 struct cdns_pcie
*pcie
;
240 struct resource
*res
;
243 bridge
= devm_pci_alloc_host_bridge(dev
, sizeof(*rc
));
247 rc
= pci_host_bridge_priv(bridge
);
253 rc
->max_regions
= 32;
254 of_property_read_u32(np
, "cdns,max-outbound-regions", &rc
->max_regions
);
256 rc
->no_bar_nbits
= 32;
257 of_property_read_u32(np
, "cdns,no-bar-match-nbits", &rc
->no_bar_nbits
);
259 rc
->vendor_id
= 0xffff;
260 of_property_read_u16(np
, "vendor-id", &rc
->vendor_id
);
262 rc
->device_id
= 0xffff;
263 of_property_read_u16(np
, "device-id", &rc
->device_id
);
265 type
= of_get_property(np
, "device_type", NULL
);
266 if (!type
|| strcmp(type
, "pci")) {
267 dev_err(dev
, "invalid \"device_type\" %s\n", type
);
271 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "reg");
272 pcie
->reg_base
= devm_ioremap_resource(dev
, res
);
273 if (IS_ERR(pcie
->reg_base
)) {
274 dev_err(dev
, "missing \"reg\"\n");
275 return PTR_ERR(pcie
->reg_base
);
278 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "cfg");
279 rc
->cfg_base
= devm_pci_remap_cfg_resource(dev
, res
);
280 if (IS_ERR(rc
->cfg_base
)) {
281 dev_err(dev
, "missing \"cfg\"\n");
282 return PTR_ERR(rc
->cfg_base
);
286 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "mem");
288 dev_err(dev
, "missing \"mem\"\n");
293 pm_runtime_enable(dev
);
294 ret
= pm_runtime_get_sync(dev
);
296 dev_err(dev
, "pm_runtime_get_sync() failed\n");
300 ret
= cdns_pcie_host_init(dev
, &resources
, rc
);
304 list_splice_init(&resources
, &bridge
->windows
);
305 bridge
->dev
.parent
= dev
;
306 bridge
->busnr
= pcie
->bus
;
307 bridge
->ops
= &cdns_pcie_host_ops
;
308 bridge
->map_irq
= of_irq_parse_and_map_pci
;
309 bridge
->swizzle_irq
= pci_common_swizzle
;
311 ret
= pci_host_probe(bridge
);
318 pci_free_resource_list(&resources
);
321 pm_runtime_put_sync(dev
);
324 pm_runtime_disable(dev
);
329 static struct platform_driver cdns_pcie_host_driver
= {
331 .name
= "cdns-pcie-host",
332 .of_match_table
= cdns_pcie_host_of_match
,
334 .probe
= cdns_pcie_host_probe
,
336 builtin_platform_driver(cdns_pcie_host_driver
);