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