Commit ab5fe4f4 authored by Kishon Vijay Abraham I's avatar Kishon Vijay Abraham I Committed by Bjorn Helgaas

PCI: dra7xx: Add support to force RC to work in GEN1 mode

PCIe in AM57x/DRA7x devices is by default configured to work in GEN2 mode.
However there may be situations when working in GEN1 mode is desired.  One
example is limitation i925 (PCIe GEN2 mode not supported at junction
temperatures < 0C).

Add support to force Root Complex to work in GEN1 mode if so desired, but
don't force GEN1 mode on any board just yet.
Signed-off-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 602d38bc
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_pci.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -63,11 +64,14 @@ ...@@ -63,11 +64,14 @@
#define LINK_UP BIT(16) #define LINK_UP BIT(16)
#define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF #define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF
#define EXP_CAP_ID_OFFSET 0x70
struct dra7xx_pcie { struct dra7xx_pcie {
struct pcie_port pp; struct pcie_port pp;
void __iomem *base; /* DT ti_conf */ void __iomem *base; /* DT ti_conf */
int phy_count; /* DT phy-names count */ int phy_count; /* DT phy-names count */
struct phy **phy; struct phy **phy;
int link_gen;
}; };
#define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp) #define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp)
...@@ -96,12 +100,33 @@ static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx) ...@@ -96,12 +100,33 @@ static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx)
struct pcie_port *pp = &dra7xx->pp; struct pcie_port *pp = &dra7xx->pp;
struct device *dev = pp->dev; struct device *dev = pp->dev;
u32 reg; u32 reg;
u32 exp_cap_off = EXP_CAP_ID_OFFSET;
if (dw_pcie_link_up(pp)) { if (dw_pcie_link_up(pp)) {
dev_err(dev, "link is already up\n"); dev_err(dev, "link is already up\n");
return 0; return 0;
} }
if (dra7xx->link_gen == 1) {
dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCAP,
4, &reg);
if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
reg &= ~((u32)PCI_EXP_LNKCAP_SLS);
reg |= PCI_EXP_LNKCAP_SLS_2_5GB;
dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
PCI_EXP_LNKCAP, 4, reg);
}
dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2,
2, &reg);
if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
reg &= ~((u32)PCI_EXP_LNKCAP_SLS);
reg |= PCI_EXP_LNKCAP_SLS_2_5GB;
dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
PCI_EXP_LNKCTL2, 2, reg);
}
}
reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD); reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
reg |= LTSSM_EN; reg |= LTSSM_EN;
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
...@@ -397,6 +422,10 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) ...@@ -397,6 +422,10 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
reg &= ~LTSSM_EN; reg &= ~LTSSM_EN;
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
dra7xx->link_gen = of_pci_get_max_link_speed(np);
if (dra7xx->link_gen < 0 || dra7xx->link_gen > 2)
dra7xx->link_gen = 2;
ret = dra7xx_add_pcie_port(dra7xx, pdev); ret = dra7xx_add_pcie_port(dra7xx, pdev);
if (ret < 0) if (ret < 0)
goto err_gpio; goto err_gpio;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment