From 8e42e9842066d3b7f4f7f48af08ee8e4f636bdca Mon Sep 17 00:00:00 2001 From: Manikanta Maddireddy Date: Thu, 19 Jul 2018 22:30:25 +0530 Subject: [PATCH] PCI: tegra: Convert WRAP transactions to increment burst AFI module doesn't support WRAP transactions in Tegra. WRAP instructions from CPU targeting PCIe BAR memory can cause data corruption. This can happen if PCIe memory is marked as normal cacheable or GRE device. Program mselect register to convert WRAP transactions to increment burst for slave PCIe. bug 200353330 bug 200420606 Change-Id: I867da85eb63332708bc294238e30ad99a71f345d Signed-off-by: Manikanta Maddireddy Reviewed-on: https://git-master.nvidia.com/r/1786561 (cherry picked from commit b345cfae7b7633a3a52e0f2a659baf44feee1466) Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407869 Reviewed-by: automaticguardword Reviewed-by: Bitan Biswas Reviewed-by: mobile promotions Tested-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/pci/controller/pci-tegra.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 936e3479ad63..77003e7abf4c 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -310,6 +310,7 @@ struct tegra_pcie_soc { bool program_deskew_time; bool update_fc_timer; bool has_cache_bars; + bool enable_wrap; struct { struct { u32 rp_ectl_1_r1; @@ -671,6 +672,26 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port) writel(value, port->base + RP_ECTL_6_R2); } +static void tegra_pcie_enable_wrap(void) +{ + u32 val; + void __iomem *msel_base; + +#define MSELECT_CONFIG_BASE 0x50060000 +#define MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1 BIT(28) +#define MSELECT_CONFIG_ERR_RESP_EN_SLAVE1 BIT(24) + + /* Config MSELECT to support wrap trans for normal NC & GRE mapping */ + msel_base = ioremap(MSELECT_CONFIG_BASE, 4); + val = readl(msel_base); + /* Enable WRAP_TO_INCR_SLAVE1 */ + val |= MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1; + /* Disable ERR_RESP_EN_SLAVE1 */ + val &= ~MSELECT_CONFIG_ERR_RESP_EN_SLAVE1; + writel(val, msel_base); + iounmap(msel_base); +} + static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port) { const struct tegra_pcie_soc *soc = port->pcie->soc; @@ -705,6 +726,9 @@ static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port) value &= ~PCI_EXP_LNKSTA_CLS; value |= PCI_EXP_LNKSTA_CLS_2_5GB; writel(value, port->base + RP_LINK_CONTROL_STATUS_2); + + if (soc->enable_wrap) + tegra_pcie_enable_wrap(); } static void tegra_pcie_port_enable(struct tegra_pcie_port *port) @@ -2462,6 +2486,7 @@ static const struct tegra_pcie_soc tegra20_pcie = { .program_deskew_time = false, .update_fc_timer = false, .has_cache_bars = true, + .enable_wrap = false, .ectl.enable = false, }; @@ -2491,6 +2516,7 @@ static const struct tegra_pcie_soc tegra30_pcie = { .program_deskew_time = false, .update_fc_timer = false, .has_cache_bars = false, + .enable_wrap = false, .ectl.enable = false, }; @@ -2512,6 +2538,7 @@ static const struct tegra_pcie_soc tegra124_pcie = { .program_deskew_time = false, .update_fc_timer = false, .has_cache_bars = false, + .enable_wrap = false, .ectl.enable = false, }; @@ -2535,6 +2562,7 @@ static const struct tegra_pcie_soc tegra210_pcie = { .program_deskew_time = true, .update_fc_timer = true, .has_cache_bars = false, + .enable_wrap = true, .ectl = { .regs = { .rp_ectl_1_r1 = 0x0000001f, @@ -2614,6 +2642,7 @@ static const struct tegra_pcie_soc tegra186_pcie = { .program_deskew_time = false, .update_fc_timer = false, .has_cache_bars = false, + .enable_wrap = false, .ectl.enable = false, };