180090810SAbel Vesa // SPDX-License-Identifier: GPL-2.0 280090810SAbel Vesa /* 380090810SAbel Vesa * Copyright (c) 2023, Linaro Limited 480090810SAbel Vesa */ 580090810SAbel Vesa 6037d05afSVinod Koul #include <linux/bitfield.h> 780090810SAbel Vesa #include <linux/clk.h> 880090810SAbel Vesa #include <linux/delay.h> 9037d05afSVinod Koul #include <linux/iopoll.h> 1080090810SAbel Vesa #include <linux/phy/phy.h> 1180090810SAbel Vesa #include <linux/platform_device.h> 1280090810SAbel Vesa #include <linux/regulator/consumer.h> 1380090810SAbel Vesa #include <linux/reset.h> 1480090810SAbel Vesa 1580090810SAbel Vesa #define USB_PHY_UTMI_CTRL0 (0x3c) 1680090810SAbel Vesa #define SLEEPM BIT(0) 1780090810SAbel Vesa #define OPMODE_MASK GENMASK(4, 3) 1880090810SAbel Vesa #define OPMODE_NONDRIVING BIT(3) 1980090810SAbel Vesa 2080090810SAbel Vesa #define USB_PHY_UTMI_CTRL5 (0x50) 2180090810SAbel Vesa #define POR BIT(1) 2280090810SAbel Vesa 2380090810SAbel Vesa #define USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) 2480090810SAbel Vesa #define PHY_ENABLE BIT(0) 2580090810SAbel Vesa #define SIDDQ_SEL BIT(1) 2680090810SAbel Vesa #define SIDDQ BIT(2) 2780090810SAbel Vesa #define RETENABLEN BIT(3) 2880090810SAbel Vesa #define FSEL_MASK GENMASK(6, 4) 2980090810SAbel Vesa #define FSEL_19_2_MHZ_VAL (0x0) 3080090810SAbel Vesa #define FSEL_38_4_MHZ_VAL (0x4) 3180090810SAbel Vesa 3280090810SAbel Vesa #define USB_PHY_CFG_CTRL_1 (0x58) 3380090810SAbel Vesa #define PHY_CFG_PLL_CPBIAS_CNTRL_MASK GENMASK(7, 1) 3480090810SAbel Vesa 3580090810SAbel Vesa #define USB_PHY_CFG_CTRL_2 (0x5c) 3680090810SAbel Vesa #define PHY_CFG_PLL_FB_DIV_7_0_MASK GENMASK(7, 0) 3780090810SAbel Vesa #define DIV_7_0_19_2_MHZ_VAL (0x90) 3880090810SAbel Vesa #define DIV_7_0_38_4_MHZ_VAL (0xc8) 3980090810SAbel Vesa 4080090810SAbel Vesa #define USB_PHY_CFG_CTRL_3 (0x60) 4180090810SAbel Vesa #define PHY_CFG_PLL_FB_DIV_11_8_MASK GENMASK(3, 0) 4280090810SAbel Vesa #define DIV_11_8_19_2_MHZ_VAL (0x1) 4380090810SAbel Vesa #define DIV_11_8_38_4_MHZ_VAL (0x0) 4480090810SAbel Vesa 4580090810SAbel Vesa #define PHY_CFG_PLL_REF_DIV GENMASK(7, 4) 4680090810SAbel Vesa #define PLL_REF_DIV_VAL (0x0) 4780090810SAbel Vesa 4880090810SAbel Vesa #define USB_PHY_HS_PHY_CTRL2 (0x64) 4980090810SAbel Vesa #define VBUSVLDEXT0 BIT(0) 5080090810SAbel Vesa #define USB2_SUSPEND_N BIT(2) 5180090810SAbel Vesa #define USB2_SUSPEND_N_SEL BIT(3) 5280090810SAbel Vesa #define VBUS_DET_EXT_SEL BIT(4) 5380090810SAbel Vesa 5480090810SAbel Vesa #define USB_PHY_CFG_CTRL_4 (0x68) 5580090810SAbel Vesa #define PHY_CFG_PLL_GMP_CNTRL_MASK GENMASK(1, 0) 5680090810SAbel Vesa #define PHY_CFG_PLL_INT_CNTRL_MASK GENMASK(7, 2) 5780090810SAbel Vesa 5880090810SAbel Vesa #define USB_PHY_CFG_CTRL_5 (0x6c) 5980090810SAbel Vesa #define PHY_CFG_PLL_PROP_CNTRL_MASK GENMASK(4, 0) 6080090810SAbel Vesa #define PHY_CFG_PLL_VREF_TUNE_MASK GENMASK(7, 6) 6180090810SAbel Vesa 6280090810SAbel Vesa #define USB_PHY_CFG_CTRL_6 (0x70) 6380090810SAbel Vesa #define PHY_CFG_PLL_VCO_CNTRL_MASK GENMASK(2, 0) 6480090810SAbel Vesa 6580090810SAbel Vesa #define USB_PHY_CFG_CTRL_7 (0x74) 6680090810SAbel Vesa 6780090810SAbel Vesa #define USB_PHY_CFG_CTRL_8 (0x78) 6880090810SAbel Vesa #define PHY_CFG_TX_FSLS_VREF_TUNE_MASK GENMASK(1, 0) 6980090810SAbel Vesa #define PHY_CFG_TX_FSLS_VREG_BYPASS BIT(2) 7080090810SAbel Vesa #define PHY_CFG_TX_HS_VREF_TUNE_MASK GENMASK(5, 3) 7180090810SAbel Vesa #define PHY_CFG_TX_HS_XV_TUNE_MASK GENMASK(7, 6) 7280090810SAbel Vesa 7380090810SAbel Vesa #define USB_PHY_CFG_CTRL_9 (0x7c) 7480090810SAbel Vesa #define PHY_CFG_TX_PREEMP_TUNE_MASK GENMASK(2, 0) 7580090810SAbel Vesa #define PHY_CFG_TX_RES_TUNE_MASK GENMASK(4, 3) 7680090810SAbel Vesa #define PHY_CFG_TX_RISE_TUNE_MASK GENMASK(6, 5) 7780090810SAbel Vesa #define PHY_CFG_RCAL_BYPASS BIT(7) 7880090810SAbel Vesa 7980090810SAbel Vesa #define USB_PHY_CFG_CTRL_10 (0x80) 8080090810SAbel Vesa 8180090810SAbel Vesa #define USB_PHY_CFG0 (0x94) 8280090810SAbel Vesa #define DATAPATH_CTRL_OVERRIDE_EN BIT(0) 8380090810SAbel Vesa #define CMN_CTRL_OVERRIDE_EN BIT(1) 8480090810SAbel Vesa 8580090810SAbel Vesa #define UTMI_PHY_CMN_CTRL0 (0x98) 8680090810SAbel Vesa #define TESTBURNIN BIT(6) 8780090810SAbel Vesa 8880090810SAbel Vesa #define USB_PHY_FSEL_SEL (0xb8) 8980090810SAbel Vesa #define FSEL_SEL BIT(0) 9080090810SAbel Vesa 9180090810SAbel Vesa #define USB_PHY_APB_ACCESS_CMD (0x130) 9280090810SAbel Vesa #define RW_ACCESS BIT(0) 9380090810SAbel Vesa #define APB_START_CMD BIT(1) 9480090810SAbel Vesa #define APB_LOGIC_RESET BIT(2) 9580090810SAbel Vesa 9680090810SAbel Vesa #define USB_PHY_APB_ACCESS_STATUS (0x134) 9780090810SAbel Vesa #define ACCESS_DONE BIT(0) 9880090810SAbel Vesa #define TIMED_OUT BIT(1) 9980090810SAbel Vesa #define ACCESS_ERROR BIT(2) 10080090810SAbel Vesa #define ACCESS_IN_PROGRESS BIT(3) 10180090810SAbel Vesa 10280090810SAbel Vesa #define USB_PHY_APB_ADDRESS (0x138) 10380090810SAbel Vesa #define APB_REG_ADDR_MASK GENMASK(7, 0) 10480090810SAbel Vesa 10580090810SAbel Vesa #define USB_PHY_APB_WRDATA_LSB (0x13c) 10680090810SAbel Vesa #define APB_REG_WRDATA_7_0_MASK GENMASK(3, 0) 10780090810SAbel Vesa 10880090810SAbel Vesa #define USB_PHY_APB_WRDATA_MSB (0x140) 10980090810SAbel Vesa #define APB_REG_WRDATA_15_8_MASK GENMASK(7, 4) 11080090810SAbel Vesa 11180090810SAbel Vesa #define USB_PHY_APB_RDDATA_LSB (0x144) 11280090810SAbel Vesa #define APB_REG_RDDATA_7_0_MASK GENMASK(3, 0) 11380090810SAbel Vesa 11480090810SAbel Vesa #define USB_PHY_APB_RDDATA_MSB (0x148) 11580090810SAbel Vesa #define APB_REG_RDDATA_15_8_MASK GENMASK(7, 4) 11680090810SAbel Vesa 11780090810SAbel Vesa static const char * const eusb2_hsphy_vreg_names[] = { 11880090810SAbel Vesa "vdd", "vdda12", 11980090810SAbel Vesa }; 12080090810SAbel Vesa 12180090810SAbel Vesa #define EUSB2_NUM_VREGS ARRAY_SIZE(eusb2_hsphy_vreg_names) 12280090810SAbel Vesa 12380090810SAbel Vesa struct qcom_snps_eusb2_hsphy { 12480090810SAbel Vesa struct phy *phy; 12580090810SAbel Vesa void __iomem *base; 12680090810SAbel Vesa 12780090810SAbel Vesa struct clk *ref_clk; 12880090810SAbel Vesa struct reset_control *phy_reset; 12980090810SAbel Vesa 13080090810SAbel Vesa struct regulator_bulk_data vregs[EUSB2_NUM_VREGS]; 13180090810SAbel Vesa 13280090810SAbel Vesa enum phy_mode mode; 133*3584f639SNeil Armstrong 134*3584f639SNeil Armstrong struct phy *repeater; 13580090810SAbel Vesa }; 13680090810SAbel Vesa 13780090810SAbel Vesa static int qcom_snps_eusb2_hsphy_set_mode(struct phy *p, enum phy_mode mode, int submode) 13880090810SAbel Vesa { 13980090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p); 14080090810SAbel Vesa 14180090810SAbel Vesa phy->mode = mode; 14280090810SAbel Vesa 143*3584f639SNeil Armstrong return phy_set_mode_ext(phy->repeater, mode, submode); 14480090810SAbel Vesa } 14580090810SAbel Vesa 14680090810SAbel Vesa static void qcom_snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset, 14780090810SAbel Vesa u32 mask, u32 val) 14880090810SAbel Vesa { 14980090810SAbel Vesa u32 reg; 15080090810SAbel Vesa 15180090810SAbel Vesa reg = readl_relaxed(base + offset); 15280090810SAbel Vesa reg &= ~mask; 15380090810SAbel Vesa reg |= val & mask; 15480090810SAbel Vesa writel_relaxed(reg, base + offset); 15580090810SAbel Vesa 15680090810SAbel Vesa /* Ensure above write is completed */ 15780090810SAbel Vesa readl_relaxed(base + offset); 15880090810SAbel Vesa } 15980090810SAbel Vesa 16080090810SAbel Vesa static void qcom_eusb2_default_parameters(struct qcom_snps_eusb2_hsphy *phy) 16180090810SAbel Vesa { 16280090810SAbel Vesa /* default parameters: tx pre-emphasis */ 16380090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9, 16480090810SAbel Vesa PHY_CFG_TX_PREEMP_TUNE_MASK, 16580090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_PREEMP_TUNE_MASK, 0)); 16680090810SAbel Vesa 16780090810SAbel Vesa /* tx rise/fall time */ 16880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9, 16980090810SAbel Vesa PHY_CFG_TX_RISE_TUNE_MASK, 17080090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_RISE_TUNE_MASK, 0x2)); 17180090810SAbel Vesa 17280090810SAbel Vesa /* source impedance adjustment */ 17380090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9, 17480090810SAbel Vesa PHY_CFG_TX_RES_TUNE_MASK, 17580090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_RES_TUNE_MASK, 0x1)); 17680090810SAbel Vesa 17780090810SAbel Vesa /* dc voltage level adjustement */ 17880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_8, 17980090810SAbel Vesa PHY_CFG_TX_HS_VREF_TUNE_MASK, 18080090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_HS_VREF_TUNE_MASK, 0x3)); 18180090810SAbel Vesa 18280090810SAbel Vesa /* transmitter HS crossover adjustement */ 18380090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_8, 18480090810SAbel Vesa PHY_CFG_TX_HS_XV_TUNE_MASK, 18580090810SAbel Vesa FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0)); 18680090810SAbel Vesa } 18780090810SAbel Vesa 18880090810SAbel Vesa static int qcom_eusb2_ref_clk_init(struct qcom_snps_eusb2_hsphy *phy) 18980090810SAbel Vesa { 19080090810SAbel Vesa unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk); 19180090810SAbel Vesa 19280090810SAbel Vesa switch (ref_clk_freq) { 19380090810SAbel Vesa case 19200000: 19480090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 19580090810SAbel Vesa FSEL_MASK, 19680090810SAbel Vesa FIELD_PREP(FSEL_MASK, FSEL_19_2_MHZ_VAL)); 19780090810SAbel Vesa 19880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_2, 19980090810SAbel Vesa PHY_CFG_PLL_FB_DIV_7_0_MASK, 20080090810SAbel Vesa DIV_7_0_19_2_MHZ_VAL); 20180090810SAbel Vesa 20280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3, 20380090810SAbel Vesa PHY_CFG_PLL_FB_DIV_11_8_MASK, 20480090810SAbel Vesa DIV_11_8_19_2_MHZ_VAL); 20580090810SAbel Vesa break; 20680090810SAbel Vesa 20780090810SAbel Vesa case 38400000: 20880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 20980090810SAbel Vesa FSEL_MASK, 21080090810SAbel Vesa FIELD_PREP(FSEL_MASK, FSEL_38_4_MHZ_VAL)); 21180090810SAbel Vesa 21280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_2, 21380090810SAbel Vesa PHY_CFG_PLL_FB_DIV_7_0_MASK, 21480090810SAbel Vesa DIV_7_0_38_4_MHZ_VAL); 21580090810SAbel Vesa 21680090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3, 21780090810SAbel Vesa PHY_CFG_PLL_FB_DIV_11_8_MASK, 21880090810SAbel Vesa DIV_11_8_38_4_MHZ_VAL); 21980090810SAbel Vesa break; 22080090810SAbel Vesa 22180090810SAbel Vesa default: 22280090810SAbel Vesa dev_err(&phy->phy->dev, "unsupported ref_clk_freq:%lu\n", ref_clk_freq); 22380090810SAbel Vesa return -EINVAL; 22480090810SAbel Vesa } 22580090810SAbel Vesa 22680090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3, 22780090810SAbel Vesa PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL); 22880090810SAbel Vesa 22980090810SAbel Vesa return 0; 23080090810SAbel Vesa } 23180090810SAbel Vesa 23280090810SAbel Vesa static int qcom_snps_eusb2_hsphy_init(struct phy *p) 23380090810SAbel Vesa { 23480090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p); 23580090810SAbel Vesa int ret; 23680090810SAbel Vesa 23780090810SAbel Vesa ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs); 23880090810SAbel Vesa if (ret) 23980090810SAbel Vesa return ret; 24080090810SAbel Vesa 241*3584f639SNeil Armstrong ret = phy_init(phy->repeater); 242*3584f639SNeil Armstrong if (ret) { 243*3584f639SNeil Armstrong dev_err(&p->dev, "repeater init failed. %d\n", ret); 244*3584f639SNeil Armstrong goto disable_vreg; 245*3584f639SNeil Armstrong } 246*3584f639SNeil Armstrong 24780090810SAbel Vesa ret = clk_prepare_enable(phy->ref_clk); 24880090810SAbel Vesa if (ret) { 24980090810SAbel Vesa dev_err(&p->dev, "failed to enable ref clock, %d\n", ret); 25080090810SAbel Vesa goto disable_vreg; 25180090810SAbel Vesa } 25280090810SAbel Vesa 25380090810SAbel Vesa ret = reset_control_assert(phy->phy_reset); 25480090810SAbel Vesa if (ret) { 25580090810SAbel Vesa dev_err(&p->dev, "failed to assert phy_reset, %d\n", ret); 25680090810SAbel Vesa goto disable_ref_clk; 25780090810SAbel Vesa } 25880090810SAbel Vesa 25980090810SAbel Vesa usleep_range(100, 150); 26080090810SAbel Vesa 26180090810SAbel Vesa ret = reset_control_deassert(phy->phy_reset); 26280090810SAbel Vesa if (ret) { 26380090810SAbel Vesa dev_err(&p->dev, "failed to de-assert phy_reset, %d\n", ret); 26480090810SAbel Vesa goto disable_ref_clk; 26580090810SAbel Vesa } 26680090810SAbel Vesa 26780090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG0, 26880090810SAbel Vesa CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN); 26980090810SAbel Vesa 27080090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL5, POR, POR); 27180090810SAbel Vesa 27280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 27380090810SAbel Vesa PHY_ENABLE | RETENABLEN, PHY_ENABLE | RETENABLEN); 27480090810SAbel Vesa 27580090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_APB_ACCESS_CMD, 27680090810SAbel Vesa APB_LOGIC_RESET, APB_LOGIC_RESET); 27780090810SAbel Vesa 27880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, UTMI_PHY_CMN_CTRL0, TESTBURNIN, 0); 27980090810SAbel Vesa 28080090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_FSEL_SEL, 28180090810SAbel Vesa FSEL_SEL, FSEL_SEL); 28280090810SAbel Vesa 28380090810SAbel Vesa /* update ref_clk related registers */ 28480090810SAbel Vesa ret = qcom_eusb2_ref_clk_init(phy); 28580090810SAbel Vesa if (ret) 28680090810SAbel Vesa goto disable_ref_clk; 28780090810SAbel Vesa 28880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_1, 28980090810SAbel Vesa PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 29080090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 0x1)); 29180090810SAbel Vesa 29280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_4, 29380090810SAbel Vesa PHY_CFG_PLL_INT_CNTRL_MASK, 29480090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_INT_CNTRL_MASK, 0x8)); 29580090810SAbel Vesa 29680090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_4, 29780090810SAbel Vesa PHY_CFG_PLL_GMP_CNTRL_MASK, 29880090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_GMP_CNTRL_MASK, 0x1)); 29980090810SAbel Vesa 30080090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_5, 30180090810SAbel Vesa PHY_CFG_PLL_PROP_CNTRL_MASK, 30280090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_PROP_CNTRL_MASK, 0x10)); 30380090810SAbel Vesa 30480090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_6, 30580090810SAbel Vesa PHY_CFG_PLL_VCO_CNTRL_MASK, 30680090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_VCO_CNTRL_MASK, 0x0)); 30780090810SAbel Vesa 30880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_5, 30980090810SAbel Vesa PHY_CFG_PLL_VREF_TUNE_MASK, 31080090810SAbel Vesa FIELD_PREP(PHY_CFG_PLL_VREF_TUNE_MASK, 0x1)); 31180090810SAbel Vesa 31280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2, 31380090810SAbel Vesa VBUS_DET_EXT_SEL, VBUS_DET_EXT_SEL); 31480090810SAbel Vesa 31580090810SAbel Vesa /* set default parameters */ 31680090810SAbel Vesa qcom_eusb2_default_parameters(phy); 31780090810SAbel Vesa 31880090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2, 31980090810SAbel Vesa USB2_SUSPEND_N_SEL | USB2_SUSPEND_N, 32080090810SAbel Vesa USB2_SUSPEND_N_SEL | USB2_SUSPEND_N); 32180090810SAbel Vesa 32280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL0, SLEEPM, SLEEPM); 32380090810SAbel Vesa 32480090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 32580090810SAbel Vesa SIDDQ_SEL, SIDDQ_SEL); 32680090810SAbel Vesa 32780090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0, 32880090810SAbel Vesa SIDDQ, 0); 32980090810SAbel Vesa 33080090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL5, POR, 0); 33180090810SAbel Vesa 33280090810SAbel Vesa qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2, 33380090810SAbel Vesa USB2_SUSPEND_N_SEL, 0); 33480090810SAbel Vesa 33580090810SAbel Vesa return 0; 33680090810SAbel Vesa 33780090810SAbel Vesa disable_ref_clk: 33880090810SAbel Vesa clk_disable_unprepare(phy->ref_clk); 33980090810SAbel Vesa 34080090810SAbel Vesa disable_vreg: 34180090810SAbel Vesa regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs); 34280090810SAbel Vesa 34380090810SAbel Vesa return ret; 34480090810SAbel Vesa } 34580090810SAbel Vesa 34680090810SAbel Vesa static int qcom_snps_eusb2_hsphy_exit(struct phy *p) 34780090810SAbel Vesa { 34880090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p); 34980090810SAbel Vesa 35080090810SAbel Vesa clk_disable_unprepare(phy->ref_clk); 35180090810SAbel Vesa 35280090810SAbel Vesa regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs); 35380090810SAbel Vesa 354*3584f639SNeil Armstrong phy_exit(phy->repeater); 355*3584f639SNeil Armstrong 35680090810SAbel Vesa return 0; 35780090810SAbel Vesa } 35880090810SAbel Vesa 35980090810SAbel Vesa static const struct phy_ops qcom_snps_eusb2_hsphy_ops = { 36080090810SAbel Vesa .init = qcom_snps_eusb2_hsphy_init, 36180090810SAbel Vesa .exit = qcom_snps_eusb2_hsphy_exit, 36280090810SAbel Vesa .set_mode = qcom_snps_eusb2_hsphy_set_mode, 36380090810SAbel Vesa .owner = THIS_MODULE, 36480090810SAbel Vesa }; 36580090810SAbel Vesa 36680090810SAbel Vesa static int qcom_snps_eusb2_hsphy_probe(struct platform_device *pdev) 36780090810SAbel Vesa { 36880090810SAbel Vesa struct device *dev = &pdev->dev; 369*3584f639SNeil Armstrong struct device_node *np = dev->of_node; 37080090810SAbel Vesa struct qcom_snps_eusb2_hsphy *phy; 37180090810SAbel Vesa struct phy_provider *phy_provider; 37280090810SAbel Vesa struct phy *generic_phy; 37380090810SAbel Vesa int ret, i; 37480090810SAbel Vesa int num; 37580090810SAbel Vesa 37680090810SAbel Vesa phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); 37780090810SAbel Vesa if (!phy) 37880090810SAbel Vesa return -ENOMEM; 37980090810SAbel Vesa 38080090810SAbel Vesa phy->base = devm_platform_ioremap_resource(pdev, 0); 38180090810SAbel Vesa if (IS_ERR(phy->base)) 38280090810SAbel Vesa return PTR_ERR(phy->base); 38380090810SAbel Vesa 38480090810SAbel Vesa phy->phy_reset = devm_reset_control_get_exclusive(dev, NULL); 38580090810SAbel Vesa if (IS_ERR(phy->phy_reset)) 38680090810SAbel Vesa return PTR_ERR(phy->phy_reset); 38780090810SAbel Vesa 38880090810SAbel Vesa phy->ref_clk = devm_clk_get(dev, "ref"); 38980090810SAbel Vesa if (IS_ERR(phy->ref_clk)) 39080090810SAbel Vesa return dev_err_probe(dev, PTR_ERR(phy->ref_clk), 39180090810SAbel Vesa "failed to get ref clk\n"); 39280090810SAbel Vesa 39380090810SAbel Vesa num = ARRAY_SIZE(phy->vregs); 39480090810SAbel Vesa for (i = 0; i < num; i++) 39580090810SAbel Vesa phy->vregs[i].supply = eusb2_hsphy_vreg_names[i]; 39680090810SAbel Vesa 39780090810SAbel Vesa ret = devm_regulator_bulk_get(dev, num, phy->vregs); 39880090810SAbel Vesa if (ret) 39980090810SAbel Vesa return dev_err_probe(dev, ret, 40080090810SAbel Vesa "failed to get regulator supplies\n"); 401*3584f639SNeil Armstrong 402*3584f639SNeil Armstrong phy->repeater = devm_of_phy_get_by_index(dev, np, 0); 403*3584f639SNeil Armstrong if (IS_ERR(phy->repeater)) 404*3584f639SNeil Armstrong return dev_err_probe(dev, PTR_ERR(phy->repeater), 405*3584f639SNeil Armstrong "failed to get repeater\n"); 406*3584f639SNeil Armstrong 40780090810SAbel Vesa generic_phy = devm_phy_create(dev, NULL, &qcom_snps_eusb2_hsphy_ops); 40880090810SAbel Vesa if (IS_ERR(generic_phy)) { 40980090810SAbel Vesa dev_err(dev, "failed to create phy %d\n", ret); 41080090810SAbel Vesa return PTR_ERR(generic_phy); 41180090810SAbel Vesa } 41280090810SAbel Vesa 41380090810SAbel Vesa dev_set_drvdata(dev, phy); 41480090810SAbel Vesa phy_set_drvdata(generic_phy, phy); 41580090810SAbel Vesa 41680090810SAbel Vesa phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 41780090810SAbel Vesa if (IS_ERR(phy_provider)) 41880090810SAbel Vesa return PTR_ERR(phy_provider); 41980090810SAbel Vesa 42080090810SAbel Vesa dev_info(dev, "Registered Qcom-eUSB2 phy\n"); 42180090810SAbel Vesa 42280090810SAbel Vesa return 0; 42380090810SAbel Vesa } 42480090810SAbel Vesa 42580090810SAbel Vesa static const struct of_device_id qcom_snps_eusb2_hsphy_of_match_table[] = { 42680090810SAbel Vesa { .compatible = "qcom,sm8550-snps-eusb2-phy", }, 42780090810SAbel Vesa { }, 42880090810SAbel Vesa }; 42980090810SAbel Vesa MODULE_DEVICE_TABLE(of, qcom_snps_eusb2_hsphy_of_match_table); 43080090810SAbel Vesa 43180090810SAbel Vesa static struct platform_driver qcom_snps_eusb2_hsphy_driver = { 43280090810SAbel Vesa .probe = qcom_snps_eusb2_hsphy_probe, 43380090810SAbel Vesa .driver = { 43480090810SAbel Vesa .name = "qcom-snps-eusb2-hsphy", 43580090810SAbel Vesa .of_match_table = qcom_snps_eusb2_hsphy_of_match_table, 43680090810SAbel Vesa }, 43780090810SAbel Vesa }; 43880090810SAbel Vesa 43980090810SAbel Vesa module_platform_driver(qcom_snps_eusb2_hsphy_driver); 44080090810SAbel Vesa MODULE_DESCRIPTION("Qualcomm SNPS eUSB2 HS PHY driver"); 44180090810SAbel Vesa MODULE_LICENSE("GPL"); 442