1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2010 Google, Inc.
4*4882a593Smuzhiyun * Copyright (C) 2013 NVIDIA Corporation
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Author:
7*4882a593Smuzhiyun * Erik Gilling <konkers@google.com>
8*4882a593Smuzhiyun * Benoit Goby <benoit@android.com>
9*4882a593Smuzhiyun * Venu Byravarasu <vbyravarasu@nvidia.com>
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/err.h>
14*4882a593Smuzhiyun #include <linux/export.h>
15*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
16*4882a593Smuzhiyun #include <linux/iopoll.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/of.h>
19*4882a593Smuzhiyun #include <linux/of_device.h>
20*4882a593Smuzhiyun #include <linux/platform_device.h>
21*4882a593Smuzhiyun #include <linux/resource.h>
22*4882a593Smuzhiyun #include <linux/slab.h>
23*4882a593Smuzhiyun #include <linux/spinlock.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <linux/usb/ehci_def.h>
28*4882a593Smuzhiyun #include <linux/usb/of.h>
29*4882a593Smuzhiyun #include <linux/usb/tegra_usb_phy.h>
30*4882a593Smuzhiyun #include <linux/usb/ulpi.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define ULPI_VIEWPORT 0x170
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /* PORTSC PTS/PHCD bits, Tegra20 only */
35*4882a593Smuzhiyun #define TEGRA_USB_PORTSC1 0x184
36*4882a593Smuzhiyun #define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
37*4882a593Smuzhiyun #define TEGRA_USB_PORTSC1_PHCD BIT(23)
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* HOSTPC1 PTS/PHCD bits, Tegra30 and above */
40*4882a593Smuzhiyun #define TEGRA_USB_HOSTPC1_DEVLC 0x1b4
41*4882a593Smuzhiyun #define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
42*4882a593Smuzhiyun #define TEGRA_USB_HOSTPC1_DEVLC_PHCD BIT(22)
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* Bits of PORTSC1, which will get cleared by writing 1 into them */
45*4882a593Smuzhiyun #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define USB_SUSP_CTRL 0x400
48*4882a593Smuzhiyun #define USB_WAKE_ON_CNNT_EN_DEV BIT(3)
49*4882a593Smuzhiyun #define USB_WAKE_ON_DISCON_EN_DEV BIT(4)
50*4882a593Smuzhiyun #define USB_SUSP_CLR BIT(5)
51*4882a593Smuzhiyun #define USB_PHY_CLK_VALID BIT(7)
52*4882a593Smuzhiyun #define UTMIP_RESET BIT(11)
53*4882a593Smuzhiyun #define UHSIC_RESET BIT(11)
54*4882a593Smuzhiyun #define UTMIP_PHY_ENABLE BIT(12)
55*4882a593Smuzhiyun #define ULPI_PHY_ENABLE BIT(13)
56*4882a593Smuzhiyun #define USB_SUSP_SET BIT(14)
57*4882a593Smuzhiyun #define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define USB1_LEGACY_CTRL 0x410
60*4882a593Smuzhiyun #define USB1_NO_LEGACY_MODE BIT(0)
61*4882a593Smuzhiyun #define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
62*4882a593Smuzhiyun #define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
63*4882a593Smuzhiyun #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
64*4882a593Smuzhiyun (1 << 1)
65*4882a593Smuzhiyun #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
66*4882a593Smuzhiyun #define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define ULPI_TIMING_CTRL_0 0x424
69*4882a593Smuzhiyun #define ULPI_OUTPUT_PINMUX_BYP BIT(10)
70*4882a593Smuzhiyun #define ULPI_CLKOUT_PINMUX_BYP BIT(11)
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun #define ULPI_TIMING_CTRL_1 0x428
73*4882a593Smuzhiyun #define ULPI_DATA_TRIMMER_LOAD BIT(0)
74*4882a593Smuzhiyun #define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
75*4882a593Smuzhiyun #define ULPI_STPDIRNXT_TRIMMER_LOAD BIT(16)
76*4882a593Smuzhiyun #define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
77*4882a593Smuzhiyun #define ULPI_DIR_TRIMMER_LOAD BIT(24)
78*4882a593Smuzhiyun #define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #define UTMIP_PLL_CFG1 0x804
81*4882a593Smuzhiyun #define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
82*4882a593Smuzhiyun #define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #define UTMIP_XCVR_CFG0 0x808
85*4882a593Smuzhiyun #define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
86*4882a593Smuzhiyun #define UTMIP_XCVR_SETUP_MSB(x) ((((x) & 0x70) >> 4) << 22)
87*4882a593Smuzhiyun #define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
88*4882a593Smuzhiyun #define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
89*4882a593Smuzhiyun #define UTMIP_FORCE_PD_POWERDOWN BIT(14)
90*4882a593Smuzhiyun #define UTMIP_FORCE_PD2_POWERDOWN BIT(16)
91*4882a593Smuzhiyun #define UTMIP_FORCE_PDZI_POWERDOWN BIT(18)
92*4882a593Smuzhiyun #define UTMIP_XCVR_LSBIAS_SEL BIT(21)
93*4882a593Smuzhiyun #define UTMIP_XCVR_HSSLEW(x) (((x) & 0x3) << 4)
94*4882a593Smuzhiyun #define UTMIP_XCVR_HSSLEW_MSB(x) ((((x) & 0x1fc) >> 2) << 25)
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun #define UTMIP_BIAS_CFG0 0x80c
97*4882a593Smuzhiyun #define UTMIP_OTGPD BIT(11)
98*4882a593Smuzhiyun #define UTMIP_BIASPD BIT(10)
99*4882a593Smuzhiyun #define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
100*4882a593Smuzhiyun #define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
101*4882a593Smuzhiyun #define UTMIP_HSDISCON_LEVEL_MSB(x) ((((x) & 0x4) >> 2) << 24)
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun #define UTMIP_HSRX_CFG0 0x810
104*4882a593Smuzhiyun #define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
105*4882a593Smuzhiyun #define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun #define UTMIP_HSRX_CFG1 0x814
108*4882a593Smuzhiyun #define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun #define UTMIP_TX_CFG0 0x820
111*4882a593Smuzhiyun #define UTMIP_FS_PREABMLE_J BIT(19)
112*4882a593Smuzhiyun #define UTMIP_HS_DISCON_DISABLE BIT(8)
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun #define UTMIP_MISC_CFG0 0x824
115*4882a593Smuzhiyun #define UTMIP_DPDM_OBSERVE BIT(26)
116*4882a593Smuzhiyun #define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
117*4882a593Smuzhiyun #define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
118*4882a593Smuzhiyun #define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
119*4882a593Smuzhiyun #define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
120*4882a593Smuzhiyun #define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
121*4882a593Smuzhiyun #define UTMIP_SUSPEND_EXIT_ON_EDGE BIT(22)
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun #define UTMIP_MISC_CFG1 0x828
124*4882a593Smuzhiyun #define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
125*4882a593Smuzhiyun #define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun #define UTMIP_DEBOUNCE_CFG0 0x82c
128*4882a593Smuzhiyun #define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun #define UTMIP_BAT_CHRG_CFG0 0x830
131*4882a593Smuzhiyun #define UTMIP_PD_CHRG BIT(0)
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun #define UTMIP_SPARE_CFG0 0x834
134*4882a593Smuzhiyun #define FUSE_SETUP_SEL BIT(3)
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun #define UTMIP_XCVR_CFG1 0x838
137*4882a593Smuzhiyun #define UTMIP_FORCE_PDDISC_POWERDOWN BIT(0)
138*4882a593Smuzhiyun #define UTMIP_FORCE_PDCHRP_POWERDOWN BIT(2)
139*4882a593Smuzhiyun #define UTMIP_FORCE_PDDR_POWERDOWN BIT(4)
140*4882a593Smuzhiyun #define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun #define UTMIP_BIAS_CFG1 0x83c
143*4882a593Smuzhiyun #define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* For Tegra30 and above only, the address is different in Tegra20 */
146*4882a593Smuzhiyun #define USB_USBMODE 0x1f8
147*4882a593Smuzhiyun #define USB_USBMODE_MASK (3 << 0)
148*4882a593Smuzhiyun #define USB_USBMODE_HOST (3 << 0)
149*4882a593Smuzhiyun #define USB_USBMODE_DEVICE (2 << 0)
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun static DEFINE_SPINLOCK(utmip_pad_lock);
152*4882a593Smuzhiyun static unsigned int utmip_pad_count;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun struct tegra_xtal_freq {
155*4882a593Smuzhiyun unsigned int freq;
156*4882a593Smuzhiyun u8 enable_delay;
157*4882a593Smuzhiyun u8 stable_count;
158*4882a593Smuzhiyun u8 active_delay;
159*4882a593Smuzhiyun u8 xtal_freq_count;
160*4882a593Smuzhiyun u16 debounce;
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun static const struct tegra_xtal_freq tegra_freq_table[] = {
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun .freq = 12000000,
166*4882a593Smuzhiyun .enable_delay = 0x02,
167*4882a593Smuzhiyun .stable_count = 0x2F,
168*4882a593Smuzhiyun .active_delay = 0x04,
169*4882a593Smuzhiyun .xtal_freq_count = 0x76,
170*4882a593Smuzhiyun .debounce = 0x7530,
171*4882a593Smuzhiyun },
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun .freq = 13000000,
174*4882a593Smuzhiyun .enable_delay = 0x02,
175*4882a593Smuzhiyun .stable_count = 0x33,
176*4882a593Smuzhiyun .active_delay = 0x05,
177*4882a593Smuzhiyun .xtal_freq_count = 0x7F,
178*4882a593Smuzhiyun .debounce = 0x7EF4,
179*4882a593Smuzhiyun },
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun .freq = 19200000,
182*4882a593Smuzhiyun .enable_delay = 0x03,
183*4882a593Smuzhiyun .stable_count = 0x4B,
184*4882a593Smuzhiyun .active_delay = 0x06,
185*4882a593Smuzhiyun .xtal_freq_count = 0xBB,
186*4882a593Smuzhiyun .debounce = 0xBB80,
187*4882a593Smuzhiyun },
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun .freq = 26000000,
190*4882a593Smuzhiyun .enable_delay = 0x04,
191*4882a593Smuzhiyun .stable_count = 0x66,
192*4882a593Smuzhiyun .active_delay = 0x09,
193*4882a593Smuzhiyun .xtal_freq_count = 0xFE,
194*4882a593Smuzhiyun .debounce = 0xFDE8,
195*4882a593Smuzhiyun },
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun
to_tegra_usb_phy(struct usb_phy * u_phy)198*4882a593Smuzhiyun static inline struct tegra_usb_phy *to_tegra_usb_phy(struct usb_phy *u_phy)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun return container_of(u_phy, struct tegra_usb_phy, u_phy);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
set_pts(struct tegra_usb_phy * phy,u8 pts_val)203*4882a593Smuzhiyun static void set_pts(struct tegra_usb_phy *phy, u8 pts_val)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun void __iomem *base = phy->regs;
206*4882a593Smuzhiyun u32 val;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (phy->soc_config->has_hostpc) {
209*4882a593Smuzhiyun val = readl_relaxed(base + TEGRA_USB_HOSTPC1_DEVLC);
210*4882a593Smuzhiyun val &= ~TEGRA_USB_HOSTPC1_DEVLC_PTS(~0);
211*4882a593Smuzhiyun val |= TEGRA_USB_HOSTPC1_DEVLC_PTS(pts_val);
212*4882a593Smuzhiyun writel_relaxed(val, base + TEGRA_USB_HOSTPC1_DEVLC);
213*4882a593Smuzhiyun } else {
214*4882a593Smuzhiyun val = readl_relaxed(base + TEGRA_USB_PORTSC1);
215*4882a593Smuzhiyun val &= ~TEGRA_PORTSC1_RWC_BITS;
216*4882a593Smuzhiyun val &= ~TEGRA_USB_PORTSC1_PTS(~0);
217*4882a593Smuzhiyun val |= TEGRA_USB_PORTSC1_PTS(pts_val);
218*4882a593Smuzhiyun writel_relaxed(val, base + TEGRA_USB_PORTSC1);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
set_phcd(struct tegra_usb_phy * phy,bool enable)222*4882a593Smuzhiyun static void set_phcd(struct tegra_usb_phy *phy, bool enable)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun void __iomem *base = phy->regs;
225*4882a593Smuzhiyun u32 val;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (phy->soc_config->has_hostpc) {
228*4882a593Smuzhiyun val = readl_relaxed(base + TEGRA_USB_HOSTPC1_DEVLC);
229*4882a593Smuzhiyun if (enable)
230*4882a593Smuzhiyun val |= TEGRA_USB_HOSTPC1_DEVLC_PHCD;
231*4882a593Smuzhiyun else
232*4882a593Smuzhiyun val &= ~TEGRA_USB_HOSTPC1_DEVLC_PHCD;
233*4882a593Smuzhiyun writel_relaxed(val, base + TEGRA_USB_HOSTPC1_DEVLC);
234*4882a593Smuzhiyun } else {
235*4882a593Smuzhiyun val = readl_relaxed(base + TEGRA_USB_PORTSC1) & ~PORT_RWC_BITS;
236*4882a593Smuzhiyun if (enable)
237*4882a593Smuzhiyun val |= TEGRA_USB_PORTSC1_PHCD;
238*4882a593Smuzhiyun else
239*4882a593Smuzhiyun val &= ~TEGRA_USB_PORTSC1_PHCD;
240*4882a593Smuzhiyun writel_relaxed(val, base + TEGRA_USB_PORTSC1);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
utmip_pad_open(struct tegra_usb_phy * phy)244*4882a593Smuzhiyun static int utmip_pad_open(struct tegra_usb_phy *phy)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun int ret;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun ret = clk_prepare_enable(phy->pad_clk);
249*4882a593Smuzhiyun if (ret) {
250*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
251*4882a593Smuzhiyun "Failed to enable UTMI-pads clock: %d\n", ret);
252*4882a593Smuzhiyun return ret;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun spin_lock(&utmip_pad_lock);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun ret = reset_control_deassert(phy->pad_rst);
258*4882a593Smuzhiyun if (ret) {
259*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
260*4882a593Smuzhiyun "Failed to initialize UTMI-pads reset: %d\n", ret);
261*4882a593Smuzhiyun goto unlock;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun ret = reset_control_assert(phy->pad_rst);
265*4882a593Smuzhiyun if (ret) {
266*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
267*4882a593Smuzhiyun "Failed to assert UTMI-pads reset: %d\n", ret);
268*4882a593Smuzhiyun goto unlock;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun udelay(1);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun ret = reset_control_deassert(phy->pad_rst);
274*4882a593Smuzhiyun if (ret)
275*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
276*4882a593Smuzhiyun "Failed to deassert UTMI-pads reset: %d\n", ret);
277*4882a593Smuzhiyun unlock:
278*4882a593Smuzhiyun spin_unlock(&utmip_pad_lock);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun clk_disable_unprepare(phy->pad_clk);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun return ret;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
utmip_pad_close(struct tegra_usb_phy * phy)285*4882a593Smuzhiyun static int utmip_pad_close(struct tegra_usb_phy *phy)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun int ret;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun ret = clk_prepare_enable(phy->pad_clk);
290*4882a593Smuzhiyun if (ret) {
291*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
292*4882a593Smuzhiyun "Failed to enable UTMI-pads clock: %d\n", ret);
293*4882a593Smuzhiyun return ret;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun ret = reset_control_assert(phy->pad_rst);
297*4882a593Smuzhiyun if (ret)
298*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
299*4882a593Smuzhiyun "Failed to assert UTMI-pads reset: %d\n", ret);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun udelay(1);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun clk_disable_unprepare(phy->pad_clk);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun return ret;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
utmip_pad_power_on(struct tegra_usb_phy * phy)308*4882a593Smuzhiyun static int utmip_pad_power_on(struct tegra_usb_phy *phy)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun struct tegra_utmip_config *config = phy->config;
311*4882a593Smuzhiyun void __iomem *base = phy->pad_regs;
312*4882a593Smuzhiyun u32 val;
313*4882a593Smuzhiyun int err;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun err = clk_prepare_enable(phy->pad_clk);
316*4882a593Smuzhiyun if (err)
317*4882a593Smuzhiyun return err;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun spin_lock(&utmip_pad_lock);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (utmip_pad_count++ == 0) {
322*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_BIAS_CFG0);
323*4882a593Smuzhiyun val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (phy->soc_config->requires_extra_tuning_parameters) {
326*4882a593Smuzhiyun val &= ~(UTMIP_HSSQUELCH_LEVEL(~0) |
327*4882a593Smuzhiyun UTMIP_HSDISCON_LEVEL(~0) |
328*4882a593Smuzhiyun UTMIP_HSDISCON_LEVEL_MSB(~0));
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun val |= UTMIP_HSSQUELCH_LEVEL(config->hssquelch_level);
331*4882a593Smuzhiyun val |= UTMIP_HSDISCON_LEVEL(config->hsdiscon_level);
332*4882a593Smuzhiyun val |= UTMIP_HSDISCON_LEVEL_MSB(config->hsdiscon_level);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_BIAS_CFG0);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun spin_unlock(&utmip_pad_lock);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun clk_disable_unprepare(phy->pad_clk);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
utmip_pad_power_off(struct tegra_usb_phy * phy)344*4882a593Smuzhiyun static int utmip_pad_power_off(struct tegra_usb_phy *phy)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun void __iomem *base = phy->pad_regs;
347*4882a593Smuzhiyun u32 val;
348*4882a593Smuzhiyun int ret;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun ret = clk_prepare_enable(phy->pad_clk);
351*4882a593Smuzhiyun if (ret)
352*4882a593Smuzhiyun return ret;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun spin_lock(&utmip_pad_lock);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (!utmip_pad_count) {
357*4882a593Smuzhiyun dev_err(phy->u_phy.dev, "UTMIP pad already powered off\n");
358*4882a593Smuzhiyun ret = -EINVAL;
359*4882a593Smuzhiyun goto ulock;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun if (--utmip_pad_count == 0) {
363*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_BIAS_CFG0);
364*4882a593Smuzhiyun val |= UTMIP_OTGPD | UTMIP_BIASPD;
365*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_BIAS_CFG0);
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun ulock:
368*4882a593Smuzhiyun spin_unlock(&utmip_pad_lock);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun clk_disable_unprepare(phy->pad_clk);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun return ret;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
utmi_wait_register(void __iomem * reg,u32 mask,u32 result)375*4882a593Smuzhiyun static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun u32 tmp;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun return readl_relaxed_poll_timeout(reg, tmp, (tmp & mask) == result,
380*4882a593Smuzhiyun 2000, 6000);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
utmi_phy_clk_disable(struct tegra_usb_phy * phy)383*4882a593Smuzhiyun static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun void __iomem *base = phy->regs;
386*4882a593Smuzhiyun u32 val;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /*
389*4882a593Smuzhiyun * The USB driver may have already initiated the phy clock
390*4882a593Smuzhiyun * disable so wait to see if the clock turns off and if not
391*4882a593Smuzhiyun * then proceed with gating the clock.
392*4882a593Smuzhiyun */
393*4882a593Smuzhiyun if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) == 0)
394*4882a593Smuzhiyun return;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun if (phy->is_legacy_phy) {
397*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
398*4882a593Smuzhiyun val |= USB_SUSP_SET;
399*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun usleep_range(10, 100);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
404*4882a593Smuzhiyun val &= ~USB_SUSP_SET;
405*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
406*4882a593Smuzhiyun } else {
407*4882a593Smuzhiyun set_phcd(phy, true);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0))
411*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
412*4882a593Smuzhiyun "Timeout waiting for PHY to stabilize on disable\n");
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
utmi_phy_clk_enable(struct tegra_usb_phy * phy)415*4882a593Smuzhiyun static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun void __iomem *base = phy->regs;
418*4882a593Smuzhiyun u32 val;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /*
421*4882a593Smuzhiyun * The USB driver may have already initiated the phy clock
422*4882a593Smuzhiyun * enable so wait to see if the clock turns on and if not
423*4882a593Smuzhiyun * then proceed with ungating the clock.
424*4882a593Smuzhiyun */
425*4882a593Smuzhiyun if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
426*4882a593Smuzhiyun USB_PHY_CLK_VALID) == 0)
427*4882a593Smuzhiyun return;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun if (phy->is_legacy_phy) {
430*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
431*4882a593Smuzhiyun val |= USB_SUSP_CLR;
432*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun usleep_range(10, 100);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
437*4882a593Smuzhiyun val &= ~USB_SUSP_CLR;
438*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
439*4882a593Smuzhiyun } else {
440*4882a593Smuzhiyun set_phcd(phy, false);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
444*4882a593Smuzhiyun USB_PHY_CLK_VALID))
445*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
446*4882a593Smuzhiyun "Timeout waiting for PHY to stabilize on enable\n");
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
utmi_phy_power_on(struct tegra_usb_phy * phy)449*4882a593Smuzhiyun static int utmi_phy_power_on(struct tegra_usb_phy *phy)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun struct tegra_utmip_config *config = phy->config;
452*4882a593Smuzhiyun void __iomem *base = phy->regs;
453*4882a593Smuzhiyun u32 val;
454*4882a593Smuzhiyun int err;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
457*4882a593Smuzhiyun val |= UTMIP_RESET;
458*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun if (phy->is_legacy_phy) {
461*4882a593Smuzhiyun val = readl_relaxed(base + USB1_LEGACY_CTRL);
462*4882a593Smuzhiyun val |= USB1_NO_LEGACY_MODE;
463*4882a593Smuzhiyun writel_relaxed(val, base + USB1_LEGACY_CTRL);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_TX_CFG0);
467*4882a593Smuzhiyun val |= UTMIP_FS_PREABMLE_J;
468*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_TX_CFG0);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_HSRX_CFG0);
471*4882a593Smuzhiyun val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
472*4882a593Smuzhiyun val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
473*4882a593Smuzhiyun val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
474*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_HSRX_CFG0);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_HSRX_CFG1);
477*4882a593Smuzhiyun val &= ~UTMIP_HS_SYNC_START_DLY(~0);
478*4882a593Smuzhiyun val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
479*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_HSRX_CFG1);
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_DEBOUNCE_CFG0);
482*4882a593Smuzhiyun val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
483*4882a593Smuzhiyun val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
484*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_DEBOUNCE_CFG0);
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_MISC_CFG0);
487*4882a593Smuzhiyun val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
488*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_MISC_CFG0);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun if (!phy->soc_config->utmi_pll_config_in_car_module) {
491*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_MISC_CFG1);
492*4882a593Smuzhiyun val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) |
493*4882a593Smuzhiyun UTMIP_PLLU_STABLE_COUNT(~0));
494*4882a593Smuzhiyun val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
495*4882a593Smuzhiyun UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
496*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_MISC_CFG1);
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_PLL_CFG1);
499*4882a593Smuzhiyun val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) |
500*4882a593Smuzhiyun UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
501*4882a593Smuzhiyun val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
502*4882a593Smuzhiyun UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
503*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_PLL_CFG1);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun if (phy->mode == USB_DR_MODE_PERIPHERAL) {
507*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
508*4882a593Smuzhiyun val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
509*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0);
512*4882a593Smuzhiyun val &= ~UTMIP_PD_CHRG;
513*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_BAT_CHRG_CFG0);
514*4882a593Smuzhiyun } else {
515*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0);
516*4882a593Smuzhiyun val |= UTMIP_PD_CHRG;
517*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_BAT_CHRG_CFG0);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun err = utmip_pad_power_on(phy);
521*4882a593Smuzhiyun if (err)
522*4882a593Smuzhiyun return err;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_XCVR_CFG0);
525*4882a593Smuzhiyun val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
526*4882a593Smuzhiyun UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_LSBIAS_SEL |
527*4882a593Smuzhiyun UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_SETUP_MSB(~0) |
528*4882a593Smuzhiyun UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0));
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun if (!config->xcvr_setup_use_fuses) {
531*4882a593Smuzhiyun val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
532*4882a593Smuzhiyun val |= UTMIP_XCVR_SETUP_MSB(config->xcvr_setup);
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
535*4882a593Smuzhiyun val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun if (phy->soc_config->requires_extra_tuning_parameters) {
538*4882a593Smuzhiyun val &= ~(UTMIP_XCVR_HSSLEW(~0) | UTMIP_XCVR_HSSLEW_MSB(~0));
539*4882a593Smuzhiyun val |= UTMIP_XCVR_HSSLEW(config->xcvr_hsslew);
540*4882a593Smuzhiyun val |= UTMIP_XCVR_HSSLEW_MSB(config->xcvr_hsslew);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_XCVR_CFG0);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_XCVR_CFG1);
545*4882a593Smuzhiyun val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
546*4882a593Smuzhiyun UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
547*4882a593Smuzhiyun val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
548*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_XCVR_CFG1);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_BIAS_CFG1);
551*4882a593Smuzhiyun val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
552*4882a593Smuzhiyun val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
553*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_BIAS_CFG1);
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_SPARE_CFG0);
556*4882a593Smuzhiyun if (config->xcvr_setup_use_fuses)
557*4882a593Smuzhiyun val |= FUSE_SETUP_SEL;
558*4882a593Smuzhiyun else
559*4882a593Smuzhiyun val &= ~FUSE_SETUP_SEL;
560*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_SPARE_CFG0);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun if (!phy->is_legacy_phy) {
563*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
564*4882a593Smuzhiyun val |= UTMIP_PHY_ENABLE;
565*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
569*4882a593Smuzhiyun val &= ~UTMIP_RESET;
570*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun if (phy->is_legacy_phy) {
573*4882a593Smuzhiyun val = readl_relaxed(base + USB1_LEGACY_CTRL);
574*4882a593Smuzhiyun val &= ~USB1_VBUS_SENSE_CTL_MASK;
575*4882a593Smuzhiyun val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
576*4882a593Smuzhiyun writel_relaxed(val, base + USB1_LEGACY_CTRL);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
579*4882a593Smuzhiyun val &= ~USB_SUSP_SET;
580*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun utmi_phy_clk_enable(phy);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (phy->soc_config->requires_usbmode_setup) {
586*4882a593Smuzhiyun val = readl_relaxed(base + USB_USBMODE);
587*4882a593Smuzhiyun val &= ~USB_USBMODE_MASK;
588*4882a593Smuzhiyun if (phy->mode == USB_DR_MODE_HOST)
589*4882a593Smuzhiyun val |= USB_USBMODE_HOST;
590*4882a593Smuzhiyun else
591*4882a593Smuzhiyun val |= USB_USBMODE_DEVICE;
592*4882a593Smuzhiyun writel_relaxed(val, base + USB_USBMODE);
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun if (!phy->is_legacy_phy)
596*4882a593Smuzhiyun set_pts(phy, 0);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
utmi_phy_power_off(struct tegra_usb_phy * phy)601*4882a593Smuzhiyun static int utmi_phy_power_off(struct tegra_usb_phy *phy)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun void __iomem *base = phy->regs;
604*4882a593Smuzhiyun u32 val;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun utmi_phy_clk_disable(phy);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun if (phy->mode == USB_DR_MODE_PERIPHERAL) {
609*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
610*4882a593Smuzhiyun val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
611*4882a593Smuzhiyun val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
612*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
616*4882a593Smuzhiyun val |= UTMIP_RESET;
617*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0);
620*4882a593Smuzhiyun val |= UTMIP_PD_CHRG;
621*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_BAT_CHRG_CFG0);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_XCVR_CFG0);
624*4882a593Smuzhiyun val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
625*4882a593Smuzhiyun UTMIP_FORCE_PDZI_POWERDOWN;
626*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_XCVR_CFG0);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_XCVR_CFG1);
629*4882a593Smuzhiyun val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
630*4882a593Smuzhiyun UTMIP_FORCE_PDDR_POWERDOWN;
631*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_XCVR_CFG1);
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun return utmip_pad_power_off(phy);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
utmi_phy_preresume(struct tegra_usb_phy * phy)636*4882a593Smuzhiyun static void utmi_phy_preresume(struct tegra_usb_phy *phy)
637*4882a593Smuzhiyun {
638*4882a593Smuzhiyun void __iomem *base = phy->regs;
639*4882a593Smuzhiyun u32 val;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_TX_CFG0);
642*4882a593Smuzhiyun val |= UTMIP_HS_DISCON_DISABLE;
643*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_TX_CFG0);
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
utmi_phy_postresume(struct tegra_usb_phy * phy)646*4882a593Smuzhiyun static void utmi_phy_postresume(struct tegra_usb_phy *phy)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun void __iomem *base = phy->regs;
649*4882a593Smuzhiyun u32 val;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_TX_CFG0);
652*4882a593Smuzhiyun val &= ~UTMIP_HS_DISCON_DISABLE;
653*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_TX_CFG0);
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun
utmi_phy_restore_start(struct tegra_usb_phy * phy,enum tegra_usb_phy_port_speed port_speed)656*4882a593Smuzhiyun static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
657*4882a593Smuzhiyun enum tegra_usb_phy_port_speed port_speed)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun void __iomem *base = phy->regs;
660*4882a593Smuzhiyun u32 val;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_MISC_CFG0);
663*4882a593Smuzhiyun val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
664*4882a593Smuzhiyun if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
665*4882a593Smuzhiyun val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
666*4882a593Smuzhiyun else
667*4882a593Smuzhiyun val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
668*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_MISC_CFG0);
669*4882a593Smuzhiyun usleep_range(1, 10);
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_MISC_CFG0);
672*4882a593Smuzhiyun val |= UTMIP_DPDM_OBSERVE;
673*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_MISC_CFG0);
674*4882a593Smuzhiyun usleep_range(10, 100);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
utmi_phy_restore_end(struct tegra_usb_phy * phy)677*4882a593Smuzhiyun static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun void __iomem *base = phy->regs;
680*4882a593Smuzhiyun u32 val;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun val = readl_relaxed(base + UTMIP_MISC_CFG0);
683*4882a593Smuzhiyun val &= ~UTMIP_DPDM_OBSERVE;
684*4882a593Smuzhiyun writel_relaxed(val, base + UTMIP_MISC_CFG0);
685*4882a593Smuzhiyun usleep_range(10, 100);
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
ulpi_phy_power_on(struct tegra_usb_phy * phy)688*4882a593Smuzhiyun static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun void __iomem *base = phy->regs;
691*4882a593Smuzhiyun u32 val;
692*4882a593Smuzhiyun int err;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun gpiod_set_value_cansleep(phy->reset_gpio, 1);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun err = clk_prepare_enable(phy->clk);
697*4882a593Smuzhiyun if (err)
698*4882a593Smuzhiyun return err;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun usleep_range(5000, 6000);
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun gpiod_set_value_cansleep(phy->reset_gpio, 0);
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun usleep_range(1000, 2000);
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
707*4882a593Smuzhiyun val |= UHSIC_RESET;
708*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun val = readl_relaxed(base + ULPI_TIMING_CTRL_0);
711*4882a593Smuzhiyun val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
712*4882a593Smuzhiyun writel_relaxed(val, base + ULPI_TIMING_CTRL_0);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
715*4882a593Smuzhiyun val |= ULPI_PHY_ENABLE;
716*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun val = 0;
719*4882a593Smuzhiyun writel_relaxed(val, base + ULPI_TIMING_CTRL_1);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun val |= ULPI_DATA_TRIMMER_SEL(4);
722*4882a593Smuzhiyun val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
723*4882a593Smuzhiyun val |= ULPI_DIR_TRIMMER_SEL(4);
724*4882a593Smuzhiyun writel_relaxed(val, base + ULPI_TIMING_CTRL_1);
725*4882a593Smuzhiyun usleep_range(10, 100);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun val |= ULPI_DATA_TRIMMER_LOAD;
728*4882a593Smuzhiyun val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
729*4882a593Smuzhiyun val |= ULPI_DIR_TRIMMER_LOAD;
730*4882a593Smuzhiyun writel_relaxed(val, base + ULPI_TIMING_CTRL_1);
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun /* Fix VbusInvalid due to floating VBUS */
733*4882a593Smuzhiyun err = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
734*4882a593Smuzhiyun if (err) {
735*4882a593Smuzhiyun dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", err);
736*4882a593Smuzhiyun goto disable_clk;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun err = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
740*4882a593Smuzhiyun if (err) {
741*4882a593Smuzhiyun dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", err);
742*4882a593Smuzhiyun goto disable_clk;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
746*4882a593Smuzhiyun val |= USB_SUSP_CLR;
747*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
748*4882a593Smuzhiyun usleep_range(100, 1000);
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun val = readl_relaxed(base + USB_SUSP_CTRL);
751*4882a593Smuzhiyun val &= ~USB_SUSP_CLR;
752*4882a593Smuzhiyun writel_relaxed(val, base + USB_SUSP_CTRL);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun return 0;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun disable_clk:
757*4882a593Smuzhiyun clk_disable_unprepare(phy->clk);
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun return err;
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun
ulpi_phy_power_off(struct tegra_usb_phy * phy)762*4882a593Smuzhiyun static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun gpiod_set_value_cansleep(phy->reset_gpio, 1);
765*4882a593Smuzhiyun usleep_range(5000, 6000);
766*4882a593Smuzhiyun clk_disable_unprepare(phy->clk);
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun return 0;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
tegra_usb_phy_power_on(struct tegra_usb_phy * phy)771*4882a593Smuzhiyun static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun int err;
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun if (phy->powered_on)
776*4882a593Smuzhiyun return 0;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun if (phy->is_ulpi_phy)
779*4882a593Smuzhiyun err = ulpi_phy_power_on(phy);
780*4882a593Smuzhiyun else
781*4882a593Smuzhiyun err = utmi_phy_power_on(phy);
782*4882a593Smuzhiyun if (err)
783*4882a593Smuzhiyun return err;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun phy->powered_on = true;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun return 0;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
tegra_usb_phy_power_off(struct tegra_usb_phy * phy)790*4882a593Smuzhiyun static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
791*4882a593Smuzhiyun {
792*4882a593Smuzhiyun int err;
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun if (!phy->powered_on)
795*4882a593Smuzhiyun return 0;
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun if (phy->is_ulpi_phy)
798*4882a593Smuzhiyun err = ulpi_phy_power_off(phy);
799*4882a593Smuzhiyun else
800*4882a593Smuzhiyun err = utmi_phy_power_off(phy);
801*4882a593Smuzhiyun if (err)
802*4882a593Smuzhiyun return err;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun phy->powered_on = false;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun return 0;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun
tegra_usb_phy_shutdown(struct usb_phy * u_phy)809*4882a593Smuzhiyun static void tegra_usb_phy_shutdown(struct usb_phy *u_phy)
810*4882a593Smuzhiyun {
811*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun if (WARN_ON(!phy->freq))
814*4882a593Smuzhiyun return;
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun tegra_usb_phy_power_off(phy);
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun if (!phy->is_ulpi_phy)
819*4882a593Smuzhiyun utmip_pad_close(phy);
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun regulator_disable(phy->vbus);
822*4882a593Smuzhiyun clk_disable_unprepare(phy->pll_u);
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun phy->freq = NULL;
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun
tegra_usb_phy_set_suspend(struct usb_phy * u_phy,int suspend)827*4882a593Smuzhiyun static int tegra_usb_phy_set_suspend(struct usb_phy *u_phy, int suspend)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun if (WARN_ON(!phy->freq))
832*4882a593Smuzhiyun return -EINVAL;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun if (suspend)
835*4882a593Smuzhiyun return tegra_usb_phy_power_off(phy);
836*4882a593Smuzhiyun else
837*4882a593Smuzhiyun return tegra_usb_phy_power_on(phy);
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
tegra_usb_phy_init(struct usb_phy * u_phy)840*4882a593Smuzhiyun static int tegra_usb_phy_init(struct usb_phy *u_phy)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
843*4882a593Smuzhiyun unsigned long parent_rate;
844*4882a593Smuzhiyun unsigned int i;
845*4882a593Smuzhiyun int err;
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun if (WARN_ON(phy->freq))
848*4882a593Smuzhiyun return 0;
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun err = clk_prepare_enable(phy->pll_u);
851*4882a593Smuzhiyun if (err)
852*4882a593Smuzhiyun return err;
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
855*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
856*4882a593Smuzhiyun if (tegra_freq_table[i].freq == parent_rate) {
857*4882a593Smuzhiyun phy->freq = &tegra_freq_table[i];
858*4882a593Smuzhiyun break;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun if (!phy->freq) {
862*4882a593Smuzhiyun dev_err(phy->u_phy.dev, "Invalid pll_u parent rate %ld\n",
863*4882a593Smuzhiyun parent_rate);
864*4882a593Smuzhiyun err = -EINVAL;
865*4882a593Smuzhiyun goto disable_clk;
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun err = regulator_enable(phy->vbus);
869*4882a593Smuzhiyun if (err) {
870*4882a593Smuzhiyun dev_err(phy->u_phy.dev,
871*4882a593Smuzhiyun "Failed to enable USB VBUS regulator: %d\n", err);
872*4882a593Smuzhiyun goto disable_clk;
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun if (!phy->is_ulpi_phy) {
876*4882a593Smuzhiyun err = utmip_pad_open(phy);
877*4882a593Smuzhiyun if (err)
878*4882a593Smuzhiyun goto disable_vbus;
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun err = tegra_usb_phy_power_on(phy);
882*4882a593Smuzhiyun if (err)
883*4882a593Smuzhiyun goto close_phy;
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun return 0;
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun close_phy:
888*4882a593Smuzhiyun if (!phy->is_ulpi_phy)
889*4882a593Smuzhiyun utmip_pad_close(phy);
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun disable_vbus:
892*4882a593Smuzhiyun regulator_disable(phy->vbus);
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun disable_clk:
895*4882a593Smuzhiyun clk_disable_unprepare(phy->pll_u);
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun phy->freq = NULL;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun return err;
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun
tegra_usb_phy_preresume(struct usb_phy * u_phy)902*4882a593Smuzhiyun void tegra_usb_phy_preresume(struct usb_phy *u_phy)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun if (!phy->is_ulpi_phy)
907*4882a593Smuzhiyun utmi_phy_preresume(phy);
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
910*4882a593Smuzhiyun
tegra_usb_phy_postresume(struct usb_phy * u_phy)911*4882a593Smuzhiyun void tegra_usb_phy_postresume(struct usb_phy *u_phy)
912*4882a593Smuzhiyun {
913*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun if (!phy->is_ulpi_phy)
916*4882a593Smuzhiyun utmi_phy_postresume(phy);
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
919*4882a593Smuzhiyun
tegra_ehci_phy_restore_start(struct usb_phy * u_phy,enum tegra_usb_phy_port_speed port_speed)920*4882a593Smuzhiyun void tegra_ehci_phy_restore_start(struct usb_phy *u_phy,
921*4882a593Smuzhiyun enum tegra_usb_phy_port_speed port_speed)
922*4882a593Smuzhiyun {
923*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun if (!phy->is_ulpi_phy)
926*4882a593Smuzhiyun utmi_phy_restore_start(phy, port_speed);
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
929*4882a593Smuzhiyun
tegra_ehci_phy_restore_end(struct usb_phy * u_phy)930*4882a593Smuzhiyun void tegra_ehci_phy_restore_end(struct usb_phy *u_phy)
931*4882a593Smuzhiyun {
932*4882a593Smuzhiyun struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun if (!phy->is_ulpi_phy)
935*4882a593Smuzhiyun utmi_phy_restore_end(phy);
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
938*4882a593Smuzhiyun
read_utmi_param(struct platform_device * pdev,const char * param,u8 * dest)939*4882a593Smuzhiyun static int read_utmi_param(struct platform_device *pdev, const char *param,
940*4882a593Smuzhiyun u8 *dest)
941*4882a593Smuzhiyun {
942*4882a593Smuzhiyun u32 value;
943*4882a593Smuzhiyun int err;
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun err = of_property_read_u32(pdev->dev.of_node, param, &value);
946*4882a593Smuzhiyun if (err)
947*4882a593Smuzhiyun dev_err(&pdev->dev,
948*4882a593Smuzhiyun "Failed to read USB UTMI parameter %s: %d\n",
949*4882a593Smuzhiyun param, err);
950*4882a593Smuzhiyun else
951*4882a593Smuzhiyun *dest = value;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun return err;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun
utmi_phy_probe(struct tegra_usb_phy * tegra_phy,struct platform_device * pdev)956*4882a593Smuzhiyun static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
957*4882a593Smuzhiyun struct platform_device *pdev)
958*4882a593Smuzhiyun {
959*4882a593Smuzhiyun struct tegra_utmip_config *config;
960*4882a593Smuzhiyun struct resource *res;
961*4882a593Smuzhiyun int err;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun tegra_phy->is_ulpi_phy = false;
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
966*4882a593Smuzhiyun if (!res) {
967*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to get UTMI pad regs\n");
968*4882a593Smuzhiyun return -ENXIO;
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun /*
972*4882a593Smuzhiyun * Note that UTMI pad registers are shared by all PHYs, therefore
973*4882a593Smuzhiyun * devm_platform_ioremap_resource() can't be used here.
974*4882a593Smuzhiyun */
975*4882a593Smuzhiyun tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
976*4882a593Smuzhiyun resource_size(res));
977*4882a593Smuzhiyun if (!tegra_phy->pad_regs) {
978*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to remap UTMI pad regs\n");
979*4882a593Smuzhiyun return -ENOMEM;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun tegra_phy->config = devm_kzalloc(&pdev->dev, sizeof(*config),
983*4882a593Smuzhiyun GFP_KERNEL);
984*4882a593Smuzhiyun if (!tegra_phy->config)
985*4882a593Smuzhiyun return -ENOMEM;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun config = tegra_phy->config;
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,hssync-start-delay",
990*4882a593Smuzhiyun &config->hssync_start_delay);
991*4882a593Smuzhiyun if (err)
992*4882a593Smuzhiyun return err;
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,elastic-limit",
995*4882a593Smuzhiyun &config->elastic_limit);
996*4882a593Smuzhiyun if (err)
997*4882a593Smuzhiyun return err;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,idle-wait-delay",
1000*4882a593Smuzhiyun &config->idle_wait_delay);
1001*4882a593Smuzhiyun if (err)
1002*4882a593Smuzhiyun return err;
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,term-range-adj",
1005*4882a593Smuzhiyun &config->term_range_adj);
1006*4882a593Smuzhiyun if (err)
1007*4882a593Smuzhiyun return err;
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,xcvr-lsfslew",
1010*4882a593Smuzhiyun &config->xcvr_lsfslew);
1011*4882a593Smuzhiyun if (err)
1012*4882a593Smuzhiyun return err;
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,xcvr-lsrslew",
1015*4882a593Smuzhiyun &config->xcvr_lsrslew);
1016*4882a593Smuzhiyun if (err)
1017*4882a593Smuzhiyun return err;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun if (tegra_phy->soc_config->requires_extra_tuning_parameters) {
1020*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,xcvr-hsslew",
1021*4882a593Smuzhiyun &config->xcvr_hsslew);
1022*4882a593Smuzhiyun if (err)
1023*4882a593Smuzhiyun return err;
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,hssquelch-level",
1026*4882a593Smuzhiyun &config->hssquelch_level);
1027*4882a593Smuzhiyun if (err)
1028*4882a593Smuzhiyun return err;
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,hsdiscon-level",
1031*4882a593Smuzhiyun &config->hsdiscon_level);
1032*4882a593Smuzhiyun if (err)
1033*4882a593Smuzhiyun return err;
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun config->xcvr_setup_use_fuses = of_property_read_bool(
1037*4882a593Smuzhiyun pdev->dev.of_node, "nvidia,xcvr-setup-use-fuses");
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun if (!config->xcvr_setup_use_fuses) {
1040*4882a593Smuzhiyun err = read_utmi_param(pdev, "nvidia,xcvr-setup",
1041*4882a593Smuzhiyun &config->xcvr_setup);
1042*4882a593Smuzhiyun if (err)
1043*4882a593Smuzhiyun return err;
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun return 0;
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun static const struct tegra_phy_soc_config tegra20_soc_config = {
1050*4882a593Smuzhiyun .utmi_pll_config_in_car_module = false,
1051*4882a593Smuzhiyun .has_hostpc = false,
1052*4882a593Smuzhiyun .requires_usbmode_setup = false,
1053*4882a593Smuzhiyun .requires_extra_tuning_parameters = false,
1054*4882a593Smuzhiyun };
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun static const struct tegra_phy_soc_config tegra30_soc_config = {
1057*4882a593Smuzhiyun .utmi_pll_config_in_car_module = true,
1058*4882a593Smuzhiyun .has_hostpc = true,
1059*4882a593Smuzhiyun .requires_usbmode_setup = true,
1060*4882a593Smuzhiyun .requires_extra_tuning_parameters = true,
1061*4882a593Smuzhiyun };
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun static const struct of_device_id tegra_usb_phy_id_table[] = {
1064*4882a593Smuzhiyun { .compatible = "nvidia,tegra30-usb-phy", .data = &tegra30_soc_config },
1065*4882a593Smuzhiyun { .compatible = "nvidia,tegra20-usb-phy", .data = &tegra20_soc_config },
1066*4882a593Smuzhiyun { },
1067*4882a593Smuzhiyun };
1068*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table);
1069*4882a593Smuzhiyun
tegra_usb_phy_probe(struct platform_device * pdev)1070*4882a593Smuzhiyun static int tegra_usb_phy_probe(struct platform_device *pdev)
1071*4882a593Smuzhiyun {
1072*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
1073*4882a593Smuzhiyun struct tegra_usb_phy *tegra_phy;
1074*4882a593Smuzhiyun enum usb_phy_interface phy_type;
1075*4882a593Smuzhiyun struct reset_control *reset;
1076*4882a593Smuzhiyun struct gpio_desc *gpiod;
1077*4882a593Smuzhiyun struct resource *res;
1078*4882a593Smuzhiyun struct usb_phy *phy;
1079*4882a593Smuzhiyun int err;
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL);
1082*4882a593Smuzhiyun if (!tegra_phy)
1083*4882a593Smuzhiyun return -ENOMEM;
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun tegra_phy->soc_config = of_device_get_match_data(&pdev->dev);
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1088*4882a593Smuzhiyun if (!res) {
1089*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to get I/O memory\n");
1090*4882a593Smuzhiyun return -ENXIO;
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun /*
1094*4882a593Smuzhiyun * Note that PHY and USB controller are using shared registers,
1095*4882a593Smuzhiyun * therefore devm_platform_ioremap_resource() can't be used here.
1096*4882a593Smuzhiyun */
1097*4882a593Smuzhiyun tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
1098*4882a593Smuzhiyun resource_size(res));
1099*4882a593Smuzhiyun if (!tegra_phy->regs) {
1100*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to remap I/O memory\n");
1101*4882a593Smuzhiyun return -ENOMEM;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun tegra_phy->is_legacy_phy =
1105*4882a593Smuzhiyun of_property_read_bool(np, "nvidia,has-legacy-mode");
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun if (of_find_property(np, "dr_mode", NULL))
1108*4882a593Smuzhiyun tegra_phy->mode = usb_get_dr_mode(&pdev->dev);
1109*4882a593Smuzhiyun else
1110*4882a593Smuzhiyun tegra_phy->mode = USB_DR_MODE_HOST;
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun if (tegra_phy->mode == USB_DR_MODE_UNKNOWN) {
1113*4882a593Smuzhiyun dev_err(&pdev->dev, "dr_mode is invalid\n");
1114*4882a593Smuzhiyun return -EINVAL;
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun /* On some boards, the VBUS regulator doesn't need to be controlled */
1118*4882a593Smuzhiyun tegra_phy->vbus = devm_regulator_get(&pdev->dev, "vbus");
1119*4882a593Smuzhiyun if (IS_ERR(tegra_phy->vbus))
1120*4882a593Smuzhiyun return PTR_ERR(tegra_phy->vbus);
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun tegra_phy->pll_u = devm_clk_get(&pdev->dev, "pll_u");
1123*4882a593Smuzhiyun err = PTR_ERR_OR_ZERO(tegra_phy->pll_u);
1124*4882a593Smuzhiyun if (err) {
1125*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to get pll_u clock: %d\n", err);
1126*4882a593Smuzhiyun return err;
1127*4882a593Smuzhiyun }
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun phy_type = of_usb_get_phy_mode(np);
1130*4882a593Smuzhiyun switch (phy_type) {
1131*4882a593Smuzhiyun case USBPHY_INTERFACE_MODE_UTMI:
1132*4882a593Smuzhiyun err = utmi_phy_probe(tegra_phy, pdev);
1133*4882a593Smuzhiyun if (err)
1134*4882a593Smuzhiyun return err;
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun tegra_phy->pad_clk = devm_clk_get(&pdev->dev, "utmi-pads");
1137*4882a593Smuzhiyun err = PTR_ERR_OR_ZERO(tegra_phy->pad_clk);
1138*4882a593Smuzhiyun if (err) {
1139*4882a593Smuzhiyun dev_err(&pdev->dev,
1140*4882a593Smuzhiyun "Failed to get UTMIP pad clock: %d\n", err);
1141*4882a593Smuzhiyun return err;
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun reset = devm_reset_control_get_optional_shared(&pdev->dev,
1145*4882a593Smuzhiyun "utmi-pads");
1146*4882a593Smuzhiyun err = PTR_ERR_OR_ZERO(reset);
1147*4882a593Smuzhiyun if (err) {
1148*4882a593Smuzhiyun dev_err(&pdev->dev,
1149*4882a593Smuzhiyun "Failed to get UTMI-pads reset: %d\n", err);
1150*4882a593Smuzhiyun return err;
1151*4882a593Smuzhiyun }
1152*4882a593Smuzhiyun tegra_phy->pad_rst = reset;
1153*4882a593Smuzhiyun break;
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun case USBPHY_INTERFACE_MODE_ULPI:
1156*4882a593Smuzhiyun tegra_phy->is_ulpi_phy = true;
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun tegra_phy->clk = devm_clk_get(&pdev->dev, "ulpi-link");
1159*4882a593Smuzhiyun err = PTR_ERR_OR_ZERO(tegra_phy->clk);
1160*4882a593Smuzhiyun if (err) {
1161*4882a593Smuzhiyun dev_err(&pdev->dev,
1162*4882a593Smuzhiyun "Failed to get ULPI clock: %d\n", err);
1163*4882a593Smuzhiyun return err;
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun gpiod = devm_gpiod_get_from_of_node(&pdev->dev, np,
1167*4882a593Smuzhiyun "nvidia,phy-reset-gpio",
1168*4882a593Smuzhiyun 0, GPIOD_OUT_HIGH,
1169*4882a593Smuzhiyun "ulpi_phy_reset_b");
1170*4882a593Smuzhiyun err = PTR_ERR_OR_ZERO(gpiod);
1171*4882a593Smuzhiyun if (err) {
1172*4882a593Smuzhiyun dev_err(&pdev->dev,
1173*4882a593Smuzhiyun "Request failed for reset GPIO: %d\n", err);
1174*4882a593Smuzhiyun return err;
1175*4882a593Smuzhiyun }
1176*4882a593Smuzhiyun tegra_phy->reset_gpio = gpiod;
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun phy = devm_otg_ulpi_create(&pdev->dev,
1179*4882a593Smuzhiyun &ulpi_viewport_access_ops, 0);
1180*4882a593Smuzhiyun if (!phy) {
1181*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to create ULPI OTG\n");
1182*4882a593Smuzhiyun return -ENOMEM;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun
1185*4882a593Smuzhiyun tegra_phy->ulpi = phy;
1186*4882a593Smuzhiyun tegra_phy->ulpi->io_priv = tegra_phy->regs + ULPI_VIEWPORT;
1187*4882a593Smuzhiyun break;
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun default:
1190*4882a593Smuzhiyun dev_err(&pdev->dev, "phy_type %u is invalid or unsupported\n",
1191*4882a593Smuzhiyun phy_type);
1192*4882a593Smuzhiyun return -EINVAL;
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun tegra_phy->u_phy.dev = &pdev->dev;
1196*4882a593Smuzhiyun tegra_phy->u_phy.init = tegra_usb_phy_init;
1197*4882a593Smuzhiyun tegra_phy->u_phy.shutdown = tegra_usb_phy_shutdown;
1198*4882a593Smuzhiyun tegra_phy->u_phy.set_suspend = tegra_usb_phy_set_suspend;
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun platform_set_drvdata(pdev, tegra_phy);
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun return usb_add_phy_dev(&tegra_phy->u_phy);
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun
tegra_usb_phy_remove(struct platform_device * pdev)1205*4882a593Smuzhiyun static int tegra_usb_phy_remove(struct platform_device *pdev)
1206*4882a593Smuzhiyun {
1207*4882a593Smuzhiyun struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev);
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun usb_remove_phy(&tegra_phy->u_phy);
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun return 0;
1212*4882a593Smuzhiyun }
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun static struct platform_driver tegra_usb_phy_driver = {
1215*4882a593Smuzhiyun .probe = tegra_usb_phy_probe,
1216*4882a593Smuzhiyun .remove = tegra_usb_phy_remove,
1217*4882a593Smuzhiyun .driver = {
1218*4882a593Smuzhiyun .name = "tegra-phy",
1219*4882a593Smuzhiyun .of_match_table = tegra_usb_phy_id_table,
1220*4882a593Smuzhiyun },
1221*4882a593Smuzhiyun };
1222*4882a593Smuzhiyun module_platform_driver(tegra_usb_phy_driver);
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun MODULE_DESCRIPTION("Tegra USB PHY driver");
1225*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1226