diff options
author | Richard Zhu <hongxing.zhu@nxp.com> | 2017-11-14 13:36:31 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:29:11 +0800 |
commit | 777d092e325b33c30ef07137c4283fd374419a2e (patch) | |
tree | 8befcfde06f8d56335acac6539c913abe2d4befd /drivers/pci/dwc | |
parent | 97f8dc5aaa8eb393fa039431756559884f77a6e3 (diff) |
MLK-16817-2 PCI: imx: enable the pm on imx8qm/qxp
Enable the pcie pm on imx8qm/qxp
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Diffstat (limited to 'drivers/pci/dwc')
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 1079e75a6286..5391c6a06a9b 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -74,6 +74,7 @@ struct imx6_pcie { struct clk *pcie_bus; struct clk *pcie_phy; struct clk *pcie_inbound_axi; + struct clk *pcie_per; struct clk *pcie; struct clk *pcie_ext_src; struct regmap *iomuxc_gpr; @@ -188,10 +189,13 @@ struct imx6_pcie { #define IMX8QM_LPCG_PHY_PCG1 BIT(5) #define IMX8QM_CTRL_LTSSM_ENABLE BIT(4) +#define IMX8QM_CTRL_READY_ENTR_L23 BIT(5) +#define IMX8QM_CTRL_PM_XMT_TURNOFF BIT(9) #define IMX8QM_CTRL_BUTTON_RST_N BIT(21) #define IMX8QM_CTRL_PERST_N BIT(22) #define IMX8QM_CTRL_POWER_UP_RST_N BIT(23) +#define IMX8QM_CTRL_STTS0_PM_LINKST_IN_L2 BIT(13) #define IMX8QM_CTRL_STTS0_PM_REQ_CORE_RST BIT(19) #define IMX8QM_STTS0_LANE0_TX_PLL_LOCK BIT(4) #define IMX8QM_STTS0_LANE1_TX_PLL_LOCK BIT(12) @@ -542,6 +546,13 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) dev_err(dev, "unable to enable pcie_axi clock\n"); break; } + ret = clk_prepare_enable(imx6_pcie->pcie_per); + if (ret) { + dev_err(dev, "unable to enable pcie_per clock\n"); + clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); + break; + } + break; } @@ -1247,6 +1258,7 @@ static void pci_imx_clk_disable(struct device *dev) break; case IMX8QXP: case IMX8QM: + clk_disable_unprepare(imx6_pcie->pcie_per); clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); break; } @@ -1658,7 +1670,8 @@ static void imx6_pcie_setup_ep(struct dw_pcie *pci) /* PM_TURN_OFF */ static void pci_imx_pm_turn_off(struct imx6_pcie *imx6_pcie) { - u32 val; + int i; + u32 dst, val; struct device *dev = imx6_pcie->pci->dev; /* PM_TURN_OFF */ @@ -1680,19 +1693,45 @@ static void pci_imx_pm_turn_off(struct imx6_pcie *imx6_pcie) case IMX7D: case IMX8MQ: if (imx6_pcie->ctrl_id == 0) - val = IMX8MQ_SRC_PCIEPHY_RCR_OFFSET; + dst = IMX8MQ_SRC_PCIEPHY_RCR_OFFSET; else - val = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET; - regmap_update_bits(imx6_pcie->reg_src, val, + dst = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET; + regmap_update_bits(imx6_pcie->reg_src, dst, IMX8MQ_PCIE_CTRL_APPS_TURNOFF, IMX8MQ_PCIE_CTRL_APPS_TURNOFF); - regmap_update_bits(imx6_pcie->reg_src, val, + regmap_update_bits(imx6_pcie->reg_src, dst, IMX8MQ_PCIE_CTRL_APPS_TURNOFF, 0); break; - case IMX6Q: case IMX8QXP: case IMX8QM: + dst = IMX8QM_CSR_PCIEA_OFFSET + imx6_pcie->ctrl_id * SZ_64K; + regmap_update_bits(imx6_pcie->iomuxc_gpr, + dst + IMX8QM_CSR_PCIE_CTRL2_OFFSET, + IMX8QM_CTRL_PM_XMT_TURNOFF, + IMX8QM_CTRL_PM_XMT_TURNOFF); + regmap_update_bits(imx6_pcie->iomuxc_gpr, + dst + IMX8QM_CSR_PCIE_CTRL2_OFFSET, + IMX8QM_CTRL_PM_XMT_TURNOFF, + 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, + dst + IMX8QM_CSR_PCIE_CTRL2_OFFSET, + IMX8QM_CTRL_READY_ENTR_L23, + IMX8QM_CTRL_READY_ENTR_L23); + /* check the L2 is entered or not. */ + for (i = 0; i < 10000; i++) { + regmap_read(imx6_pcie->iomuxc_gpr, + dst + IMX8QM_CSR_PCIE_STTS0_OFFSET, + &val); + if (val & IMX8QM_CTRL_STTS0_PM_LINKST_IN_L2) + break; + udelay(10); + } + if ((val & IMX8QM_CTRL_STTS0_PM_LINKST_IN_L2) == 0) + dev_err(dev, "PCIE%d can't enter into L2.\n", + imx6_pcie->ctrl_id); + break; + case IMX6Q: dev_info(dev, "Info: don't support pm_turn_off yet.\n"); break; } @@ -1767,6 +1806,9 @@ static void pci_imx_ltssm_disable(struct device *dev) regmap_update_bits(imx6_pcie->iomuxc_gpr, val + IMX8QM_CSR_PCIE_CTRL2_OFFSET, IMX8QM_CTRL_LTSSM_ENABLE, 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, + val + IMX8QM_CSR_PCIE_CTRL2_OFFSET, + IMX8QM_CTRL_READY_ENTR_L23, 0); break; } } @@ -2039,6 +2081,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) ("fsl,imx6sx-iomuxc-gpr"); } else if (imx6_pcie->variant == IMX8QM || imx6_pcie->variant == IMX8QXP) { + imx6_pcie->pcie_per = devm_clk_get(dev, "pcie_per"); + if (IS_ERR(imx6_pcie->pcie_per)) { + dev_err(dev, "pcie_per clock source missing or invalid\n"); + return PTR_ERR(imx6_pcie->pcie_per); + } + imx6_pcie->iomuxc_gpr = syscon_regmap_lookup_by_phandle(node, "hsio"); imx6_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev, |