[U-Boot] [PATCH 1/5] pci: tegra: clip RAM size to 32-bits

From: Stephen Warren swarren@nvidia.com
Tegra peripherals can generally access a 32-bit physical address space, and I believe this applies to PCIe. Clip the PCI region that refers to DRAM so it fits into 32-bits to avoid issues.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/pci/pci_tegra.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index ebb959f1f31f..357e7793b4ff 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -997,6 +997,14 @@ static const struct tegra_pcie_soc tegra124_pcie_soc = { static int process_nodes(const void *fdt, int nodes[], unsigned int count) { unsigned int i; + uint64_t dram_end; + uint32_t pci_dram_size; + + /* Clip PCI-accessible DRAM to 32-bits */ + dram_end = ((uint64_t)NV_PA_SDRAM_BASE) + gd->ram_size; + if (dram_end > 0x100000000) + dram_end = 0x100000000; + pci_dram_size = dram_end - NV_PA_SDRAM_BASE;
for (i = 0; i < count; i++) { const struct tegra_pcie_soc *soc; @@ -1069,7 +1077,7 @@ static int process_nodes(const void *fdt, int nodes[], unsigned int count) pcie->hose.last_busno = 0;
pci_set_region(&pcie->hose.regions[0], NV_PA_SDRAM_BASE, - NV_PA_SDRAM_BASE, gd->ram_size, + NV_PA_SDRAM_BASE, pci_dram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
pci_set_region(&pcie->hose.regions[1], pcie->io.start,

From: Stephen Warren swarren@nvidia.com
The number of cells used by each entry in the DT ranges property is determined by the #address-cells/#size-cells properties. Fix the code to respect this.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/pci/pci_tegra.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 357e7793b4ff..c1103661b0f2 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -406,9 +406,34 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes, static int tegra_pcie_parse_dt_ranges(const void *fdt, int node, struct tegra_pcie *pcie) { + int parent, na_parent, na_pcie, ns_pcie; const u32 *ptr, *end; int len;
+ parent = fdt_parent_offset(fdt, node); + if (parent < 0) { + error("Can't find PCI parent node\n"); + return -FDT_ERR_NOTFOUND; + } + + na_parent = fdt_address_cells(fdt, parent); + if (na_parent < 1) { + error("bad #address-cells for PCIE parent\n"); + return -FDT_ERR_NOTFOUND; + } + + na_pcie = fdt_address_cells(fdt, node); + if (na_pcie < 1) { + error("bad #address-cells for PCIE\n"); + return -FDT_ERR_NOTFOUND; + } + + ns_pcie = fdt_size_cells(fdt, node); + if (ns_pcie < 1) { + error("bad #size-cells for PCIE\n"); + return -FDT_ERR_NOTFOUND; + } + ptr = fdt_getprop(fdt, node, "ranges", &len); if (!ptr) { error("missing "ranges" property"); @@ -437,11 +462,13 @@ static int tegra_pcie_parse_dt_ranges(const void *fdt, int node, }
if (res) { - res->start = fdt32_to_cpu(ptr[3]); - res->end = res->start + fdt32_to_cpu(ptr[5]); + int start_low = na_pcie + (na_parent - 1); + int size_low = na_pcie + na_parent + (ns_pcie - 1); + res->start = fdt32_to_cpu(ptr[start_low]); + res->end = res->start + fdt32_to_cpu(ptr[size_low]); }
- ptr += 3 + 1 + 2; + ptr += na_pcie + na_parent + ns_pcie; }
debug("PCI regions:\n");

From: Stephen Warren swarren@nvidia.com
Tegra210's PCIe controller has a bug that requires the PCA (performance counter) feature to be enabled. If this isn't done, accesses to device configuration space will hang the chip for tens of seconds. Implement the workaround.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/pci/pci_tegra.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index c1103661b0f2..177d48dde477 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -166,6 +166,9 @@ DECLARE_GLOBAL_DATA_PTR; #define RP_VEND_XP 0x00000F00 #define RP_VEND_XP_DL_UP (1 << 30)
+#define RP_VEND_CTL2 0x00000FA8 +#define RP_VEND_CTL2_PCA_ENABLE (1 << 7) + #define RP_PRIV_MISC 0x00000FE0 #define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0) #define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0) @@ -194,6 +197,7 @@ struct tegra_pcie_soc { bool has_pex_bias_ctrl; bool has_cml_clk; bool has_gen2; + bool force_pca_enable; };
struct tegra_pcie { @@ -887,6 +891,7 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
static void tegra_pcie_port_enable(struct tegra_pcie_port *port) { + const struct tegra_pcie_soc *soc = port->pcie->soc; unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); unsigned long value;
@@ -902,6 +907,12 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port) afi_writel(port->pcie, value, ctrl);
tegra_pcie_port_reset(port); + + if (soc->force_pca_enable) { + value = rp_readl(port, RP_VEND_CTL2); + value |= RP_VEND_CTL2_PCA_ENABLE; + rp_writel(port, value, RP_VEND_CTL2); + } }
static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port) @@ -999,6 +1010,7 @@ static const struct tegra_pcie_soc tegra20_pcie_soc = { .has_pex_bias_ctrl = false, .has_cml_clk = false, .has_gen2 = false, + .force_pca_enable = false, };
static const struct tegra_pcie_soc tegra30_pcie_soc = { @@ -1009,6 +1021,7 @@ static const struct tegra_pcie_soc tegra30_pcie_soc = { .has_pex_bias_ctrl = true, .has_cml_clk = true, .has_gen2 = false, + .force_pca_enable = false, };
static const struct tegra_pcie_soc tegra124_pcie_soc = { @@ -1019,6 +1032,7 @@ static const struct tegra_pcie_soc tegra124_pcie_soc = { .has_pex_bias_ctrl = true, .has_cml_clk = true, .has_gen2 = true, + .force_pca_enable = false, };
static int process_nodes(const void *fdt, int nodes[], unsigned int count)

From: Stephen Warren swarren@nvidia.com
The board PCI setup code may control regulators that are required simply to bring up the PCI controller itself (or PLLs, IOs, ... it uses). Move the call to this function earlier so that all board-provided resources are ready early enough for everything to work.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/pci/pci_tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 177d48dde477..bf078b3369ba 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -618,8 +618,6 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) return err; }
- tegra_pcie_board_init(); - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, PERIPH_ID_PCIE); if (err < 0) { @@ -1164,6 +1162,8 @@ void pci_init_board(void) const void *fdt = gd->fdt_blob; int count, nodes[1];
+ tegra_pcie_board_init(); + count = fdtdec_find_aliases_for_id(fdt, "pcie-controller", COMPAT_NVIDIA_TEGRA124_PCIE, nodes, ARRAY_SIZE(nodes));

Hi Stephen,
On 6 October 2015 at 00:00, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
The board PCI setup code may control regulators that are required simply to bring up the PCI controller itself (or PLLs, IOs, ... it uses). Move the call to this function earlier so that all board-provided resources are ready early enough for everything to work.
Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/pci/pci_tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 177d48dde477..bf078b3369ba 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -618,8 +618,6 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) return err; }
tegra_pcie_board_init();
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, PERIPH_ID_PCIE); if (err < 0) {
@@ -1164,6 +1162,8 @@ void pci_init_board(void) const void *fdt = gd->fdt_blob; int count, nodes[1];
tegra_pcie_board_init();
count = fdtdec_find_aliases_for_id(fdt, "pcie-controller", COMPAT_NVIDIA_TEGRA124_PCIE, nodes, ARRAY_SIZE(nodes));
-- 1.9.1
It might be a good time to move Tegra to driver model for PCI.
Regards, Simon

Hi Stephen,
On 6 October 2015 at 09:14, Simon Glass sjg@chromium.org wrote:
Hi Stephen,
On 6 October 2015 at 00:00, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
The board PCI setup code may control regulators that are required simply to bring up the PCI controller itself (or PLLs, IOs, ... it uses). Move the call to this function earlier so that all board-provided resources are ready early enough for everything to work.
Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/pci/pci_tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 177d48dde477..bf078b3369ba 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -618,8 +618,6 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) return err; }
tegra_pcie_board_init();
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, PERIPH_ID_PCIE); if (err < 0) {
@@ -1164,6 +1162,8 @@ void pci_init_board(void) const void *fdt = gd->fdt_blob; int count, nodes[1];
tegra_pcie_board_init();
count = fdtdec_find_aliases_for_id(fdt, "pcie-controller", COMPAT_NVIDIA_TEGRA124_PCIE, nodes, ARRAY_SIZE(nodes));
-- 1.9.1
It might be a good time to move Tegra to driver model for PCI.
I had a look at this and will send some patches.
Regards, Simon

From: Stephen Warren swarren@nvidia.com
This needs a separate compatible value from Tegra124 since the new HW version has bugs that would prevent a driver for previous HW versions from operating at all.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/pci/pci_tegra.c | 22 ++++++++++++++++++++++ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 3 files changed, 24 insertions(+)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index bf078b3369ba..690896f9f571 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -387,6 +387,7 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes, break;
case COMPAT_NVIDIA_TEGRA124_PCIE: + case COMPAT_NVIDIA_TEGRA210_PCIE: switch (lanes) { case 0x0000104: debug("4x1, 1x1 configuration\n"); @@ -1033,6 +1034,17 @@ static const struct tegra_pcie_soc tegra124_pcie_soc = { .force_pca_enable = false, };
+static const struct tegra_pcie_soc tegra210_pcie_soc = { + .num_ports = 2, + .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, + .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .has_pex_clkreq_en = true, + .has_pex_bias_ctrl = true, + .has_cml_clk = true, + .has_gen2 = true, + .force_pca_enable = true, +}; + static int process_nodes(const void *fdt, int nodes[], unsigned int count) { unsigned int i; @@ -1068,6 +1080,10 @@ static int process_nodes(const void *fdt, int nodes[], unsigned int count) soc = &tegra124_pcie_soc; break;
+ case COMPAT_NVIDIA_TEGRA210_PCIE: + soc = &tegra210_pcie_soc; + break; + default: error("unsupported compatible: %s", fdtdec_get_compatible(id)); @@ -1165,6 +1181,12 @@ void pci_init_board(void) tegra_pcie_board_init();
count = fdtdec_find_aliases_for_id(fdt, "pcie-controller", + COMPAT_NVIDIA_TEGRA210_PCIE, + nodes, ARRAY_SIZE(nodes)); + if (process_nodes(fdt, nodes, count)) + return; + + count = fdtdec_find_aliases_for_id(fdt, "pcie-controller", COMPAT_NVIDIA_TEGRA124_PCIE, nodes, ARRAY_SIZE(nodes)); if (process_nodes(fdt, nodes, count)) diff --git a/include/fdtdec.h b/include/fdtdec.h index 2de6dda04c5d..b99eda5497ae 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -130,6 +130,7 @@ enum fdt_compat_id { COMPAT_NVIDIA_TEGRA30_SDMMC, /* Tegra30 SDMMC controller */ COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra20 SDMMC controller */ COMPAT_NVIDIA_TEGRA124_PCIE, /* Tegra 124 PCIe controller */ + COMPAT_NVIDIA_TEGRA210_PCIE, /* Tegra 210 PCIe controller */ COMPAT_NVIDIA_TEGRA30_PCIE, /* Tegra 30 PCIe controller */ COMPAT_NVIDIA_TEGRA20_PCIE, /* Tegra 20 PCIe controller */ COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL, diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 275971d40096..5ff5b37e4469 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -36,6 +36,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"), COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"), + COMPAT(NVIDIA_TEGRA210_PCIE, "nvidia,tegra210-pcie"), COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"), COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"), COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),

On 10/05/2015 05:00 PM, Stephen Warren wrote:
From: Stephen Warren swarren@nvidia.com
Tegra peripherals can generally access a 32-bit physical address space, and I believe this applies to PCIe. Clip the PCI region that refers to DRAM so it fits into 32-bits to avoid issues.
Tom,
Is this patch OK? I assume it can be applied now the merge window is over?
participants (2)
-
Simon Glass
-
Stephen Warren