PCI: imx6: Enable PHY internal regulator when supplied >3V
authorRichard Zhu <hongxing.zhu@nxp.com>
Fri, 4 Jun 2021 01:47:49 +0000 (09:47 +0800)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 24 Jun 2021 19:50:34 +0000 (14:50 -0500)
The i.MX8MQ PCIe PHY needs 1.8V in default but can be supplied by either a
1.8V or a 3.3V regulator.

The "vph-supply" DT property tells us which external regulator supplies the
PHY. If that regulator supplies anything over 3V, enable the PHY's internal
3.3V-to-1.8V regulator.

Link: https://lore.kernel.org/r/1622771269-13844-3-git-send-email-hongxing.zhu@nxp.com
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
drivers/pci/controller/dwc/pci-imx6.c

index dc48dd7cd7c5886acab6117ccca6de783bea077d..80fc98acf097f6ff85b2a34276a7cca80825e8d7 100644 (file)
@@ -37,6 +37,7 @@
 #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_GPR_PCIE_VREG_BYPASS            BIT(12)
 #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE    GENMASK(11, 8)
 #define IMX8MQ_PCIE2_BASE_ADDR                 0x33c00000
 
@@ -80,6 +81,7 @@ struct imx6_pcie {
        u32                     tx_swing_full;
        u32                     tx_swing_low;
        struct regulator        *vpcie;
+       struct regulator        *vph;
        void __iomem            *phy_base;
 
        /* power domain for pcie */
@@ -621,6 +623,17 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
                                   imx6_pcie_grp_offset(imx6_pcie),
                                   IMX8MQ_GPR_PCIE_REF_USE_PAD,
                                   IMX8MQ_GPR_PCIE_REF_USE_PAD);
+               /*
+                * Regarding the datasheet, the PCIE_VPH is suggested
+                * to be 1.8V. If the PCIE_VPH is supplied by 3.3V, the
+                * VREG_BYPASS should be cleared to zero.
+                */
+               if (imx6_pcie->vph &&
+                   regulator_get_voltage(imx6_pcie->vph) > 3000000)
+                       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                                          imx6_pcie_grp_offset(imx6_pcie),
+                                          IMX8MQ_GPR_PCIE_VREG_BYPASS,
+                                          0);
                break;
        case IMX7D:
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
@@ -1128,6 +1141,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
                imx6_pcie->vpcie = NULL;
        }
 
+       imx6_pcie->vph = devm_regulator_get_optional(&pdev->dev, "vph");
+       if (IS_ERR(imx6_pcie->vph)) {
+               if (PTR_ERR(imx6_pcie->vph) != -ENODEV)
+                       return PTR_ERR(imx6_pcie->vph);
+               imx6_pcie->vph = NULL;
+       }
+
        platform_set_drvdata(pdev, imx6_pcie);
 
        ret = imx6_pcie_attach_pd(dev);