1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2014-2023, The Linux Foundation. All rights reserved.
7 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
13 #include <linux/phy/phy.h>
14 #include <linux/platform_device.h>
15 #include <linux/reset.h>
16 #include <linux/slab.h>
18 #define USB2PHY_PORT_UTMI_CTRL1 0x40
20 #define USB2PHY_PORT_UTMI_CTRL2 0x44
21 #define UTMI_ULPI_SEL BIT(7)
22 #define UTMI_TEST_MUX_SEL BIT(6)
24 #define HS_PHY_CTRL_REG 0x10
25 #define UTMI_OTG_VBUS_VALID BIT(20)
26 #define SW_SESSVLD_SEL BIT(28)
28 #define USB_PHY_UTMI_CTRL0 0x3c
30 #define USB_PHY_UTMI_CTRL5 0x50
33 #define USB_PHY_HS_PHY_CTRL_COMMON0 0x54
34 #define COMMONONN BIT(7)
36 #define RETENABLEN BIT(3)
37 #define FREQ_24MHZ (BIT(6) | BIT(4))
39 #define USB_PHY_HS_PHY_CTRL2 0x64
40 #define USB2_SUSPEND_N_SEL BIT(3)
41 #define USB2_SUSPEND_N BIT(2)
42 #define USB2_UTMI_CLK_EN BIT(1)
44 #define USB_PHY_CFG0 0x94
45 #define UTMI_PHY_OVERRIDE_EN BIT(1)
47 #define USB_PHY_REFCLK_CTRL 0xa0
48 #define CLKCORE BIT(1)
50 #define USB2PHY_PORT_POWERDOWN 0xa4
51 #define POWER_UP BIT(0)
54 #define USB_PHY_FSEL_SEL 0xb8
55 #define FREQ_SEL BIT(0)
57 #define USB2PHY_USB_PHY_M31_XCFGI_1 0xbc
58 #define USB2_0_TX_ENABLE BIT(2)
60 #define USB2PHY_USB_PHY_M31_XCFGI_4 0xc8
61 #define HSTX_SLEW_RATE_565PS GENMASK(1, 0)
62 #define PLL_CHARGING_PUMP_CURRENT_35UA GENMASK(4, 3)
63 #define ODT_VALUE_38_02_OHM GENMASK(7, 6)
65 #define USB2PHY_USB_PHY_M31_XCFGI_5 0xcc
66 #define ODT_VALUE_45_02_OHM BIT(2)
67 #define HSTX_PRE_EMPHASIS_LEVEL_0_55MA BIT(0)
69 #define USB2PHY_USB_PHY_M31_XCFGI_11 0xe4
70 #define XCFG_COARSE_TUNE_NUM BIT(1)
71 #define XCFG_FINE_TUNE_NUM BIT(3)
79 struct m31_priv_data
{
81 const struct m31_phy_regs
*regs
;
85 static const struct m31_phy_regs m31_ipq5018_regs
[] = {
88 .val
= UTMI_PHY_OVERRIDE_EN
91 .off
= USB_PHY_UTMI_CTRL5
,
96 .off
= USB_PHY_FSEL_SEL
,
100 .off
= USB_PHY_HS_PHY_CTRL_COMMON0
,
101 .val
= COMMONONN
| FSEL
| RETENABLEN
104 .off
= USB_PHY_REFCLK_CTRL
,
108 .off
= USB_PHY_UTMI_CTRL5
,
112 .off
= USB_PHY_HS_PHY_CTRL2
,
113 .val
= USB2_SUSPEND_N_SEL
| USB2_SUSPEND_N
| USB2_UTMI_CLK_EN
116 .off
= USB_PHY_UTMI_CTRL5
,
120 .off
= USB_PHY_HS_PHY_CTRL2
,
121 .val
= USB2_SUSPEND_N
| USB2_UTMI_CLK_EN
129 static struct m31_phy_regs m31_ipq5332_regs
[] = {
132 UTMI_PHY_OVERRIDE_EN
,
146 USB_PHY_HS_PHY_CTRL_COMMON0
,
147 COMMONONN
| FREQ_24MHZ
| RETENABLEN
,
156 USB_PHY_HS_PHY_CTRL2
,
157 USB2_SUSPEND_N_SEL
| USB2_SUSPEND_N
| USB2_UTMI_CLK_EN
,
161 USB2PHY_USB_PHY_M31_XCFGI_11
,
162 XCFG_COARSE_TUNE_NUM
| XCFG_FINE_TUNE_NUM
,
166 USB2PHY_USB_PHY_M31_XCFGI_4
,
167 HSTX_SLEW_RATE_565PS
| PLL_CHARGING_PUMP_CURRENT_35UA
| ODT_VALUE_38_02_OHM
,
171 USB2PHY_USB_PHY_M31_XCFGI_1
,
176 USB2PHY_USB_PHY_M31_XCFGI_5
,
177 ODT_VALUE_45_02_OHM
| HSTX_PRE_EMPHASIS_LEVEL_0_55MA
,
186 USB_PHY_HS_PHY_CTRL2
,
187 USB2_SUSPEND_N
| USB2_UTMI_CLK_EN
,
195 const struct m31_phy_regs
*regs
;
198 struct regulator
*vreg
;
200 struct reset_control
*reset
;
205 static int m31usb_phy_init(struct phy
*phy
)
207 struct m31usb_phy
*qphy
= phy_get_drvdata(phy
);
208 const struct m31_phy_regs
*regs
= qphy
->regs
;
211 ret
= regulator_enable(qphy
->vreg
);
213 dev_err(&phy
->dev
, "failed to enable regulator, %d\n", ret
);
217 ret
= clk_prepare_enable(qphy
->clk
);
219 regulator_disable(qphy
->vreg
);
220 dev_err(&phy
->dev
, "failed to enable cfg ahb clock, %d\n", ret
);
224 /* Perform phy reset */
225 reset_control_assert(qphy
->reset
);
227 reset_control_deassert(qphy
->reset
);
229 /* configure for ULPI mode if requested */
231 writel(0x0, qphy
->base
+ USB2PHY_PORT_UTMI_CTRL2
);
234 writel(POWER_UP
, qphy
->base
+ USB2PHY_PORT_POWERDOWN
);
236 /* Turn on phy ref clock */
237 for (i
= 0; i
< qphy
->nregs
; i
++) {
238 writel(regs
[i
].val
, qphy
->base
+ regs
[i
].off
);
240 udelay(regs
[i
].delay
);
246 static int m31usb_phy_shutdown(struct phy
*phy
)
248 struct m31usb_phy
*qphy
= phy_get_drvdata(phy
);
250 /* Disable the PHY */
251 writel_relaxed(POWER_DOWN
, qphy
->base
+ USB2PHY_PORT_POWERDOWN
);
253 clk_disable_unprepare(qphy
->clk
);
255 regulator_disable(qphy
->vreg
);
260 static const struct phy_ops m31usb_phy_gen_ops
= {
261 .power_on
= m31usb_phy_init
,
262 .power_off
= m31usb_phy_shutdown
,
263 .owner
= THIS_MODULE
,
266 static int m31usb_phy_probe(struct platform_device
*pdev
)
268 struct phy_provider
*phy_provider
;
269 const struct m31_priv_data
*data
;
270 struct device
*dev
= &pdev
->dev
;
271 struct m31usb_phy
*qphy
;
273 qphy
= devm_kzalloc(dev
, sizeof(*qphy
), GFP_KERNEL
);
277 qphy
->base
= devm_platform_ioremap_resource(pdev
, 0);
278 if (IS_ERR(qphy
->base
))
279 return PTR_ERR(qphy
->base
);
281 qphy
->reset
= devm_reset_control_get_exclusive_by_index(dev
, 0);
282 if (IS_ERR(qphy
->reset
))
283 return PTR_ERR(qphy
->reset
);
285 qphy
->clk
= devm_clk_get(dev
, NULL
);
286 if (IS_ERR(qphy
->clk
))
287 return dev_err_probe(dev
, PTR_ERR(qphy
->clk
),
288 "failed to get clk\n");
290 data
= of_device_get_match_data(dev
);
291 qphy
->regs
= data
->regs
;
292 qphy
->nregs
= data
->nregs
;
293 qphy
->ulpi_mode
= data
->ulpi_mode
;
295 qphy
->phy
= devm_phy_create(dev
, NULL
, &m31usb_phy_gen_ops
);
296 if (IS_ERR(qphy
->phy
))
297 return dev_err_probe(dev
, PTR_ERR(qphy
->phy
),
298 "failed to create phy\n");
300 qphy
->vreg
= devm_regulator_get(dev
, "vdd");
301 if (IS_ERR(qphy
->vreg
))
302 return dev_err_probe(dev
, PTR_ERR(qphy
->vreg
),
303 "failed to get vreg\n");
305 phy_set_drvdata(qphy
->phy
, qphy
);
307 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
308 if (!IS_ERR(phy_provider
))
309 dev_info(dev
, "Registered M31 USB phy\n");
311 return PTR_ERR_OR_ZERO(phy_provider
);
314 static const struct m31_priv_data m31_ipq5018_data
= {
316 .regs
= m31_ipq5018_regs
,
317 .nregs
= ARRAY_SIZE(m31_ipq5018_regs
),
320 static const struct m31_priv_data m31_ipq5332_data
= {
322 .regs
= m31_ipq5332_regs
,
323 .nregs
= ARRAY_SIZE(m31_ipq5332_regs
),
326 static const struct of_device_id m31usb_phy_id_table
[] = {
327 { .compatible
= "qcom,ipq5018-usb-hsphy", .data
= &m31_ipq5018_data
},
328 { .compatible
= "qcom,ipq5332-usb-hsphy", .data
= &m31_ipq5332_data
},
331 MODULE_DEVICE_TABLE(of
, m31usb_phy_id_table
);
333 static struct platform_driver m31usb_phy_driver
= {
334 .probe
= m31usb_phy_probe
,
336 .name
= "qcom-m31usb-phy",
337 .of_match_table
= m31usb_phy_id_table
,
341 module_platform_driver(m31usb_phy_driver
);
343 MODULE_DESCRIPTION("USB2 Qualcomm M31 HSPHY driver");
344 MODULE_LICENSE("GPL");