mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 22:23:18 +00:00
PCI: imx6: Simplify switch-case logic by involve core_reset callback
Instead of using the switch case statement to assert/dassert the core reset handled by this driver itself, let's introduce a new callback core_reset() and define it for platforms that require it. This simplifies the code. Link: https://lore.kernel.org/linux-pci/20240729-pci2_upstream-v8-5-b68ee5ef2b4d@nxp.com Signed-off-by: Frank Li <Frank.Li@nxp.com> [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
This commit is contained in:
parent
256867b746
commit
5223084d13
@ -102,6 +102,7 @@ struct imx_pcie_drvdata {
|
||||
const struct pci_epc_features *epc_features;
|
||||
int (*init_phy)(struct imx_pcie *pcie);
|
||||
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
|
||||
int (*core_reset)(struct imx_pcie *pcie, bool assert);
|
||||
};
|
||||
|
||||
struct imx_pcie {
|
||||
@ -668,35 +669,75 @@ static void imx_pcie_clk_disable(struct imx_pcie *imx_pcie)
|
||||
clk_bulk_disable_unprepare(imx_pcie->drvdata->clks_cnt, imx_pcie->clks);
|
||||
}
|
||||
|
||||
static int imx6sx_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
|
||||
{
|
||||
if (assert)
|
||||
regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
|
||||
IMX6SX_GPR12_PCIE_TEST_POWERDOWN);
|
||||
|
||||
/* Force PCIe PHY reset */
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, IMX6SX_GPR5_PCIE_BTNRST_RESET,
|
||||
assert ? IMX6SX_GPR5_PCIE_BTNRST_RESET : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx6qp_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
|
||||
{
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_SW_RST,
|
||||
assert ? IMX6Q_GPR1_PCIE_SW_RST : 0);
|
||||
if (!assert)
|
||||
usleep_range(200, 500);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx6q_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
|
||||
{
|
||||
if (!assert)
|
||||
return 0;
|
||||
|
||||
regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD);
|
||||
regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
|
||||
{
|
||||
struct dw_pcie *pci = imx_pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
|
||||
if (assert)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Workaround for ERR010728, failure of PCI-e PLL VCO to
|
||||
* oscillate, especially when cold. This turns off "Duty-cycle
|
||||
* Corrector" and other mysterious undocumented things.
|
||||
*/
|
||||
|
||||
if (likely(imx_pcie->phy_base)) {
|
||||
/* De-assert DCC_FB_EN */
|
||||
writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, imx_pcie->phy_base + PCIE_PHY_CMN_REG4);
|
||||
/* Assert RX_EQS and RX_EQS_SEL */
|
||||
writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL | PCIE_PHY_CMN_REG24_RX_EQ,
|
||||
imx_pcie->phy_base + PCIE_PHY_CMN_REG24);
|
||||
/* Assert ATT_MODE */
|
||||
writel(PCIE_PHY_CMN_REG26_ATT_MODE, imx_pcie->phy_base + PCIE_PHY_CMN_REG26);
|
||||
} else {
|
||||
dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n");
|
||||
}
|
||||
imx7d_pcie_wait_for_phy_pll_lock(imx_pcie);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
|
||||
{
|
||||
reset_control_assert(imx_pcie->pciephy_reset);
|
||||
reset_control_assert(imx_pcie->apps_reset);
|
||||
|
||||
switch (imx_pcie->drvdata->variant) {
|
||||
case IMX6SX:
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
|
||||
IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
|
||||
IMX6SX_GPR12_PCIE_TEST_POWERDOWN);
|
||||
/* Force PCIe PHY reset */
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5,
|
||||
IMX6SX_GPR5_PCIE_BTNRST_RESET,
|
||||
IMX6SX_GPR5_PCIE_BTNRST_RESET);
|
||||
break;
|
||||
case IMX6QP:
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
|
||||
IMX6Q_GPR1_PCIE_SW_RST,
|
||||
IMX6Q_GPR1_PCIE_SW_RST);
|
||||
break;
|
||||
case IMX6Q:
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
|
||||
IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
|
||||
IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (imx_pcie->drvdata->core_reset)
|
||||
imx_pcie->drvdata->core_reset(imx_pcie, true);
|
||||
|
||||
/* Some boards don't have PCIe reset GPIO. */
|
||||
gpiod_set_value_cansleep(imx_pcie->reset_gpiod, 1);
|
||||
@ -704,47 +745,10 @@ static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
|
||||
|
||||
static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie)
|
||||
{
|
||||
struct dw_pcie *pci = imx_pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
|
||||
reset_control_deassert(imx_pcie->pciephy_reset);
|
||||
|
||||
switch (imx_pcie->drvdata->variant) {
|
||||
case IMX7D:
|
||||
/* Workaround for ERR010728, failure of PCI-e PLL VCO to
|
||||
* oscillate, especially when cold. This turns off "Duty-cycle
|
||||
* Corrector" and other mysterious undocumented things.
|
||||
*/
|
||||
if (likely(imx_pcie->phy_base)) {
|
||||
/* De-assert DCC_FB_EN */
|
||||
writel(PCIE_PHY_CMN_REG4_DCC_FB_EN,
|
||||
imx_pcie->phy_base + PCIE_PHY_CMN_REG4);
|
||||
/* Assert RX_EQS and RX_EQS_SEL */
|
||||
writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL
|
||||
| PCIE_PHY_CMN_REG24_RX_EQ,
|
||||
imx_pcie->phy_base + PCIE_PHY_CMN_REG24);
|
||||
/* Assert ATT_MODE */
|
||||
writel(PCIE_PHY_CMN_REG26_ATT_MODE,
|
||||
imx_pcie->phy_base + PCIE_PHY_CMN_REG26);
|
||||
} else {
|
||||
dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n");
|
||||
}
|
||||
|
||||
imx7d_pcie_wait_for_phy_pll_lock(imx_pcie);
|
||||
break;
|
||||
case IMX6SX:
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5,
|
||||
IMX6SX_GPR5_PCIE_BTNRST_RESET, 0);
|
||||
break;
|
||||
case IMX6QP:
|
||||
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
|
||||
IMX6Q_GPR1_PCIE_SW_RST, 0);
|
||||
|
||||
usleep_range(200, 500);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (imx_pcie->drvdata->core_reset)
|
||||
imx_pcie->drvdata->core_reset(imx_pcie, false);
|
||||
|
||||
/* Some boards don't have PCIe reset GPIO. */
|
||||
if (imx_pcie->reset_gpiod) {
|
||||
@ -1441,6 +1445,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
||||
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
|
||||
.init_phy = imx_pcie_init_phy,
|
||||
.enable_ref_clk = imx6q_pcie_enable_ref_clk,
|
||||
.core_reset = imx6q_pcie_core_reset,
|
||||
},
|
||||
[IMX6SX] = {
|
||||
.variant = IMX6SX,
|
||||
@ -1456,6 +1461,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
||||
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
|
||||
.init_phy = imx6sx_pcie_init_phy,
|
||||
.enable_ref_clk = imx6sx_pcie_enable_ref_clk,
|
||||
.core_reset = imx6sx_pcie_core_reset,
|
||||
},
|
||||
[IMX6QP] = {
|
||||
.variant = IMX6QP,
|
||||
@ -1472,6 +1478,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
||||
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
|
||||
.init_phy = imx_pcie_init_phy,
|
||||
.enable_ref_clk = imx6q_pcie_enable_ref_clk,
|
||||
.core_reset = imx6qp_pcie_core_reset,
|
||||
},
|
||||
[IMX7D] = {
|
||||
.variant = IMX7D,
|
||||
@ -1485,6 +1492,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
|
||||
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
|
||||
.init_phy = imx7d_pcie_init_phy,
|
||||
.enable_ref_clk = imx7d_pcie_enable_ref_clk,
|
||||
.core_reset = imx7d_pcie_core_reset,
|
||||
},
|
||||
[IMX8MQ] = {
|
||||
.variant = IMX8MQ,
|
||||
|
Loading…
Reference in New Issue
Block a user