From 3cfc6be4a85c722e9e0a657c7696f5fa1ac2ed48 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 21 Jun 2016 12:47:51 -0600 Subject: pci: tegra: correctly program PADS_REFCLK registers The value that should be programmed into the PADS_REFCLK register varies per SoC. Fix the Tegra PCIe driver to program the correct values. Future SoCs will require different values in cfg0/1, so the two values are stored separately in the per-SoC data structures. For reference, the values are all documented in NV bug 1771116 comment 20. The Tegra210 value doesn't match the current TRM, but I've filed a bug to get the TRM fixed. Earlier TRMs don't document the value this register should contain, but the ASIC team has validated all these values, except for the Tegra20 value which is simply left unchanged in this patch. Signed-off-by: Stephen Warren Signed-off-by: Tom Warren --- drivers/pci/pci_tegra.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/pci/pci_tegra.c') diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index c5b04da..1aa56fc 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -154,15 +154,6 @@ DECLARE_GLOBAL_DATA_PTR; #define PADS_REFCLK_CFG_PREDI_SHIFT 8 /* 11:8 */ #define PADS_REFCLK_CFG_DRVI_SHIFT 12 /* 15:12 */ -/* Default value provided by HW engineering is 0xfa5c */ -#define PADS_REFCLK_CFG_VALUE \ - ( \ - (0x17 << PADS_REFCLK_CFG_TERM_SHIFT) | \ - (0 << PADS_REFCLK_CFG_E_TERM_SHIFT) | \ - (0xa << PADS_REFCLK_CFG_PREDI_SHIFT) | \ - (0xf << PADS_REFCLK_CFG_DRVI_SHIFT) \ - ) - #define RP_VEND_XP 0x00000F00 #define RP_VEND_XP_DL_UP (1 << 30) @@ -198,6 +189,8 @@ struct tegra_pcie_soc { unsigned int num_ports; unsigned long pads_pll_ctl; unsigned long tx_ref_sel; + u32 pads_refclk_cfg0; + u32 pads_refclk_cfg1; bool has_pex_clkreq_en; bool has_pex_bias_ctrl; bool has_cml_clk; @@ -628,11 +621,9 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) pads_writel(pcie, value, soc->pads_pll_ctl); /* configure the reference clock driver */ - value = PADS_REFCLK_CFG_VALUE | (PADS_REFCLK_CFG_VALUE << 16); - pads_writel(pcie, value, PADS_REFCLK_CFG0); - + pads_writel(pcie, soc->pads_refclk_cfg0, PADS_REFCLK_CFG0); if (soc->num_ports > 2) - pads_writel(pcie, PADS_REFCLK_CFG_VALUE, PADS_REFCLK_CFG1); + pads_writel(pcie, soc->pads_refclk_cfg1, PADS_REFCLK_CFG1); /* wait for the PLL to lock */ err = tegra_pcie_pll_wait(pcie, 500); @@ -943,6 +934,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 2, .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10, + .pads_refclk_cfg0 = 0xfa5cfa5c, .has_pex_clkreq_en = false, .has_pex_bias_ctrl = false, .has_cml_clk = false, @@ -952,6 +944,8 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 3, .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0xfa5cfa5c, + .pads_refclk_cfg1 = 0xfa5cfa5c, .has_pex_clkreq_en = true, .has_pex_bias_ctrl = true, .has_cml_clk = true, @@ -961,6 +955,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 2, .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0x44ac44ac, .has_pex_clkreq_en = true, .has_pex_bias_ctrl = true, .has_cml_clk = true, @@ -970,6 +965,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 2, .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0x90b890b8, .has_pex_clkreq_en = true, .has_pex_bias_ctrl = true, .has_cml_clk = true, -- cgit v1.1 From f39a6a327721285aa68f7e4d57b887c165ed3f14 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 24 Jun 2016 08:36:04 -0600 Subject: pci: tegra: actually program REFCLK_CFG* on recent SoCs On recent SoCs, tegra_pcie_phy_enable() isn't called; but instead tegra_pcie_enable_controller() calls tegra_xusb_phy_enable(). However, part of tegra_pcie_phy_enable() needs to happen in all cases. Move that code to tegra_pcie_port_enable() instead. For reference, NVIDIA's downstream Linux kernel performs this operation in tegra_pcie_enable_rp_features(), which is called immediately after tegra_pcie_port_enable(). Since that function doesn't exist in the U-Boot driver, we'll just add it to the tail of tegra_pcie_port_enable() instead. Signed-off-by: Stephen Warren Signed-off-by: Tom Warren --- drivers/pci/pci_tegra.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/pci/pci_tegra.c') diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 1aa56fc..352cdef 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -620,11 +620,6 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) value |= PADS_PLL_CTL_RST_B4SM; pads_writel(pcie, value, soc->pads_pll_ctl); - /* configure the reference clock driver */ - pads_writel(pcie, soc->pads_refclk_cfg0, PADS_REFCLK_CFG0); - if (soc->num_ports > 2) - pads_writel(pcie, soc->pads_refclk_cfg1, PADS_REFCLK_CFG1); - /* wait for the PLL to lock */ err = tegra_pcie_pll_wait(pcie, 500); if (err < 0) { @@ -818,20 +813,21 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) static void tegra_pcie_port_enable(struct tegra_pcie_port *port) { - const struct tegra_pcie_soc *soc = port->pcie->soc; + struct tegra_pcie *pcie = port->pcie; + const struct tegra_pcie_soc *soc = pcie->soc; unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); unsigned long value; /* enable reference clock */ - value = afi_readl(port->pcie, ctrl); + value = afi_readl(pcie, ctrl); value |= AFI_PEX_CTRL_REFCLK_EN; - if (port->pcie->soc->has_pex_clkreq_en) + if (pcie->soc->has_pex_clkreq_en) value |= AFI_PEX_CTRL_CLKREQ_EN; value |= AFI_PEX_CTRL_OVERRIDE_EN; - afi_writel(port->pcie, value, ctrl); + afi_writel(pcie, value, ctrl); tegra_pcie_port_reset(port); @@ -840,6 +836,11 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port) value |= RP_VEND_CTL2_PCA_ENABLE; rp_writel(port, value, RP_VEND_CTL2); } + + /* configure the reference clock driver */ + pads_writel(pcie, soc->pads_refclk_cfg0, PADS_REFCLK_CFG0); + if (soc->num_ports > 2) + pads_writel(pcie, soc->pads_refclk_cfg1, PADS_REFCLK_CFG1); } static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port) -- cgit v1.1