1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
7 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/phy/phy.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 #include <linux/regulator/consumer.h>
18 #include <linux/reset.h>
19 #include <linux/slab.h>
21 #define USB2_PHY_USB_PHY_UTMI_CTRL0 (0x3c)
23 #define OPMODE_MASK GENMASK(4, 3)
24 #define OPMODE_NORMAL (0x00)
25 #define OPMODE_NONDRIVING BIT(3)
26 #define TERMSEL BIT(5)
28 #define USB2_PHY_USB_PHY_UTMI_CTRL1 (0x40)
29 #define XCVRSEL BIT(0)
31 #define USB2_PHY_USB_PHY_UTMI_CTRL5 (0x50)
34 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54)
35 #define RETENABLEN BIT(3)
36 #define FSEL_MASK GENMASK(7, 5)
37 #define FSEL_DEFAULT (0x3 << 4)
39 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58)
40 #define VBUSVLDEXTSEL0 BIT(4)
41 #define PLLBTUNE BIT(5)
43 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2 (0x5c)
44 #define VREGBYPASS BIT(0)
46 #define USB2_PHY_USB_PHY_HS_PHY_CTRL1 (0x60)
47 #define VBUSVLDEXT0 BIT(0)
49 #define USB2_PHY_USB_PHY_HS_PHY_CTRL2 (0x64)
50 #define USB2_AUTO_RESUME BIT(0)
51 #define USB2_SUSPEND_N BIT(2)
52 #define USB2_SUSPEND_N_SEL BIT(3)
54 #define USB2_PHY_USB_PHY_CFG0 (0x94)
55 #define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0)
56 #define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1)
58 #define USB2_PHY_USB_PHY_REFCLK_CTRL (0xa0)
59 #define REFCLK_SEL_MASK GENMASK(1, 0)
60 #define REFCLK_SEL_DEFAULT (0x2 << 0)
62 static const char * const qcom_snps_hsphy_vreg_names
[] = {
63 "vdda-pll", "vdda33", "vdda18",
66 #define SNPS_HS_NUM_VREGS ARRAY_SIZE(qcom_snps_hsphy_vreg_names)
69 * struct qcom_snps_hsphy - snps hs phy attributes
72 * @base: iomapped memory space for snps hs phy
74 * @cfg_ahb_clk: AHB2PHY interface clock
75 * @ref_clk: phy reference clock
76 * @iface_clk: phy interface clock
77 * @phy_reset: phy reset control
78 * @vregs: regulator supplies bulk data
79 * @phy_initialized: if PHY has been initialized correctly
80 * @mode: contains the current mode the PHY is in
82 struct qcom_snps_hsphy
{
86 struct clk
*cfg_ahb_clk
;
88 struct reset_control
*phy_reset
;
89 struct regulator_bulk_data vregs
[SNPS_HS_NUM_VREGS
];
95 static inline void qcom_snps_hsphy_write_mask(void __iomem
*base
, u32 offset
,
100 reg
= readl_relaxed(base
+ offset
);
103 writel_relaxed(reg
, base
+ offset
);
105 /* Ensure above write is completed */
106 readl_relaxed(base
+ offset
);
109 static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy
*hsphy
)
111 dev_dbg(&hsphy
->phy
->dev
, "Suspend QCOM SNPS PHY\n");
113 if (hsphy
->mode
== PHY_MODE_USB_HOST
) {
114 /* Enable auto-resume to meet remote wakeup timing */
115 qcom_snps_hsphy_write_mask(hsphy
->base
,
116 USB2_PHY_USB_PHY_HS_PHY_CTRL2
,
119 usleep_range(500, 1000);
120 qcom_snps_hsphy_write_mask(hsphy
->base
,
121 USB2_PHY_USB_PHY_HS_PHY_CTRL2
,
122 0, USB2_AUTO_RESUME
);
125 clk_disable_unprepare(hsphy
->cfg_ahb_clk
);
129 static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy
*hsphy
)
133 dev_dbg(&hsphy
->phy
->dev
, "Resume QCOM SNPS PHY, mode\n");
135 ret
= clk_prepare_enable(hsphy
->cfg_ahb_clk
);
137 dev_err(&hsphy
->phy
->dev
, "failed to enable cfg ahb clock\n");
144 static int __maybe_unused
qcom_snps_hsphy_runtime_suspend(struct device
*dev
)
146 struct qcom_snps_hsphy
*hsphy
= dev_get_drvdata(dev
);
148 if (!hsphy
->phy_initialized
)
151 qcom_snps_hsphy_suspend(hsphy
);
155 static int __maybe_unused
qcom_snps_hsphy_runtime_resume(struct device
*dev
)
157 struct qcom_snps_hsphy
*hsphy
= dev_get_drvdata(dev
);
159 if (!hsphy
->phy_initialized
)
162 qcom_snps_hsphy_resume(hsphy
);
166 static int qcom_snps_hsphy_set_mode(struct phy
*phy
, enum phy_mode mode
,
169 struct qcom_snps_hsphy
*hsphy
= phy_get_drvdata(phy
);
175 static int qcom_snps_hsphy_init(struct phy
*phy
)
177 struct qcom_snps_hsphy
*hsphy
= phy_get_drvdata(phy
);
180 dev_vdbg(&phy
->dev
, "%s(): Initializing SNPS HS phy\n", __func__
);
182 ret
= regulator_bulk_enable(ARRAY_SIZE(hsphy
->vregs
), hsphy
->vregs
);
186 ret
= clk_prepare_enable(hsphy
->cfg_ahb_clk
);
188 dev_err(&phy
->dev
, "failed to enable cfg ahb clock, %d\n", ret
);
192 ret
= reset_control_assert(hsphy
->phy_reset
);
194 dev_err(&phy
->dev
, "failed to assert phy_reset, %d\n", ret
);
195 goto disable_ahb_clk
;
198 usleep_range(100, 150);
200 ret
= reset_control_deassert(hsphy
->phy_reset
);
202 dev_err(&phy
->dev
, "failed to de-assert phy_reset, %d\n", ret
);
203 goto disable_ahb_clk
;
206 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_CFG0
,
207 UTMI_PHY_CMN_CTRL_OVERRIDE_EN
,
208 UTMI_PHY_CMN_CTRL_OVERRIDE_EN
);
209 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_UTMI_CTRL5
,
211 qcom_snps_hsphy_write_mask(hsphy
->base
,
212 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0
,
214 qcom_snps_hsphy_write_mask(hsphy
->base
,
215 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1
,
217 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_REFCLK_CTRL
,
218 REFCLK_SEL_DEFAULT
, REFCLK_SEL_MASK
);
219 qcom_snps_hsphy_write_mask(hsphy
->base
,
220 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1
,
221 VBUSVLDEXTSEL0
, VBUSVLDEXTSEL0
);
222 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_HS_PHY_CTRL1
,
223 VBUSVLDEXT0
, VBUSVLDEXT0
);
225 qcom_snps_hsphy_write_mask(hsphy
->base
,
226 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2
,
227 VREGBYPASS
, VREGBYPASS
);
229 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_HS_PHY_CTRL2
,
230 USB2_SUSPEND_N_SEL
| USB2_SUSPEND_N
,
231 USB2_SUSPEND_N_SEL
| USB2_SUSPEND_N
);
233 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_UTMI_CTRL0
,
236 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_UTMI_CTRL5
,
239 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_HS_PHY_CTRL2
,
240 USB2_SUSPEND_N_SEL
, 0);
242 qcom_snps_hsphy_write_mask(hsphy
->base
, USB2_PHY_USB_PHY_CFG0
,
243 UTMI_PHY_CMN_CTRL_OVERRIDE_EN
, 0);
245 hsphy
->phy_initialized
= true;
250 clk_disable_unprepare(hsphy
->cfg_ahb_clk
);
252 regulator_bulk_disable(ARRAY_SIZE(hsphy
->vregs
), hsphy
->vregs
);
257 static int qcom_snps_hsphy_exit(struct phy
*phy
)
259 struct qcom_snps_hsphy
*hsphy
= phy_get_drvdata(phy
);
261 reset_control_assert(hsphy
->phy_reset
);
262 clk_disable_unprepare(hsphy
->cfg_ahb_clk
);
263 regulator_bulk_disable(ARRAY_SIZE(hsphy
->vregs
), hsphy
->vregs
);
264 hsphy
->phy_initialized
= false;
269 static const struct phy_ops qcom_snps_hsphy_gen_ops
= {
270 .init
= qcom_snps_hsphy_init
,
271 .exit
= qcom_snps_hsphy_exit
,
272 .set_mode
= qcom_snps_hsphy_set_mode
,
273 .owner
= THIS_MODULE
,
276 static const struct of_device_id qcom_snps_hsphy_of_match_table
[] = {
277 { .compatible
= "qcom,sm8150-usb-hs-phy", },
278 { .compatible
= "qcom,usb-snps-hs-7nm-phy", },
279 { .compatible
= "qcom,usb-snps-femto-v2-phy", },
282 MODULE_DEVICE_TABLE(of
, qcom_snps_hsphy_of_match_table
);
284 static const struct dev_pm_ops qcom_snps_hsphy_pm_ops
= {
285 SET_RUNTIME_PM_OPS(qcom_snps_hsphy_runtime_suspend
,
286 qcom_snps_hsphy_runtime_resume
, NULL
)
289 static int qcom_snps_hsphy_probe(struct platform_device
*pdev
)
291 struct device
*dev
= &pdev
->dev
;
292 struct qcom_snps_hsphy
*hsphy
;
293 struct phy_provider
*phy_provider
;
294 struct phy
*generic_phy
;
298 hsphy
= devm_kzalloc(dev
, sizeof(*hsphy
), GFP_KERNEL
);
302 hsphy
->base
= devm_platform_ioremap_resource(pdev
, 0);
303 if (IS_ERR(hsphy
->base
))
304 return PTR_ERR(hsphy
->base
);
306 hsphy
->ref_clk
= devm_clk_get(dev
, "ref");
307 if (IS_ERR(hsphy
->ref_clk
)) {
308 ret
= PTR_ERR(hsphy
->ref_clk
);
309 if (ret
!= -EPROBE_DEFER
)
310 dev_err(dev
, "failed to get ref clk, %d\n", ret
);
314 hsphy
->phy_reset
= devm_reset_control_get_exclusive(&pdev
->dev
, NULL
);
315 if (IS_ERR(hsphy
->phy_reset
)) {
316 dev_err(dev
, "failed to get phy core reset\n");
317 return PTR_ERR(hsphy
->phy_reset
);
320 num
= ARRAY_SIZE(hsphy
->vregs
);
321 for (i
= 0; i
< num
; i
++)
322 hsphy
->vregs
[i
].supply
= qcom_snps_hsphy_vreg_names
[i
];
324 ret
= devm_regulator_bulk_get(dev
, num
, hsphy
->vregs
);
326 if (ret
!= -EPROBE_DEFER
)
327 dev_err(dev
, "failed to get regulator supplies: %d\n",
332 pm_runtime_set_active(dev
);
333 pm_runtime_enable(dev
);
335 * Prevent runtime pm from being ON by default. Users can enable
336 * it using power/control in sysfs.
338 pm_runtime_forbid(dev
);
340 generic_phy
= devm_phy_create(dev
, NULL
, &qcom_snps_hsphy_gen_ops
);
341 if (IS_ERR(generic_phy
)) {
342 ret
= PTR_ERR(generic_phy
);
343 dev_err(dev
, "failed to create phy, %d\n", ret
);
346 hsphy
->phy
= generic_phy
;
348 dev_set_drvdata(dev
, hsphy
);
349 phy_set_drvdata(generic_phy
, hsphy
);
351 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
352 if (!IS_ERR(phy_provider
))
353 dev_dbg(dev
, "Registered Qcom-SNPS HS phy\n");
355 pm_runtime_disable(dev
);
357 return PTR_ERR_OR_ZERO(phy_provider
);
360 static struct platform_driver qcom_snps_hsphy_driver
= {
361 .probe
= qcom_snps_hsphy_probe
,
363 .name
= "qcom-snps-hs-femto-v2-phy",
364 .pm
= &qcom_snps_hsphy_pm_ops
,
365 .of_match_table
= qcom_snps_hsphy_of_match_table
,
369 module_platform_driver(qcom_snps_hsphy_driver
);
371 MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver");
372 MODULE_LICENSE("GPL v2");