1 // SPDX-License-Identifier: GPL-2.0-only
3 * Phy provider for USB 3.1 controller on HiSilicon Kirin970 platform
5 * Copyright (C) 2017-2020 Hilisicon Electronics Co., Ltd.
6 * http://www.huawei.com
8 * Authors: Yu Chen <chenyu56@huawei.com>
11 #include <linux/clk.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/phy/phy.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
19 #define SCTRL_SCDEEPSLEEPED (0x0)
20 #define USB_CLK_SELECTED BIT(20)
22 #define PERI_CRG_PEREN0 (0x00)
23 #define PERI_CRG_PERDIS0 (0x04)
24 #define PERI_CRG_PEREN4 (0x40)
25 #define PERI_CRG_PERDIS4 (0x44)
26 #define PERI_CRG_PERRSTEN4 (0x90)
27 #define PERI_CRG_PERRSTDIS4 (0x94)
28 #define PERI_CRG_ISODIS (0x148)
29 #define PERI_CRG_PEREN6 (0x410)
30 #define PERI_CRG_PERDIS6 (0x414)
32 #define USB_REFCLK_ISO_EN BIT(25)
34 #define GT_CLK_USB2PHY_REF BIT(19)
36 #define PCTRL_PERI_CTRL3 (0x10)
37 #define PCTRL_PERI_CTRL3_MSK_START (16)
38 #define USB_TCXO_EN BIT(1)
40 #define PCTRL_PERI_CTRL24 (0x64)
41 #define SC_CLK_USB3PHY_3MUX1_SEL BIT(25)
43 #define USB3OTG_CTRL0 (0x00)
44 #define USB3OTG_CTRL3 (0x0C)
45 #define USB3OTG_CTRL4 (0x10)
46 #define USB3OTG_CTRL5 (0x14)
47 #define USB3OTG_CTRL7 (0x1C)
48 #define USB_MISC_CFG50 (0x50)
49 #define USB_MISC_CFG54 (0x54)
50 #define USB_MISC_CFG58 (0x58)
51 #define USB_MISC_CFG5C (0x5C)
52 #define USB_MISC_CFGA0 (0xA0)
53 #define TCA_CLK_RST (0x200)
54 #define TCA_INTR_EN (0x204)
55 #define TCA_INTR_STS (0x208)
56 #define TCA_GCFG (0x210)
57 #define TCA_TCPC (0x214)
58 #define TCA_SYSMODE_CFG (0x218)
59 #define TCA_VBUS_CTRL (0x240)
61 #define CTRL0_USB3_VBUSVLD BIT(7)
62 #define CTRL0_USB3_VBUSVLD_SEL BIT(6)
64 #define CTRL3_USB2_VBUSVLDEXT0 BIT(6)
65 #define CTRL3_USB2_VBUSVLDEXTSEL0 BIT(5)
67 #define CTRL5_USB2_SIDDQ BIT(0)
69 #define CTRL7_USB2_REFCLKSEL_MASK (3 << 3)
70 #define CTRL7_USB2_REFCLKSEL_ABB (3 << 3)
71 #define CTRL7_USB2_REFCLKSEL_PAD (2 << 3)
73 #define CFG50_USB3_PHY_TEST_POWERDOWN BIT(23)
75 #define CFG54_USB31PHY_CR_ADDR_MASK (0xFFFF)
76 #define CFG54_USB31PHY_CR_ADDR_SHIFT (16)
77 #define CFG54_USB3PHY_REF_USE_PAD BIT(12)
78 #define CFG54_PHY0_PMA_PWR_STABLE BIT(11)
79 #define CFG54_PHY0_PCS_PWR_STABLE BIT(9)
80 #define CFG54_USB31PHY_CR_ACK BIT(7)
81 #define CFG54_USB31PHY_CR_WR_EN BIT(5)
82 #define CFG54_USB31PHY_CR_SEL BIT(4)
83 #define CFG54_USB31PHY_CR_RD_EN BIT(3)
84 #define CFG54_USB31PHY_CR_CLK BIT(2)
85 #define CFG54_USB3_PHY0_ANA_PWR_EN BIT(1)
87 #define CFG58_USB31PHY_CR_DATA_MASK (0xFFFF)
88 #define CFG58_USB31PHY_CR_DATA_RD_START (16)
90 #define CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN BIT(1)
92 #define CFGA0_VAUX_RESET BIT(9)
93 #define CFGA0_USB31C_RESET BIT(8)
94 #define CFGA0_USB2PHY_REFCLK_SELECT BIT(4)
95 #define CFGA0_USB3PHY_RESET BIT(1)
96 #define CFGA0_USB2PHY_POR BIT(0)
98 #define INTR_EN_XA_TIMEOUT_EVT_EN BIT(1)
99 #define INTR_EN_XA_ACK_EVT_EN BIT(0)
101 #define CLK_RST_TCA_REF_CLK_EN BIT(1)
102 #define CLK_RST_SUSPEND_CLK_EN BIT(0)
104 #define GCFG_ROLE_HSTDEV BIT(4)
105 #define GCFG_OP_MODE (3 << 0)
106 #define GCFG_OP_MODE_CTRL_SYNC_MODE BIT(0)
108 #define TCPC_VALID BIT(4)
109 #define TCPC_LOW_POWER_EN BIT(3)
110 #define TCPC_MUX_CONTROL_MASK (3 << 0)
111 #define TCPC_MUX_CONTROL_USB31 BIT(0)
113 #define SYSMODE_CFG_TYPEC_DISABLE BIT(3)
115 #define VBUS_CTRL_POWERPRESENT_OVERRD (3 << 2)
116 #define VBUS_CTRL_VBUSVALID_OVERRD (3 << 0)
118 #define KIRIN970_USB_DEFAULT_PHY_PARAM (0xFDFEE4)
119 #define KIRIN970_USB_DEFAULT_PHY_VBOOST (0x5)
121 #define TX_VBOOST_LVL_REG (0xf)
122 #define TX_VBOOST_LVL_START (6)
123 #define TX_VBOOST_LVL_ENABLE BIT(9)
127 struct regmap
*peri_crg
;
128 struct regmap
*pctrl
;
129 struct regmap
*sctrl
;
130 struct regmap
*usb31misc
;
132 u32 eye_diagram_param
;
137 u32 usb31misc_offset
;
140 static int hi3670_phy_cr_clk(struct regmap
*usb31misc
)
145 ret
= regmap_update_bits(usb31misc
, USB_MISC_CFG54
,
146 CFG54_USB31PHY_CR_CLK
, CFG54_USB31PHY_CR_CLK
);
151 ret
= regmap_update_bits(usb31misc
, USB_MISC_CFG54
,
152 CFG54_USB31PHY_CR_CLK
, 0);
157 static int hi3670_phy_cr_set_sel(struct regmap
*usb31misc
)
159 return regmap_update_bits(usb31misc
, USB_MISC_CFG54
,
160 CFG54_USB31PHY_CR_SEL
, CFG54_USB31PHY_CR_SEL
);
163 static int hi3670_phy_cr_start(struct regmap
*usb31misc
, int direction
)
168 ret
= regmap_update_bits(usb31misc
, USB_MISC_CFG54
,
169 CFG54_USB31PHY_CR_WR_EN
,
170 CFG54_USB31PHY_CR_WR_EN
);
172 ret
= regmap_update_bits(usb31misc
, USB_MISC_CFG54
,
173 CFG54_USB31PHY_CR_RD_EN
,
174 CFG54_USB31PHY_CR_RD_EN
);
179 ret
= hi3670_phy_cr_clk(usb31misc
);
183 ret
= regmap_update_bits(usb31misc
, USB_MISC_CFG54
,
184 CFG54_USB31PHY_CR_RD_EN
| CFG54_USB31PHY_CR_WR_EN
, 0);
189 static int hi3670_phy_cr_wait_ack(struct regmap
*usb31misc
)
195 while (retry
-- > 0) {
196 ret
= regmap_read(usb31misc
, USB_MISC_CFG54
, ®
);
199 if ((reg
& CFG54_USB31PHY_CR_ACK
) == CFG54_USB31PHY_CR_ACK
)
202 ret
= hi3670_phy_cr_clk(usb31misc
);
210 static int hi3670_phy_cr_set_addr(struct regmap
*usb31misc
, u32 addr
)
215 ret
= regmap_read(usb31misc
, USB_MISC_CFG54
, ®
);
219 reg
&= ~(CFG54_USB31PHY_CR_ADDR_MASK
<< CFG54_USB31PHY_CR_ADDR_SHIFT
);
220 reg
|= ((addr
& CFG54_USB31PHY_CR_ADDR_MASK
) << CFG54_USB31PHY_CR_ADDR_SHIFT
);
221 ret
= regmap_write(usb31misc
, USB_MISC_CFG54
, reg
);
226 static int hi3670_phy_cr_read(struct regmap
*usb31misc
, u32 addr
, u32
*val
)
232 for (i
= 0; i
< 100; i
++) {
233 ret
= hi3670_phy_cr_clk(usb31misc
);
238 ret
= hi3670_phy_cr_set_sel(usb31misc
);
242 ret
= hi3670_phy_cr_set_addr(usb31misc
, addr
);
246 ret
= hi3670_phy_cr_start(usb31misc
, 0);
250 ret
= hi3670_phy_cr_wait_ack(usb31misc
);
254 ret
= regmap_read(usb31misc
, USB_MISC_CFG58
, ®
);
258 *val
= (reg
>> CFG58_USB31PHY_CR_DATA_RD_START
) &
259 CFG58_USB31PHY_CR_DATA_MASK
;
264 static int hi3670_phy_cr_write(struct regmap
*usb31misc
, u32 addr
, u32 val
)
269 for (i
= 0; i
< 100; i
++) {
270 ret
= hi3670_phy_cr_clk(usb31misc
);
275 ret
= hi3670_phy_cr_set_sel(usb31misc
);
279 ret
= hi3670_phy_cr_set_addr(usb31misc
, addr
);
283 ret
= regmap_write(usb31misc
, USB_MISC_CFG58
,
284 val
& CFG58_USB31PHY_CR_DATA_MASK
);
288 ret
= hi3670_phy_cr_start(usb31misc
, 1);
292 ret
= hi3670_phy_cr_wait_ack(usb31misc
);
297 static int hi3670_phy_set_params(struct hi3670_priv
*priv
)
303 ret
= regmap_write(priv
->usb31misc
, USB3OTG_CTRL4
,
304 priv
->eye_diagram_param
);
306 dev_err(priv
->dev
, "set USB3OTG_CTRL4 failed\n");
310 while (retry
-- > 0) {
311 ret
= hi3670_phy_cr_read(priv
->usb31misc
,
312 TX_VBOOST_LVL_REG
, ®
);
316 if (ret
!= -ETIMEDOUT
) {
317 dev_err(priv
->dev
, "read TX_VBOOST_LVL_REG failed\n");
324 reg
|= (TX_VBOOST_LVL_ENABLE
| (priv
->tx_vboost_lvl
<< TX_VBOOST_LVL_START
));
325 ret
= hi3670_phy_cr_write(priv
->usb31misc
, TX_VBOOST_LVL_REG
, reg
);
327 dev_err(priv
->dev
, "write TX_VBOOST_LVL_REG failed\n");
332 static int hi3670_is_abbclk_seleted(struct hi3670_priv
*priv
)
337 dev_err(priv
->dev
, "priv->sctrl is null!\n");
341 if (regmap_read(priv
->sctrl
, SCTRL_SCDEEPSLEEPED
, ®
)) {
342 dev_err(priv
->dev
, "SCTRL_SCDEEPSLEEPED read failed!\n");
346 if ((reg
& USB_CLK_SELECTED
) == 0)
352 static int hi3670_config_phy_clock(struct hi3670_priv
*priv
)
357 if (hi3670_is_abbclk_seleted(priv
)) {
358 /* usb refclk iso disable */
359 ret
= regmap_write(priv
->peri_crg
, PERI_CRG_ISODIS
,
364 /* enable usb_tcxo_en */
365 ret
= regmap_write(priv
->pctrl
, PCTRL_PERI_CTRL3
,
367 (USB_TCXO_EN
<< PCTRL_PERI_CTRL3_MSK_START
));
369 /* select usbphy clk from abb */
370 mask
= SC_CLK_USB3PHY_3MUX1_SEL
;
371 ret
= regmap_update_bits(priv
->pctrl
,
372 PCTRL_PERI_CTRL24
, mask
, 0);
376 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFGA0
,
377 CFGA0_USB2PHY_REFCLK_SELECT
, 0);
381 ret
= regmap_read(priv
->usb31misc
, USB3OTG_CTRL7
, &val
);
384 val
&= ~CTRL7_USB2_REFCLKSEL_MASK
;
385 val
|= CTRL7_USB2_REFCLKSEL_ABB
;
386 ret
= regmap_write(priv
->usb31misc
, USB3OTG_CTRL7
, val
);
393 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFG54
,
394 CFG54_USB3PHY_REF_USE_PAD
,
395 CFG54_USB3PHY_REF_USE_PAD
);
399 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFGA0
,
400 CFGA0_USB2PHY_REFCLK_SELECT
,
401 CFGA0_USB2PHY_REFCLK_SELECT
);
405 ret
= regmap_read(priv
->usb31misc
, USB3OTG_CTRL7
, &val
);
408 val
&= ~CTRL7_USB2_REFCLKSEL_MASK
;
409 val
|= CTRL7_USB2_REFCLKSEL_PAD
;
410 ret
= regmap_write(priv
->usb31misc
, USB3OTG_CTRL7
, val
);
414 ret
= regmap_write(priv
->peri_crg
,
415 PERI_CRG_PEREN6
, GT_CLK_USB2PHY_REF
);
421 dev_err(priv
->dev
, "failed to config phy clock ret: %d\n", ret
);
425 static int hi3670_config_tca(struct hi3670_priv
*priv
)
430 ret
= regmap_write(priv
->usb31misc
, TCA_INTR_STS
, 0xffff);
434 ret
= regmap_write(priv
->usb31misc
, TCA_INTR_EN
,
435 INTR_EN_XA_TIMEOUT_EVT_EN
| INTR_EN_XA_ACK_EVT_EN
);
439 mask
= CLK_RST_TCA_REF_CLK_EN
| CLK_RST_SUSPEND_CLK_EN
;
440 ret
= regmap_update_bits(priv
->usb31misc
, TCA_CLK_RST
, mask
, 0);
444 ret
= regmap_update_bits(priv
->usb31misc
, TCA_GCFG
,
445 GCFG_ROLE_HSTDEV
| GCFG_OP_MODE
,
446 GCFG_ROLE_HSTDEV
| GCFG_OP_MODE_CTRL_SYNC_MODE
);
450 ret
= regmap_update_bits(priv
->usb31misc
, TCA_SYSMODE_CFG
,
451 SYSMODE_CFG_TYPEC_DISABLE
, 0);
455 ret
= regmap_read(priv
->usb31misc
, TCA_TCPC
, &val
);
458 val
&= ~(TCPC_VALID
| TCPC_LOW_POWER_EN
| TCPC_MUX_CONTROL_MASK
);
459 val
|= (TCPC_VALID
| TCPC_MUX_CONTROL_USB31
);
460 ret
= regmap_write(priv
->usb31misc
, TCA_TCPC
, val
);
464 ret
= regmap_write(priv
->usb31misc
, TCA_VBUS_CTRL
,
465 VBUS_CTRL_POWERPRESENT_OVERRD
| VBUS_CTRL_VBUSVALID_OVERRD
);
471 dev_err(priv
->dev
, "failed to config phy clock ret: %d\n", ret
);
475 static int hi3670_phy_init(struct phy
*phy
)
477 struct hi3670_priv
*priv
= phy_get_drvdata(phy
);
481 /* assert controller */
482 val
= CFGA0_VAUX_RESET
| CFGA0_USB31C_RESET
|
483 CFGA0_USB3PHY_RESET
| CFGA0_USB2PHY_POR
;
484 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFGA0
, val
, 0);
488 ret
= hi3670_config_phy_clock(priv
);
492 /* Exit from IDDQ mode */
493 ret
= regmap_update_bits(priv
->usb31misc
, USB3OTG_CTRL5
,
494 CTRL5_USB2_SIDDQ
, 0);
498 /* Release USB31 PHY out of TestPowerDown mode */
499 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFG50
,
500 CFG50_USB3_PHY_TEST_POWERDOWN
, 0);
505 val
= CFGA0_USB3PHY_RESET
| CFGA0_USB2PHY_POR
;
506 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFGA0
, val
, val
);
510 usleep_range(100, 120);
512 /* Tell the PHY power is stable */
513 val
= CFG54_USB3_PHY0_ANA_PWR_EN
| CFG54_PHY0_PCS_PWR_STABLE
|
514 CFG54_PHY0_PMA_PWR_STABLE
;
515 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFG54
,
520 ret
= hi3670_config_tca(priv
);
525 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFG5C
,
526 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN
,
527 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN
);
531 /* Deassert controller */
532 val
= CFGA0_VAUX_RESET
| CFGA0_USB31C_RESET
;
533 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFGA0
, val
, val
);
537 usleep_range(100, 120);
539 /* Set fake vbus valid signal */
540 val
= CTRL0_USB3_VBUSVLD
| CTRL0_USB3_VBUSVLD_SEL
;
541 ret
= regmap_update_bits(priv
->usb31misc
, USB3OTG_CTRL0
, val
, val
);
545 val
= CTRL3_USB2_VBUSVLDEXT0
| CTRL3_USB2_VBUSVLDEXTSEL0
;
546 ret
= regmap_update_bits(priv
->usb31misc
, USB3OTG_CTRL3
, val
, val
);
550 usleep_range(100, 120);
552 ret
= hi3670_phy_set_params(priv
);
558 dev_err(priv
->dev
, "failed to init phy ret: %d\n", ret
);
562 static int hi3670_phy_exit(struct phy
*phy
)
564 struct hi3670_priv
*priv
= phy_get_drvdata(phy
);
569 mask
= CFGA0_USB3PHY_RESET
| CFGA0_USB2PHY_POR
;
570 ret
= regmap_update_bits(priv
->usb31misc
, USB_MISC_CFGA0
, mask
, 0);
574 if (hi3670_is_abbclk_seleted(priv
)) {
575 /* disable usb_tcxo_en */
576 ret
= regmap_write(priv
->pctrl
, PCTRL_PERI_CTRL3
,
577 USB_TCXO_EN
<< PCTRL_PERI_CTRL3_MSK_START
);
579 ret
= regmap_write(priv
->peri_crg
, PERI_CRG_PERDIS6
,
587 dev_err(priv
->dev
, "failed to exit phy ret: %d\n", ret
);
591 static struct phy_ops hi3670_phy_ops
= {
592 .init
= hi3670_phy_init
,
593 .exit
= hi3670_phy_exit
,
594 .owner
= THIS_MODULE
,
597 static int hi3670_phy_probe(struct platform_device
*pdev
)
599 struct phy_provider
*phy_provider
;
600 struct device
*dev
= &pdev
->dev
;
602 struct hi3670_priv
*priv
;
604 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
609 priv
->peri_crg
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
610 "hisilicon,pericrg-syscon");
611 if (IS_ERR(priv
->peri_crg
)) {
612 dev_err(dev
, "no hisilicon,pericrg-syscon\n");
613 return PTR_ERR(priv
->peri_crg
);
616 priv
->pctrl
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
617 "hisilicon,pctrl-syscon");
618 if (IS_ERR(priv
->pctrl
)) {
619 dev_err(dev
, "no hisilicon,pctrl-syscon\n");
620 return PTR_ERR(priv
->pctrl
);
623 priv
->sctrl
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
624 "hisilicon,sctrl-syscon");
625 if (IS_ERR(priv
->sctrl
)) {
626 dev_err(dev
, "no hisilicon,sctrl-syscon\n");
627 return PTR_ERR(priv
->sctrl
);
630 /* node of hi3670 phy is a sub-node of usb3_otg_bc */
631 priv
->usb31misc
= syscon_node_to_regmap(dev
->parent
->of_node
);
632 if (IS_ERR(priv
->usb31misc
)) {
633 dev_err(dev
, "no hisilicon,usb3-otg-bc-syscon\n");
634 return PTR_ERR(priv
->usb31misc
);
637 if (of_property_read_u32(dev
->of_node
, "hisilicon,eye-diagram-param",
638 &priv
->eye_diagram_param
))
639 priv
->eye_diagram_param
= KIRIN970_USB_DEFAULT_PHY_PARAM
;
641 if (of_property_read_u32(dev
->of_node
, "hisilicon,tx-vboost-lvl",
642 &priv
->tx_vboost_lvl
))
643 priv
->tx_vboost_lvl
= KIRIN970_USB_DEFAULT_PHY_VBOOST
;
645 phy
= devm_phy_create(dev
, NULL
, &hi3670_phy_ops
);
649 phy_set_drvdata(phy
, priv
);
650 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
651 return PTR_ERR_OR_ZERO(phy_provider
);
654 static const struct of_device_id hi3670_phy_of_match
[] = {
655 { .compatible
= "hisilicon,hi3670-usb-phy" },
658 MODULE_DEVICE_TABLE(of
, hi3670_phy_of_match
);
660 static struct platform_driver hi3670_phy_driver
= {
661 .probe
= hi3670_phy_probe
,
663 .name
= "hi3670-usb-phy",
664 .of_match_table
= hi3670_phy_of_match
,
667 module_platform_driver(hi3670_phy_driver
);
669 MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
670 MODULE_LICENSE("GPL v2");
671 MODULE_DESCRIPTION("Hilisicon Kirin970 USB31 PHY Driver");