1 // SPDX-License-Identifier: GPL-2.0+
11 #include <generic-phy.h>
12 #include <linux/bitops.h>
13 #include <linux/err.h>
17 #define PHY_CTRL0_REF_SSP_EN BIT(2)
18 #define PHY_CTRL0_FSEL_MASK GENMASK(10, 5)
19 #define PHY_CTRL0_FSEL_24M 0x2a
20 #define PHY_CTRL0_FSEL_100M 0x27
21 #define PHY_CTRL0_SSC_RANGE_MASK GENMASK(23, 21)
22 #define PHY_CTRL0_SSC_RANGE_4003PPM (0x2 << 21)
25 #define PHY_CTRL1_RESET BIT(0)
26 #define PHY_CTRL1_COMMONONN BIT(1)
27 #define PHY_CTRL1_ATERESET BIT(3)
28 #define PHY_CTRL1_DCDENB BIT(17)
29 #define PHY_CTRL1_CHRGSEL BIT(18)
30 #define PHY_CTRL1_VDATSRCENB0 BIT(19)
31 #define PHY_CTRL1_VDATDETENB0 BIT(20)
34 #define PHY_CTRL2_TXENABLEN0 BIT(8)
35 #define PHY_CTRL2_OTG_DISABLE BIT(9)
38 #define PHY_CTRL3_COMPDISTUNE_MASK GENMASK(2, 0)
39 #define PHY_CTRL3_TXPREEMP_TUNE_MASK GENMASK(16, 15)
40 #define PHY_CTRL3_TXPREEMP_TUNE_SHIFT 15
41 #define PHY_CTRL3_TXRISE_TUNE_MASK GENMASK(21, 20)
42 #define PHY_CTRL3_TXRISE_TUNE_SHIFT 20
43 /* 1111: +24% ... 0000: -6% step: 2% */
44 #define PHY_CTRL3_TXVREF_TUNE_MASK GENMASK(25, 22)
45 #define PHY_CTRL3_TXVREF_TUNE_SHIFT 22
46 #define PHY_CTRL3_TX_VBOOST_LEVEL_MASK GENMASK(31, 29)
47 #define PHY_CTRL3_TX_VBOOST_LEVEL_SHIFT 29
49 #define PHY_CTRL4 0x10
50 #define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(20, 15)
51 #define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_SHIFT 15
53 #define PHY_CTRL5 0x14
54 #define PHY_CTRL5_DMPWD_OVERRIDE_SEL BIT(23)
55 #define PHY_CTRL5_DMPWD_OVERRIDE BIT(22)
56 #define PHY_CTRL5_DPPWD_OVERRIDE_SEL BIT(21)
57 #define PHY_CTRL5_DPPWD_OVERRIDE BIT(20)
58 #define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0)
60 #define PHY_CTRL6 0x18
61 #define PHY_CTRL6_RXTERM_OVERRIDE_SEL BIT(29)
62 #define PHY_CTRL6_ALT_CLK_EN BIT(1)
63 #define PHY_CTRL6_ALT_CLK_SEL BIT(0)
66 #define PHY_STS0_OTGSESSVLD BIT(7)
67 #define PHY_STS0_CHGDET BIT(4)
68 #define PHY_STS0_FSVPLUS BIT(3)
69 #define PHY_STS0_FSVMINUS BIT(2)
71 struct imx8mq_usb_phy {
72 #if CONFIG_IS_ENABLED(CLK)
78 static const struct udevice_id imx8mq_usb_phy_of_match[] = {
80 .compatible = "fsl,imx8mq-usb-phy",
85 static int imx8mq_usb_phy_init(struct phy *usb_phy)
87 struct udevice *dev = usb_phy->dev;
88 struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
91 value = readl(imx_phy->base + PHY_CTRL1);
92 value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0 |
94 value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
95 writel(value, imx_phy->base + PHY_CTRL1);
97 value = readl(imx_phy->base + PHY_CTRL0);
98 value |= PHY_CTRL0_REF_SSP_EN;
99 value &= ~PHY_CTRL0_SSC_RANGE_MASK;
100 value |= PHY_CTRL0_SSC_RANGE_4003PPM;
101 writel(value, imx_phy->base + PHY_CTRL0);
103 value = readl(imx_phy->base + PHY_CTRL2);
104 value |= PHY_CTRL2_TXENABLEN0;
105 writel(value, imx_phy->base + PHY_CTRL2);
107 value = readl(imx_phy->base + PHY_CTRL1);
108 value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
109 writel(value, imx_phy->base + PHY_CTRL1);
114 static int imx8mq_usb_phy_power_on(struct phy *usb_phy)
116 struct udevice *dev = usb_phy->dev;
117 struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
120 #if CONFIG_IS_ENABLED(CLK)
122 ret = clk_enable(&imx_phy->phy_clk);
124 printf("Failed to enable usb phy clock\n");
129 /* Disable rx term override */
130 value = readl(imx_phy->base + PHY_CTRL6);
131 value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL;
132 writel(value, imx_phy->base + PHY_CTRL6);
137 static int imx8mq_usb_phy_power_off(struct phy *usb_phy)
139 struct udevice *dev = usb_phy->dev;
140 struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
143 /* Override rx term to be 0 */
144 value = readl(imx_phy->base + PHY_CTRL6);
145 value |= PHY_CTRL6_RXTERM_OVERRIDE_SEL;
146 writel(value, imx_phy->base + PHY_CTRL6);
148 #if CONFIG_IS_ENABLED(CLK)
149 clk_disable(&imx_phy->phy_clk);
155 static int imx8mq_usb_phy_exit(struct phy *usb_phy)
157 return imx8mq_usb_phy_power_off(usb_phy);
160 struct phy_ops imx8mq_usb_phy_ops = {
161 .init = imx8mq_usb_phy_init,
162 .power_on = imx8mq_usb_phy_power_on,
163 .power_off = imx8mq_usb_phy_power_off,
164 .exit = imx8mq_usb_phy_exit,
167 int imx8mq_usb_phy_probe(struct udevice *dev)
169 struct imx8mq_usb_phy *priv = dev_get_priv(dev);
171 priv->base = dev_read_addr_ptr(dev);
176 #if CONFIG_IS_ENABLED(CLK)
179 /* Assigned clock already set clock */
180 ret = clk_get_by_name(dev, "phy", &priv->phy_clk);
182 printf("Failed to get usb phy clock\n");
190 U_BOOT_DRIVER(nxp_imx8mq_usb_phy) = {
191 .name = "nxp_imx8mq_usb_phy",
193 .of_match = imx8mq_usb_phy_of_match,
194 .probe = imx8mq_usb_phy_probe,
195 .ops = &imx8mq_usb_phy_ops,
196 .priv_auto = sizeof(struct imx8mq_usb_phy),