diff options
-rw-r--r-- | drivers/phy/phy-mt65xx-usb3.c | 99 |
1 files changed, 96 insertions, 3 deletions
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c index 2afbf9f36d83..c0e7b4b0cf5c 100644 --- a/drivers/phy/phy-mt65xx-usb3.c +++ b/drivers/phy/phy-mt65xx-usb3.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/iopoll.h> | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
22 | #include <linux/phy/phy.h> | 23 | #include <linux/phy/phy.h> |
@@ -27,6 +28,7 @@ | |||
27 | * relative to USB3_SIF2_BASE base address | 28 | * relative to USB3_SIF2_BASE base address |
28 | */ | 29 | */ |
29 | #define SSUSB_SIFSLV_SPLLC 0x0000 | 30 | #define SSUSB_SIFSLV_SPLLC 0x0000 |
31 | #define SSUSB_SIFSLV_U2FREQ 0x0100 | ||
30 | 32 | ||
31 | /* offsets of sub-segment in each port registers */ | 33 | /* offsets of sub-segment in each port registers */ |
32 | #define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000 | 34 | #define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000 |
@@ -41,6 +43,7 @@ | |||
41 | #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) | 43 | #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) |
42 | 44 | ||
43 | #define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014) | 45 | #define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014) |
46 | #define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) | ||
44 | #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) | 47 | #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) |
45 | #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) | 48 | #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) |
46 | #define PA5_RG_U2_HS_100U_U3_EN BIT(11) | 49 | #define PA5_RG_U2_HS_100U_U3_EN BIT(11) |
@@ -113,6 +116,24 @@ | |||
113 | #define XC3_RG_U3_XTAL_RX_PWD BIT(9) | 116 | #define XC3_RG_U3_XTAL_RX_PWD BIT(9) |
114 | #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) | 117 | #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) |
115 | 118 | ||
119 | #define U3P_U2FREQ_FMCR0 (SSUSB_SIFSLV_U2FREQ + 0x00) | ||
120 | #define P2F_RG_MONCLK_SEL GENMASK(27, 26) | ||
121 | #define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26) | ||
122 | #define P2F_RG_FREQDET_EN BIT(24) | ||
123 | #define P2F_RG_CYCLECNT GENMASK(23, 0) | ||
124 | #define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) | ||
125 | |||
126 | #define U3P_U2FREQ_VALUE (SSUSB_SIFSLV_U2FREQ + 0x0c) | ||
127 | |||
128 | #define U3P_U2FREQ_FMMONR1 (SSUSB_SIFSLV_U2FREQ + 0x10) | ||
129 | #define P2F_USB_FM_VALID BIT(0) | ||
130 | #define P2F_RG_FRCK_EN BIT(8) | ||
131 | |||
132 | #define U3P_REF_CLK 26 /* MHZ */ | ||
133 | #define U3P_SLEW_RATE_COEF 28 | ||
134 | #define U3P_SR_COEF_DIVISOR 1000 | ||
135 | #define U3P_FM_DET_CYCLE_CNT 1024 | ||
136 | |||
116 | struct mt65xx_phy_instance { | 137 | struct mt65xx_phy_instance { |
117 | struct phy *phy; | 138 | struct phy *phy; |
118 | void __iomem *port_base; | 139 | void __iomem *port_base; |
@@ -128,6 +149,77 @@ struct mt65xx_u3phy { | |||
128 | int nphys; | 149 | int nphys; |
129 | }; | 150 | }; |
130 | 151 | ||
152 | static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, | ||
153 | struct mt65xx_phy_instance *instance) | ||
154 | { | ||
155 | void __iomem *sif_base = u3phy->sif_base; | ||
156 | int calibration_val; | ||
157 | int fm_out; | ||
158 | u32 tmp; | ||
159 | |||
160 | /* enable USB ring oscillator */ | ||
161 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | ||
162 | tmp |= PA5_RG_U2_HSTX_SRCAL_EN; | ||
163 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | ||
164 | udelay(1); | ||
165 | |||
166 | /*enable free run clock */ | ||
167 | tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); | ||
168 | tmp |= P2F_RG_FRCK_EN; | ||
169 | writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); | ||
170 | |||
171 | /* set cycle count as 1024, and select u2 channel */ | ||
172 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | ||
173 | tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); | ||
174 | tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); | ||
175 | tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index); | ||
176 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | ||
177 | |||
178 | /* enable frequency meter */ | ||
179 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | ||
180 | tmp |= P2F_RG_FREQDET_EN; | ||
181 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | ||
182 | |||
183 | /* ignore return value */ | ||
184 | readl_poll_timeout(sif_base + U3P_U2FREQ_FMMONR1, tmp, | ||
185 | (tmp & P2F_USB_FM_VALID), 10, 200); | ||
186 | |||
187 | fm_out = readl(sif_base + U3P_U2FREQ_VALUE); | ||
188 | |||
189 | /* disable frequency meter */ | ||
190 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | ||
191 | tmp &= ~P2F_RG_FREQDET_EN; | ||
192 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | ||
193 | |||
194 | /*disable free run clock */ | ||
195 | tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); | ||
196 | tmp &= ~P2F_RG_FRCK_EN; | ||
197 | writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); | ||
198 | |||
199 | if (fm_out) { | ||
200 | /* ( 1024 / FM_OUT ) x reference clock frequency x 0.028 */ | ||
201 | tmp = U3P_FM_DET_CYCLE_CNT * U3P_REF_CLK * U3P_SLEW_RATE_COEF; | ||
202 | tmp /= fm_out; | ||
203 | calibration_val = DIV_ROUND_CLOSEST(tmp, U3P_SR_COEF_DIVISOR); | ||
204 | } else { | ||
205 | /* if FM detection fail, set default value */ | ||
206 | calibration_val = 4; | ||
207 | } | ||
208 | dev_dbg(u3phy->dev, "phy:%d, fm_out:%d, calib:%d\n", | ||
209 | instance->index, fm_out, calibration_val); | ||
210 | |||
211 | /* set HS slew rate */ | ||
212 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | ||
213 | tmp &= ~PA5_RG_U2_HSTX_SRCTRL; | ||
214 | tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); | ||
215 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | ||
216 | |||
217 | /* disable USB ring oscillator */ | ||
218 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | ||
219 | tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; | ||
220 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | ||
221 | } | ||
222 | |||
131 | static void phy_instance_init(struct mt65xx_u3phy *u3phy, | 223 | static void phy_instance_init(struct mt65xx_u3phy *u3phy, |
132 | struct mt65xx_phy_instance *instance) | 224 | struct mt65xx_phy_instance *instance) |
133 | { | 225 | { |
@@ -226,9 +318,9 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, | |||
226 | tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; | 318 | tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; |
227 | writel(tmp, u3phy->sif_base + U3P_XTALCTL3); | 319 | writel(tmp, u3phy->sif_base + U3P_XTALCTL3); |
228 | 320 | ||
229 | /* [mt8173]disable Change 100uA current from SSUSB */ | 321 | /* [mt8173]switch 100uA current to SSUSB */ |
230 | tmp = readl(port_base + U3P_USBPHYACR5); | 322 | tmp = readl(port_base + U3P_USBPHYACR5); |
231 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; | 323 | tmp |= PA5_RG_U2_HS_100U_U3_EN; |
232 | writel(tmp, port_base + U3P_USBPHYACR5); | 324 | writel(tmp, port_base + U3P_USBPHYACR5); |
233 | } | 325 | } |
234 | 326 | ||
@@ -273,7 +365,7 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, | |||
273 | writel(tmp, port_base + U3P_USBPHYACR6); | 365 | writel(tmp, port_base + U3P_USBPHYACR6); |
274 | 366 | ||
275 | if (!index) { | 367 | if (!index) { |
276 | /* (also disable)Change 100uA current switch to USB2.0 */ | 368 | /* switch 100uA current back to USB2.0 */ |
277 | tmp = readl(port_base + U3P_USBPHYACR5); | 369 | tmp = readl(port_base + U3P_USBPHYACR5); |
278 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; | 370 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; |
279 | writel(tmp, port_base + U3P_USBPHYACR5); | 371 | writel(tmp, port_base + U3P_USBPHYACR5); |
@@ -343,6 +435,7 @@ static int mt65xx_phy_power_on(struct phy *phy) | |||
343 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); | 435 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); |
344 | 436 | ||
345 | phy_instance_power_on(u3phy, instance); | 437 | phy_instance_power_on(u3phy, instance); |
438 | hs_slew_rate_calibrate(u3phy, instance); | ||
346 | return 0; | 439 | return 0; |
347 | } | 440 | } |
348 | 441 | ||