aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/pci/host/Kconfig10
-rw-r--r--drivers/pci/host/Makefile1
-rw-r--r--drivers/pci/host/pcie-cadence-host.c397
-rw-r--r--drivers/pci/host/pcie-cadence.h189
5 files changed, 604 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index a6e86e20761e..460d5580f87e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10402,6 +10402,13 @@ S: Maintained
10402F: Documentation/devicetree/bindings/pci/pci-armada8k.txt 10402F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
10403F: drivers/pci/dwc/pcie-armada8k.c 10403F: drivers/pci/dwc/pcie-armada8k.c
10404 10404
10405PCI DRIVER FOR CADENCE PCIE IP
10406M: Alan Douglas <adouglas@cadence.com>
10407L: linux-pci@vger.kernel.org
10408S: Maintained
10409F: Documentation/devicetree/bindings/pci/cdns,*.txt
10410F: drivers/pci/host/pcie-cadence*
10411
10405PCI DRIVER FOR FREESCALE LAYERSCAPE 10412PCI DRIVER FOR FREESCALE LAYERSCAPE
10406M: Minghuan Lian <minghuan.Lian@freescale.com> 10413M: Minghuan Lian <minghuan.Lian@freescale.com>
10407M: Mingkai Hu <mingkai.hu@freescale.com> 10414M: Mingkai Hu <mingkai.hu@freescale.com>
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 38d12980db0f..d6866733d69d 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -210,6 +210,16 @@ config PCIE_TANGO_SMP8759
210 This can lead to data corruption if drivers perform concurrent 210 This can lead to data corruption if drivers perform concurrent
211 config and MMIO accesses. 211 config and MMIO accesses.
212 212
213config PCIE_CADENCE_HOST
214 bool "Cadence PCIe host controller"
215 depends on OF
216 depends on PCI
217 select IRQ_DOMAIN
218 help
219 Say Y here if you want to support the Cadence PCIe controller in host
220 mode. This PCIe controller may be embedded into many different vendors
221 SoCs.
222
213config VMD 223config VMD
214 depends on PCI_MSI && X86_64 && SRCU 224 depends on PCI_MSI && X86_64 && SRCU
215 tristate "Intel Volume Management Device Driver" 225 tristate "Intel Volume Management Device Driver"
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 3b1059190867..2460f0785120 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
22obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o 22obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
23obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o 23obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
24obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o 24obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
25obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
25obj-$(CONFIG_VMD) += vmd.o 26obj-$(CONFIG_VMD) += vmd.o
26 27
27# The following drivers are for devices that use the generic ACPI 28# The following drivers are for devices that use the generic ACPI
diff --git a/drivers/pci/host/pcie-cadence-host.c b/drivers/pci/host/pcie-cadence-host.c
new file mode 100644
index 000000000000..9332601845ea
--- /dev/null
+++ b/drivers/pci/host/pcie-cadence-host.c
@@ -0,0 +1,397 @@
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>
5
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>
11
12#include "pcie-cadence.h"
13
14/**
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
28 */
29struct cdns_pcie_rc {
30 struct cdns_pcie pcie;
31 struct device *dev;
32 struct resource *cfg_res;
33 struct resource *bus_range;
34 void __iomem *cfg_base;
35 u32 max_regions;
36 u32 no_bar_nbits;
37 u16 vendor_id;
38 u16 device_id;
39};
40
41static void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie,
42 u32 r, bool is_io,
43 u64 cpu_addr, u64 pci_addr, size_t size)
44{
45 /*
46 * roundup_pow_of_two() returns an unsigned long, which is not suited
47 * for 64bit values.
48 */
49 u64 sz = 1ULL << fls64(size - 1);
50 int nbits = ilog2(sz);
51 u32 addr0, addr1, desc0, desc1;
52
53 if (nbits < 8)
54 nbits = 8;
55
56 /* Set the PCI address */
57 addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(nbits) |
58 (lower_32_bits(pci_addr) & GENMASK(31, 8));
59 addr1 = upper_32_bits(pci_addr);
60
61 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(r), addr0);
62 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(r), addr1);
63
64 /* Set the PCIe header descriptor */
65 if (is_io)
66 desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_IO;
67 else
68 desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_MEM;
69 desc1 = 0;
70
71 /*
72 * Whatever Bit [23] is set or not inside DESC0 register of the outbound
73 * PCIe descriptor, the PCI function number must be set into
74 * Bits [26:24] of DESC0 anyway.
75 *
76 * In Root Complex mode, the function number is always 0 but in Endpoint
77 * mode, the PCIe controller may support more than one function. This
78 * function number needs to be set properly into the outbound PCIe
79 * descriptor.
80 *
81 * Besides, setting Bit [23] is mandatory when in Root Complex mode:
82 * then the driver must provide the bus, resp. device, number in
83 * Bits [7:0] of DESC1, resp. Bits[31:27] of DESC0. Like the function
84 * number, the device number is always 0 in Root Complex mode.
85 */
86 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
87 CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
88 desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(pcie->bus);
89
90 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(r), desc0);
91 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), desc1);
92
93 /* Set the CPU address */
94 cpu_addr -= pcie->mem_res->start;
95 addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) |
96 (lower_32_bits(cpu_addr) & GENMASK(31, 8));
97 addr1 = upper_32_bits(cpu_addr);
98
99 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
100 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
101}
102
103static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
104 int where)
105{
106 struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
107 struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
108 struct cdns_pcie *pcie = &rc->pcie;
109 unsigned int busn = bus->number;
110 u32 addr0, desc0;
111
112 if (busn == rc->bus_range->start) {
113 /*
114 * Only the root port (devfn == 0) is connected to this bus.
115 * All other PCI devices are behind some bridge hence on another
116 * bus.
117 */
118 if (devfn)
119 return NULL;
120
121 return pcie->reg_base + (where & 0xfff);
122 }
123
124 /* Update Output registers for AXI region 0. */
125 addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
126 CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) |
127 CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(busn);
128 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(0), addr0);
129
130 /* Configuration Type 0 or Type 1 access. */
131 desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
132 CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
133 /*
134 * The bus number was already set once for all in desc1 by
135 * cdns_pcie_host_init_address_translation().
136 */
137 if (busn == rc->bus_range->start + 1)
138 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
139 else
140 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
141 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0);
142
143 return rc->cfg_base + (where & 0xfff);
144}
145
146static struct pci_ops cdns_pcie_host_ops = {
147 .map_bus = cdns_pci_map_bus,
148 .read = pci_generic_config_read,
149 .write = pci_generic_config_write,
150};
151
152static const struct of_device_id cdns_pcie_host_of_match[] = {
153 { .compatible = "cdns,cdns-pcie-host" },
154
155 { },
156};
157
158static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
159{
160 struct cdns_pcie *pcie = &rc->pcie;
161 u32 value, ctrl;
162
163 /*
164 * Set the root complex BAR configuration register:
165 * - disable both BAR0 and BAR1.
166 * - enable Prefetchable Memory Base and Limit registers in type 1
167 * config space (64 bits).
168 * - enable IO Base and Limit registers in type 1 config
169 * space (32 bits).
170 */
171 ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
172 value = CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
173 CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
174 CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
175 CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
176 CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
177 CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS;
178 cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
179
180 /* Set root port configuration space */
181 if (rc->vendor_id != 0xffff)
182 cdns_pcie_rp_writew(pcie, PCI_VENDOR_ID, rc->vendor_id);
183 if (rc->device_id != 0xffff)
184 cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, rc->device_id);
185
186 cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0);
187 cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0);
188 cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
189
190 return 0;
191}
192
193static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
194{
195 struct cdns_pcie *pcie = &rc->pcie;
196 struct resource *cfg_res = rc->cfg_res;
197 struct resource *mem_res = pcie->mem_res;
198 struct resource *bus_range = rc->bus_range;
199 struct device *dev = rc->dev;
200 struct device_node *np = dev->of_node;
201 struct of_pci_range_parser parser;
202 struct of_pci_range range;
203 u32 addr0, addr1, desc1;
204 u64 cpu_addr;
205 int r, err;
206
207 /*
208 * Reserve region 0 for PCI configure space accesses:
209 * OB_REGION_PCI_ADDR0 and OB_REGION_DESC0 are updated dynamically by
210 * cdns_pci_map_bus(), other region registers are set here once for all.
211 */
212 addr1 = 0; /* Should be programmed to zero. */
213 desc1 = CDNS_PCIE_AT_OB_REGION_DESC1_BUS(bus_range->start);
214 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1);
215 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1);
216
217 cpu_addr = cfg_res->start - mem_res->start;
218 addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) |
219 (lower_32_bits(cpu_addr) & GENMASK(31, 8));
220 addr1 = upper_32_bits(cpu_addr);
221 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(0), addr0);
222 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(0), addr1);
223
224 err = of_pci_range_parser_init(&parser, np);
225 if (err)
226 return err;
227
228 r = 1;
229 for_each_of_pci_range(&parser, &range) {
230 bool is_io;
231
232 if (r >= rc->max_regions)
233 break;
234
235 if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
236 is_io = false;
237 else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
238 is_io = true;
239 else
240 continue;
241
242 cdns_pcie_set_outbound_region(pcie, r, is_io,
243 range.cpu_addr,
244 range.pci_addr,
245 range.size);
246 r++;
247 }
248
249 /*
250 * Set Root Port no BAR match Inbound Translation registers:
251 * needed for MSI and DMA.
252 * Root Port BAR0 and BAR1 are disabled, hence no need to set their
253 * inbound translation registers.
254 */
255 addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(rc->no_bar_nbits);
256 addr1 = 0;
257 cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(RP_NO_BAR), addr0);
258 cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(RP_NO_BAR), addr1);
259
260 return 0;
261}
262
263static int cdns_pcie_host_init(struct device *dev,
264 struct list_head *resources,
265 struct cdns_pcie_rc *rc)
266{
267 struct resource *bus_range = NULL;
268 int err;
269
270 /* Parse our PCI ranges and request their resources */
271 err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
272 if (err)
273 return err;
274
275 rc->bus_range = bus_range;
276 rc->pcie.bus = bus_range->start;
277
278 err = cdns_pcie_host_init_root_port(rc);
279 if (err)
280 goto err_out;
281
282 err = cdns_pcie_host_init_address_translation(rc);
283 if (err)
284 goto err_out;
285
286 return 0;
287
288 err_out:
289 pci_free_resource_list(resources);
290 return err;
291}
292
293static int cdns_pcie_host_probe(struct platform_device *pdev)
294{
295 const char *type;
296 struct device *dev = &pdev->dev;
297 struct device_node *np = dev->of_node;
298 struct pci_host_bridge *bridge;
299 struct list_head resources;
300 struct cdns_pcie_rc *rc;
301 struct cdns_pcie *pcie;
302 struct resource *res;
303 int ret;
304
305 bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
306 if (!bridge)
307 return -ENOMEM;
308
309 rc = pci_host_bridge_priv(bridge);
310 rc->dev = dev;
311
312 pcie = &rc->pcie;
313
314 rc->max_regions = 32;
315 of_property_read_u32(np, "cdns,max-outbound-regions", &rc->max_regions);
316
317 rc->no_bar_nbits = 32;
318 of_property_read_u32(np, "cdns,no-bar-match-nbits", &rc->no_bar_nbits);
319
320 rc->vendor_id = 0xffff;
321 of_property_read_u16(np, "vendor-id", &rc->vendor_id);
322
323 rc->device_id = 0xffff;
324 of_property_read_u16(np, "device-id", &rc->device_id);
325
326 type = of_get_property(np, "device_type", NULL);
327 if (!type || strcmp(type, "pci")) {
328 dev_err(dev, "invalid \"device_type\" %s\n", type);
329 return -EINVAL;
330 }
331
332 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
333 pcie->reg_base = devm_ioremap_resource(dev, res);
334 if (IS_ERR(pcie->reg_base)) {
335 dev_err(dev, "missing \"reg\"\n");
336 return PTR_ERR(pcie->reg_base);
337 }
338
339 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
340 rc->cfg_base = devm_pci_remap_cfg_resource(dev, res);
341 if (IS_ERR(rc->cfg_base)) {
342 dev_err(dev, "missing \"cfg\"\n");
343 return PTR_ERR(rc->cfg_base);
344 }
345 rc->cfg_res = res;
346
347 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
348 if (!res) {
349 dev_err(dev, "missing \"mem\"\n");
350 return -EINVAL;
351 }
352 pcie->mem_res = res;
353
354 pm_runtime_enable(dev);
355 ret = pm_runtime_get_sync(dev);
356 if (ret < 0) {
357 dev_err(dev, "pm_runtime_get_sync() failed\n");
358 goto err_get_sync;
359 }
360
361 ret = cdns_pcie_host_init(dev, &resources, rc);
362 if (ret)
363 goto err_init;
364
365 list_splice_init(&resources, &bridge->windows);
366 bridge->dev.parent = dev;
367 bridge->busnr = pcie->bus;
368 bridge->ops = &cdns_pcie_host_ops;
369 bridge->map_irq = of_irq_parse_and_map_pci;
370 bridge->swizzle_irq = pci_common_swizzle;
371
372 ret = pci_host_probe(bridge);
373 if (ret < 0)
374 goto err_host_probe;
375
376 return 0;
377
378 err_host_probe:
379 pci_free_resource_list(&resources);
380
381 err_init:
382 pm_runtime_put_sync(dev);
383
384 err_get_sync:
385 pm_runtime_disable(dev);
386
387 return ret;
388}
389
390static struct platform_driver cdns_pcie_host_driver = {
391 .driver = {
392 .name = "cdns-pcie-host",
393 .of_match_table = cdns_pcie_host_of_match,
394 },
395 .probe = cdns_pcie_host_probe,
396};
397builtin_platform_driver(cdns_pcie_host_driver);
diff --git a/drivers/pci/host/pcie-cadence.h b/drivers/pci/host/pcie-cadence.h
new file mode 100644
index 000000000000..a28afdee0d02
--- /dev/null
+++ b/drivers/pci/host/pcie-cadence.h
@@ -0,0 +1,189 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2017 Cadence
3// Cadence PCIe controller driver.
4// Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
5
6#ifndef _PCIE_CADENCE_H
7#define _PCIE_CADENCE_H
8
9#include <linux/kernel.h>
10#include <linux/pci.h>
11
12/*
13 * Local Management Registers
14 */
15#define CDNS_PCIE_LM_BASE 0x00100000
16
17/* Vendor ID Register */
18#define CDNS_PCIE_LM_ID (CDNS_PCIE_LM_BASE + 0x0044)
19#define CDNS_PCIE_LM_ID_VENDOR_MASK GENMASK(15, 0)
20#define CDNS_PCIE_LM_ID_VENDOR_SHIFT 0
21#define CDNS_PCIE_LM_ID_VENDOR(vid) \
22 (((vid) << CDNS_PCIE_LM_ID_VENDOR_SHIFT) & CDNS_PCIE_LM_ID_VENDOR_MASK)
23#define CDNS_PCIE_LM_ID_SUBSYS_MASK GENMASK(31, 16)
24#define CDNS_PCIE_LM_ID_SUBSYS_SHIFT 16
25#define CDNS_PCIE_LM_ID_SUBSYS(sub) \
26 (((sub) << CDNS_PCIE_LM_ID_SUBSYS_SHIFT) & CDNS_PCIE_LM_ID_SUBSYS_MASK)
27
28/* Root Port Requestor ID Register */
29#define CDNS_PCIE_LM_RP_RID (CDNS_PCIE_LM_BASE + 0x0228)
30#define CDNS_PCIE_LM_RP_RID_MASK GENMASK(15, 0)
31#define CDNS_PCIE_LM_RP_RID_SHIFT 0
32#define CDNS_PCIE_LM_RP_RID_(rid) \
33 (((rid) << CDNS_PCIE_LM_RP_RID_SHIFT) & CDNS_PCIE_LM_RP_RID_MASK)
34
35/* Root Complex BAR Configuration Register */
36#define CDNS_PCIE_LM_RC_BAR_CFG (CDNS_PCIE_LM_BASE + 0x0300)
37#define CDNS_PCIE_LM_RC_BAR_CFG_BAR0_APERTURE_MASK GENMASK(5, 0)
38#define CDNS_PCIE_LM_RC_BAR_CFG_BAR0_APERTURE(a) \
39 (((a) << 0) & CDNS_PCIE_LM_RC_BAR_CFG_BAR0_APERTURE_MASK)
40#define CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL_MASK GENMASK(8, 6)
41#define CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(c) \
42 (((c) << 6) & CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL_MASK)
43#define CDNS_PCIE_LM_RC_BAR_CFG_BAR1_APERTURE_MASK GENMASK(13, 9)
44#define CDNS_PCIE_LM_RC_BAR_CFG_BAR1_APERTURE(a) \
45 (((a) << 9) & CDNS_PCIE_LM_RC_BAR_CFG_BAR1_APERTURE_MASK)
46#define CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL_MASK GENMASK(16, 14)
47#define CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(c) \
48 (((c) << 14) & CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL_MASK)
49#define CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE BIT(17)
50#define CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_32BITS 0
51#define CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS BIT(18)
52#define CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE BIT(19)
53#define CDNS_PCIE_LM_RC_BAR_CFG_IO_16BITS 0
54#define CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS BIT(20)
55#define CDNS_PCIE_LM_RC_BAR_CFG_CHECK_ENABLE BIT(31)
56
57/* BAR control values applicable to both Endpoint Function and Root Complex */
58#define CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED 0x0
59#define CDNS_PCIE_LM_BAR_CFG_CTRL_IO_32BITS 0x1
60#define CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_32BITS 0x4
61#define CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_32BITS 0x5
62#define CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS 0x6
63#define CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS 0x7
64
65
66/*
67 * Root Port Registers (PCI configuration space for the root port function)
68 */
69#define CDNS_PCIE_RP_BASE 0x00200000
70
71
72/*
73 * Address Translation Registers
74 */
75#define CDNS_PCIE_AT_BASE 0x00400000
76
77/* Region r Outbound AXI to PCIe Address Translation Register 0 */
78#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(r) \
79 (CDNS_PCIE_AT_BASE + 0x0000 + ((r) & 0x1f) * 0x0020)
80#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS_MASK GENMASK(5, 0)
81#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(nbits) \
82 (((nbits) - 1) & CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS_MASK)
83#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12)
84#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \
85 (((devfn) << 12) & CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK)
86#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20)
87#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \
88 (((bus) << 20) & CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK)
89
90/* Region r Outbound AXI to PCIe Address Translation Register 1 */
91#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(r) \
92 (CDNS_PCIE_AT_BASE + 0x0004 + ((r) & 0x1f) * 0x0020)
93
94/* Region r Outbound PCIe Descriptor Register 0 */
95#define CDNS_PCIE_AT_OB_REGION_DESC0(r) \
96 (CDNS_PCIE_AT_BASE + 0x0008 + ((r) & 0x1f) * 0x0020)
97#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_MASK GENMASK(3, 0)
98#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_MEM 0x2
99#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_IO 0x6
100#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0 0xa
101#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1 0xb
102#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_NORMAL_MSG 0xc
103#define CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_VENDOR_MSG 0xd
104/* Bit 23 MUST be set in RC mode. */
105#define CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23)
106#define CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24)
107#define CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \
108 (((devfn) << 24) & CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK)
109
110/* Region r Outbound PCIe Descriptor Register 1 */
111#define CDNS_PCIE_AT_OB_REGION_DESC1(r) \
112 (CDNS_PCIE_AT_BASE + 0x000c + ((r) & 0x1f) * 0x0020)
113#define CDNS_PCIE_AT_OB_REGION_DESC1_BUS_MASK GENMASK(7, 0)
114#define CDNS_PCIE_AT_OB_REGION_DESC1_BUS(bus) \
115 ((bus) & CDNS_PCIE_AT_OB_REGION_DESC1_BUS_MASK)
116
117/* Region r AXI Region Base Address Register 0 */
118#define CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r) \
119 (CDNS_PCIE_AT_BASE + 0x0018 + ((r) & 0x1f) * 0x0020)
120#define CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS_MASK GENMASK(5, 0)
121#define CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) \
122 (((nbits) - 1) & CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS_MASK)
123
124/* Region r AXI Region Base Address Register 1 */
125#define CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r) \
126 (CDNS_PCIE_AT_BASE + 0x001c + ((r) & 0x1f) * 0x0020)
127
128/* Root Port BAR Inbound PCIe to AXI Address Translation Register */
129#define CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar) \
130 (CDNS_PCIE_AT_BASE + 0x0800 + (bar) * 0x0008)
131#define CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS_MASK GENMASK(5, 0)
132#define CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(nbits) \
133 (((nbits) - 1) & CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS_MASK)
134#define CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar) \
135 (CDNS_PCIE_AT_BASE + 0x0804 + (bar) * 0x0008)
136
137enum cdns_pcie_rp_bar {
138 RP_BAR0,
139 RP_BAR1,
140 RP_NO_BAR
141};
142
143/**
144 * struct cdns_pcie - private data for Cadence PCIe controller drivers
145 * @reg_base: IO mapped register base
146 * @mem_res: start/end offsets in the physical system memory to map PCI accesses
147 * @bus: In Root Complex mode, the bus number
148 */
149struct cdns_pcie {
150 void __iomem *reg_base;
151 struct resource *mem_res;
152 u8 bus;
153};
154
155/* Register access */
156static inline void cdns_pcie_writeb(struct cdns_pcie *pcie, u32 reg, u8 value)
157{
158 writeb(value, pcie->reg_base + reg);
159}
160
161static inline void cdns_pcie_writew(struct cdns_pcie *pcie, u32 reg, u16 value)
162{
163 writew(value, pcie->reg_base + reg);
164}
165
166static inline void cdns_pcie_writel(struct cdns_pcie *pcie, u32 reg, u32 value)
167{
168 writel(value, pcie->reg_base + reg);
169}
170
171static inline u32 cdns_pcie_readl(struct cdns_pcie *pcie, u32 reg)
172{
173 return readl(pcie->reg_base + reg);
174}
175
176/* Root Port register access */
177static inline void cdns_pcie_rp_writeb(struct cdns_pcie *pcie,
178 u32 reg, u8 value)
179{
180 writeb(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
181}
182
183static inline void cdns_pcie_rp_writew(struct cdns_pcie *pcie,
184 u32 reg, u16 value)
185{
186 writew(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
187}
188
189#endif /* _PCIE_CADENCE_H */