|
@@ -68,6 +68,40 @@
|
|
|
#define PCIE_PCS_MASK 0xFF0000
|
|
|
#define PCIE_PCS_DELAY_COUNT_SHIFT 0x10
|
|
|
|
|
|
+#define PCIEPHYRX_ANA_PROGRAMMABILITY 0x0000000C
|
|
|
+#define INTERFACE_MASK GENMASK(31, 27)
|
|
|
+#define INTERFACE_SHIFT 27
|
|
|
+#define LOSD_MASK GENMASK(17, 14)
|
|
|
+#define LOSD_SHIFT 14
|
|
|
+#define MEM_PLLDIV GENMASK(6, 5)
|
|
|
+
|
|
|
+#define PCIEPHYRX_TRIM 0x0000001C
|
|
|
+#define MEM_DLL_TRIM_SEL GENMASK(31, 30)
|
|
|
+#define MEM_DLL_TRIM_SHIFT 30
|
|
|
+
|
|
|
+#define PCIEPHYRX_DLL 0x00000024
|
|
|
+#define MEM_DLL_PHINT_RATE GENMASK(31, 30)
|
|
|
+
|
|
|
+#define PCIEPHYRX_DIGITAL_MODES 0x00000028
|
|
|
+#define MEM_CDR_FASTLOCK BIT(23)
|
|
|
+#define MEM_CDR_LBW GENMASK(22, 21)
|
|
|
+#define MEM_CDR_STEPCNT GENMASK(20, 19)
|
|
|
+#define MEM_CDR_STL_MASK GENMASK(18, 16)
|
|
|
+#define MEM_CDR_STL_SHIFT 16
|
|
|
+#define MEM_CDR_THR_MASK GENMASK(15, 13)
|
|
|
+#define MEM_CDR_THR_SHIFT 13
|
|
|
+#define MEM_CDR_THR_MODE BIT(12)
|
|
|
+#define MEM_CDR_CDR_2NDO_SDM_MODE BIT(11)
|
|
|
+#define MEM_OVRD_HS_RATE BIT(26)
|
|
|
+
|
|
|
+#define PCIEPHYRX_EQUALIZER 0x00000038
|
|
|
+#define MEM_EQLEV GENMASK(31, 16)
|
|
|
+#define MEM_EQFTC GENMASK(15, 11)
|
|
|
+#define MEM_EQCTL GENMASK(10, 7)
|
|
|
+#define MEM_EQCTL_SHIFT 7
|
|
|
+#define MEM_OVRD_EQLEV BIT(2)
|
|
|
+#define MEM_OVRD_EQFTC BIT(1)
|
|
|
+
|
|
|
/*
|
|
|
* This is an Empirical value that works, need to confirm the actual
|
|
|
* value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
|
|
@@ -91,6 +125,8 @@ struct pipe3_dpll_map {
|
|
|
|
|
|
struct ti_pipe3 {
|
|
|
void __iomem *pll_ctrl_base;
|
|
|
+ void __iomem *phy_rx;
|
|
|
+ void __iomem *phy_tx;
|
|
|
struct device *dev;
|
|
|
struct device *control_dev;
|
|
|
struct clk *wkupclk;
|
|
@@ -261,6 +297,37 @@ static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
|
|
|
return ti_pipe3_dpll_wait_lock(phy);
|
|
|
}
|
|
|
|
|
|
+static void ti_pipe3_calibrate(struct ti_pipe3 *phy)
|
|
|
+{
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_ANA_PROGRAMMABILITY);
|
|
|
+ val &= ~(INTERFACE_MASK | LOSD_MASK | MEM_PLLDIV);
|
|
|
+ val = (0x1 << INTERFACE_SHIFT | 0xA << LOSD_SHIFT);
|
|
|
+ ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_ANA_PROGRAMMABILITY, val);
|
|
|
+
|
|
|
+ val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_DIGITAL_MODES);
|
|
|
+ val &= ~(MEM_CDR_STEPCNT | MEM_CDR_STL_MASK | MEM_CDR_THR_MASK |
|
|
|
+ MEM_CDR_CDR_2NDO_SDM_MODE | MEM_OVRD_HS_RATE);
|
|
|
+ val |= (MEM_CDR_FASTLOCK | MEM_CDR_LBW | 0x3 << MEM_CDR_STL_SHIFT |
|
|
|
+ 0x1 << MEM_CDR_THR_SHIFT | MEM_CDR_THR_MODE);
|
|
|
+ ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_DIGITAL_MODES, val);
|
|
|
+
|
|
|
+ val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_TRIM);
|
|
|
+ val &= ~MEM_DLL_TRIM_SEL;
|
|
|
+ val |= 0x2 << MEM_DLL_TRIM_SHIFT;
|
|
|
+ ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_TRIM, val);
|
|
|
+
|
|
|
+ val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_DLL);
|
|
|
+ val |= MEM_DLL_PHINT_RATE;
|
|
|
+ ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_DLL, val);
|
|
|
+
|
|
|
+ val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_EQUALIZER);
|
|
|
+ val &= ~(MEM_EQLEV | MEM_EQCTL | MEM_OVRD_EQLEV | MEM_OVRD_EQFTC);
|
|
|
+ val |= MEM_EQFTC | 0x1 << MEM_EQCTL_SHIFT;
|
|
|
+ ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_EQUALIZER, val);
|
|
|
+}
|
|
|
+
|
|
|
static int ti_pipe3_init(struct phy *x)
|
|
|
{
|
|
|
struct ti_pipe3 *phy = phy_get_drvdata(x);
|
|
@@ -282,7 +349,12 @@ static int ti_pipe3_init(struct phy *x)
|
|
|
val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT;
|
|
|
ret = regmap_update_bits(phy->pcs_syscon, phy->pcie_pcs_reg,
|
|
|
PCIE_PCS_MASK, val);
|
|
|
- return ret;
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ti_pipe3_calibrate(phy);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/* Bring it out of IDLE if it is IDLE */
|
|
@@ -513,6 +585,29 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ti_pipe3_get_tx_rx_base(struct ti_pipe3 *phy)
|
|
|
+{
|
|
|
+ struct resource *res;
|
|
|
+ struct device *dev = phy->dev;
|
|
|
+ struct device_node *node = dev->of_node;
|
|
|
+ struct platform_device *pdev = to_platform_device(dev);
|
|
|
+
|
|
|
+ if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie"))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
|
+ "phy_rx");
|
|
|
+ phy->phy_rx = devm_ioremap_resource(dev, res);
|
|
|
+ if (IS_ERR(phy->phy_rx))
|
|
|
+ return PTR_ERR(phy->phy_rx);
|
|
|
+
|
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
|
+ "phy_tx");
|
|
|
+ phy->phy_tx = devm_ioremap_resource(dev, res);
|
|
|
+
|
|
|
+ return PTR_ERR_OR_ZERO(phy->phy_tx);
|
|
|
+}
|
|
|
+
|
|
|
static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy)
|
|
|
{
|
|
|
struct resource *res;
|
|
@@ -559,6 +654,10 @@ static int ti_pipe3_probe(struct platform_device *pdev)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
+ ret = ti_pipe3_get_tx_rx_base(phy);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
ret = ti_pipe3_get_sysctrl(phy);
|
|
|
if (ret)
|
|
|
return ret;
|