From 041fd1c835cc7bfe6e77fc9cb6669dec322f99c9 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Mon, 22 Jan 2024 15:30:18 -0800 Subject: [PATCH] imx: kernel: add imx8mp PCI support IMX8MP PCI support requires a few patches backported from Linux 6.2. Signed-off-by: Tim Harvey --- ...x8m-pcie-Refine-register-definitions.patch | 49 +++++ ...x8m-pcie-Refine-i.MX8MM-PCIe-PHY-dri.patch | 197 ++++++++++++++++++ ...x8m-pcie-Add-i.MX8MP-PCIe-PHY-suppor.patch | 99 +++++++++ 3 files changed, 345 insertions(+) create mode 100644 target/linux/imx/patches-6.1/001-6.2-phy-freescale-imx8m-pcie-Refine-register-definitions.patch create mode 100644 target/linux/imx/patches-6.1/002-6.2-phy-freescale-imx8m-pcie-Refine-i.MX8MM-PCIe-PHY-dri.patch create mode 100644 target/linux/imx/patches-6.1/003-6.3-phy-freescale-imx8m-pcie-Add-i.MX8MP-PCIe-PHY-suppor.patch diff --git a/target/linux/imx/patches-6.1/001-6.2-phy-freescale-imx8m-pcie-Refine-register-definitions.patch b/target/linux/imx/patches-6.1/001-6.2-phy-freescale-imx8m-pcie-Refine-register-definitions.patch new file mode 100644 index 0000000000..0af479aae9 --- /dev/null +++ b/target/linux/imx/patches-6.1/001-6.2-phy-freescale-imx8m-pcie-Refine-register-definitions.patch @@ -0,0 +1,49 @@ +From ffcbb4ccd357eeb649036e379a34bf5fb8d4f47c Mon Sep 17 00:00:00 2001 +From: Richard Zhu +Date: Thu, 13 Oct 2022 09:47:00 +0800 +Subject: [PATCH 1/3] phy: freescale: imx8m-pcie: Refine register definitions + +No function changes, refine PHY register definitions. +- Keep align with other CMN PHY registers, refine the definitions of + PHY_CMN_REG75. +- Remove two BIT definitions that are not used at all. + +Signed-off-by: Richard Zhu +Signed-off-by: Lucas Stach +Tested-by: Marek Vasut +Tested-by: Richard Leitner +Tested-by: Alexander Stein +Reviewed-by: Lucas Stach +--- + drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c ++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +@@ -31,12 +31,10 @@ + #define IMX8MM_PCIE_PHY_CMN_REG065 0x194 + #define ANA_AUX_RX_TERM (BIT(7) | BIT(4)) + #define ANA_AUX_TX_LVL GENMASK(3, 0) +-#define IMX8MM_PCIE_PHY_CMN_REG75 0x1D4 +-#define PCIE_PHY_CMN_REG75_PLL_DONE 0x3 ++#define IMX8MM_PCIE_PHY_CMN_REG075 0x1D4 ++#define ANA_PLL_DONE 0x3 + #define PCIE_PHY_TRSV_REG5 0x414 +-#define PCIE_PHY_TRSV_REG5_GEN1_DEEMP 0x2D + #define PCIE_PHY_TRSV_REG6 0x418 +-#define PCIE_PHY_TRSV_REG6_GEN2_DEEMP 0xF + + #define IMX8MM_GPR_PCIE_REF_CLK_SEL GENMASK(25, 24) + #define IMX8MM_GPR_PCIE_REF_CLK_PLL FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3) +@@ -131,9 +129,8 @@ static int imx8_pcie_phy_power_on(struct + reset_control_deassert(imx8_phy->reset); + + /* Polling to check the phy is ready or not. */ +- ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75, +- val, val == PCIE_PHY_CMN_REG75_PLL_DONE, +- 10, 20000); ++ ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075, ++ val, val == ANA_PLL_DONE, 10, 20000); + return ret; + } + diff --git a/target/linux/imx/patches-6.1/002-6.2-phy-freescale-imx8m-pcie-Refine-i.MX8MM-PCIe-PHY-dri.patch b/target/linux/imx/patches-6.1/002-6.2-phy-freescale-imx8m-pcie-Refine-i.MX8MM-PCIe-PHY-dri.patch new file mode 100644 index 0000000000..c2264c0bb4 --- /dev/null +++ b/target/linux/imx/patches-6.1/002-6.2-phy-freescale-imx8m-pcie-Refine-i.MX8MM-PCIe-PHY-dri.patch @@ -0,0 +1,197 @@ +From fb681544808b85c0cdf41a627401e5d470633914 Mon Sep 17 00:00:00 2001 +From: Richard Zhu +Date: Thu, 13 Oct 2022 09:47:01 +0800 +Subject: [PATCH 2/3] phy: freescale: imx8m-pcie: Refine i.MX8MM PCIe PHY + driver + +To make it more flexible and easy to expand. Refine i.MX8MM PCIe PHY +driver. +- Use gpr compatible string to avoid the codes duplications when add + another platform PCIe PHY support. +- Re-arrange the codes to let it more flexible and easy to expand. +No functional change. Re-arrange the TX tuning, since internal registers +can be wrote through APB interface before assertion of CMN_RST. + +Signed-off-by: Richard Zhu +Signed-off-by: Lucas Stach +Tested-by: Marek Vasut +Tested-by: Richard Leitner +Tested-by: Alexander Stein +Reviewed-by: Lucas Stach +Reviewed-by: Ahmad Fatoum +--- + drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 106 +++++++++++++-------- + 1 file changed, 66 insertions(+), 40 deletions(-) + +--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c ++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -45,6 +46,15 @@ + #define IMX8MM_GPR_PCIE_SSC_EN BIT(16) + #define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE BIT(9) + ++enum imx8_pcie_phy_type { ++ IMX8MM, ++}; ++ ++struct imx8_pcie_phy_drvdata { ++ const char *gpr; ++ enum imx8_pcie_phy_type variant; ++}; ++ + struct imx8_pcie_phy { + void __iomem *base; + struct clk *clk; +@@ -55,6 +65,7 @@ struct imx8_pcie_phy { + u32 tx_deemph_gen1; + u32 tx_deemph_gen2; + bool clkreq_unused; ++ const struct imx8_pcie_phy_drvdata *drvdata; + }; + + static int imx8_pcie_phy_power_on(struct phy *phy) +@@ -66,31 +77,17 @@ static int imx8_pcie_phy_power_on(struct + reset_control_assert(imx8_phy->reset); + + pad_mode = imx8_phy->refclk_pad_mode; +- /* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */ +- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, +- IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE, +- imx8_phy->clkreq_unused ? +- 0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE); +- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, +- IMX8MM_GPR_PCIE_AUX_EN, +- IMX8MM_GPR_PCIE_AUX_EN); +- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, +- IMX8MM_GPR_PCIE_POWER_OFF, 0); +- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, +- IMX8MM_GPR_PCIE_SSC_EN, 0); +- +- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, +- IMX8MM_GPR_PCIE_REF_CLK_SEL, +- pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ? +- IMX8MM_GPR_PCIE_REF_CLK_EXT : +- IMX8MM_GPR_PCIE_REF_CLK_PLL); +- usleep_range(100, 200); +- +- /* Do the PHY common block reset */ +- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, +- IMX8MM_GPR_PCIE_CMN_RST, +- IMX8MM_GPR_PCIE_CMN_RST); +- usleep_range(200, 500); ++ switch (imx8_phy->drvdata->variant) { ++ case IMX8MM: ++ /* Tune PHY de-emphasis setting to pass PCIe compliance. */ ++ if (imx8_phy->tx_deemph_gen1) ++ writel(imx8_phy->tx_deemph_gen1, ++ imx8_phy->base + PCIE_PHY_TRSV_REG5); ++ if (imx8_phy->tx_deemph_gen2) ++ writel(imx8_phy->tx_deemph_gen2, ++ imx8_phy->base + PCIE_PHY_TRSV_REG6); ++ break; ++ } + + if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT || + pad_mode == IMX8_PCIE_REFCLK_PAD_UNUSED) { +@@ -118,15 +115,37 @@ static int imx8_pcie_phy_power_on(struct + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065); + } + +- /* Tune PHY de-emphasis setting to pass PCIe compliance. */ +- if (imx8_phy->tx_deemph_gen1) +- writel(imx8_phy->tx_deemph_gen1, +- imx8_phy->base + PCIE_PHY_TRSV_REG5); +- if (imx8_phy->tx_deemph_gen2) +- writel(imx8_phy->tx_deemph_gen2, +- imx8_phy->base + PCIE_PHY_TRSV_REG6); ++ /* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */ ++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ++ IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE, ++ imx8_phy->clkreq_unused ? ++ 0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE); ++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ++ IMX8MM_GPR_PCIE_AUX_EN, ++ IMX8MM_GPR_PCIE_AUX_EN); ++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ++ IMX8MM_GPR_PCIE_POWER_OFF, 0); ++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ++ IMX8MM_GPR_PCIE_SSC_EN, 0); + +- reset_control_deassert(imx8_phy->reset); ++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ++ IMX8MM_GPR_PCIE_REF_CLK_SEL, ++ pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ? ++ IMX8MM_GPR_PCIE_REF_CLK_EXT : ++ IMX8MM_GPR_PCIE_REF_CLK_PLL); ++ usleep_range(100, 200); ++ ++ /* Do the PHY common block reset */ ++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ++ IMX8MM_GPR_PCIE_CMN_RST, ++ IMX8MM_GPR_PCIE_CMN_RST); ++ ++ switch (imx8_phy->drvdata->variant) { ++ case IMX8MM: ++ reset_control_deassert(imx8_phy->reset); ++ usleep_range(200, 500); ++ break; ++ } + + /* Polling to check the phy is ready or not. */ + ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075, +@@ -157,6 +176,17 @@ static const struct phy_ops imx8_pcie_ph + .owner = THIS_MODULE, + }; + ++static const struct imx8_pcie_phy_drvdata imx8mm_drvdata = { ++ .gpr = "fsl,imx8mm-iomuxc-gpr", ++ .variant = IMX8MM, ++}; ++ ++static const struct of_device_id imx8_pcie_phy_of_match[] = { ++ {.compatible = "fsl,imx8mm-pcie-phy", .data = &imx8mm_drvdata, }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match); ++ + static int imx8_pcie_phy_probe(struct platform_device *pdev) + { + struct phy_provider *phy_provider; +@@ -169,6 +199,8 @@ static int imx8_pcie_phy_probe(struct pl + if (!imx8_phy) + return -ENOMEM; + ++ imx8_phy->drvdata = of_device_get_match_data(dev); ++ + /* get PHY refclk pad mode */ + of_property_read_u32(np, "fsl,refclk-pad-mode", + &imx8_phy->refclk_pad_mode); +@@ -194,7 +226,7 @@ static int imx8_pcie_phy_probe(struct pl + + /* Grab GPR config register range */ + imx8_phy->iomuxc_gpr = +- syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); ++ syscon_regmap_lookup_by_compatible(imx8_phy->drvdata->gpr); + if (IS_ERR(imx8_phy->iomuxc_gpr)) { + dev_err(dev, "unable to find iomuxc registers\n"); + return PTR_ERR(imx8_phy->iomuxc_gpr); +@@ -222,12 +254,6 @@ static int imx8_pcie_phy_probe(struct pl + return PTR_ERR_OR_ZERO(phy_provider); + } + +-static const struct of_device_id imx8_pcie_phy_of_match[] = { +- {.compatible = "fsl,imx8mm-pcie-phy",}, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match); +- + static struct platform_driver imx8_pcie_phy_driver = { + .probe = imx8_pcie_phy_probe, + .driver = { diff --git a/target/linux/imx/patches-6.1/003-6.3-phy-freescale-imx8m-pcie-Add-i.MX8MP-PCIe-PHY-suppor.patch b/target/linux/imx/patches-6.1/003-6.3-phy-freescale-imx8m-pcie-Add-i.MX8MP-PCIe-PHY-suppor.patch new file mode 100644 index 0000000000..03b41e4153 --- /dev/null +++ b/target/linux/imx/patches-6.1/003-6.3-phy-freescale-imx8m-pcie-Add-i.MX8MP-PCIe-PHY-suppor.patch @@ -0,0 +1,99 @@ +From bf03b9281b119bcdc167b2dd6ac98294587eb5ff Mon Sep 17 00:00:00 2001 +From: Richard Zhu +Date: Thu, 13 Oct 2022 09:47:02 +0800 +Subject: [PATCH 3/3] phy: freescale: imx8m-pcie: Add i.MX8MP PCIe PHY support + +Add i.MX8MP PCIe PHY support. + +Signed-off-by: Richard Zhu +Signed-off-by: Lucas Stach +Tested-by: Marek Vasut +Tested-by: Richard Leitner +Tested-by: Alexander Stein +Reviewed-by: Lucas Stach +Reviewed-by: Ahmad Fatoum +--- + drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 25 ++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c ++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +@@ -48,6 +48,7 @@ + + enum imx8_pcie_phy_type { + IMX8MM, ++ IMX8MP, + }; + + struct imx8_pcie_phy_drvdata { +@@ -60,6 +61,7 @@ struct imx8_pcie_phy { + struct clk *clk; + struct phy *phy; + struct regmap *iomuxc_gpr; ++ struct reset_control *perst; + struct reset_control *reset; + u32 refclk_pad_mode; + u32 tx_deemph_gen1; +@@ -74,11 +76,11 @@ static int imx8_pcie_phy_power_on(struct + u32 val, pad_mode; + struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy); + +- reset_control_assert(imx8_phy->reset); +- + pad_mode = imx8_phy->refclk_pad_mode; + switch (imx8_phy->drvdata->variant) { + case IMX8MM: ++ reset_control_assert(imx8_phy->reset); ++ + /* Tune PHY de-emphasis setting to pass PCIe compliance. */ + if (imx8_phy->tx_deemph_gen1) + writel(imx8_phy->tx_deemph_gen1, +@@ -87,6 +89,8 @@ static int imx8_pcie_phy_power_on(struct + writel(imx8_phy->tx_deemph_gen2, + imx8_phy->base + PCIE_PHY_TRSV_REG6); + break; ++ case IMX8MP: /* Do nothing. */ ++ break; + } + + if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT || +@@ -141,6 +145,9 @@ static int imx8_pcie_phy_power_on(struct + IMX8MM_GPR_PCIE_CMN_RST); + + switch (imx8_phy->drvdata->variant) { ++ case IMX8MP: ++ reset_control_deassert(imx8_phy->perst); ++ fallthrough; + case IMX8MM: + reset_control_deassert(imx8_phy->reset); + usleep_range(200, 500); +@@ -181,8 +188,14 @@ static const struct imx8_pcie_phy_drvdat + .variant = IMX8MM, + }; + ++static const struct imx8_pcie_phy_drvdata imx8mp_drvdata = { ++ .gpr = "fsl,imx8mp-iomuxc-gpr", ++ .variant = IMX8MP, ++}; ++ + static const struct of_device_id imx8_pcie_phy_of_match[] = { + {.compatible = "fsl,imx8mm-pcie-phy", .data = &imx8mm_drvdata, }, ++ {.compatible = "fsl,imx8mp-pcie-phy", .data = &imx8mp_drvdata, }, + { }, + }; + MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match); +@@ -238,6 +251,14 @@ static int imx8_pcie_phy_probe(struct pl + return PTR_ERR(imx8_phy->reset); + } + ++ if (imx8_phy->drvdata->variant == IMX8MP) { ++ imx8_phy->perst = ++ devm_reset_control_get_exclusive(dev, "perst"); ++ if (IS_ERR(imx8_phy->perst)) ++ dev_err_probe(dev, PTR_ERR(imx8_phy->perst), ++ "Failed to get PCIE PHY PERST control\n"); ++ } ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + imx8_phy->base = devm_ioremap_resource(dev, res); + if (IS_ERR(imx8_phy->base))