[U-Boot] [PATCH] pci: tegra: fix DM conversion issues on Tegra20

From: Stephen Warren swarren@nvidia.com
Tegra20's PCIe controller has a couple of quirks. There are workarounds in the driver for these, but they don't work after the DM conversion:
1) The PCI_CLASS value is wrong in HW.
This is worked around in pci_tegra_read_config() by patching up the value read from that register. Pre-DM, the PCIe core always read this via a 16-bit access to the 16-bit offset 0xa. With DM, 32-bit accesses are used, so we need to check for offset 0x8 instead. Mask the offset value back to 32-bit alignment to make this work in all cases.
2) Accessing devices other than dev 1 causes a data abort.
Pre-DM, this was worked around in pci_skip_dev(), which the PCIe core code called during enumeration while iterating over a bus. The DM PCIe core doesn't use this function. Instead, enhance tegra_pcie_conf_address() to validate the bdf being accessed, and refuse to access invalid devices. Since pci_skip_dev() isn't used, delete it.
I've also validated that both these WARs are only needed for Tegra20, by testing on Tegra30/Cardhu and Tegra124/Jetson TKx. So, compile them in conditionally.
Fixes: e81ca88451cf ("dm: tegra: pci: Convert tegra boards to driver model for PCI") Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/pci/pci_tegra.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 5dadf6fa62a7..c5b04daffa65 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -275,12 +275,17 @@ static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf, return 0; } } + return -EFAULT; } else { +#ifdef CONFIG_TEGRA20 + unsigned int dev = PCI_DEV(bdf); + if (dev != 0) + return -EFAULT; +#endif + *address = pcie->cs.start + tegra_pcie_conf_offset(bdf, where); return 0; } - - return -EFAULT; }
static int pci_tegra_read_config(struct udevice *bus, pci_dev_t bdf, @@ -299,13 +304,15 @@ static int pci_tegra_read_config(struct udevice *bus, pci_dev_t bdf,
value = readl(address);
+#ifdef CONFIG_TEGRA20 /* fixup root port class */ if (PCI_BUS(bdf) == 0) { - if (offset == PCI_CLASS_REVISION) { + if ((offset & ~3) == PCI_CLASS_REVISION) { value &= ~0x00ff0000; value |= PCI_CLASS_BRIDGE_PCI << 16; } } +#endif
done: *valuep = pci_conv_32_to_size(value, offset, size); @@ -1041,11 +1048,3 @@ U_BOOT_DRIVER(pci_tegra) = { .probe = pci_tegra_probe, .priv_auto_alloc_size = sizeof(struct tegra_pcie), }; - -int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) -{ - if (PCI_BUS(dev) != 0 && PCI_DEV(dev) > 0) - return 1; - - return 0; -}

On Wed, Apr 20, 2016 at 03:46:50PM -0600, Stephen Warren wrote:
From: Stephen Warren swarren@nvidia.com
Tegra20's PCIe controller has a couple of quirks. There are workarounds in the driver for these, but they don't work after the DM conversion:
- The PCI_CLASS value is wrong in HW.
This is worked around in pci_tegra_read_config() by patching up the value read from that register. Pre-DM, the PCIe core always read this via a 16-bit access to the 16-bit offset 0xa. With DM, 32-bit accesses are used, so we need to check for offset 0x8 instead. Mask the offset value back to 32-bit alignment to make this work in all cases.
- Accessing devices other than dev 1 causes a data abort.
Pre-DM, this was worked around in pci_skip_dev(), which the PCIe core code called during enumeration while iterating over a bus. The DM PCIe core doesn't use this function. Instead, enhance tegra_pcie_conf_address() to validate the bdf being accessed, and refuse to access invalid devices. Since pci_skip_dev() isn't used, delete it.
I've also validated that both these WARs are only needed for Tegra20, by testing on Tegra30/Cardhu and Tegra124/Jetson TKx. So, compile them in conditionally.
Fixes: e81ca88451cf ("dm: tegra: pci: Convert tegra boards to driver model for PCI") Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/pci/pci_tegra.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
Neat:
Reviewed-by: Thierry Reding treding@nvidia.com

Hi Stephen,
On 20 April 2016 at 15:46, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Tegra20's PCIe controller has a couple of quirks. There are workarounds in the driver for these, but they don't work after the DM conversion:
- The PCI_CLASS value is wrong in HW.
This is worked around in pci_tegra_read_config() by patching up the value read from that register. Pre-DM, the PCIe core always read this via a 16-bit access to the 16-bit offset 0xa. With DM, 32-bit accesses are used, so we need to check for offset 0x8 instead. Mask the offset value back to 32-bit alignment to make this work in all cases.
- Accessing devices other than dev 1 causes a data abort.
Pre-DM, this was worked around in pci_skip_dev(), which the PCIe core code called during enumeration while iterating over a bus. The DM PCIe core doesn't use this function. Instead, enhance tegra_pcie_conf_address() to validate the bdf being accessed, and refuse to access invalid devices. Since pci_skip_dev() isn't used, delete it.
I've also validated that both these WARs are only needed for Tegra20, by testing on Tegra30/Cardhu and Tegra124/Jetson TKx. So, compile them in conditionally.
Fixes: e81ca88451cf ("dm: tegra: pci: Convert tegra boards to driver model for PCI") Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/pci/pci_tegra.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
Nice patch.
Reviewed-by: Simon Glass sjg@chromium.org
- Simon

On 04/20/2016 03:46 PM, Stephen Warren wrote:
From: Stephen Warren swarren@nvidia.com
Tegra20's PCIe controller has a couple of quirks. There are workarounds in the driver for these, but they don't work after the DM conversion:
- The PCI_CLASS value is wrong in HW.
This is worked around in pci_tegra_read_config() by patching up the value read from that register. Pre-DM, the PCIe core always read this via a 16-bit access to the 16-bit offset 0xa. With DM, 32-bit accesses are used, so we need to check for offset 0x8 instead. Mask the offset value back to 32-bit alignment to make this work in all cases.
- Accessing devices other than dev 1 causes a data abort.
Pre-DM, this was worked around in pci_skip_dev(), which the PCIe core code called during enumeration while iterating over a bus. The DM PCIe core doesn't use this function. Instead, enhance tegra_pcie_conf_address() to validate the bdf being accessed, and refuse to access invalid devices. Since pci_skip_dev() isn't used, delete it.
I've also validated that both these WARs are only needed for Tegra20, by testing on Tegra30/Cardhu and Tegra124/Jetson TKx. So, compile them in conditionally.
Fixes: e81ca88451cf ("dm: tegra: pci: Convert tegra boards to driver model for PCI") Signed-off-by: Stephen Warren swarren@nvidia.com
TomW, I'd like to make sure this one gets into the upcoming release, since it's a functional bug-fix.

I'll add it to u-boot-tegra/master for the next PR.
-----Original Message----- From: Stephen Warren [mailto:swarren@wwwdotorg.org] Sent: Wednesday, May 04, 2016 12:00 PM To: Tom Warren TWarren@nvidia.com Cc: u-boot@lists.denx.de; Simon Glass sjg@chromium.org; Stephen Warren swarren@nvidia.com Subject: Re: [U-Boot] [PATCH] pci: tegra: fix DM conversion issues on Tegra20
On 04/20/2016 03:46 PM, Stephen Warren wrote:
From: Stephen Warren swarren@nvidia.com
Tegra20's PCIe controller has a couple of quirks. There are workarounds in the driver for these, but they don't work after the DM
conversion:
- The PCI_CLASS value is wrong in HW.
This is worked around in pci_tegra_read_config() by patching up the value read from that register. Pre-DM, the PCIe core always read this via a 16-bit access to the 16-bit offset 0xa. With DM, 32-bit accesses are used, so we need to check for offset 0x8 instead. Mask the offset value back to 32-bit alignment to make this work in all cases.
- Accessing devices other than dev 1 causes a data abort.
Pre-DM, this was worked around in pci_skip_dev(), which the PCIe core code called during enumeration while iterating over a bus. The DM PCIe core doesn't use this function. Instead, enhance tegra_pcie_conf_address() to validate the bdf being accessed, and refuse to
access invalid devices.
Since pci_skip_dev() isn't used, delete it.
I've also validated that both these WARs are only needed for Tegra20, by testing on Tegra30/Cardhu and Tegra124/Jetson TKx. So, compile them in conditionally.
Fixes: e81ca88451cf ("dm: tegra: pci: Convert tegra boards to driver model for PCI") Signed-off-by: Stephen Warren swarren@nvidia.com
TomW, I'd like to make sure this one gets into the upcoming release, since it's a functional bug-fix.
----------------------------------------------------------------------------------- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. -----------------------------------------------------------------------------------
participants (4)
-
Simon Glass
-
Stephen Warren
-
Thierry Reding
-
Tom Warren