aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc/pci-imx6.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/controller/dwc/pci-imx6.c')
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index c1d434ba3642..64c74334f7d0 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -19,6 +19,7 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/of_gpio.h> 20#include <linux/of_gpio.h>
21#include <linux/of_device.h> 21#include <linux/of_device.h>
22#include <linux/of_address.h>
22#include <linux/pci.h> 23#include <linux/pci.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
24#include <linux/regmap.h> 25#include <linux/regmap.h>
@@ -77,6 +78,7 @@ struct imx6_pcie {
77 u32 tx_swing_low; 78 u32 tx_swing_low;
78 int link_gen; 79 int link_gen;
79 struct regulator *vpcie; 80 struct regulator *vpcie;
81 void __iomem *phy_base;
80 82
81 /* power domain for pcie */ 83 /* power domain for pcie */
82 struct device *pd_pcie; 84 struct device *pd_pcie;
@@ -134,6 +136,23 @@ struct imx6_pcie {
134#define PCIE_PHY_RX_ASIC_OUT 0x100D 136#define PCIE_PHY_RX_ASIC_OUT 0x100D
135#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) 137#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
136 138
139/* iMX7 PCIe PHY registers */
140#define PCIE_PHY_CMN_REG4 0x14
141/* These are probably the bits that *aren't* DCC_FB_EN */
142#define PCIE_PHY_CMN_REG4_DCC_FB_EN 0x29
143
144#define PCIE_PHY_CMN_REG15 0x54
145#define PCIE_PHY_CMN_REG15_DLY_4 BIT(2)
146#define PCIE_PHY_CMN_REG15_PLL_PD BIT(5)
147#define PCIE_PHY_CMN_REG15_OVRD_PLL_PD BIT(7)
148
149#define PCIE_PHY_CMN_REG24 0x90
150#define PCIE_PHY_CMN_REG24_RX_EQ BIT(6)
151#define PCIE_PHY_CMN_REG24_RX_EQ_SEL BIT(3)
152
153#define PCIE_PHY_CMN_REG26 0x98
154#define PCIE_PHY_CMN_REG26_ATT_MODE 0xBC
155
137#define PHY_RX_OVRD_IN_LO 0x1005 156#define PHY_RX_OVRD_IN_LO 0x1005
138#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) 157#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
139#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) 158#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
@@ -533,6 +552,26 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
533 break; 552 break;
534 case IMX7D: 553 case IMX7D:
535 reset_control_deassert(imx6_pcie->pciephy_reset); 554 reset_control_deassert(imx6_pcie->pciephy_reset);
555
556 /* Workaround for ERR010728, failure of PCI-e PLL VCO to
557 * oscillate, especially when cold. This turns off "Duty-cycle
558 * Corrector" and other mysterious undocumented things.
559 */
560 if (likely(imx6_pcie->phy_base)) {
561 /* De-assert DCC_FB_EN */
562 writel(PCIE_PHY_CMN_REG4_DCC_FB_EN,
563 imx6_pcie->phy_base + PCIE_PHY_CMN_REG4);
564 /* Assert RX_EQS and RX_EQS_SEL */
565 writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL
566 | PCIE_PHY_CMN_REG24_RX_EQ,
567 imx6_pcie->phy_base + PCIE_PHY_CMN_REG24);
568 /* Assert ATT_MODE */
569 writel(PCIE_PHY_CMN_REG26_ATT_MODE,
570 imx6_pcie->phy_base + PCIE_PHY_CMN_REG26);
571 } else {
572 dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n");
573 }
574
536 imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); 575 imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie);
537 break; 576 break;
538 case IMX6SX: 577 case IMX6SX:
@@ -994,6 +1033,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)
994 struct device *dev = &pdev->dev; 1033 struct device *dev = &pdev->dev;
995 struct dw_pcie *pci; 1034 struct dw_pcie *pci;
996 struct imx6_pcie *imx6_pcie; 1035 struct imx6_pcie *imx6_pcie;
1036 struct device_node *np;
997 struct resource *dbi_base; 1037 struct resource *dbi_base;
998 struct device_node *node = dev->of_node; 1038 struct device_node *node = dev->of_node;
999 int ret; 1039 int ret;
@@ -1013,6 +1053,23 @@ static int imx6_pcie_probe(struct platform_device *pdev)
1013 imx6_pcie->pci = pci; 1053 imx6_pcie->pci = pci;
1014 imx6_pcie->drvdata = of_device_get_match_data(dev); 1054 imx6_pcie->drvdata = of_device_get_match_data(dev);
1015 1055
1056 /* Find the PHY if one is defined, only imx7d uses it */
1057 np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0);
1058 if (np) {
1059 struct resource res;
1060
1061 ret = of_address_to_resource(np, 0, &res);
1062 if (ret) {
1063 dev_err(dev, "Unable to map PCIe PHY\n");
1064 return ret;
1065 }
1066 imx6_pcie->phy_base = devm_ioremap_resource(dev, &res);
1067 if (IS_ERR(imx6_pcie->phy_base)) {
1068 dev_err(dev, "Unable to map PCIe PHY\n");
1069 return PTR_ERR(imx6_pcie->phy_base);
1070 }
1071 }
1072
1016 dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1073 dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1017 pci->dbi_base = devm_ioremap_resource(dev, dbi_base); 1074 pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
1018 if (IS_ERR(pci->dbi_base)) 1075 if (IS_ERR(pci->dbi_base))