1 // SPDX-License-Identifier: GPL-2.0
3 * MediaTek USB3.1 gen2 xsphy Driver
5 * Copyright (c) 2018 MediaTek Inc.
6 * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
10 #include <dt-bindings/phy/phy.h>
11 #include <linux/clk.h>
12 #include <linux/delay.h>
13 #include <linux/iopoll.h>
14 #include <linux/module.h>
15 #include <linux/of_address.h>
16 #include <linux/phy/phy.h>
17 #include <linux/platform_device.h>
19 #include "phy-mtk-io.h"
22 #define SSUSB_SIFSLV_MISC 0x000
23 #define SSUSB_SIFSLV_U2FREQ 0x100
24 #define SSUSB_SIFSLV_U2PHY_COM 0x300
26 /* u3 phy shared banks */
27 #define SSPXTP_SIFSLV_DIG_GLB 0x000
28 #define SSPXTP_SIFSLV_PHYA_GLB 0x100
31 #define SSPXTP_SIFSLV_DIG_LN_TOP 0x000
32 #define SSPXTP_SIFSLV_DIG_LN_TX0 0x100
33 #define SSPXTP_SIFSLV_DIG_LN_RX0 0x200
34 #define SSPXTP_SIFSLV_DIG_LN_DAIF 0x300
35 #define SSPXTP_SIFSLV_PHYA_LN 0x400
37 #define XSP_U2FREQ_FMCR0 ((SSUSB_SIFSLV_U2FREQ) + 0x00)
38 #define P2F_RG_FREQDET_EN BIT(24)
39 #define P2F_RG_CYCLECNT GENMASK(23, 0)
41 #define XSP_U2FREQ_MMONR0 ((SSUSB_SIFSLV_U2FREQ) + 0x0c)
43 #define XSP_U2FREQ_FMMONR1 ((SSUSB_SIFSLV_U2FREQ) + 0x10)
44 #define P2F_RG_FRCK_EN BIT(8)
45 #define P2F_USB_FM_VALID BIT(0)
47 #define XSP_USBPHYACR0 ((SSUSB_SIFSLV_U2PHY_COM) + 0x00)
48 #define P2A0_RG_INTR_EN BIT(5)
50 #define XSP_USBPHYACR1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x04)
51 #define P2A1_RG_INTR_CAL GENMASK(23, 19)
52 #define P2A1_RG_VRT_SEL GENMASK(14, 12)
53 #define P2A1_RG_TERM_SEL GENMASK(10, 8)
55 #define XSP_USBPHYACR5 ((SSUSB_SIFSLV_U2PHY_COM) + 0x014)
56 #define P2A5_RG_HSTX_SRCAL_EN BIT(15)
57 #define P2A5_RG_HSTX_SRCTRL GENMASK(14, 12)
59 #define XSP_USBPHYACR6 ((SSUSB_SIFSLV_U2PHY_COM) + 0x018)
60 #define P2A6_RG_BC11_SW_EN BIT(23)
61 #define P2A6_RG_OTG_VBUSCMP_EN BIT(20)
63 #define XSP_U2PHYDTM1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x06C)
64 #define P2D_FORCE_IDDIG BIT(9)
65 #define P2D_RG_VBUSVALID BIT(5)
66 #define P2D_RG_SESSEND BIT(4)
67 #define P2D_RG_AVALID BIT(2)
68 #define P2D_RG_IDDIG BIT(1)
70 #define SSPXTP_PHYA_GLB_00 ((SSPXTP_SIFSLV_PHYA_GLB) + 0x00)
71 #define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(21, 16)
73 #define SSPXTP_PHYA_LN_04 ((SSPXTP_SIFSLV_PHYA_LN) + 0x04)
74 #define RG_XTP_LN0_TX_IMPSEL GENMASK(4, 0)
76 #define SSPXTP_PHYA_LN_14 ((SSPXTP_SIFSLV_PHYA_LN) + 0x014)
77 #define RG_XTP_LN0_RX_IMPSEL GENMASK(4, 0)
79 #define XSP_REF_CLK 26 /* MHZ */
80 #define XSP_SLEW_RATE_COEF 17
81 #define XSP_SR_COEF_DIVISOR 1000
82 #define XSP_FM_DET_CYCLE_CNT 1024
84 struct xsphy_instance
{
86 void __iomem
*port_base
;
87 struct clk
*ref_clk
; /* reference clock of anolog phy */
90 /* only for HQA test */
102 void __iomem
*glb_base
; /* only shared u3 sif */
103 struct xsphy_instance
**phys
;
105 int src_ref_clk
; /* MHZ, reference clock for slew rate calibrate */
106 int src_coef
; /* coefficient for slew rate calibrate */
109 static void u2_phy_slew_rate_calibrate(struct mtk_xsphy
*xsphy
,
110 struct xsphy_instance
*inst
)
112 void __iomem
*pbase
= inst
->port_base
;
117 /* use force value */
121 /* enable USB ring oscillator */
122 mtk_phy_set_bits(pbase
+ XSP_USBPHYACR5
, P2A5_RG_HSTX_SRCAL_EN
);
123 udelay(1); /* wait clock stable */
125 /* enable free run clock */
126 mtk_phy_set_bits(pbase
+ XSP_U2FREQ_FMMONR1
, P2F_RG_FRCK_EN
);
128 /* set cycle count as 1024 */
129 mtk_phy_update_field(pbase
+ XSP_U2FREQ_FMCR0
, P2F_RG_CYCLECNT
,
130 XSP_FM_DET_CYCLE_CNT
);
132 /* enable frequency meter */
133 mtk_phy_set_bits(pbase
+ XSP_U2FREQ_FMCR0
, P2F_RG_FREQDET_EN
);
135 /* ignore return value */
136 readl_poll_timeout(pbase
+ XSP_U2FREQ_FMMONR1
, tmp
,
137 (tmp
& P2F_USB_FM_VALID
), 10, 200);
139 fm_out
= readl(pbase
+ XSP_U2FREQ_MMONR0
);
141 /* disable frequency meter */
142 mtk_phy_clear_bits(pbase
+ XSP_U2FREQ_FMCR0
, P2F_RG_FREQDET_EN
);
144 /* disable free run clock */
145 mtk_phy_clear_bits(pbase
+ XSP_U2FREQ_FMMONR1
, P2F_RG_FRCK_EN
);
148 /* (1024 / FM_OUT) x reference clock frequency x coefficient */
149 tmp
= xsphy
->src_ref_clk
* xsphy
->src_coef
;
150 tmp
= (tmp
* XSP_FM_DET_CYCLE_CNT
) / fm_out
;
151 calib_val
= DIV_ROUND_CLOSEST(tmp
, XSP_SR_COEF_DIVISOR
);
153 /* if FM detection fail, set default value */
156 dev_dbg(xsphy
->dev
, "phy.%d, fm_out:%d, calib:%d (clk:%d, coef:%d)\n",
157 inst
->index
, fm_out
, calib_val
,
158 xsphy
->src_ref_clk
, xsphy
->src_coef
);
160 /* set HS slew rate */
161 mtk_phy_update_field(pbase
+ XSP_USBPHYACR5
, P2A5_RG_HSTX_SRCTRL
, calib_val
);
163 /* disable USB ring oscillator */
164 mtk_phy_clear_bits(pbase
+ XSP_USBPHYACR5
, P2A5_RG_HSTX_SRCAL_EN
);
167 static void u2_phy_instance_init(struct mtk_xsphy
*xsphy
,
168 struct xsphy_instance
*inst
)
170 void __iomem
*pbase
= inst
->port_base
;
172 /* DP/DM BC1.1 path Disable */
173 mtk_phy_clear_bits(pbase
+ XSP_USBPHYACR6
, P2A6_RG_BC11_SW_EN
);
175 mtk_phy_set_bits(pbase
+ XSP_USBPHYACR0
, P2A0_RG_INTR_EN
);
178 static void u2_phy_instance_power_on(struct mtk_xsphy
*xsphy
,
179 struct xsphy_instance
*inst
)
181 void __iomem
*pbase
= inst
->port_base
;
182 u32 index
= inst
->index
;
184 mtk_phy_set_bits(pbase
+ XSP_USBPHYACR6
, P2A6_RG_OTG_VBUSCMP_EN
);
186 mtk_phy_update_bits(pbase
+ XSP_U2PHYDTM1
,
187 P2D_RG_VBUSVALID
| P2D_RG_AVALID
| P2D_RG_SESSEND
,
188 P2D_RG_VBUSVALID
| P2D_RG_AVALID
);
190 dev_dbg(xsphy
->dev
, "%s(%d)\n", __func__
, index
);
193 static void u2_phy_instance_power_off(struct mtk_xsphy
*xsphy
,
194 struct xsphy_instance
*inst
)
196 void __iomem
*pbase
= inst
->port_base
;
197 u32 index
= inst
->index
;
199 mtk_phy_clear_bits(pbase
+ XSP_USBPHYACR6
, P2A6_RG_OTG_VBUSCMP_EN
);
201 mtk_phy_update_bits(pbase
+ XSP_U2PHYDTM1
,
202 P2D_RG_VBUSVALID
| P2D_RG_AVALID
| P2D_RG_SESSEND
,
205 dev_dbg(xsphy
->dev
, "%s(%d)\n", __func__
, index
);
208 static void u2_phy_instance_set_mode(struct mtk_xsphy
*xsphy
,
209 struct xsphy_instance
*inst
,
214 tmp
= readl(inst
->port_base
+ XSP_U2PHYDTM1
);
216 case PHY_MODE_USB_DEVICE
:
217 tmp
|= P2D_FORCE_IDDIG
| P2D_RG_IDDIG
;
219 case PHY_MODE_USB_HOST
:
220 tmp
|= P2D_FORCE_IDDIG
;
221 tmp
&= ~P2D_RG_IDDIG
;
223 case PHY_MODE_USB_OTG
:
224 tmp
&= ~(P2D_FORCE_IDDIG
| P2D_RG_IDDIG
);
229 writel(tmp
, inst
->port_base
+ XSP_U2PHYDTM1
);
232 static void phy_parse_property(struct mtk_xsphy
*xsphy
,
233 struct xsphy_instance
*inst
)
235 struct device
*dev
= &inst
->phy
->dev
;
237 switch (inst
->type
) {
239 device_property_read_u32(dev
, "mediatek,efuse-intr",
241 device_property_read_u32(dev
, "mediatek,eye-src",
243 device_property_read_u32(dev
, "mediatek,eye-vrt",
245 device_property_read_u32(dev
, "mediatek,eye-term",
247 dev_dbg(dev
, "intr:%d, src:%d, vrt:%d, term:%d\n",
248 inst
->efuse_intr
, inst
->eye_src
,
249 inst
->eye_vrt
, inst
->eye_term
);
252 device_property_read_u32(dev
, "mediatek,efuse-intr",
254 device_property_read_u32(dev
, "mediatek,efuse-tx-imp",
255 &inst
->efuse_tx_imp
);
256 device_property_read_u32(dev
, "mediatek,efuse-rx-imp",
257 &inst
->efuse_rx_imp
);
258 dev_dbg(dev
, "intr:%d, tx-imp:%d, rx-imp:%d\n",
259 inst
->efuse_intr
, inst
->efuse_tx_imp
,
263 dev_err(xsphy
->dev
, "incompatible phy type\n");
268 static void u2_phy_props_set(struct mtk_xsphy
*xsphy
,
269 struct xsphy_instance
*inst
)
271 void __iomem
*pbase
= inst
->port_base
;
273 if (inst
->efuse_intr
)
274 mtk_phy_update_field(pbase
+ XSP_USBPHYACR1
, P2A1_RG_INTR_CAL
,
278 mtk_phy_update_field(pbase
+ XSP_USBPHYACR5
, P2A5_RG_HSTX_SRCTRL
,
282 mtk_phy_update_field(pbase
+ XSP_USBPHYACR1
, P2A1_RG_VRT_SEL
,
286 mtk_phy_update_field(pbase
+ XSP_USBPHYACR1
, P2A1_RG_TERM_SEL
,
290 static void u3_phy_props_set(struct mtk_xsphy
*xsphy
,
291 struct xsphy_instance
*inst
)
293 void __iomem
*pbase
= inst
->port_base
;
295 if (inst
->efuse_intr
)
296 mtk_phy_update_field(xsphy
->glb_base
+ SSPXTP_PHYA_GLB_00
,
297 RG_XTP_GLB_BIAS_INTR_CTRL
, inst
->efuse_intr
);
299 if (inst
->efuse_tx_imp
)
300 mtk_phy_update_field(pbase
+ SSPXTP_PHYA_LN_04
,
301 RG_XTP_LN0_TX_IMPSEL
, inst
->efuse_tx_imp
);
303 if (inst
->efuse_rx_imp
)
304 mtk_phy_update_field(pbase
+ SSPXTP_PHYA_LN_14
,
305 RG_XTP_LN0_RX_IMPSEL
, inst
->efuse_rx_imp
);
308 static int mtk_phy_init(struct phy
*phy
)
310 struct xsphy_instance
*inst
= phy_get_drvdata(phy
);
311 struct mtk_xsphy
*xsphy
= dev_get_drvdata(phy
->dev
.parent
);
314 ret
= clk_prepare_enable(inst
->ref_clk
);
316 dev_err(xsphy
->dev
, "failed to enable ref_clk\n");
320 switch (inst
->type
) {
322 u2_phy_instance_init(xsphy
, inst
);
323 u2_phy_props_set(xsphy
, inst
);
326 u3_phy_props_set(xsphy
, inst
);
329 dev_err(xsphy
->dev
, "incompatible phy type\n");
330 clk_disable_unprepare(inst
->ref_clk
);
337 static int mtk_phy_power_on(struct phy
*phy
)
339 struct xsphy_instance
*inst
= phy_get_drvdata(phy
);
340 struct mtk_xsphy
*xsphy
= dev_get_drvdata(phy
->dev
.parent
);
342 if (inst
->type
== PHY_TYPE_USB2
) {
343 u2_phy_instance_power_on(xsphy
, inst
);
344 u2_phy_slew_rate_calibrate(xsphy
, inst
);
350 static int mtk_phy_power_off(struct phy
*phy
)
352 struct xsphy_instance
*inst
= phy_get_drvdata(phy
);
353 struct mtk_xsphy
*xsphy
= dev_get_drvdata(phy
->dev
.parent
);
355 if (inst
->type
== PHY_TYPE_USB2
)
356 u2_phy_instance_power_off(xsphy
, inst
);
361 static int mtk_phy_exit(struct phy
*phy
)
363 struct xsphy_instance
*inst
= phy_get_drvdata(phy
);
365 clk_disable_unprepare(inst
->ref_clk
);
369 static int mtk_phy_set_mode(struct phy
*phy
, enum phy_mode mode
, int submode
)
371 struct xsphy_instance
*inst
= phy_get_drvdata(phy
);
372 struct mtk_xsphy
*xsphy
= dev_get_drvdata(phy
->dev
.parent
);
374 if (inst
->type
== PHY_TYPE_USB2
)
375 u2_phy_instance_set_mode(xsphy
, inst
, mode
);
380 static struct phy
*mtk_phy_xlate(struct device
*dev
,
381 const struct of_phandle_args
*args
)
383 struct mtk_xsphy
*xsphy
= dev_get_drvdata(dev
);
384 struct xsphy_instance
*inst
= NULL
;
385 struct device_node
*phy_np
= args
->np
;
388 if (args
->args_count
!= 1) {
389 dev_err(dev
, "invalid number of cells in 'phy' property\n");
390 return ERR_PTR(-EINVAL
);
393 for (index
= 0; index
< xsphy
->nphys
; index
++)
394 if (phy_np
== xsphy
->phys
[index
]->phy
->dev
.of_node
) {
395 inst
= xsphy
->phys
[index
];
400 dev_err(dev
, "failed to find appropriate phy\n");
401 return ERR_PTR(-EINVAL
);
404 inst
->type
= args
->args
[0];
405 if (!(inst
->type
== PHY_TYPE_USB2
||
406 inst
->type
== PHY_TYPE_USB3
)) {
407 dev_err(dev
, "unsupported phy type: %d\n", inst
->type
);
408 return ERR_PTR(-EINVAL
);
411 phy_parse_property(xsphy
, inst
);
416 static const struct phy_ops mtk_xsphy_ops
= {
417 .init
= mtk_phy_init
,
418 .exit
= mtk_phy_exit
,
419 .power_on
= mtk_phy_power_on
,
420 .power_off
= mtk_phy_power_off
,
421 .set_mode
= mtk_phy_set_mode
,
422 .owner
= THIS_MODULE
,
425 static const struct of_device_id mtk_xsphy_id_table
[] = {
426 { .compatible
= "mediatek,xsphy", },
429 MODULE_DEVICE_TABLE(of
, mtk_xsphy_id_table
);
431 static int mtk_xsphy_probe(struct platform_device
*pdev
)
433 struct device
*dev
= &pdev
->dev
;
434 struct device_node
*np
= dev
->of_node
;
435 struct phy_provider
*provider
;
436 struct resource
*glb_res
;
437 struct mtk_xsphy
*xsphy
;
441 xsphy
= devm_kzalloc(dev
, sizeof(*xsphy
), GFP_KERNEL
);
445 xsphy
->nphys
= of_get_child_count(np
);
446 xsphy
->phys
= devm_kcalloc(dev
, xsphy
->nphys
,
447 sizeof(*xsphy
->phys
), GFP_KERNEL
);
452 platform_set_drvdata(pdev
, xsphy
);
454 glb_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
455 /* optional, may not exist if no u3 phys */
457 /* get banks shared by multiple u3 phys */
458 xsphy
->glb_base
= devm_ioremap_resource(dev
, glb_res
);
459 if (IS_ERR(xsphy
->glb_base
)) {
460 dev_err(dev
, "failed to remap glb regs\n");
461 return PTR_ERR(xsphy
->glb_base
);
465 xsphy
->src_ref_clk
= XSP_REF_CLK
;
466 xsphy
->src_coef
= XSP_SLEW_RATE_COEF
;
467 /* update parameters of slew rate calibrate if exist */
468 device_property_read_u32(dev
, "mediatek,src-ref-clk-mhz",
469 &xsphy
->src_ref_clk
);
470 device_property_read_u32(dev
, "mediatek,src-coef", &xsphy
->src_coef
);
473 for_each_child_of_node_scoped(np
, child_np
) {
474 struct xsphy_instance
*inst
;
478 inst
= devm_kzalloc(dev
, sizeof(*inst
), GFP_KERNEL
);
482 xsphy
->phys
[port
] = inst
;
484 phy
= devm_phy_create(dev
, child_np
, &mtk_xsphy_ops
);
486 dev_err(dev
, "failed to create phy\n");
490 retval
= of_address_to_resource(child_np
, 0, &res
);
492 dev_err(dev
, "failed to get address resource(id-%d)\n",
497 inst
->port_base
= devm_ioremap_resource(&phy
->dev
, &res
);
498 if (IS_ERR(inst
->port_base
)) {
499 dev_err(dev
, "failed to remap phy regs\n");
500 return PTR_ERR(inst
->port_base
);
505 phy_set_drvdata(phy
, inst
);
508 inst
->ref_clk
= devm_clk_get(&phy
->dev
, "ref");
509 if (IS_ERR(inst
->ref_clk
)) {
510 dev_err(dev
, "failed to get ref_clk(id-%d)\n", port
);
511 return PTR_ERR(inst
->ref_clk
);
515 provider
= devm_of_phy_provider_register(dev
, mtk_phy_xlate
);
516 return PTR_ERR_OR_ZERO(provider
);
519 static struct platform_driver mtk_xsphy_driver
= {
520 .probe
= mtk_xsphy_probe
,
523 .of_match_table
= mtk_xsphy_id_table
,
527 module_platform_driver(mtk_xsphy_driver
);
529 MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
530 MODULE_DESCRIPTION("MediaTek USB XS-PHY driver");
531 MODULE_LICENSE("GPL v2");