IPQ9650 requires a different PHY sequence compared to the existing SNPS
femto v2 PHY init. Introduce a per-compatible init callback and add the
IPQ9650-specific sequence, selected via the new "qcom,ipq9650-usb-hs-phy"
compatible.

Signed-off-by: Badhrinath S <[email protected]>
---
 drivers/phy/qcom/phy-qcom-snps-femto-v2.c | 122 +++++++++++++++++++++-
 1 file changed, 117 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/qcom/phy-qcom-snps-femto-v2.c 
b/drivers/phy/qcom/phy-qcom-snps-femto-v2.c
index bf1f16e4a22f..489bc8706975 100644
--- a/drivers/phy/qcom/phy-qcom-snps-femto-v2.c
+++ b/drivers/phy/qcom/phy-qcom-snps-femto-v2.c
@@ -28,12 +28,15 @@
 
 #define USB2_PHY_USB_PHY_UTMI_CTRL5 (0x50)
 #define POR BIT(1)
+#define ATERESET BIT(0)
 
 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54)
 #define SIDDQ BIT(2)
 #define RETENABLEN BIT(3)
 #define FSEL_MASK GENMASK(6, 4)
 #define FSEL_DEFAULT (0x3 << 4)
+#define FSEL_24MHZ (0x2 << 4)
+#define VATESTENB_MASK GENMASK(1, 0)
 
 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58)
 #define VBUSVLDEXTSEL0 BIT(4)
@@ -50,6 +53,16 @@
 #define USB2_SUSPEND_N BIT(2)
 #define USB2_SUSPEND_N_SEL BIT(3)
 
+#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1 (0x70)
+#define TXPREEMPAMPTUNE0_MASK GENMASK(7, 6)
+
+#define USB2_PHY_USB_PHY_HS_PHY_TEST0 (0x80)
+#define TESTDATAIN_MASK GENMASK(7, 0)
+
+#define USB2_PHY_USB_PHY_HS_PHY_TEST1 (0x84)
+#define TESTDATAOUTSEL BIT(4)
+#define TESTCLK BIT(6)
+
 #define USB2_PHY_USB_PHY_CFG0 (0x94)
 #define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0)
 #define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1)
@@ -58,6 +71,12 @@
 #define REFCLK_SEL_MASK GENMASK(1, 0)
 #define REFCLK_SEL_DEFAULT (0x2 << 0)
 
+#define USB2_PHY_USB_PHY_FSEL_SEL (0xb8)
+#define FSEL_SEL BIT(0)
+
+/* Special delay values */
+#define DELAY_MIN_US 10
+
 struct qcom_snps_hsphy {
        void __iomem *base;
        struct reset_ctl_bulk resets;
@@ -135,16 +154,108 @@ static int qcom_snps_hsphy_usb_init(struct phy *phy)
        return 0;
 }
 
+static int ipq9650_hsphy_usb_init(struct phy *phy)
+{
+       struct qcom_snps_hsphy *priv = dev_get_priv(phy->dev);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_CFG0,
+                                  UTMI_PHY_CMN_CTRL_OVERRIDE_EN,
+                                  UTMI_PHY_CMN_CTRL_OVERRIDE_EN);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
+                                  POR, POR);
+       udelay(DELAY_MIN_US + 10);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_FSEL_SEL,
+                                  FSEL_SEL, FSEL_SEL);
+
+       qcom_snps_hsphy_write_mask(priv->base,
+                                  USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
+                                  FSEL_MASK, FSEL_24MHZ);
+
+       qcom_snps_hsphy_write_mask(priv->base,
+                                  USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
+                                  PLLBTUNE, PLLBTUNE);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_REFCLK_CTRL,
+                                  REFCLK_SEL_MASK, REFCLK_SEL_DEFAULT);
+
+       qcom_snps_hsphy_write_mask(priv->base,
+                                  USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
+                                  VBUSVLDEXTSEL0, VBUSVLDEXTSEL0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
+                                  VBUSVLDEXT0, VBUSVLDEXT0);
+
+       qcom_snps_hsphy_write_mask(priv->base,
+                                  USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
+                                  TXPREEMPAMPTUNE0_MASK, (0x1 << 6));
+
+       qcom_snps_hsphy_write_mask(priv->base,
+                                  USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
+                                  VREGBYPASS, VREGBYPASS);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
+                                  ATERESET, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_TEST1,
+                                  TESTDATAOUTSEL, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_TEST1,
+                                  TESTCLK, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base,
+                                  USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
+                                  VATESTENB_MASK, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_TEST0,
+                                  TESTDATAIN_MASK, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
+                                  USB2_SUSPEND_N_SEL, USB2_SUSPEND_N_SEL);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
+                                  USB2_SUSPEND_N, USB2_SUSPEND_N);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_UTMI_CTRL0,
+                                  SLEEPM, SLEEPM);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
+                                  POR, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
+                                  USB2_SUSPEND_N_SEL, 0);
+
+       qcom_snps_hsphy_write_mask(priv->base, USB2_PHY_USB_PHY_CFG0,
+                                  UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0);
+
+       return 0;
+}
+
+struct hsphy_data {
+       int (*init)(struct phy *phy);
+};
+
+static const struct hsphy_data hsphy_data_default = {
+       .init = qcom_snps_hsphy_usb_init,
+};
+
+static const struct hsphy_data hsphy_data_ipq9650 = {
+       .init = ipq9650_hsphy_usb_init,
+};
+
 static int qcom_snps_hsphy_power_on(struct phy *phy)
 {
        struct qcom_snps_hsphy *priv = dev_get_priv(phy->dev);
+       const struct hsphy_data *data =
+               (const struct hsphy_data *)dev_get_driver_data(phy->dev);
        int ret;
 
        ret = reset_deassert_bulk(&priv->resets);
        if (ret)
                return ret;
 
-       ret = qcom_snps_hsphy_usb_init(phy);
+       ret = data->init(phy);
        if (ret)
                return ret;
 
@@ -186,10 +297,11 @@ static struct phy_ops qcom_snps_hsphy_phy_ops = {
 };
 
 static const struct udevice_id qcom_snps_hsphy_phy_ids[] = {
-       { .compatible = "qcom,sm8150-usb-hs-phy" },
-       { .compatible = "qcom,usb-snps-hs-5nm-phy" },
-       { .compatible = "qcom,usb-snps-hs-7nm-phy" },
-       { .compatible = "qcom,usb-snps-femto-v2-phy" },
+       { .compatible = "qcom,sm8150-usb-hs-phy", .data = 
(ulong)&hsphy_data_default },
+       { .compatible = "qcom,usb-snps-hs-5nm-phy", .data = 
(ulong)&hsphy_data_default },
+       { .compatible = "qcom,usb-snps-hs-7nm-phy", .data = 
(ulong)&hsphy_data_default },
+       { .compatible = "qcom,usb-snps-femto-v2-phy", .data = 
(ulong)&hsphy_data_default },
+       { .compatible = "qcom,ipq9650-usb-hs-phy", .data = 
(ulong)&hsphy_data_ipq9650 },
        {}
 };
 
-- 
2.34.1

Reply via email to