diff options
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 171 |
1 files changed, 34 insertions, 137 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index f9d3960dc39f..dd9b3bcc41c3 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Tegra SoCs | 3 | * PCIe host controller driver for Tegra SoCs |
3 | * | 4 | * |
@@ -10,20 +11,6 @@ | |||
10 | * Bits taken from arch/arm/mach-dove/pcie.c | 11 | * Bits taken from arch/arm/mach-dove/pcie.c |
11 | * | 12 | * |
12 | * Author: Thierry Reding <treding@nvidia.com> | 13 | * Author: Thierry Reding <treding@nvidia.com> |
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
22 | * more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License along | ||
25 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
26 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
27 | */ | 14 | */ |
28 | 15 | ||
29 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
@@ -269,11 +256,10 @@ struct tegra_pcie { | |||
269 | 256 | ||
270 | void __iomem *pads; | 257 | void __iomem *pads; |
271 | void __iomem *afi; | 258 | void __iomem *afi; |
259 | void __iomem *cfg; | ||
272 | int irq; | 260 | int irq; |
273 | 261 | ||
274 | struct list_head buses; | 262 | struct resource cs; |
275 | struct resource *cs; | ||
276 | |||
277 | struct resource io; | 263 | struct resource io; |
278 | struct resource pio; | 264 | struct resource pio; |
279 | struct resource mem; | 265 | struct resource mem; |
@@ -322,7 +308,6 @@ struct tegra_pcie_port { | |||
322 | }; | 308 | }; |
323 | 309 | ||
324 | struct tegra_pcie_bus { | 310 | struct tegra_pcie_bus { |
325 | struct vm_struct *area; | ||
326 | struct list_head list; | 311 | struct list_head list; |
327 | unsigned int nr; | 312 | unsigned int nr; |
328 | }; | 313 | }; |
@@ -362,109 +347,26 @@ static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset) | |||
362 | * | 347 | * |
363 | * Mapping the whole extended configuration space would require 256 MiB of | 348 | * Mapping the whole extended configuration space would require 256 MiB of |
364 | * virtual address space, only a small part of which will actually be used. | 349 | * virtual address space, only a small part of which will actually be used. |
365 | * To work around this, a 1 MiB of virtual addresses are allocated per bus | ||
366 | * when the bus is first accessed. When the physical range is mapped, the | ||
367 | * the bus number bits are hidden so that the extended register number bits | ||
368 | * appear as bits [19:16]. Therefore the virtual mapping looks like this: | ||
369 | * | 350 | * |
370 | * [19:16] extended register number | 351 | * To work around this, a 4 KiB region is used to generate the required |
371 | * [15:11] device number | 352 | * configuration transaction with relevant B:D:F and register offset values. |
372 | * [10: 8] function number | 353 | * This is achieved by dynamically programming base address and size of |
373 | * [ 7: 0] register number | 354 | * AFI_AXI_BAR used for end point config space mapping to make sure that the |
374 | * | 355 | * address (access to which generates correct config transaction) falls in |
375 | * This is achieved by stitching together 16 chunks of 64 KiB of physical | 356 | * this 4 KiB region. |
376 | * address space via the MMU. | ||
377 | */ | 357 | */ |
378 | static unsigned long tegra_pcie_conf_offset(unsigned int devfn, int where) | 358 | static unsigned int tegra_pcie_conf_offset(u8 bus, unsigned int devfn, |
379 | { | 359 | unsigned int where) |
380 | return ((where & 0xf00) << 8) | (PCI_SLOT(devfn) << 11) | | ||
381 | (PCI_FUNC(devfn) << 8) | (where & 0xfc); | ||
382 | } | ||
383 | |||
384 | static struct tegra_pcie_bus *tegra_pcie_bus_alloc(struct tegra_pcie *pcie, | ||
385 | unsigned int busnr) | ||
386 | { | ||
387 | struct device *dev = pcie->dev; | ||
388 | pgprot_t prot = pgprot_noncached(PAGE_KERNEL); | ||
389 | phys_addr_t cs = pcie->cs->start; | ||
390 | struct tegra_pcie_bus *bus; | ||
391 | unsigned int i; | ||
392 | int err; | ||
393 | |||
394 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); | ||
395 | if (!bus) | ||
396 | return ERR_PTR(-ENOMEM); | ||
397 | |||
398 | INIT_LIST_HEAD(&bus->list); | ||
399 | bus->nr = busnr; | ||
400 | |||
401 | /* allocate 1 MiB of virtual addresses */ | ||
402 | bus->area = get_vm_area(SZ_1M, VM_IOREMAP); | ||
403 | if (!bus->area) { | ||
404 | err = -ENOMEM; | ||
405 | goto free; | ||
406 | } | ||
407 | |||
408 | /* map each of the 16 chunks of 64 KiB each */ | ||
409 | for (i = 0; i < 16; i++) { | ||
410 | unsigned long virt = (unsigned long)bus->area->addr + | ||
411 | i * SZ_64K; | ||
412 | phys_addr_t phys = cs + i * SZ_16M + busnr * SZ_64K; | ||
413 | |||
414 | err = ioremap_page_range(virt, virt + SZ_64K, phys, prot); | ||
415 | if (err < 0) { | ||
416 | dev_err(dev, "ioremap_page_range() failed: %d\n", err); | ||
417 | goto unmap; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | return bus; | ||
422 | |||
423 | unmap: | ||
424 | vunmap(bus->area->addr); | ||
425 | free: | ||
426 | kfree(bus); | ||
427 | return ERR_PTR(err); | ||
428 | } | ||
429 | |||
430 | static int tegra_pcie_add_bus(struct pci_bus *bus) | ||
431 | { | ||
432 | struct pci_host_bridge *host = pci_find_host_bridge(bus); | ||
433 | struct tegra_pcie *pcie = pci_host_bridge_priv(host); | ||
434 | struct tegra_pcie_bus *b; | ||
435 | |||
436 | b = tegra_pcie_bus_alloc(pcie, bus->number); | ||
437 | if (IS_ERR(b)) | ||
438 | return PTR_ERR(b); | ||
439 | |||
440 | list_add_tail(&b->list, &pcie->buses); | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | static void tegra_pcie_remove_bus(struct pci_bus *child) | ||
446 | { | 360 | { |
447 | struct pci_host_bridge *host = pci_find_host_bridge(child); | 361 | return ((where & 0xf00) << 16) | (bus << 16) | (PCI_SLOT(devfn) << 11) | |
448 | struct tegra_pcie *pcie = pci_host_bridge_priv(host); | 362 | (PCI_FUNC(devfn) << 8) | (where & 0xff); |
449 | struct tegra_pcie_bus *bus, *tmp; | ||
450 | |||
451 | list_for_each_entry_safe(bus, tmp, &pcie->buses, list) { | ||
452 | if (bus->nr == child->number) { | ||
453 | vunmap(bus->area->addr); | ||
454 | list_del(&bus->list); | ||
455 | kfree(bus); | ||
456 | break; | ||
457 | } | ||
458 | } | ||
459 | } | 363 | } |
460 | 364 | ||
461 | static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, | 365 | static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, |
462 | unsigned int devfn, | 366 | unsigned int devfn, |
463 | int where) | 367 | int where) |
464 | { | 368 | { |
465 | struct pci_host_bridge *host = pci_find_host_bridge(bus); | 369 | struct tegra_pcie *pcie = bus->sysdata; |
466 | struct tegra_pcie *pcie = pci_host_bridge_priv(host); | ||
467 | struct device *dev = pcie->dev; | ||
468 | void __iomem *addr = NULL; | 370 | void __iomem *addr = NULL; |
469 | 371 | ||
470 | if (bus->number == 0) { | 372 | if (bus->number == 0) { |
@@ -478,19 +380,17 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, | |||
478 | } | 380 | } |
479 | } | 381 | } |
480 | } else { | 382 | } else { |
481 | struct tegra_pcie_bus *b; | 383 | unsigned int offset; |
384 | u32 base; | ||
482 | 385 | ||
483 | list_for_each_entry(b, &pcie->buses, list) | 386 | offset = tegra_pcie_conf_offset(bus->number, devfn, where); |
484 | if (b->nr == bus->number) | ||
485 | addr = (void __iomem *)b->area->addr; | ||
486 | 387 | ||
487 | if (!addr) { | 388 | /* move 4 KiB window to offset within the FPCI region */ |
488 | dev_err(dev, "failed to map cfg. space for bus %u\n", | 389 | base = 0xfe100000 + ((offset & ~(SZ_4K - 1)) >> 8); |
489 | bus->number); | 390 | afi_writel(pcie, base, AFI_FPCI_BAR0); |
490 | return NULL; | ||
491 | } | ||
492 | 391 | ||
493 | addr += tegra_pcie_conf_offset(devfn, where); | 392 | /* move to correct offset within the 4 KiB page */ |
393 | addr = pcie->cfg + (offset & (SZ_4K - 1)); | ||
494 | } | 394 | } |
495 | 395 | ||
496 | return addr; | 396 | return addr; |
@@ -517,8 +417,6 @@ static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn, | |||
517 | } | 417 | } |
518 | 418 | ||
519 | static struct pci_ops tegra_pcie_ops = { | 419 | static struct pci_ops tegra_pcie_ops = { |
520 | .add_bus = tegra_pcie_add_bus, | ||
521 | .remove_bus = tegra_pcie_remove_bus, | ||
522 | .map_bus = tegra_pcie_map_bus, | 420 | .map_bus = tegra_pcie_map_bus, |
523 | .read = tegra_pcie_config_read, | 421 | .read = tegra_pcie_config_read, |
524 | .write = tegra_pcie_config_write, | 422 | .write = tegra_pcie_config_write, |
@@ -661,8 +559,7 @@ static int tegra_pcie_request_resources(struct tegra_pcie *pcie) | |||
661 | 559 | ||
662 | static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) | 560 | static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) |
663 | { | 561 | { |
664 | struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus); | 562 | struct tegra_pcie *pcie = pdev->bus->sysdata; |
665 | struct tegra_pcie *pcie = pci_host_bridge_priv(host); | ||
666 | int irq; | 563 | int irq; |
667 | 564 | ||
668 | tegra_cpuidle_pcie_irqs_in_use(); | 565 | tegra_cpuidle_pcie_irqs_in_use(); |
@@ -743,12 +640,9 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) | |||
743 | u32 fpci_bar, size, axi_address; | 640 | u32 fpci_bar, size, axi_address; |
744 | 641 | ||
745 | /* Bar 0: type 1 extended configuration space */ | 642 | /* Bar 0: type 1 extended configuration space */ |
746 | fpci_bar = 0xfe100000; | 643 | size = resource_size(&pcie->cs); |
747 | size = resource_size(pcie->cs); | 644 | afi_writel(pcie, pcie->cs.start, AFI_AXI_BAR0_START); |
748 | axi_address = pcie->cs->start; | ||
749 | afi_writel(pcie, axi_address, AFI_AXI_BAR0_START); | ||
750 | afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ); | 645 | afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ); |
751 | afi_writel(pcie, fpci_bar, AFI_FPCI_BAR0); | ||
752 | 646 | ||
753 | /* Bar 1: downstream IO bar */ | 647 | /* Bar 1: downstream IO bar */ |
754 | fpci_bar = 0xfdfc0000; | 648 | fpci_bar = 0xfdfc0000; |
@@ -1353,10 +1247,14 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) | |||
1353 | goto poweroff; | 1247 | goto poweroff; |
1354 | } | 1248 | } |
1355 | 1249 | ||
1356 | pcie->cs = devm_request_mem_region(dev, res->start, | 1250 | pcie->cs = *res; |
1357 | resource_size(res), res->name); | 1251 | |
1358 | if (!pcie->cs) { | 1252 | /* constrain configuration space to 4 KiB */ |
1359 | err = -EADDRNOTAVAIL; | 1253 | pcie->cs.end = pcie->cs.start + SZ_4K - 1; |
1254 | |||
1255 | pcie->cfg = devm_ioremap_resource(dev, &pcie->cs); | ||
1256 | if (IS_ERR(pcie->cfg)) { | ||
1257 | err = PTR_ERR(pcie->cfg); | ||
1360 | goto poweroff; | 1258 | goto poweroff; |
1361 | } | 1259 | } |
1362 | 1260 | ||
@@ -2345,9 +2243,9 @@ static int tegra_pcie_probe(struct platform_device *pdev) | |||
2345 | return -ENOMEM; | 2243 | return -ENOMEM; |
2346 | 2244 | ||
2347 | pcie = pci_host_bridge_priv(host); | 2245 | pcie = pci_host_bridge_priv(host); |
2246 | host->sysdata = pcie; | ||
2348 | 2247 | ||
2349 | pcie->soc = of_device_get_match_data(dev); | 2248 | pcie->soc = of_device_get_match_data(dev); |
2350 | INIT_LIST_HEAD(&pcie->buses); | ||
2351 | INIT_LIST_HEAD(&pcie->ports); | 2249 | INIT_LIST_HEAD(&pcie->ports); |
2352 | pcie->dev = dev; | 2250 | pcie->dev = dev; |
2353 | 2251 | ||
@@ -2382,7 +2280,6 @@ static int tegra_pcie_probe(struct platform_device *pdev) | |||
2382 | 2280 | ||
2383 | tegra_pcie_enable_ports(pcie); | 2281 | tegra_pcie_enable_ports(pcie); |
2384 | 2282 | ||
2385 | pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); | ||
2386 | host->busnr = pcie->busn.start; | 2283 | host->busnr = pcie->busn.start; |
2387 | host->dev.parent = &pdev->dev; | 2284 | host->dev.parent = &pdev->dev; |
2388 | host->ops = &tegra_pcie_ops; | 2285 | host->ops = &tegra_pcie_ops; |