From 23c60e3f4a66191f2fca0de29bab4caf7c560531 Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Mon, 22 Jun 2020 15:12:22 +0800 Subject: MLK-24171-5 PCI: imx8mp: verify the pcie internal pll reference clock - Verify the both internal PLL_SYS and external OSC reference clock modes on iMX8MP EVK board, and pass the PCIe compliance tests. - Remove the no-needed bypass setting. - PHY configration should be completed before CMN_RSTN is set to 1b1 - To manually initiate the speed change to make sure GEN2 is linked up: - Write to LINK_CONTROL2_LINK_STATUS2_REG.PCIE_CAP_TARGET_LINK_SPEED in the local device - De-assert GEN2_CTRL_OFF.DIRECT_SPEED_CHANGE in the local device - Assert GEN2_CTRL_OFF.DIRECT_SPEED_CHANGE in the local device Signed-off-by: Richard Zhu Reviewed-by: Fugang Duan (cherry picked from commit 12589ba98b1145e2d2a9f439b20064197aea8ca9) --- drivers/pci/controller/dwc/pci-imx6.c | 114 +++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 51 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index f7fcc1f6c300..ac2b1e740caa 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -40,7 +40,7 @@ #include "pcie-designware.h" #define IMX8MQ_PCIE_LINK_CAP_REG_OFFSET 0x7c -#define IMX8MQ_PCIE_LINK_CAP_L1EL_64US (BIT(18) | BIT(17)) +#define IMX8MQ_PCIE_LINK_CAP_L1EL_64US GENMASK(18, 17) #define IMX8MQ_PCIE_L1SUB_CTRL1_REG_EN_MASK 0xf #define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9) #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10) @@ -62,15 +62,16 @@ #define IMX8MP_GPR_REG2_P_PLL (0xc << 0) #define IMX8MP_GPR_REG2_M_PLL (0x320 << 6) #define IMX8MP_GPR_REG2_S_PLL (0x4 << 16) -#define IMX8MP_GPR_REG2_BYPASS_PLL BIT(21) #define IMX8MP_GPR_REG3 0xc #define IMX8MP_GPR_REG3_PLL_CKE BIT(17) -#define IMX8MP_GPR_REG3_PLL_EXT_BYPASS BIT(18) #define IMX8MP_GPR_REG3_PLL_RST BIT(31) +#define IMX8MP_GPR_PCIE_SSC_EN BIT(16) +#define IMX8MP_GPR_PCIE_PWR_OFF BIT(17) +#define IMX8MP_GPR_PCIE_CMN_RSTN BIT(18) +#define IMX8MP_GPR_PCIE_AUX_EN BIT(19) #define IMX8MP_GPR_PCIE_REF_SEL_MASK GENMASK(25, 24) -#define IMX8MP_GPR_PCIE_REF_PLL (BIT(24) | BIT(25)) +#define IMX8MP_GPR_PCIE_REF_PLL_SYS GENMASK(25, 24) #define IMX8MP_GPR_PCIE_REF_EXT_OSC BIT(25) -#define IMX8MP_GPR_PCIE_REF_EXT_XO BIT(24) #define to_imx6_pcie(x) dev_get_drvdata((x)->dev) @@ -171,6 +172,7 @@ struct imx6_pcie { #define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf #define PCIE_RC_LCSR 0x80 +#define PCIE_RC_LC2SR 0xa0 /* PCIe Port Logic registers (memory-mapped) */ #define PL_OFFSET 0x700 @@ -1045,7 +1047,9 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) /* fall through */ case IMX8MP: - reset_control_assert(imx6_pcie->apps_reset); + imx6_pcie_ltssm_disable(dev); + reset_control_assert(imx6_pcie->pciephy_reset); + reset_control_assert(imx6_pcie->pciephy_perst); break; case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, @@ -1288,14 +1292,30 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) imx6_pcie_set_l1_latency(imx6_pcie); break; case IMX8MP: - if (phy_power_on(imx6_pcie->phy) < 0) - dev_err(dev, "Failed to power on PHY!\n"); - reset_control_assert(imx6_pcie->pciephy_perst); - reset_control_assert(imx6_pcie->pciephy_reset); - udelay(10); + reset_control_deassert(imx6_pcie->pciephy_reset); + reset_control_deassert(imx6_pcie->pciephy_perst); + + /* release pcie_phy_apb_reset and pcie_phy_init_resetn */ + val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG0); + val |= IMX8MP_GPR_REG0_PHY_APB_RST; + val |= IMX8MP_GPR_REG0_PHY_INIT_RST; + writel(val, imx6_pcie->hsmix_base + IMX8MP_GPR_REG0); + val = imx6_pcie_grp_offset(imx6_pcie); if (imx6_pcie->ext_osc) { /*TODO Configure the external OSC as REF clock */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_REF_SEL_MASK, + IMX8MP_GPR_PCIE_REF_SEL_MASK); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_AUX_EN, + IMX8MP_GPR_PCIE_AUX_EN); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_SSC_EN, 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_PWR_OFF, 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_CMN_RSTN, 0); regmap_update_bits(imx6_pcie->iomuxc_gpr, val, IMX8MP_GPR_PCIE_REF_SEL_MASK, IMX8MP_GPR_PCIE_REF_EXT_OSC); @@ -1303,20 +1323,19 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) /* Configure the internal PLL as REF clock */ regmap_update_bits(imx6_pcie->iomuxc_gpr, val, IMX8MP_GPR_PCIE_REF_SEL_MASK, - IMX8MP_GPR_PCIE_REF_PLL); + IMX8MP_GPR_PCIE_REF_PLL_SYS); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_AUX_EN, + IMX8MP_GPR_PCIE_AUX_EN); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_SSC_EN, 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_PWR_OFF, 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, val, + IMX8MP_GPR_PCIE_CMN_RSTN, 0); } - udelay(100); - - /* release pcie_phy_apb_reset and pcie_phy_init_resetn */ - val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG0); - val |= IMX8MP_GPR_REG0_PHY_APB_RST; - val |= IMX8MP_GPR_REG0_PHY_INIT_RST; - writel(val, imx6_pcie->hsmix_base + IMX8MP_GPR_REG0); - udelay(1); - - /* turn off pcie ltssm */ - imx6_pcie_ltssm_disable(dev); + phy_calibrate(imx6_pcie->phy); /* * GPR_PCIE_PHY_CTRL_BUS[3:0] * 0:i_ssc_en 1:i_power_off @@ -1324,12 +1343,8 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) */ val = imx6_pcie_grp_offset(imx6_pcie); regmap_update_bits(imx6_pcie->iomuxc_gpr, val, - BIT(18), - BIT(18)); - udelay(200); - - reset_control_deassert(imx6_pcie->pciephy_reset); - udelay(10); + IMX8MP_GPR_PCIE_CMN_RSTN, + IMX8MP_GPR_PCIE_CMN_RSTN); if(imx8_pcie_wait_for_phy_pll_lock(imx6_pcie) != 0) goto err_pll; @@ -1629,14 +1644,12 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) IMX8MQ_GPR_PCIE_REF_USE_PAD); break; case IMX8MP: + phy_power_on(imx6_pcie->phy); dev_info(imx6_pcie->pci->dev, "%s REF_CLK is used!.\n", imx6_pcie->ext_osc ? "EXT" : "PLL"); imx6_pcie_clk_enable(imx6_pcie); - /* - * Make sure that the bypass_pll of gpr_reg2 is set to - * 1'b1. Set P=12,M=800,S=4 and must set ICP=2'b01. - */ + /* Set P=12,M=800,S=4 and must set ICP=2'b01. */ val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG2); val &= ~IMX8MP_GPR_REG2_P_PLL_MASK; val |= IMX8MP_GPR_REG2_P_PLL; @@ -1644,29 +1657,17 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) val |= IMX8MP_GPR_REG2_M_PLL; val &= ~IMX8MP_GPR_REG2_S_PLL_MASK; val |= IMX8MP_GPR_REG2_S_PLL; - val |= IMX8MP_GPR_REG2_BYPASS_PLL; writel(val, imx6_pcie->hsmix_base + IMX8MP_GPR_REG2); /* wait greater than 1/F_FREF =1/2MHZ=0.5us */ udelay(1); - /* release reset */ + val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG3); val |= IMX8MP_GPR_REG3_PLL_RST; writel(val, imx6_pcie->hsmix_base + IMX8MP_GPR_REG3); + udelay(10); - /* - * Make sure that the pll_ext_bypass of gpr_reg3 is set - * to 1'b0. set 1 to pll_cke of GPR_REG3 - */ - val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG2); - val &= ~IMX8MP_GPR_REG2_BYPASS_PLL; - writel(val, imx6_pcie->hsmix_base + IMX8MP_GPR_REG2); - - /* - * Make sure that the pll_ext_bypass of gpr_reg3 is set - * to 1'b0. set 1 to pll_cke of GPR_REG3 - */ + /* Set 1 to pll_cke of GPR_REG3 */ val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG3); - val &= ~IMX8MP_GPR_REG3_PLL_EXT_BYPASS; val |= IMX8MP_GPR_REG3_PLL_CKE; writel(val, imx6_pcie->hsmix_base + IMX8MP_GPR_REG3); @@ -1678,10 +1679,12 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) break; udelay(10); } - if (i >= 100) { + if (i >= 100) dev_err(imx6_pcie->pci->dev, "PCIe PHY PLL clock is not locked.\n"); - } + else + dev_info(imx6_pcie->pci->dev, + "PCIe PHY PLL clock is locked.\n"); /* pcie_clock_module_en */ val = readl(imx6_pcie->hsmix_base + IMX8MP_GPR_REG0); @@ -1845,12 +1848,21 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) /* Start LTSSM. */ imx6_pcie_ltssm_enable(dev); - ret = dw_pcie_wait_for_link(pci); if (ret) goto err_reset_phy; if (imx6_pcie->link_gen >= 2) { + /* Fill up target link speed before speed change. */ + tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LC2SR); + tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; + tmp |= imx6_pcie->link_gen; + dw_pcie_writel_dbi(pci, PCIE_RC_LC2SR, tmp); + + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + tmp &= ~PORT_LOGIC_SPEED_CHANGE; + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); + /* Allow Gen2 mode after the link is up. */ tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; -- cgit v1.2.3