diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/Kconfig | 13 | ||||
-rw-r--r-- | drivers/pci/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-dra7xx.c | 6 | ||||
-rw-r--r-- | drivers/pci/host/pci-exynos.c | 18 | ||||
-rw-r--r-- | drivers/pci/host/pci-host-generic.c | 126 | ||||
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 4 | ||||
-rw-r--r-- | drivers/pci/host/pci-layerscape.c | 179 | ||||
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rcar.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pcie-spear13xx.c | 13 |
11 files changed, 242 insertions, 123 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 3dc25fad490c..c4b6568e486d 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -32,7 +32,10 @@ config PCI_IMX6 | |||
32 | 32 | ||
33 | config PCI_TEGRA | 33 | config PCI_TEGRA |
34 | bool "NVIDIA Tegra PCIe controller" | 34 | bool "NVIDIA Tegra PCIe controller" |
35 | depends on ARCH_TEGRA | 35 | depends on ARCH_TEGRA && !ARM64 |
36 | help | ||
37 | Say Y here if you want support for the PCIe host controller found | ||
38 | on NVIDIA Tegra SoCs. | ||
36 | 39 | ||
37 | config PCI_RCAR_GEN2 | 40 | config PCI_RCAR_GEN2 |
38 | bool "Renesas R-Car Gen2 Internal PCI controller" | 41 | bool "Renesas R-Car Gen2 Internal PCI controller" |
@@ -91,4 +94,12 @@ config PCI_XGENE | |||
91 | There are 5 internal PCIe ports available. Each port is GEN3 capable | 94 | There are 5 internal PCIe ports available. Each port is GEN3 capable |
92 | and have varied lanes from x1 to x8. | 95 | and have varied lanes from x1 to x8. |
93 | 96 | ||
97 | config PCI_LAYERSCAPE | ||
98 | bool "Freescale Layerscape PCIe controller" | ||
99 | depends on OF && ARM | ||
100 | select PCIE_DW | ||
101 | select MFD_SYSCON | ||
102 | help | ||
103 | Say Y here if you want PCIe controller support on Layerscape SoCs. | ||
104 | |||
94 | endmenu | 105 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 26b3461d68d7..44c26998027f 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o | |||
11 | obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o | 11 | obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o |
12 | obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o | 12 | obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o |
13 | obj-$(CONFIG_PCI_XGENE) += pci-xgene.o | 13 | obj-$(CONFIG_PCI_XGENE) += pci-xgene.o |
14 | obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o | ||
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 52b34fee07fd..8c6969747acd 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c | |||
@@ -270,8 +270,8 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) | |||
270 | return IRQ_HANDLED; | 270 | return IRQ_HANDLED; |
271 | } | 271 | } |
272 | 272 | ||
273 | static int add_pcie_port(struct dra7xx_pcie *dra7xx, | 273 | static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, |
274 | struct platform_device *pdev) | 274 | struct platform_device *pdev) |
275 | { | 275 | { |
276 | int ret; | 276 | int ret; |
277 | struct pcie_port *pp; | 277 | struct pcie_port *pp; |
@@ -398,7 +398,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
398 | 398 | ||
399 | platform_set_drvdata(pdev, dra7xx); | 399 | platform_set_drvdata(pdev, dra7xx); |
400 | 400 | ||
401 | ret = add_pcie_port(dra7xx, pdev); | 401 | ret = dra7xx_add_pcie_port(dra7xx, pdev); |
402 | if (ret < 0) | 402 | if (ret < 0) |
403 | goto err_add_port; | 403 | goto err_add_port; |
404 | 404 | ||
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index c5d0ca384502..850c9f951a3f 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -312,7 +312,6 @@ static void exynos_pcie_assert_reset(struct pcie_port *pp) | |||
312 | if (exynos_pcie->reset_gpio >= 0) | 312 | if (exynos_pcie->reset_gpio >= 0) |
313 | devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio, | 313 | devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio, |
314 | GPIOF_OUT_INIT_HIGH, "RESET"); | 314 | GPIOF_OUT_INIT_HIGH, "RESET"); |
315 | return; | ||
316 | } | 315 | } |
317 | 316 | ||
318 | static int exynos_pcie_establish_link(struct pcie_port *pp) | 317 | static int exynos_pcie_establish_link(struct pcie_port *pp) |
@@ -388,7 +387,6 @@ static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp) | |||
388 | 387 | ||
389 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); | 388 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); |
390 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); | 389 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); |
391 | return; | ||
392 | } | 390 | } |
393 | 391 | ||
394 | static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) | 392 | static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) |
@@ -400,7 +398,6 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) | |||
400 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | | 398 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | |
401 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, | 399 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, |
402 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); | 400 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); |
403 | return; | ||
404 | } | 401 | } |
405 | 402 | ||
406 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) | 403 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) |
@@ -429,7 +426,6 @@ static void exynos_pcie_msi_init(struct pcie_port *pp) | |||
429 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); | 426 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); |
430 | val |= IRQ_MSI_ENABLE; | 427 | val |= IRQ_MSI_ENABLE; |
431 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); | 428 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); |
432 | return; | ||
433 | } | 429 | } |
434 | 430 | ||
435 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) | 431 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) |
@@ -438,8 +434,6 @@ static void exynos_pcie_enable_interrupts(struct pcie_port *pp) | |||
438 | 434 | ||
439 | if (IS_ENABLED(CONFIG_PCI_MSI)) | 435 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
440 | exynos_pcie_msi_init(pp); | 436 | exynos_pcie_msi_init(pp); |
441 | |||
442 | return; | ||
443 | } | 437 | } |
444 | 438 | ||
445 | static inline void exynos_pcie_readl_rc(struct pcie_port *pp, | 439 | static inline void exynos_pcie_readl_rc(struct pcie_port *pp, |
@@ -448,7 +442,6 @@ static inline void exynos_pcie_readl_rc(struct pcie_port *pp, | |||
448 | exynos_pcie_sideband_dbi_r_mode(pp, true); | 442 | exynos_pcie_sideband_dbi_r_mode(pp, true); |
449 | *val = readl(dbi_base); | 443 | *val = readl(dbi_base); |
450 | exynos_pcie_sideband_dbi_r_mode(pp, false); | 444 | exynos_pcie_sideband_dbi_r_mode(pp, false); |
451 | return; | ||
452 | } | 445 | } |
453 | 446 | ||
454 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, | 447 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, |
@@ -457,7 +450,6 @@ static inline void exynos_pcie_writel_rc(struct pcie_port *pp, | |||
457 | exynos_pcie_sideband_dbi_w_mode(pp, true); | 450 | exynos_pcie_sideband_dbi_w_mode(pp, true); |
458 | writel(val, dbi_base); | 451 | writel(val, dbi_base); |
459 | exynos_pcie_sideband_dbi_w_mode(pp, false); | 452 | exynos_pcie_sideband_dbi_w_mode(pp, false); |
460 | return; | ||
461 | } | 453 | } |
462 | 454 | ||
463 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | 455 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
@@ -509,8 +501,8 @@ static struct pcie_host_ops exynos_pcie_host_ops = { | |||
509 | .host_init = exynos_pcie_host_init, | 501 | .host_init = exynos_pcie_host_init, |
510 | }; | 502 | }; |
511 | 503 | ||
512 | static int __init add_pcie_port(struct pcie_port *pp, | 504 | static int __init exynos_add_pcie_port(struct pcie_port *pp, |
513 | struct platform_device *pdev) | 505 | struct platform_device *pdev) |
514 | { | 506 | { |
515 | int ret; | 507 | int ret; |
516 | 508 | ||
@@ -615,7 +607,7 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
615 | goto fail_bus_clk; | 607 | goto fail_bus_clk; |
616 | } | 608 | } |
617 | 609 | ||
618 | ret = add_pcie_port(pp, pdev); | 610 | ret = exynos_add_pcie_port(pp, pdev); |
619 | if (ret < 0) | 611 | if (ret < 0) |
620 | goto fail_bus_clk; | 612 | goto fail_bus_clk; |
621 | 613 | ||
@@ -656,11 +648,11 @@ static struct platform_driver exynos_pcie_driver = { | |||
656 | 648 | ||
657 | /* Exynos PCIe driver does not allow module unload */ | 649 | /* Exynos PCIe driver does not allow module unload */ |
658 | 650 | ||
659 | static int __init pcie_init(void) | 651 | static int __init exynos_pcie_init(void) |
660 | { | 652 | { |
661 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); | 653 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); |
662 | } | 654 | } |
663 | subsys_initcall(pcie_init); | 655 | subsys_initcall(exynos_pcie_init); |
664 | 656 | ||
665 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | 657 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); |
666 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); | 658 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); |
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c index 3d2076f59911..18959075d164 100644 --- a/drivers/pci/host/pci-host-generic.c +++ b/drivers/pci/host/pci-host-generic.c | |||
@@ -32,7 +32,7 @@ struct gen_pci_cfg_bus_ops { | |||
32 | 32 | ||
33 | struct gen_pci_cfg_windows { | 33 | struct gen_pci_cfg_windows { |
34 | struct resource res; | 34 | struct resource res; |
35 | struct resource bus_range; | 35 | struct resource *bus_range; |
36 | void __iomem **win; | 36 | void __iomem **win; |
37 | 37 | ||
38 | const struct gen_pci_cfg_bus_ops *ops; | 38 | const struct gen_pci_cfg_bus_ops *ops; |
@@ -50,7 +50,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, | |||
50 | { | 50 | { |
51 | struct pci_sys_data *sys = bus->sysdata; | 51 | struct pci_sys_data *sys = bus->sysdata; |
52 | struct gen_pci *pci = sys->private_data; | 52 | struct gen_pci *pci = sys->private_data; |
53 | resource_size_t idx = bus->number - pci->cfg.bus_range.start; | 53 | resource_size_t idx = bus->number - pci->cfg.bus_range->start; |
54 | 54 | ||
55 | return pci->cfg.win[idx] + ((devfn << 8) | where); | 55 | return pci->cfg.win[idx] + ((devfn << 8) | where); |
56 | } | 56 | } |
@@ -66,7 +66,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, | |||
66 | { | 66 | { |
67 | struct pci_sys_data *sys = bus->sysdata; | 67 | struct pci_sys_data *sys = bus->sysdata; |
68 | struct gen_pci *pci = sys->private_data; | 68 | struct gen_pci *pci = sys->private_data; |
69 | resource_size_t idx = bus->number - pci->cfg.bus_range.start; | 69 | resource_size_t idx = bus->number - pci->cfg.bus_range->start; |
70 | 70 | ||
71 | return pci->cfg.win[idx] + ((devfn << 12) | where); | 71 | return pci->cfg.win[idx] + ((devfn << 12) | where); |
72 | } | 72 | } |
@@ -138,106 +138,50 @@ static const struct of_device_id gen_pci_of_match[] = { | |||
138 | }; | 138 | }; |
139 | MODULE_DEVICE_TABLE(of, gen_pci_of_match); | 139 | MODULE_DEVICE_TABLE(of, gen_pci_of_match); |
140 | 140 | ||
141 | static int gen_pci_calc_io_offset(struct device *dev, | ||
142 | struct of_pci_range *range, | ||
143 | struct resource *res, | ||
144 | resource_size_t *offset) | ||
145 | { | ||
146 | static atomic_t wins = ATOMIC_INIT(0); | ||
147 | int err, idx, max_win; | ||
148 | unsigned int window; | ||
149 | |||
150 | if (!PAGE_ALIGNED(range->cpu_addr)) | ||
151 | return -EINVAL; | ||
152 | |||
153 | max_win = (IO_SPACE_LIMIT + 1) / SZ_64K; | ||
154 | idx = atomic_inc_return(&wins); | ||
155 | if (idx > max_win) | ||
156 | return -ENOSPC; | ||
157 | |||
158 | window = (idx - 1) * SZ_64K; | ||
159 | err = pci_ioremap_io(window, range->cpu_addr); | ||
160 | if (err) | ||
161 | return err; | ||
162 | |||
163 | of_pci_range_to_resource(range, dev->of_node, res); | ||
164 | res->start = window; | ||
165 | res->end = res->start + range->size - 1; | ||
166 | *offset = window - range->pci_addr; | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int gen_pci_calc_mem_offset(struct device *dev, | ||
171 | struct of_pci_range *range, | ||
172 | struct resource *res, | ||
173 | resource_size_t *offset) | ||
174 | { | ||
175 | of_pci_range_to_resource(range, dev->of_node, res); | ||
176 | *offset = range->cpu_addr - range->pci_addr; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) | 141 | static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) |
181 | { | 142 | { |
182 | struct pci_host_bridge_window *win; | ||
183 | |||
184 | list_for_each_entry(win, &pci->resources, list) | ||
185 | release_resource(win->res); | ||
186 | |||
187 | pci_free_resource_list(&pci->resources); | 143 | pci_free_resource_list(&pci->resources); |
188 | } | 144 | } |
189 | 145 | ||
190 | static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) | 146 | static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) |
191 | { | 147 | { |
192 | struct of_pci_range range; | ||
193 | struct of_pci_range_parser parser; | ||
194 | int err, res_valid = 0; | 148 | int err, res_valid = 0; |
195 | struct device *dev = pci->host.dev.parent; | 149 | struct device *dev = pci->host.dev.parent; |
196 | struct device_node *np = dev->of_node; | 150 | struct device_node *np = dev->of_node; |
151 | resource_size_t iobase; | ||
152 | struct pci_host_bridge_window *win; | ||
197 | 153 | ||
198 | if (of_pci_range_parser_init(&parser, np)) { | 154 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, |
199 | dev_err(dev, "missing \"ranges\" property\n"); | 155 | &iobase); |
200 | return -EINVAL; | 156 | if (err) |
201 | } | 157 | return err; |
202 | |||
203 | for_each_of_pci_range(&parser, &range) { | ||
204 | struct resource *parent, *res; | ||
205 | resource_size_t offset; | ||
206 | u32 restype = range.flags & IORESOURCE_TYPE_BITS; | ||
207 | 158 | ||
208 | res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); | 159 | list_for_each_entry(win, &pci->resources, list) { |
209 | if (!res) { | 160 | struct resource *parent, *res = win->res; |
210 | err = -ENOMEM; | ||
211 | goto out_release_res; | ||
212 | } | ||
213 | 161 | ||
214 | switch (restype) { | 162 | switch (resource_type(res)) { |
215 | case IORESOURCE_IO: | 163 | case IORESOURCE_IO: |
216 | parent = &ioport_resource; | 164 | parent = &ioport_resource; |
217 | err = gen_pci_calc_io_offset(dev, &range, res, &offset); | 165 | err = pci_remap_iospace(res, iobase); |
166 | if (err) { | ||
167 | dev_warn(dev, "error %d: failed to map resource %pR\n", | ||
168 | err, res); | ||
169 | continue; | ||
170 | } | ||
218 | break; | 171 | break; |
219 | case IORESOURCE_MEM: | 172 | case IORESOURCE_MEM: |
220 | parent = &iomem_resource; | 173 | parent = &iomem_resource; |
221 | err = gen_pci_calc_mem_offset(dev, &range, res, &offset); | 174 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); |
222 | res_valid |= !(res->flags & IORESOURCE_PREFETCH || err); | ||
223 | break; | 175 | break; |
176 | case IORESOURCE_BUS: | ||
177 | pci->cfg.bus_range = res; | ||
224 | default: | 178 | default: |
225 | err = -EINVAL; | ||
226 | continue; | ||
227 | } | ||
228 | |||
229 | if (err) { | ||
230 | dev_warn(dev, | ||
231 | "error %d: failed to add resource [type 0x%x, %lld bytes]\n", | ||
232 | err, restype, range.size); | ||
233 | continue; | 179 | continue; |
234 | } | 180 | } |
235 | 181 | ||
236 | err = request_resource(parent, res); | 182 | err = devm_request_resource(dev, parent, res); |
237 | if (err) | 183 | if (err) |
238 | goto out_release_res; | 184 | goto out_release_res; |
239 | |||
240 | pci_add_resource_offset(&pci->resources, res, offset); | ||
241 | } | 185 | } |
242 | 186 | ||
243 | if (!res_valid) { | 187 | if (!res_valid) { |
@@ -262,38 +206,30 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) | |||
262 | struct device *dev = pci->host.dev.parent; | 206 | struct device *dev = pci->host.dev.parent; |
263 | struct device_node *np = dev->of_node; | 207 | struct device_node *np = dev->of_node; |
264 | 208 | ||
265 | if (of_pci_parse_bus_range(np, &pci->cfg.bus_range)) | ||
266 | pci->cfg.bus_range = (struct resource) { | ||
267 | .name = np->name, | ||
268 | .start = 0, | ||
269 | .end = 0xff, | ||
270 | .flags = IORESOURCE_BUS, | ||
271 | }; | ||
272 | |||
273 | err = of_address_to_resource(np, 0, &pci->cfg.res); | 209 | err = of_address_to_resource(np, 0, &pci->cfg.res); |
274 | if (err) { | 210 | if (err) { |
275 | dev_err(dev, "missing \"reg\" property\n"); | 211 | dev_err(dev, "missing \"reg\" property\n"); |
276 | return err; | 212 | return err; |
277 | } | 213 | } |
278 | 214 | ||
279 | pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), | 215 | /* Limit the bus-range to fit within reg */ |
216 | bus_max = pci->cfg.bus_range->start + | ||
217 | (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; | ||
218 | pci->cfg.bus_range->end = min_t(resource_size_t, | ||
219 | pci->cfg.bus_range->end, bus_max); | ||
220 | |||
221 | pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range), | ||
280 | sizeof(*pci->cfg.win), GFP_KERNEL); | 222 | sizeof(*pci->cfg.win), GFP_KERNEL); |
281 | if (!pci->cfg.win) | 223 | if (!pci->cfg.win) |
282 | return -ENOMEM; | 224 | return -ENOMEM; |
283 | 225 | ||
284 | /* Limit the bus-range to fit within reg */ | ||
285 | bus_max = pci->cfg.bus_range.start + | ||
286 | (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; | ||
287 | pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end, | ||
288 | bus_max); | ||
289 | |||
290 | /* Map our Configuration Space windows */ | 226 | /* Map our Configuration Space windows */ |
291 | if (!devm_request_mem_region(dev, pci->cfg.res.start, | 227 | if (!devm_request_mem_region(dev, pci->cfg.res.start, |
292 | resource_size(&pci->cfg.res), | 228 | resource_size(&pci->cfg.res), |
293 | "Configuration Space")) | 229 | "Configuration Space")) |
294 | return -ENOMEM; | 230 | return -ENOMEM; |
295 | 231 | ||
296 | bus_range = &pci->cfg.bus_range; | 232 | bus_range = pci->cfg.bus_range; |
297 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { | 233 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { |
298 | u32 idx = busn - bus_range->start; | 234 | u32 idx = busn - bus_range->start; |
299 | u32 sz = 1 << pci->cfg.ops->bus_shift; | 235 | u32 sz = 1 << pci->cfg.ops->bus_shift; |
@@ -305,8 +241,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) | |||
305 | return -ENOMEM; | 241 | return -ENOMEM; |
306 | } | 242 | } |
307 | 243 | ||
308 | /* Register bus resource */ | ||
309 | pci_add_resource(&pci->resources, bus_range); | ||
310 | return 0; | 244 | return 0; |
311 | } | 245 | } |
312 | 246 | ||
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 233fe8a88264..8a7530b3b62a 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -526,8 +526,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp, | |||
526 | } | 526 | } |
527 | 527 | ||
528 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, | 528 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, |
529 | imx6_pcie_msi_handler, | 529 | imx6_pcie_msi_handler, |
530 | IRQF_SHARED, "mx6-pcie-msi", pp); | 530 | IRQF_SHARED, "mx6-pcie-msi", pp); |
531 | if (ret) { | 531 | if (ret) { |
532 | dev_err(&pdev->dev, "failed to request MSI irq\n"); | 532 | dev_err(&pdev->dev, "failed to request MSI irq\n"); |
533 | return -ENODEV; | 533 | return -ENODEV; |
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c new file mode 100644 index 000000000000..6697b1a4d4fa --- /dev/null +++ b/drivers/pci/host/pci-layerscape.c | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * PCIe host controller driver for Freescale Layerscape SoCs | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor. | ||
5 | * | ||
6 | * Author: Minghuan Lian <Minghuan.Lian@freescale.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of_pci.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/of_irq.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/resource.h> | ||
24 | #include <linux/mfd/syscon.h> | ||
25 | #include <linux/regmap.h> | ||
26 | |||
27 | #include "pcie-designware.h" | ||
28 | |||
29 | /* PEX1/2 Misc Ports Status Register */ | ||
30 | #define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) | ||
31 | #define LTSSM_STATE_SHIFT 20 | ||
32 | #define LTSSM_STATE_MASK 0x3f | ||
33 | #define LTSSM_PCIE_L0 0x11 /* L0 state */ | ||
34 | |||
35 | /* Symbol Timer Register and Filter Mask Register 1 */ | ||
36 | #define PCIE_STRFMR1 0x71c | ||
37 | |||
38 | struct ls_pcie { | ||
39 | struct list_head node; | ||
40 | struct device *dev; | ||
41 | struct pci_bus *bus; | ||
42 | void __iomem *dbi; | ||
43 | struct regmap *scfg; | ||
44 | struct pcie_port pp; | ||
45 | int index; | ||
46 | int msi_irq; | ||
47 | }; | ||
48 | |||
49 | #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) | ||
50 | |||
51 | static int ls_pcie_link_up(struct pcie_port *pp) | ||
52 | { | ||
53 | u32 state; | ||
54 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
55 | |||
56 | regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); | ||
57 | state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; | ||
58 | |||
59 | if (state < LTSSM_PCIE_L0) | ||
60 | return 0; | ||
61 | |||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | static void ls_pcie_host_init(struct pcie_port *pp) | ||
66 | { | ||
67 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
68 | int count = 0; | ||
69 | u32 val; | ||
70 | |||
71 | dw_pcie_setup_rc(pp); | ||
72 | |||
73 | while (!ls_pcie_link_up(pp)) { | ||
74 | usleep_range(100, 1000); | ||
75 | count++; | ||
76 | if (count >= 200) { | ||
77 | dev_err(pp->dev, "phy link never came up\n"); | ||
78 | return; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * LS1021A Workaround for internal TKT228622 | ||
84 | * to fix the INTx hang issue | ||
85 | */ | ||
86 | val = ioread32(pcie->dbi + PCIE_STRFMR1); | ||
87 | val &= 0xffff; | ||
88 | iowrite32(val, pcie->dbi + PCIE_STRFMR1); | ||
89 | } | ||
90 | |||
91 | static struct pcie_host_ops ls_pcie_host_ops = { | ||
92 | .link_up = ls_pcie_link_up, | ||
93 | .host_init = ls_pcie_host_init, | ||
94 | }; | ||
95 | |||
96 | static int ls_add_pcie_port(struct ls_pcie *pcie) | ||
97 | { | ||
98 | struct pcie_port *pp; | ||
99 | int ret; | ||
100 | |||
101 | pp = &pcie->pp; | ||
102 | pp->dev = pcie->dev; | ||
103 | pp->dbi_base = pcie->dbi; | ||
104 | pp->root_bus_nr = -1; | ||
105 | pp->ops = &ls_pcie_host_ops; | ||
106 | |||
107 | ret = dw_pcie_host_init(pp); | ||
108 | if (ret) { | ||
109 | dev_err(pp->dev, "failed to initialize host\n"); | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int __init ls_pcie_probe(struct platform_device *pdev) | ||
117 | { | ||
118 | struct ls_pcie *pcie; | ||
119 | struct resource *dbi_base; | ||
120 | u32 index[2]; | ||
121 | int ret; | ||
122 | |||
123 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | ||
124 | if (!pcie) | ||
125 | return -ENOMEM; | ||
126 | |||
127 | pcie->dev = &pdev->dev; | ||
128 | |||
129 | dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | ||
130 | if (!dbi_base) { | ||
131 | dev_err(&pdev->dev, "missing *regs* space\n"); | ||
132 | return -ENODEV; | ||
133 | } | ||
134 | |||
135 | pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); | ||
136 | if (IS_ERR(pcie->dbi)) | ||
137 | return PTR_ERR(pcie->dbi); | ||
138 | |||
139 | pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
140 | "fsl,pcie-scfg"); | ||
141 | if (IS_ERR(pcie->scfg)) { | ||
142 | dev_err(&pdev->dev, "No syscfg phandle specified\n"); | ||
143 | return PTR_ERR(pcie->scfg); | ||
144 | } | ||
145 | |||
146 | ret = of_property_read_u32_array(pdev->dev.of_node, | ||
147 | "fsl,pcie-scfg", index, 2); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | pcie->index = index[1]; | ||
151 | |||
152 | ret = ls_add_pcie_port(pcie); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | platform_set_drvdata(pdev, pcie); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static const struct of_device_id ls_pcie_of_match[] = { | ||
162 | { .compatible = "fsl,ls1021a-pcie" }, | ||
163 | { }, | ||
164 | }; | ||
165 | MODULE_DEVICE_TABLE(of, ls_pcie_of_match); | ||
166 | |||
167 | static struct platform_driver ls_pcie_driver = { | ||
168 | .driver = { | ||
169 | .name = "layerscape-pcie", | ||
170 | .owner = THIS_MODULE, | ||
171 | .of_match_table = ls_pcie_of_match, | ||
172 | }, | ||
173 | }; | ||
174 | |||
175 | module_platform_driver_probe(ls_pcie_driver, ls_pcie_probe); | ||
176 | |||
177 | MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>"); | ||
178 | MODULE_DESCRIPTION("Freescale Layerscape PCIe host controller driver"); | ||
179 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index b1315e197ffb..e45f88e1244f 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -622,6 +622,7 @@ static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie, | |||
622 | 622 | ||
623 | for (i = 0; i < pcie->nports; i++) { | 623 | for (i = 0; i < pcie->nports; i++) { |
624 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 624 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
625 | |||
625 | if (bus->number == 0 && port->devfn == devfn) | 626 | if (bus->number == 0 && port->devfn == devfn) |
626 | return port; | 627 | return port; |
627 | if (bus->number != 0 && | 628 | if (bus->number != 0 && |
@@ -751,6 +752,7 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
751 | 752 | ||
752 | for (i = 0; i < pcie->nports; i++) { | 753 | for (i = 0; i < pcie->nports; i++) { |
753 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 754 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
755 | |||
754 | if (!port->base) | 756 | if (!port->base) |
755 | continue; | 757 | continue; |
756 | mvebu_pcie_setup_hw(port); | 758 | mvebu_pcie_setup_hw(port); |
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index dfed00aa3ac0..f9be37139429 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -380,6 +380,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) | |||
380 | /* Get the I/O and memory ranges from DT */ | 380 | /* Get the I/O and memory ranges from DT */ |
381 | for_each_of_pci_range(&parser, &range) { | 381 | for_each_of_pci_range(&parser, &range) { |
382 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; | 382 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; |
383 | |||
383 | if (restype == IORESOURCE_IO) { | 384 | if (restype == IORESOURCE_IO) { |
384 | of_pci_range_to_resource(&range, np, &pp->io); | 385 | of_pci_range_to_resource(&range, np, &pp->io); |
385 | pp->io.name = "I/O"; | 386 | pp->io.name = "I/O"; |
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 61158e03ab5f..0df9b2941221 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c | |||
@@ -389,7 +389,7 @@ static void rcar_pcie_add_bus(struct pci_bus *bus) | |||
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | struct hw_pci rcar_pci = { | 392 | static struct hw_pci rcar_pci = { |
393 | .setup = rcar_pcie_setup, | 393 | .setup = rcar_pcie_setup, |
394 | .map_irq = of_irq_parse_and_map_pci, | 394 | .map_irq = of_irq_parse_and_map_pci, |
395 | .ops = &rcar_pcie_ops, | 395 | .ops = &rcar_pcie_ops, |
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c index 85f594e1708f..2ca10cc887ee 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/host/pcie-spear13xx.c | |||
@@ -269,7 +269,8 @@ static struct pcie_host_ops spear13xx_pcie_host_ops = { | |||
269 | .host_init = spear13xx_pcie_host_init, | 269 | .host_init = spear13xx_pcie_host_init, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev) | 272 | static int __init spear13xx_add_pcie_port(struct pcie_port *pp, |
273 | struct platform_device *pdev) | ||
273 | { | 274 | { |
274 | struct device *dev = &pdev->dev; | 275 | struct device *dev = &pdev->dev; |
275 | int ret; | 276 | int ret; |
@@ -308,10 +309,8 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev) | |||
308 | int ret; | 309 | int ret; |
309 | 310 | ||
310 | spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); | 311 | spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); |
311 | if (!spear13xx_pcie) { | 312 | if (!spear13xx_pcie) |
312 | dev_err(dev, "no memory for SPEAr13xx pcie\n"); | ||
313 | return -ENOMEM; | 313 | return -ENOMEM; |
314 | } | ||
315 | 314 | ||
316 | spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); | 315 | spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); |
317 | if (IS_ERR(spear13xx_pcie->phy)) { | 316 | if (IS_ERR(spear13xx_pcie->phy)) { |
@@ -352,7 +351,7 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev) | |||
352 | if (of_property_read_bool(np, "st,pcie-is-gen1")) | 351 | if (of_property_read_bool(np, "st,pcie-is-gen1")) |
353 | spear13xx_pcie->is_gen1 = true; | 352 | spear13xx_pcie->is_gen1 = true; |
354 | 353 | ||
355 | ret = add_pcie_port(pp, pdev); | 354 | ret = spear13xx_add_pcie_port(pp, pdev); |
356 | if (ret < 0) | 355 | if (ret < 0) |
357 | goto fail_clk; | 356 | goto fail_clk; |
358 | 357 | ||
@@ -382,11 +381,11 @@ static struct platform_driver spear13xx_pcie_driver __initdata = { | |||
382 | 381 | ||
383 | /* SPEAr13xx PCIe driver does not allow module unload */ | 382 | /* SPEAr13xx PCIe driver does not allow module unload */ |
384 | 383 | ||
385 | static int __init pcie_init(void) | 384 | static int __init spear13xx_pcie_init(void) |
386 | { | 385 | { |
387 | return platform_driver_register(&spear13xx_pcie_driver); | 386 | return platform_driver_register(&spear13xx_pcie_driver); |
388 | } | 387 | } |
389 | module_init(pcie_init); | 388 | module_init(spear13xx_pcie_init); |
390 | 389 | ||
391 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); | 390 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); |
392 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); | 391 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); |