diff options
author | Richard Zhu <hongxing.zhu@nxp.com> | 2018-07-30 11:01:38 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | e5fc2bf1176a4cbd06e53a44703b591fc866cf75 (patch) | |
tree | 353be46168adbd67699c281a905eac08cbe5cc36 /drivers/pci | |
parent | f21241f50f268df8459aa22e83bec57327510727 (diff) |
MLK-19088-2 PCI: imx: enable the l1.1 aspm support on imx8mq
- Enable the L1.1 ASPM support on iMX8MQ, and verified
on the both PCIe ports of the EVK board.
- Fix the L1 exit latency larger than 64us issue
Otherwise, the L1/L1.1 ASPM would be disabled in the
initialization.
- Add the internal PLL of the PCIe REF_CLK support, and
verify the L1.1 ASPM on port0 of 8MQ EVK board
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 100 |
1 files changed, 87 insertions, 13 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 96fe59c6f16d..7132a506461a 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -256,6 +256,8 @@ struct imx_pcie { #define IMX8QM_MISC_PHYX1_EPCS_SEL BIT(12) #define IMX8QM_MISC_PCIE_AB_SELECT BIT(13) +#define IMX8MQ_PCIE_LINK_CAP_REG_OFFSET 0x7C +#define IMX8MQ_PCIE_LINK_CAP_L1EL_64US (0x6 << 15) #define IMX8MQ_SRC_PCIEPHY_RCR_OFFSET 0x2C #define IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET 0x48 #define IMX8MQ_PCIEPHY_DOMAIN_EN (BIT(31) | (0xF << 24)) @@ -263,6 +265,7 @@ struct imx_pcie { #define IMX8MQ_PCIEPHY_G_RST BIT(1) #define IMX8MQ_PCIEPHY_BTN BIT(2) #define IMX8MQ_PCIEPHY_PERST BIT(3) +#define IMX8MQ_PCIE_CTRL_APPS_CLK_REQ BIT(4) #define IMX8MQ_PCIE_CTRL_APPS_EN BIT(6) #define IMX8MQ_PCIE_CTRL_APPS_TURNOFF BIT(11) @@ -276,6 +279,15 @@ struct imx_pcie { #define IMX8MQ_GPC_PGC_PCIE2_BIT_OFFSET 12 #define IMX8MQ_GPC_PCG_PCIE_CTRL_PCR BIT(0) #define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9) +#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10) +#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE BIT(11) +#define IMX8MQ_ANA_PLLOUT_REG 0x74 +#define IMX8MQ_ANA_PLLOUT_CKE BIT(4) +#define IMX8MQ_ANA_PLLOUT_SEL_MASK 0xF +#define IMX8MQ_ANA_PLLOUT_SEL_SYSPLL1 0xB +#define IMX8MQ_ANA_PLLOUT_DIV_REG 0x7C +#define IMX8MQ_ANA_PLLOUT_SYSPLL1_DIV 0x7 + #define IMX8MM_GPR_PCIE_REF_CLK_SEL (0x3 << 24) #define IMX8MM_GPR_PCIE_REF_CLK_PLL (0x3 << 24) #define IMX8MM_GPR_PCIE_REF_CLK_EXT (0x2 << 24) @@ -872,6 +884,42 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) IMX8MQ_PCIE_CTRL_APPS_EN | IMX8MQ_PCIEPHY_DOMAIN_EN, IMX8MQ_PCIEPHY_DOMAIN_EN); + /* + * Configure the CLK_REQ# high, let the L1SS + * automatically controlled by HW. + */ + regmap_update_bits(imx_pcie->reg_src, val, + IMX8MQ_PCIE_CTRL_APPS_CLK_REQ, + IMX8MQ_PCIE_CTRL_APPS_CLK_REQ); + /* + * Set the over ride low and enabled + * make sure that REF_CLK is turned on. + */ + if (imx_pcie->ctrl_id == 0) + val = IOMUXC_GPR14; + else + val = IOMUXC_GPR16; + + regmap_update_bits(imx_pcie->iomuxc_gpr, val, + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE, + 0); + regmap_update_bits(imx_pcie->iomuxc_gpr, val, + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN); + + if (dw_pcie_readl_rc(pp, PCIE_MISC_CTRL) == 0) + dw_pcie_writel_rc(pp, PCIE_MISC_CTRL, + PCIE_MISC_DBI_RO_WR_EN); + /* + * Configure the L1 latency of rc to less than 64us + * Otherwise, the L1/L1SUB wouldn't be enable by ASPM. + */ + val = readl(pp->dbi_base + SZ_1M + + IMX8MQ_PCIE_LINK_CAP_REG_OFFSET); + val &= ~PCI_EXP_LNKCAP_L1EL; + val |= IMX8MQ_PCIE_LINK_CAP_L1EL_64US; + writel(val, pp->dbi_base + SZ_1M + + IMX8MQ_PCIE_LINK_CAP_REG_OFFSET); break; } @@ -1000,6 +1048,8 @@ static void imx_pcie_init_phy(struct imx_pcie *imx_pcie) { u32 tmp, val; int ret; + struct device_node *np; + void __iomem *base; if (imx_pcie->variant == IMX8QM || imx_pcie->variant == IMX8QXP) { @@ -1141,14 +1191,14 @@ static void imx_pcie_init_phy(struct imx_pcie *imx_pcie) "PHY Initialization End!.\n"); } } else { + regmap_update_bits(imx_pcie->iomuxc_gpr, val, + IMX8MQ_GPR_PCIE_REF_USE_PAD, + 0); if (imx_pcie->variant == IMX8MM) { /* Configure the internal PLL as REF clock */ dev_info(imx_pcie->pp.dev, "Initialize PHY with PLL REfCLK!.\n"); regmap_update_bits(imx_pcie->iomuxc_gpr, val, - IMX8MQ_GPR_PCIE_REF_USE_PAD, - 0); - regmap_update_bits(imx_pcie->iomuxc_gpr, val, IMX8MM_GPR_PCIE_REF_CLK_SEL, IMX8MM_GPR_PCIE_REF_CLK_SEL); regmap_update_bits(imx_pcie->iomuxc_gpr, val, @@ -1178,8 +1228,23 @@ static void imx_pcie_init_phy(struct imx_pcie *imx_pcie) dev_info(imx_pcie->pp.dev, "PHY Initialization End!.\n"); } else { - dev_err(imx_pcie->pp.dev, - "Don't support internal PLL.\n"); + np = of_find_compatible_node(NULL, NULL, + "fsl,imx8mq-anatop"); + base = of_iomap(np, 0); + WARN_ON(!base); + + val = readl(base + IMX8MQ_ANA_PLLOUT_REG); + val &= ~IMX8MQ_ANA_PLLOUT_SEL_MASK; + val |= IMX8MQ_ANA_PLLOUT_SEL_SYSPLL1; + writel(val, base + IMX8MQ_ANA_PLLOUT_REG); + /* SYS_PLL1 is 800M, PCIE REF CLK is 100M */ + val = readl(base + IMX8MQ_ANA_PLLOUT_DIV_REG); + val |= IMX8MQ_ANA_PLLOUT_SYSPLL1_DIV; + writel(val, base + IMX8MQ_ANA_PLLOUT_DIV_REG); + + val = readl(base + IMX8MQ_ANA_PLLOUT_REG); + val |= IMX8MQ_ANA_PLLOUT_CKE; + writel(val, base + IMX8MQ_ANA_PLLOUT_REG); } } } else if (imx_pcie->variant == IMX7D) { @@ -1342,7 +1407,6 @@ static irqreturn_t imx_pcie_msi_handler(int irq, void *arg) static void pci_imx_clk_disable(struct device *dev) { - u32 val; struct imx_pcie *imx_pcie = dev_get_drvdata(dev); clk_disable_unprepare(imx_pcie->pcie); @@ -1368,13 +1432,6 @@ static void pci_imx_clk_disable(struct device *dev) break; case IMX8MQ: case IMX8MM: - if (imx_pcie->ctrl_id == 0) - val = IOMUXC_GPR14; - else - val = IOMUXC_GPR16; - - regmap_update_bits(imx_pcie->iomuxc_gpr, val, - IMX8MQ_GPR_PCIE_REF_USE_PAD, 0); break; case IMX8QXP: case IMX8QM: @@ -1509,6 +1566,7 @@ err_reset_phy: static int imx_pcie_host_init(struct pcie_port *pp) { + u32 val; int ret; struct imx_pcie *imx_pcie = to_imx_pcie(pp); @@ -1524,6 +1582,22 @@ static int imx_pcie_host_init(struct pcie_port *pp) if (!IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)) { dw_pcie_setup_rc(pp); ret = imx_pcie_establish_link(imx_pcie); + /* + * Disable the over ride. + * Configure the CLK_REQ# high, let the L1SS automatically + * controlled by HW when link is up. + * Otherwise, turn off the REF_CLK to save power consumption. + */ + if (imx_pcie->variant == IMX8MQ) { + if (imx_pcie->ctrl_id == 0) + val = IOMUXC_GPR14; + else + val = IOMUXC_GPR16; + + regmap_update_bits(imx_pcie->iomuxc_gpr, val, + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, + 0); + } if (ret < 0) return ret; |