]> Git Repo - linux.git/blob - drivers/pci/controller/pcie-cadence-host.c
Merge tag 'drm-fixes-2018-06-22' of git://anongit.freedesktop.org/drm/drm
[linux.git] / drivers / pci / controller / pcie-cadence-host.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2017 Cadence
3 // Cadence PCIe host controller driver.
4 // Author: Cyrille Pitchen <[email protected]>
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  */
29 struct 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
41 static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
42                                       int where)
43 {
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;
48         u32 addr0, desc0;
49
50         if (busn == rc->bus_range->start) {
51                 /*
52                  * Only the root port (devfn == 0) is connected to this bus.
53                  * All other PCI devices are behind some bridge hence on another
54                  * bus.
55                  */
56                 if (devfn)
57                         return NULL;
58
59                 return pcie->reg_base + (where & 0xfff);
60         }
61
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);
67
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);
71         /*
72          * The bus number was already set once for all in desc1 by
73          * cdns_pcie_host_init_address_translation().
74          */
75         if (busn == rc->bus_range->start + 1)
76                 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
77         else
78                 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
79         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0);
80
81         return rc->cfg_base + (where & 0xfff);
82 }
83
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,
88 };
89
90 static const struct of_device_id cdns_pcie_host_of_match[] = {
91         { .compatible = "cdns,cdns-pcie-host" },
92
93         { },
94 };
95
96 static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
97 {
98         struct cdns_pcie *pcie = &rc->pcie;
99         u32 value, ctrl;
100
101         /*
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
107          *   space (32 bits).
108          */
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);
117
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);
123
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);
127
128         return 0;
129 }
130
131 static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
132 {
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;
142         u64 cpu_addr;
143         int r, err;
144
145         /*
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.
149          */
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);
154
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);
161
162         err = of_pci_range_parser_init(&parser, np);
163         if (err)
164                 return err;
165
166         r = 1;
167         for_each_of_pci_range(&parser, &range) {
168                 bool is_io;
169
170                 if (r >= rc->max_regions)
171                         break;
172
173                 if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
174                         is_io = false;
175                 else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
176                         is_io = true;
177                 else
178                         continue;
179
180                 cdns_pcie_set_outbound_region(pcie, 0, r, is_io,
181                                               range.cpu_addr,
182                                               range.pci_addr,
183                                               range.size);
184                 r++;
185         }
186
187         /*
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.
192          */
193         addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(rc->no_bar_nbits);
194         addr1 = 0;
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);
197
198         return 0;
199 }
200
201 static int cdns_pcie_host_init(struct device *dev,
202                                struct list_head *resources,
203                                struct cdns_pcie_rc *rc)
204 {
205         struct resource *bus_range = NULL;
206         int err;
207
208         /* Parse our PCI ranges and request their resources */
209         err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
210         if (err)
211                 return err;
212
213         rc->bus_range = bus_range;
214         rc->pcie.bus = bus_range->start;
215
216         err = cdns_pcie_host_init_root_port(rc);
217         if (err)
218                 goto err_out;
219
220         err = cdns_pcie_host_init_address_translation(rc);
221         if (err)
222                 goto err_out;
223
224         return 0;
225
226  err_out:
227         pci_free_resource_list(resources);
228         return err;
229 }
230
231 static int cdns_pcie_host_probe(struct platform_device *pdev)
232 {
233         const char *type;
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;
241         int ret;
242
243         bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
244         if (!bridge)
245                 return -ENOMEM;
246
247         rc = pci_host_bridge_priv(bridge);
248         rc->dev = dev;
249
250         pcie = &rc->pcie;
251         pcie->is_rc = true;
252
253         rc->max_regions = 32;
254         of_property_read_u32(np, "cdns,max-outbound-regions", &rc->max_regions);
255
256         rc->no_bar_nbits = 32;
257         of_property_read_u32(np, "cdns,no-bar-match-nbits", &rc->no_bar_nbits);
258
259         rc->vendor_id = 0xffff;
260         of_property_read_u16(np, "vendor-id", &rc->vendor_id);
261
262         rc->device_id = 0xffff;
263         of_property_read_u16(np, "device-id", &rc->device_id);
264
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);
268                 return -EINVAL;
269         }
270
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);
276         }
277
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);
283         }
284         rc->cfg_res = res;
285
286         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
287         if (!res) {
288                 dev_err(dev, "missing \"mem\"\n");
289                 return -EINVAL;
290         }
291         pcie->mem_res = res;
292
293         pm_runtime_enable(dev);
294         ret = pm_runtime_get_sync(dev);
295         if (ret < 0) {
296                 dev_err(dev, "pm_runtime_get_sync() failed\n");
297                 goto err_get_sync;
298         }
299
300         ret = cdns_pcie_host_init(dev, &resources, rc);
301         if (ret)
302                 goto err_init;
303
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;
310
311         ret = pci_host_probe(bridge);
312         if (ret < 0)
313                 goto err_host_probe;
314
315         return 0;
316
317  err_host_probe:
318         pci_free_resource_list(&resources);
319
320  err_init:
321         pm_runtime_put_sync(dev);
322
323  err_get_sync:
324         pm_runtime_disable(dev);
325
326         return ret;
327 }
328
329 static struct platform_driver cdns_pcie_host_driver = {
330         .driver = {
331                 .name = "cdns-pcie-host",
332                 .of_match_table = cdns_pcie_host_of_match,
333         },
334         .probe = cdns_pcie_host_probe,
335 };
336 builtin_platform_driver(cdns_pcie_host_driver);
This page took 0.054262 seconds and 4 git commands to generate.