aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2014-07-17 05:00:41 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-07-22 17:26:24 -0400
commitf4c55c5a3f7f68c06cc559ed7af8b2d017cbb0a7 (patch)
tree5ee2b55f134ff11382ce97459d1291939b645aa2
parent4dd964df36d0e548e1806ec2ec275b62d4dc46e8 (diff)
PCI: designware: Program ATU with untranslated address
In DRA7, the CPU sees 32-bit addresses, but the PCIe controller can see only 28-bit addresses. So whenever the CPU issues a read/write request, the 4 most significant bits are used by L3 to determine the target controller. For example, the CPU reserves [mem 0x20000000-0x2fffffff] for the PCIe controller but the PCIe controller will see only [0x00000000-0x0fffffff]. For programming the outbound translation window the *base* should be programmed as 0x00000000. Whenever we try to write to, e.g., 0x20000000, it will be translated to whatever we have programmed in the translation window with base as 0x00000000. This is needed when the dt node is modelled something like this: axi { compatible = "simple-bus"; #size-cells = <1>; #address-cells = <1>; ranges = <0x0 0x20000000 0x10000000 // 28-bit bus 0x51000000 0x51000000 0x3000>; pcie@51000000 { reg = <0x1000 0x2000>, <0x51002000 0x14c>, <0x51000000 0x2000>; reg-names = "config", "ti_conf", "rc_dbics"; #address-cells = <3>; #size-cells = <2>; ranges = <0x81000000 0 0 0x03000 0 0x00010000 0x82000000 0 0x20013000 0x13000 0 0xffed000>; }; }; Here the CPU address for configuration space is 0x20013000 and the controller address for configuration space is 0x13000. The controller address should be used while programming the ATU (in order for translation to happen properly in DRA7xx). Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Mohit Kumar <mohit.kumar@st.com> Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Cc: Jingoo Han <jg1.han@samsung.com> Cc: Marek Vasut <marex@denx.de> Cc: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--drivers/pci/host/pcie-designware.c55
-rw-r--r--drivers/pci/host/pcie-designware.h4
2 files changed, 45 insertions, 14 deletions
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 0b7b4558bcfd..8aab1d696cb0 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -401,8 +401,15 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
401 struct of_pci_range range; 401 struct of_pci_range range;
402 struct of_pci_range_parser parser; 402 struct of_pci_range_parser parser;
403 struct resource *cfg_res; 403 struct resource *cfg_res;
404 u32 val; 404 u32 val, na, ns;
405 int i; 405 const __be32 *addrp;
406 int i, index;
407
408 /* Find the address cell size and the number of cells in order to get
409 * the untranslated address.
410 */
411 of_property_read_u32(np, "#address-cells", &na);
412 ns = of_n_size_cells(np);
406 413
407 cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); 414 cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
408 if (cfg_res) { 415 if (cfg_res) {
@@ -410,6 +417,12 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
410 pp->config.cfg1_size = resource_size(cfg_res)/2; 417 pp->config.cfg1_size = resource_size(cfg_res)/2;
411 pp->cfg0_base = cfg_res->start; 418 pp->cfg0_base = cfg_res->start;
412 pp->cfg1_base = cfg_res->start + pp->config.cfg0_size; 419 pp->cfg1_base = cfg_res->start + pp->config.cfg0_size;
420
421 /* Find the untranslated configuration space address */
422 index = of_property_match_string(np, "reg-names", "config");
423 addrp = of_get_address(np, index, false, false);
424 pp->cfg0_mod_base = of_read_number(addrp, ns);
425 pp->cfg1_mod_base = pp->cfg0_mod_base + pp->config.cfg0_size;
413 } else { 426 } else {
414 dev_err(pp->dev, "missing *config* reg space\n"); 427 dev_err(pp->dev, "missing *config* reg space\n");
415 } 428 }
@@ -435,12 +448,20 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
435 pp->config.io_size = resource_size(&pp->io); 448 pp->config.io_size = resource_size(&pp->io);
436 pp->config.io_bus_addr = range.pci_addr; 449 pp->config.io_bus_addr = range.pci_addr;
437 pp->io_base = range.cpu_addr; 450 pp->io_base = range.cpu_addr;
451
452 /* Find the untranslated IO space address */
453 pp->io_mod_base = of_read_number(parser.range -
454 parser.np + na, ns);
438 } 455 }
439 if (restype == IORESOURCE_MEM) { 456 if (restype == IORESOURCE_MEM) {
440 of_pci_range_to_resource(&range, np, &pp->mem); 457 of_pci_range_to_resource(&range, np, &pp->mem);
441 pp->mem.name = "MEM"; 458 pp->mem.name = "MEM";
442 pp->config.mem_size = resource_size(&pp->mem); 459 pp->config.mem_size = resource_size(&pp->mem);
443 pp->config.mem_bus_addr = range.pci_addr; 460 pp->config.mem_bus_addr = range.pci_addr;
461
462 /* Find the untranslated MEM space address */
463 pp->mem_mod_base = of_read_number(parser.range -
464 parser.np + na, ns);
444 } 465 }
445 if (restype == 0) { 466 if (restype == 0) {
446 of_pci_range_to_resource(&range, np, &pp->cfg); 467 of_pci_range_to_resource(&range, np, &pp->cfg);
@@ -448,6 +469,12 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
448 pp->config.cfg1_size = resource_size(&pp->cfg)/2; 469 pp->config.cfg1_size = resource_size(&pp->cfg)/2;
449 pp->cfg0_base = pp->cfg.start; 470 pp->cfg0_base = pp->cfg.start;
450 pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size; 471 pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
472
473 /* Find the untranslated configuration space address */
474 pp->cfg0_mod_base = of_read_number(parser.range -
475 parser.np + na, ns);
476 pp->cfg1_mod_base = pp->cfg0_mod_base +
477 pp->config.cfg0_size;
451 } 478 }
452 } 479 }
453 480
@@ -522,9 +549,9 @@ static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
522 /* Program viewport 0 : OUTBOUND : CFG0 */ 549 /* Program viewport 0 : OUTBOUND : CFG0 */
523 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, 550 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
524 PCIE_ATU_VIEWPORT); 551 PCIE_ATU_VIEWPORT);
525 dw_pcie_writel_rc(pp, pp->cfg0_base, PCIE_ATU_LOWER_BASE); 552 dw_pcie_writel_rc(pp, pp->cfg0_mod_base, PCIE_ATU_LOWER_BASE);
526 dw_pcie_writel_rc(pp, (pp->cfg0_base >> 32), PCIE_ATU_UPPER_BASE); 553 dw_pcie_writel_rc(pp, (pp->cfg0_mod_base >> 32), PCIE_ATU_UPPER_BASE);
527 dw_pcie_writel_rc(pp, pp->cfg0_base + pp->config.cfg0_size - 1, 554 dw_pcie_writel_rc(pp, pp->cfg0_mod_base + pp->config.cfg0_size - 1,
528 PCIE_ATU_LIMIT); 555 PCIE_ATU_LIMIT);
529 dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); 556 dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
530 dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); 557 dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
@@ -538,9 +565,9 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
538 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, 565 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
539 PCIE_ATU_VIEWPORT); 566 PCIE_ATU_VIEWPORT);
540 dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); 567 dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
541 dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); 568 dw_pcie_writel_rc(pp, pp->cfg1_mod_base, PCIE_ATU_LOWER_BASE);
542 dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); 569 dw_pcie_writel_rc(pp, (pp->cfg1_mod_base >> 32), PCIE_ATU_UPPER_BASE);
543 dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, 570 dw_pcie_writel_rc(pp, pp->cfg1_mod_base + pp->config.cfg1_size - 1,
544 PCIE_ATU_LIMIT); 571 PCIE_ATU_LIMIT);
545 dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); 572 dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
546 dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); 573 dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
@@ -553,9 +580,9 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
553 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, 580 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
554 PCIE_ATU_VIEWPORT); 581 PCIE_ATU_VIEWPORT);
555 dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); 582 dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
556 dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); 583 dw_pcie_writel_rc(pp, pp->mem_mod_base, PCIE_ATU_LOWER_BASE);
557 dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); 584 dw_pcie_writel_rc(pp, (pp->mem_mod_base >> 32), PCIE_ATU_UPPER_BASE);
558 dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, 585 dw_pcie_writel_rc(pp, pp->mem_mod_base + pp->config.mem_size - 1,
559 PCIE_ATU_LIMIT); 586 PCIE_ATU_LIMIT);
560 dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); 587 dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);
561 dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), 588 dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),
@@ -569,9 +596,9 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
569 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, 596 dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
570 PCIE_ATU_VIEWPORT); 597 PCIE_ATU_VIEWPORT);
571 dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); 598 dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
572 dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); 599 dw_pcie_writel_rc(pp, pp->io_mod_base, PCIE_ATU_LOWER_BASE);
573 dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); 600 dw_pcie_writel_rc(pp, (pp->io_mod_base >> 32), PCIE_ATU_UPPER_BASE);
574 dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, 601 dw_pcie_writel_rc(pp, pp->io_mod_base + pp->config.io_size - 1,
575 PCIE_ATU_LIMIT); 602 PCIE_ATU_LIMIT);
576 dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); 603 dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);
577 dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), 604 dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index 77f592faa7bf..add652717a60 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -36,11 +36,15 @@ struct pcie_port {
36 u8 root_bus_nr; 36 u8 root_bus_nr;
37 void __iomem *dbi_base; 37 void __iomem *dbi_base;
38 u64 cfg0_base; 38 u64 cfg0_base;
39 u64 cfg0_mod_base;
39 void __iomem *va_cfg0_base; 40 void __iomem *va_cfg0_base;
40 u64 cfg1_base; 41 u64 cfg1_base;
42 u64 cfg1_mod_base;
41 void __iomem *va_cfg1_base; 43 void __iomem *va_cfg1_base;
42 u64 io_base; 44 u64 io_base;
45 u64 io_mod_base;
43 u64 mem_base; 46 u64 mem_base;
47 u64 mem_mod_base;
44 struct resource cfg; 48 struct resource cfg;
45 struct resource io; 49 struct resource io;
46 struct resource mem; 50 struct resource mem;