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
