diff options
-rw-r--r-- | drivers/of/address.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 155 |
2 files changed, 34 insertions, 122 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 8591afbdfe99..a4984e7364b1 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -359,6 +359,7 @@ invalid_range: | |||
359 | res->end = (resource_size_t)OF_BAD_ADDR; | 359 | res->end = (resource_size_t)OF_BAD_ADDR; |
360 | return err; | 360 | return err; |
361 | } | 361 | } |
362 | EXPORT_SYMBOL(of_pci_range_to_resource); | ||
362 | #endif /* CONFIG_PCI */ | 363 | #endif /* CONFIG_PCI */ |
363 | 364 | ||
364 | /* | 365 | /* |
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 67328a21d0ee..e4b47ebc91fe 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -269,11 +269,10 @@ struct tegra_pcie { | |||
269 | 269 | ||
270 | void __iomem *pads; | 270 | void __iomem *pads; |
271 | void __iomem *afi; | 271 | void __iomem *afi; |
272 | void __iomem *cfg; | ||
272 | int irq; | 273 | int irq; |
273 | 274 | ||
274 | struct list_head buses; | 275 | struct resource cs; |
275 | struct resource *cs; | ||
276 | |||
277 | struct resource io; | 276 | struct resource io; |
278 | struct resource pio; | 277 | struct resource pio; |
279 | struct resource mem; | 278 | struct resource mem; |
@@ -322,7 +321,6 @@ struct tegra_pcie_port { | |||
322 | }; | 321 | }; |
323 | 322 | ||
324 | struct tegra_pcie_bus { | 323 | struct tegra_pcie_bus { |
325 | struct vm_struct *area; | ||
326 | struct list_head list; | 324 | struct list_head list; |
327 | unsigned int nr; | 325 | unsigned int nr; |
328 | }; | 326 | }; |
@@ -362,109 +360,26 @@ static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset) | |||
362 | * | 360 | * |
363 | * Mapping the whole extended configuration space would require 256 MiB of | 361 | * 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. | 362 | * 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 | * | ||
370 | * [19:16] extended register number | ||
371 | * [15:11] device number | ||
372 | * [10: 8] function number | ||
373 | * [ 7: 0] register number | ||
374 | * | 363 | * |
375 | * This is achieved by stitching together 16 chunks of 64 KiB of physical | 364 | * To work around this, a 4 KiB region is used to generate the required |
376 | * address space via the MMU. | 365 | * configuration transaction with relevant B:D:F and register offset values. |
366 | * This is achieved by dynamically programming base address and size of | ||
367 | * AFI_AXI_BAR used for end point config space mapping to make sure that the | ||
368 | * address (access to which generates correct config transaction) falls in | ||
369 | * this 4 KiB region. | ||
377 | */ | 370 | */ |
378 | static unsigned long tegra_pcie_conf_offset(unsigned int devfn, int where) | 371 | static unsigned int tegra_pcie_conf_offset(u8 bus, unsigned int devfn, |
372 | unsigned int where) | ||
379 | { | 373 | { |
380 | return ((where & 0xf00) << 8) | (PCI_SLOT(devfn) << 11) | | 374 | return ((where & 0xf00) << 16) | (bus << 16) | (PCI_SLOT(devfn) << 11) | |
381 | (PCI_FUNC(devfn) << 8) | (where & 0xfc); | 375 | (PCI_FUNC(devfn) << 8) | (where & 0xff); |
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 | { | ||
447 | struct pci_host_bridge *host = pci_find_host_bridge(child); | ||
448 | struct tegra_pcie *pcie = pci_host_bridge_priv(host); | ||
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 | } | 376 | } |
460 | 377 | ||
461 | static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, | 378 | static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, |
462 | unsigned int devfn, | 379 | unsigned int devfn, |
463 | int where) | 380 | int where) |
464 | { | 381 | { |
465 | struct pci_host_bridge *host = pci_find_host_bridge(bus); | 382 | 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; | 383 | void __iomem *addr = NULL; |
469 | 384 | ||
470 | if (bus->number == 0) { | 385 | if (bus->number == 0) { |
@@ -478,19 +393,17 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, | |||
478 | } | 393 | } |
479 | } | 394 | } |
480 | } else { | 395 | } else { |
481 | struct tegra_pcie_bus *b; | 396 | unsigned int offset; |
397 | u32 base; | ||
482 | 398 | ||
483 | list_for_each_entry(b, &pcie->buses, list) | 399 | offset = tegra_pcie_conf_offset(bus->number, devfn, where); |
484 | if (b->nr == bus->number) | ||
485 | addr = (void __iomem *)b->area->addr; | ||
486 | 400 | ||
487 | if (!addr) { | 401 | /* move 4 KiB window to offset within the FPCI region */ |
488 | dev_err(dev, "failed to map cfg. space for bus %u\n", | 402 | base = 0xfe100000 + ((offset & ~(SZ_4K - 1)) >> 8); |
489 | bus->number); | 403 | afi_writel(pcie, base, AFI_FPCI_BAR0); |
490 | return NULL; | ||
491 | } | ||
492 | 404 | ||
493 | addr += tegra_pcie_conf_offset(devfn, where); | 405 | /* move to correct offset within the 4 KiB page */ |
406 | addr = pcie->cfg + (offset & (SZ_4K - 1)); | ||
494 | } | 407 | } |
495 | 408 | ||
496 | return addr; | 409 | return addr; |
@@ -517,8 +430,6 @@ static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn, | |||
517 | } | 430 | } |
518 | 431 | ||
519 | static struct pci_ops tegra_pcie_ops = { | 432 | 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, | 433 | .map_bus = tegra_pcie_map_bus, |
523 | .read = tegra_pcie_config_read, | 434 | .read = tegra_pcie_config_read, |
524 | .write = tegra_pcie_config_write, | 435 | .write = tegra_pcie_config_write, |
@@ -661,8 +572,7 @@ static int tegra_pcie_request_resources(struct tegra_pcie *pcie) | |||
661 | 572 | ||
662 | static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) | 573 | static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) |
663 | { | 574 | { |
664 | struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus); | 575 | struct tegra_pcie *pcie = pdev->bus->sysdata; |
665 | struct tegra_pcie *pcie = pci_host_bridge_priv(host); | ||
666 | int irq; | 576 | int irq; |
667 | 577 | ||
668 | tegra_cpuidle_pcie_irqs_in_use(); | 578 | tegra_cpuidle_pcie_irqs_in_use(); |
@@ -743,12 +653,9 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) | |||
743 | u32 fpci_bar, size, axi_address; | 653 | u32 fpci_bar, size, axi_address; |
744 | 654 | ||
745 | /* Bar 0: type 1 extended configuration space */ | 655 | /* Bar 0: type 1 extended configuration space */ |
746 | fpci_bar = 0xfe100000; | 656 | size = resource_size(&pcie->cs); |
747 | size = resource_size(pcie->cs); | 657 | 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); | 658 | afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ); |
751 | afi_writel(pcie, fpci_bar, AFI_FPCI_BAR0); | ||
752 | 659 | ||
753 | /* Bar 1: downstream IO bar */ | 660 | /* Bar 1: downstream IO bar */ |
754 | fpci_bar = 0xfdfc0000; | 661 | fpci_bar = 0xfdfc0000; |
@@ -1353,10 +1260,14 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) | |||
1353 | goto poweroff; | 1260 | goto poweroff; |
1354 | } | 1261 | } |
1355 | 1262 | ||
1356 | pcie->cs = devm_request_mem_region(dev, res->start, | 1263 | pcie->cs = *res; |
1357 | resource_size(res), res->name); | 1264 | |
1358 | if (!pcie->cs) { | 1265 | /* constrain configuration space to 4 KiB */ |
1359 | err = -EADDRNOTAVAIL; | 1266 | pcie->cs.end = pcie->cs.start + SZ_4K - 1; |
1267 | |||
1268 | pcie->cfg = devm_ioremap_resource(dev, &pcie->cs); | ||
1269 | if (IS_ERR(pcie->cfg)) { | ||
1270 | err = PTR_ERR(pcie->cfg); | ||
1360 | goto poweroff; | 1271 | goto poweroff; |
1361 | } | 1272 | } |
1362 | 1273 | ||
@@ -2345,9 +2256,9 @@ static int tegra_pcie_probe(struct platform_device *pdev) | |||
2345 | return -ENOMEM; | 2256 | return -ENOMEM; |
2346 | 2257 | ||
2347 | pcie = pci_host_bridge_priv(host); | 2258 | pcie = pci_host_bridge_priv(host); |
2259 | host->sysdata = pcie; | ||
2348 | 2260 | ||
2349 | pcie->soc = of_device_get_match_data(dev); | 2261 | pcie->soc = of_device_get_match_data(dev); |
2350 | INIT_LIST_HEAD(&pcie->buses); | ||
2351 | INIT_LIST_HEAD(&pcie->ports); | 2262 | INIT_LIST_HEAD(&pcie->ports); |
2352 | pcie->dev = dev; | 2263 | pcie->dev = dev; |
2353 | 2264 | ||