PCI: imx6: Add iMX95 PCIe Root Complex support
authorFrank Li <Frank.Li@nxp.com>
Tue, 20 Feb 2024 16:19:20 +0000 (11:19 -0500)
committerLorenzo Pieralisi <lpieralisi@kernel.org>
Mon, 4 Mar 2024 08:54:43 +0000 (09:54 +0100)
Add iMX95 PCIe Root Complex support.

Link: https://lore.kernel.org/r/20240220161924.3871774-11-Frank.Li@nxp.com
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/dwc/pci-imx6.c

index 7716cf56fa563d100437f11e34ba687f63d4a528..b3aaacc88f38448797509c866eae86c5ea07c788 100644 (file)
 #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE    GENMASK(11, 8)
 #define IMX8MQ_PCIE2_BASE_ADDR                 0x33c00000
 
+#define IMX95_PCIE_PHY_GEN_CTRL                        0x0
+#define IMX95_PCIE_REF_USE_PAD                 BIT(17)
+
+#define IMX95_PCIE_SS_RW_REG_0                 0xf0
+#define IMX95_PCIE_REF_CLKEN                   BIT(23)
+#define IMX95_PCIE_PHY_CR_PARA_SEL             BIT(9)
+
+#define IMX95_PE0_GEN_CTRL_1                   0x1050
+#define IMX95_PCIE_DEVICE_TYPE                 GENMASK(3, 0)
+
+#define IMX95_PE0_GEN_CTRL_3                   0x1058
+#define IMX95_PCIE_LTSSM_EN                    BIT(0)
+
 #define to_imx6_pcie(x)        dev_get_drvdata((x)->dev)
 
 enum imx6_pcie_variants {
@@ -52,6 +65,7 @@ enum imx6_pcie_variants {
        IMX8MQ,
        IMX8MM,
        IMX8MP,
+       IMX95,
        IMX8MQ_EP,
        IMX8MM_EP,
        IMX8MP_EP,
@@ -63,6 +77,7 @@ enum imx6_pcie_variants {
 #define IMX6_PCIE_FLAG_HAS_PHYDRV                      BIT(3)
 #define IMX6_PCIE_FLAG_HAS_APP_RESET           BIT(4)
 #define IMX6_PCIE_FLAG_HAS_PHY_RESET           BIT(5)
+#define IMX6_PCIE_FLAG_HAS_SERDES              BIT(6)
 
 #define imx6_check_flag(pci, val)     (pci->drvdata->flags & val)
 
@@ -179,6 +194,24 @@ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
        return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;
 }
 
+static int imx95_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+{
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                       IMX95_PCIE_SS_RW_REG_0,
+                       IMX95_PCIE_PHY_CR_PARA_SEL,
+                       IMX95_PCIE_PHY_CR_PARA_SEL);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                          IMX95_PCIE_PHY_GEN_CTRL,
+                          IMX95_PCIE_REF_USE_PAD, 0);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                          IMX95_PCIE_SS_RW_REG_0,
+                          IMX95_PCIE_REF_CLKEN,
+                          IMX95_PCIE_REF_CLKEN);
+
+       return 0;
+}
+
 static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
 {
        const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata;
@@ -575,6 +608,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
                                   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
                break;
        case IMX7D:
+       case IMX95:
                break;
        case IMX8MM:
        case IMX8MM_EP:
@@ -1279,12 +1313,32 @@ static int imx6_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(imx6_pcie->turnoff_reset);
        }
 
+       if (imx6_pcie->drvdata->gpr) {
        /* Grab GPR config register range */
-       imx6_pcie->iomuxc_gpr =
-                syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr);
-       if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
-               dev_err(dev, "unable to find iomuxc registers\n");
-               return PTR_ERR(imx6_pcie->iomuxc_gpr);
+               imx6_pcie->iomuxc_gpr =
+                        syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr);
+               if (IS_ERR(imx6_pcie->iomuxc_gpr))
+                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr),
+                                            "unable to find iomuxc registers\n");
+       }
+
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_SERDES)) {
+               void __iomem *off = devm_platform_ioremap_resource_byname(pdev, "app");
+
+               if (IS_ERR(off))
+                       return dev_err_probe(dev, PTR_ERR(off),
+                                            "unable to find serdes registers\n");
+
+               static const struct regmap_config regmap_config = {
+                       .reg_bits = 32,
+                       .val_bits = 32,
+                       .reg_stride = 4,
+               };
+
+               imx6_pcie->iomuxc_gpr = devm_regmap_init_mmio(dev, off, &regmap_config);
+               if (IS_ERR(imx6_pcie->iomuxc_gpr))
+                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr),
+                                            "unable to find iomuxc registers\n");
        }
 
        /* Grab PCIe PHY Tx Settings */
@@ -1457,6 +1511,17 @@ static const struct imx6_pcie_drvdata drvdata[] = {
                .mode_off[0] = IOMUXC_GPR12,
                .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
        },
+       [IMX95] = {
+               .variant = IMX95,
+               .flags = IMX6_PCIE_FLAG_HAS_SERDES,
+               .clk_names = imx8mq_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mq_clks),
+               .ltssm_off = IMX95_PE0_GEN_CTRL_3,
+               .ltssm_mask = IMX95_PCIE_LTSSM_EN,
+               .mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
+               .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
+               .init_phy = imx95_pcie_init_phy,
+       },
        [IMX8MQ_EP] = {
                .variant = IMX8MQ_EP,
                .flags = IMX6_PCIE_FLAG_HAS_APP_RESET |
@@ -1501,6 +1566,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {
        { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
        { .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
        { .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },
+       { .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], },
        { .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], },
        { .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], },
        { .compatible = "fsl,imx8mp-pcie-ep", .data = &drvdata[IMX8MP_EP], },