1*80090810SAbel Vesa // SPDX-License-Identifier: GPL-2.0 2*80090810SAbel Vesa /* 3*80090810SAbel Vesa * Copyright (c) 2023, Linaro Limited 4*80090810SAbel Vesa */ 5*80090810SAbel Vesa 6*80090810SAbel Vesa #include <linux/clk.h> 7*80090810SAbel Vesa #include <linux/delay.h> 8*80090810SAbel Vesa #include <linux/phy/phy.h> 9*80090810SAbel Vesa #include <linux/platform_device.h> 10*80090810SAbel Vesa #include <linux/regulator/consumer.h> 11*80090810SAbel Vesa #include <linux/reset.h> 12*80090810SAbel Vesa 13*80090810SAbel Vesa #define USB_PHY_UTMI_CTRL0 (0x3c) 14*80090810SAbel Vesa #define SLEEPM BIT(0) 15*80090810SAbel Vesa #define OPMODE_MASK GENMASK(4, 3) 16*80090810SAbel Vesa #define OPMODE_NONDRIVING BIT(3) 17*80090810SAbel Vesa 18*80090810SAbel Vesa #define USB_PHY_UTMI_CTRL5 (0x50) 19*80090810SAbel Vesa #define POR BIT(1) 20*80090810SAbel Vesa 21*80090810SAbel Vesa #define USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) 22*80090810SAbel Vesa #define PHY_ENABLE BIT(0) 23*80090810SAbel Vesa #define SIDDQ_SEL BIT(1) 24*80090810SAbel Vesa #define SIDDQ BIT(2) 25*80090810SAbel Vesa #define RETENABLEN BIT(3) 26*80090810SAbel Vesa #define FSEL_MASK GENMASK(6, 4) 27*80090810SAbel Vesa #define FSEL_19_2_MHZ_VAL (0x0) 28*80090810SAbel Vesa #define FSEL_38_4_MHZ_VAL (0x4) 29*80090810SAbel Vesa 30*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_1 (0x58) 31*80090810SAbel Vesa #define PHY_CFG_PLL_CPBIAS_CNTRL_MASK GENMASK(7, 1) 32*80090810SAbel Vesa 33*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_2 (0x5c) 34*80090810SAbel Vesa #define PHY_CFG_PLL_FB_DIV_7_0_MASK GENMASK(7, 0) 35*80090810SAbel Vesa #define DIV_7_0_19_2_MHZ_VAL (0x90) 36*80090810SAbel Vesa #define DIV_7_0_38_4_MHZ_VAL (0xc8) 37*80090810SAbel Vesa 38*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_3 (0x60) 39*80090810SAbel Vesa #define PHY_CFG_PLL_FB_DIV_11_8_MASK GENMASK(3, 0) 40*80090810SAbel Vesa #define DIV_11_8_19_2_MHZ_VAL (0x1) 41*80090810SAbel Vesa #define DIV_11_8_38_4_MHZ_VAL (0x0) 42*80090810SAbel Vesa 43*80090810SAbel Vesa #define PHY_CFG_PLL_REF_DIV GENMASK(7, 4) 44*80090810SAbel Vesa #define PLL_REF_DIV_VAL (0x0) 45*80090810SAbel Vesa 46*80090810SAbel Vesa #define USB_PHY_HS_PHY_CTRL2 (0x64) 47*80090810SAbel Vesa #define VBUSVLDEXT0 BIT(0) 48*80090810SAbel Vesa #define USB2_SUSPEND_N BIT(2) 49*80090810SAbel Vesa #define USB2_SUSPEND_N_SEL BIT(3) 50*80090810SAbel Vesa #define VBUS_DET_EXT_SEL BIT(4) 51*80090810SAbel Vesa 52*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_4 (0x68) 53*80090810SAbel Vesa #define PHY_CFG_PLL_GMP_CNTRL_MASK GENMASK(1, 0) 54*80090810SAbel Vesa #define PHY_CFG_PLL_INT_CNTRL_MASK GENMASK(7, 2) 55*80090810SAbel Vesa 56*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_5 (0x6c) 57*80090810SAbel Vesa #define PHY_CFG_PLL_PROP_CNTRL_MASK GENMASK(4, 0) 58*80090810SAbel Vesa #define PHY_CFG_PLL_VREF_TUNE_MASK GENMASK(7, 6) 59*80090810SAbel Vesa 60*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_6 (0x70) 61*80090810SAbel Vesa #define PHY_CFG_PLL_VCO_CNTRL_MASK GENMASK(2, 0) 62*80090810SAbel Vesa 63*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_7 (0x74) 64*80090810SAbel Vesa 65*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_8 (0x78) 66*80090810SAbel Vesa #define PHY_CFG_TX_FSLS_VREF_TUNE_MASK GENMASK(1, 0) 67*80090810SAbel Vesa #define PHY_CFG_TX_FSLS_VREG_BYPASS BIT(2) 68*80090810SAbel Vesa #define PHY_CFG_TX_HS_VREF_TUNE_MASK GENMASK(5, 3) 69*80090810SAbel Vesa #define PHY_CFG_TX_HS_XV_TUNE_MASK GENMASK(7, 6) 70*80090810SAbel Vesa 71*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_9 (0x7c) 72*80090810SAbel Vesa #define PHY_CFG_TX_PREEMP_TUNE_MASK GENMASK(2, 0) 73*80090810SAbel Vesa #define PHY_CFG_TX_RES_TUNE_MASK GENMASK(4, 3) 74*80090810SAbel Vesa #define PHY_CFG_TX_RISE_TUNE_MASK GENMASK(6, 5) 75*80090810SAbel Vesa #define PHY_CFG_RCAL_BYPASS BIT(7) 76*80090810SAbel Vesa 77*80090810SAbel Vesa #define USB_PHY_CFG_CTRL_10 (0x80) 78*80090810SAbel Vesa 79*80090810SAbel Vesa #define USB_PHY_CFG0 (0x94) 80*80090810SAbel Vesa #define DATAPATH_CTRL_OVERRIDE_EN BIT(0) 81*80090810SAbel Vesa #define CMN_CTRL_OVERRIDE_EN BIT(1) 82*80090810SAbel Vesa 83*80090810SAbel Vesa #define UTMI_PHY_CMN_CTRL0 (0x98) 84*80090810SAbel Vesa #define TESTBURNIN BIT(6) 85*80090810SAbel Vesa 86*80090810SAbel Vesa #define USB_PHY_FSEL_SEL (0xb8) 87*80090810SAbel Vesa #define FSEL_SEL BIT(0) 88*80090810SAbel Vesa 89*80090810SAbel Vesa #define USB_PHY_APB_ACCESS_CMD (0x130) 90*80090810SAbel Vesa #define RW_ACCESS BIT(0) 91*80090810SAbel Vesa #define APB_START_CMD BIT(1) 92*80090810SAbel Vesa #define APB_LOGIC_RESET BIT(2) 93*80090810SAbel Vesa 94*80090810SAbel Vesa #define USB_PHY_APB_ACCESS_STATUS (0x134) 95*80090810SAbel Vesa #define ACCESS_DONE BIT(0) 96*80090810SAbel Vesa #define TIMED_OUT BIT(1) 97*80090810SAbel Vesa #define ACCESS_ERROR BIT(2) 98*80090810SAbel Vesa #define ACCESS_IN_PROGRESS BIT(3) 99*80090810SAbel Vesa 100*80090810SAbel Vesa #define USB_PHY_APB_ADDRESS (0x138) 101*80090810SAbel Vesa #define APB_REG_ADDR_MASK GENMASK(7, 0) 102*80090810SAbel Vesa 103*80090810SAbel Vesa #define USB_PHY_APB_WRDATA_LSB (0x13c) 104*80090810SAbel Vesa #define APB_REG_WRDATA_7_0_MASK GENMASK(3, 0) 105*80090810SAbel Vesa 106*80090810SAbel Vesa #define USB_PHY_APB_WRDATA_MSB (0x140) 107*80090810SAbel Vesa #define APB_REG_WRDATA_15_8_MASK GENMASK(7, 4) 108*80090810SAbel Vesa 109*80090810SAbel Vesa #define USB_PHY_APB_RDDATA_LSB (0x144) 110*80090810SAbel Vesa #define APB_REG_RDDATA_7_0_MASK GENMASK(3, 0) 111*80090810SAbel Vesa 112*80090810SAbel Vesa #define USB_PHY_APB_RDDATA_MSB (0x148) 113*80090810SAbel Vesa #define APB_REG_RDDATA_15_8_MASK GENMASK(7, 4) 114*80090810SAbel Vesa 115*80090810SAbel Vesa static const char * const eusb2_hsphy_vreg_names[] = { 116*80090810SAbel Vesa "vdd", "vdda12", 117*80090810SAbel Vesa }; 118*80090810SAbel Vesa 119*80090810SAbel Vesa #define EUSB2_NUM_VREGS ARRAY_SIZE(eusb2_hsphy_vreg_names) 120*80090810SAbel Vesa 121*80090810SAbel Vesa struct qcom_snps_eusb2_hsphy { 122*80090810SAbel Vesa struct phy *phy; 123*80090810SAbel Vesa void __iomem *base; 124*80090810SAbel Vesa 125*80090810SAbel Vesa struct clk *ref_clk; 126*80090810SAbel Vesa struct reset_control *phy_reset; 127*80090810SAbel Vesa 128*80090810SAbel Vesa struct regulator_bulk_data vregs[EUSB2_NUM_VREGS]; 129*80090810SAbel Vesa 130*80090810SAbel Vesa enum phy_mode mode; 131*80090810SAbel Vesa }; 132*80090810SAbel Vesa 133*80090810SAbel Vesa static int qcom_snps_eusb2_hsphy_set_mode(struct phy *p, enum phy_mode mode, int submode) 134*80090810SAbel Vesa { 135*80090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p); 136*80090810SAbel Vesa 137*80090810SAbel Vesa phy->mode = mode; 138*80090810SAbel Vesa 139*80090810SAbel Vesa return 0; 140*80090810SAbel Vesa } 141*80090810SAbel Vesa 142*80090810SAbel Vesa static void qcom_snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset, 143*80090810SAbel Vesa u32 mask, u32 val) 144*80090810SAbel Vesa { 145*80090810SAbel Vesa u32 reg; 146*80090810SAbel Vesa 147*80090810SAbel Vesa reg = readl_relaxed(base + offset); 148*80090810SAbel Vesa reg &= ~mask; 149*80090810SAbel Vesa reg |= val & mask; 150*80090810SAbel Vesa writel_relaxed(reg, base + offset); 151*80090810SAbel Vesa 152*80090810SAbel Vesa /* Ensure above write is completed */ 153*80090810SAbel Vesa readl_relaxed(base + offset); 154*80090810SAbel Vesa } 155*80090810SAbel Vesa 156*80090810SAbel Vesa static void qcom_eusb2_default_parameters(struct qcom_snps_eusb2_hsphy *phy) 157*80090810SAbel Vesa { 158*80090810SAbel Vesa /* default parameters: tx pre-emphasis */ 159*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9, 160*80090810SAbel Vesa PHY_CFG_TX_PREEMP_TUNE_MASK, 161*80090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_PREEMP_TUNE_MASK, 0)); 162*80090810SAbel Vesa 163*80090810SAbel Vesa /* tx rise/fall time */ 164*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9, 165*80090810SAbel Vesa PHY_CFG_TX_RISE_TUNE_MASK, 166*80090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_RISE_TUNE_MASK, 0x2)); 167*80090810SAbel Vesa 168*80090810SAbel Vesa /* source impedance adjustment */ 169*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9, 170*80090810SAbel Vesa PHY_CFG_TX_RES_TUNE_MASK, 171*80090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_RES_TUNE_MASK, 0x1)); 172*80090810SAbel Vesa 173*80090810SAbel Vesa /* dc voltage level adjustement */ 174*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_8, 175*80090810SAbel Vesa PHY_CFG_TX_HS_VREF_TUNE_MASK, 176*80090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_HS_VREF_TUNE_MASK, 0x3)); 177*80090810SAbel Vesa 178*80090810SAbel Vesa /* transmitter HS crossover adjustement */ 179*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_8, 180*80090810SAbel Vesa PHY_CFG_TX_HS_XV_TUNE_MASK, 181*80090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0)); 182*80090810SAbel Vesa } 183*80090810SAbel Vesa 184*80090810SAbel Vesa static int qcom_eusb2_ref_clk_init(struct qcom_snps_eusb2_hsphy *phy) 185*80090810SAbel Vesa { 186*80090810SAbel Vesa unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk); 187*80090810SAbel Vesa 188*80090810SAbel Vesa switch (ref_clk_freq) { 189*80090810SAbel Vesa case 19200000: 190*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 191*80090810SAbel Vesa FSEL_MASK, 192*80090810SAbel Vesa FIELD_PREP(FSEL_MASK, FSEL_19_2_MHZ_VAL)); 193*80090810SAbel Vesa 194*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_2, 195*80090810SAbel Vesa PHY_CFG_PLL_FB_DIV_7_0_MASK, 196*80090810SAbel Vesa DIV_7_0_19_2_MHZ_VAL); 197*80090810SAbel Vesa 198*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3, 199*80090810SAbel Vesa PHY_CFG_PLL_FB_DIV_11_8_MASK, 200*80090810SAbel Vesa DIV_11_8_19_2_MHZ_VAL); 201*80090810SAbel Vesa break; 202*80090810SAbel Vesa 203*80090810SAbel Vesa case 38400000: 204*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 205*80090810SAbel Vesa FSEL_MASK, 206*80090810SAbel Vesa FIELD_PREP(FSEL_MASK, FSEL_38_4_MHZ_VAL)); 207*80090810SAbel Vesa 208*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_2, 209*80090810SAbel Vesa PHY_CFG_PLL_FB_DIV_7_0_MASK, 210*80090810SAbel Vesa DIV_7_0_38_4_MHZ_VAL); 211*80090810SAbel Vesa 212*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3, 213*80090810SAbel Vesa PHY_CFG_PLL_FB_DIV_11_8_MASK, 214*80090810SAbel Vesa DIV_11_8_38_4_MHZ_VAL); 215*80090810SAbel Vesa break; 216*80090810SAbel Vesa 217*80090810SAbel Vesa default: 218*80090810SAbel Vesa dev_err(&phy->phy->dev, "unsupported ref_clk_freq:%lu\n", ref_clk_freq); 219*80090810SAbel Vesa return -EINVAL; 220*80090810SAbel Vesa } 221*80090810SAbel Vesa 222*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3, 223*80090810SAbel Vesa PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL); 224*80090810SAbel Vesa 225*80090810SAbel Vesa return 0; 226*80090810SAbel Vesa } 227*80090810SAbel Vesa 228*80090810SAbel Vesa static int qcom_snps_eusb2_hsphy_init(struct phy *p) 229*80090810SAbel Vesa { 230*80090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p); 231*80090810SAbel Vesa int ret; 232*80090810SAbel Vesa 233*80090810SAbel Vesa ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs); 234*80090810SAbel Vesa if (ret) 235*80090810SAbel Vesa return ret; 236*80090810SAbel Vesa 237*80090810SAbel Vesa ret = clk_prepare_enable(phy->ref_clk); 238*80090810SAbel Vesa if (ret) { 239*80090810SAbel Vesa dev_err(&p->dev, "failed to enable ref clock, %d\n", ret); 240*80090810SAbel Vesa goto disable_vreg; 241*80090810SAbel Vesa } 242*80090810SAbel Vesa 243*80090810SAbel Vesa ret = reset_control_assert(phy->phy_reset); 244*80090810SAbel Vesa if (ret) { 245*80090810SAbel Vesa dev_err(&p->dev, "failed to assert phy_reset, %d\n", ret); 246*80090810SAbel Vesa goto disable_ref_clk; 247*80090810SAbel Vesa } 248*80090810SAbel Vesa 249*80090810SAbel Vesa usleep_range(100, 150); 250*80090810SAbel Vesa 251*80090810SAbel Vesa ret = reset_control_deassert(phy->phy_reset); 252*80090810SAbel Vesa if (ret) { 253*80090810SAbel Vesa dev_err(&p->dev, "failed to de-assert phy_reset, %d\n", ret); 254*80090810SAbel Vesa goto disable_ref_clk; 255*80090810SAbel Vesa } 256*80090810SAbel Vesa 257*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG0, 258*80090810SAbel Vesa CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN); 259*80090810SAbel Vesa 260*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL5, POR, POR); 261*80090810SAbel Vesa 262*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 263*80090810SAbel Vesa PHY_ENABLE | RETENABLEN, PHY_ENABLE | RETENABLEN); 264*80090810SAbel Vesa 265*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_APB_ACCESS_CMD, 266*80090810SAbel Vesa APB_LOGIC_RESET, APB_LOGIC_RESET); 267*80090810SAbel Vesa 268*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, UTMI_PHY_CMN_CTRL0, TESTBURNIN, 0); 269*80090810SAbel Vesa 270*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_FSEL_SEL, 271*80090810SAbel Vesa FSEL_SEL, FSEL_SEL); 272*80090810SAbel Vesa 273*80090810SAbel Vesa /* update ref_clk related registers */ 274*80090810SAbel Vesa ret = qcom_eusb2_ref_clk_init(phy); 275*80090810SAbel Vesa if (ret) 276*80090810SAbel Vesa goto disable_ref_clk; 277*80090810SAbel Vesa 278*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_1, 279*80090810SAbel Vesa PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 280*80090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 0x1)); 281*80090810SAbel Vesa 282*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_4, 283*80090810SAbel Vesa PHY_CFG_PLL_INT_CNTRL_MASK, 284*80090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_INT_CNTRL_MASK, 0x8)); 285*80090810SAbel Vesa 286*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_4, 287*80090810SAbel Vesa PHY_CFG_PLL_GMP_CNTRL_MASK, 288*80090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_GMP_CNTRL_MASK, 0x1)); 289*80090810SAbel Vesa 290*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_5, 291*80090810SAbel Vesa PHY_CFG_PLL_PROP_CNTRL_MASK, 292*80090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_PROP_CNTRL_MASK, 0x10)); 293*80090810SAbel Vesa 294*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_6, 295*80090810SAbel Vesa PHY_CFG_PLL_VCO_CNTRL_MASK, 296*80090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_VCO_CNTRL_MASK, 0x0)); 297*80090810SAbel Vesa 298*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_5, 299*80090810SAbel Vesa PHY_CFG_PLL_VREF_TUNE_MASK, 300*80090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_VREF_TUNE_MASK, 0x1)); 301*80090810SAbel Vesa 302*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2, 303*80090810SAbel Vesa VBUS_DET_EXT_SEL, VBUS_DET_EXT_SEL); 304*80090810SAbel Vesa 305*80090810SAbel Vesa /* set default parameters */ 306*80090810SAbel Vesa qcom_eusb2_default_parameters(phy); 307*80090810SAbel Vesa 308*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2, 309*80090810SAbel Vesa USB2_SUSPEND_N_SEL | USB2_SUSPEND_N, 310*80090810SAbel Vesa USB2_SUSPEND_N_SEL | USB2_SUSPEND_N); 311*80090810SAbel Vesa 312*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL0, SLEEPM, SLEEPM); 313*80090810SAbel Vesa 314*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 315*80090810SAbel Vesa SIDDQ_SEL, SIDDQ_SEL); 316*80090810SAbel Vesa 317*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 318*80090810SAbel Vesa SIDDQ, 0); 319*80090810SAbel Vesa 320*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL5, POR, 0); 321*80090810SAbel Vesa 322*80090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2, 323*80090810SAbel Vesa USB2_SUSPEND_N_SEL, 0); 324*80090810SAbel Vesa 325*80090810SAbel Vesa return 0; 326*80090810SAbel Vesa 327*80090810SAbel Vesa disable_ref_clk: 328*80090810SAbel Vesa clk_disable_unprepare(phy->ref_clk); 329*80090810SAbel Vesa 330*80090810SAbel Vesa disable_vreg: 331*80090810SAbel Vesa regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs); 332*80090810SAbel Vesa 333*80090810SAbel Vesa return ret; 334*80090810SAbel Vesa } 335*80090810SAbel Vesa 336*80090810SAbel Vesa static int qcom_snps_eusb2_hsphy_exit(struct phy *p) 337*80090810SAbel Vesa { 338*80090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p); 339*80090810SAbel Vesa 340*80090810SAbel Vesa clk_disable_unprepare(phy->ref_clk); 341*80090810SAbel Vesa 342*80090810SAbel Vesa regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs); 343*80090810SAbel Vesa 344*80090810SAbel Vesa return 0; 345*80090810SAbel Vesa } 346*80090810SAbel Vesa 347*80090810SAbel Vesa static const struct phy_ops qcom_snps_eusb2_hsphy_ops = { 348*80090810SAbel Vesa .init = qcom_snps_eusb2_hsphy_init, 349*80090810SAbel Vesa .exit = qcom_snps_eusb2_hsphy_exit, 350*80090810SAbel Vesa .set_mode = qcom_snps_eusb2_hsphy_set_mode, 351*80090810SAbel Vesa .owner = THIS_MODULE, 352*80090810SAbel Vesa }; 353*80090810SAbel Vesa 354*80090810SAbel Vesa static int qcom_snps_eusb2_hsphy_probe(struct platform_device *pdev) 355*80090810SAbel Vesa { 356*80090810SAbel Vesa struct device *dev = &pdev->dev; 357*80090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy; 358*80090810SAbel Vesa struct phy_provider *phy_provider; 359*80090810SAbel Vesa struct phy *generic_phy; 360*80090810SAbel Vesa int ret, i; 361*80090810SAbel Vesa int num; 362*80090810SAbel Vesa 363*80090810SAbel Vesa phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); 364*80090810SAbel Vesa if (!phy) 365*80090810SAbel Vesa return -ENOMEM; 366*80090810SAbel Vesa 367*80090810SAbel Vesa phy->base = devm_platform_ioremap_resource(pdev, 0); 368*80090810SAbel Vesa if (IS_ERR(phy->base)) 369*80090810SAbel Vesa return PTR_ERR(phy->base); 370*80090810SAbel Vesa 371*80090810SAbel Vesa phy->phy_reset = devm_reset_control_get_exclusive(dev, NULL); 372*80090810SAbel Vesa if (IS_ERR(phy->phy_reset)) 373*80090810SAbel Vesa return PTR_ERR(phy->phy_reset); 374*80090810SAbel Vesa 375*80090810SAbel Vesa phy->ref_clk = devm_clk_get(dev, "ref"); 376*80090810SAbel Vesa if (IS_ERR(phy->ref_clk)) 377*80090810SAbel Vesa return dev_err_probe(dev, PTR_ERR(phy->ref_clk), 378*80090810SAbel Vesa "failed to get ref clk\n"); 379*80090810SAbel Vesa 380*80090810SAbel Vesa num = ARRAY_SIZE(phy->vregs); 381*80090810SAbel Vesa for (i = 0; i < num; i++) 382*80090810SAbel Vesa phy->vregs[i].supply = eusb2_hsphy_vreg_names[i]; 383*80090810SAbel Vesa 384*80090810SAbel Vesa ret = devm_regulator_bulk_get(dev, num, phy->vregs); 385*80090810SAbel Vesa if (ret) 386*80090810SAbel Vesa return dev_err_probe(dev, ret, 387*80090810SAbel Vesa "failed to get regulator supplies\n"); 388*80090810SAbel Vesa generic_phy = devm_phy_create(dev, NULL, &qcom_snps_eusb2_hsphy_ops); 389*80090810SAbel Vesa if (IS_ERR(generic_phy)) { 390*80090810SAbel Vesa dev_err(dev, "failed to create phy %d\n", ret); 391*80090810SAbel Vesa return PTR_ERR(generic_phy); 392*80090810SAbel Vesa } 393*80090810SAbel Vesa 394*80090810SAbel Vesa dev_set_drvdata(dev, phy); 395*80090810SAbel Vesa phy_set_drvdata(generic_phy, phy); 396*80090810SAbel Vesa 397*80090810SAbel Vesa phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 398*80090810SAbel Vesa if (IS_ERR(phy_provider)) 399*80090810SAbel Vesa return PTR_ERR(phy_provider); 400*80090810SAbel Vesa 401*80090810SAbel Vesa dev_info(dev, "Registered Qcom-eUSB2 phy\n"); 402*80090810SAbel Vesa 403*80090810SAbel Vesa return 0; 404*80090810SAbel Vesa } 405*80090810SAbel Vesa 406*80090810SAbel Vesa static const struct of_device_id qcom_snps_eusb2_hsphy_of_match_table[] = { 407*80090810SAbel Vesa { .compatible = "qcom,sm8550-snps-eusb2-phy", }, 408*80090810SAbel Vesa { }, 409*80090810SAbel Vesa }; 410*80090810SAbel Vesa MODULE_DEVICE_TABLE(of, qcom_snps_eusb2_hsphy_of_match_table); 411*80090810SAbel Vesa 412*80090810SAbel Vesa static struct platform_driver qcom_snps_eusb2_hsphy_driver = { 413*80090810SAbel Vesa .probe = qcom_snps_eusb2_hsphy_probe, 414*80090810SAbel Vesa .driver = { 415*80090810SAbel Vesa .name = "qcom-snps-eusb2-hsphy", 416*80090810SAbel Vesa .of_match_table = qcom_snps_eusb2_hsphy_of_match_table, 417*80090810SAbel Vesa }, 418*80090810SAbel Vesa }; 419*80090810SAbel Vesa 420*80090810SAbel Vesa module_platform_driver(qcom_snps_eusb2_hsphy_driver); 421*80090810SAbel Vesa MODULE_DESCRIPTION("Qualcomm SNPS eUSB2 HS PHY driver"); 422*80090810SAbel Vesa MODULE_LICENSE("GPL"); 423