blob: f0727f20e8039a4a26af61f1accea7048e53d5bb [file] [log] [blame]
Benoit Goby91525d02011-03-09 16:28:55 -08001/*
Benoit Goby91525d02011-03-09 16:28:55 -08002 * Copyright (C) 2010 Google, Inc.
Venu Byravarasu2d22b422013-05-16 19:43:02 +05303 * Copyright (C) 2013 NVIDIA Corporation
Benoit Goby91525d02011-03-09 16:28:55 -08004 *
5 * Author:
6 * Erik Gilling <konkers@google.com>
7 * Benoit Goby <benoit@android.com>
Venu Byravarasu2d22b422013-05-16 19:43:02 +05308 * Venu Byravarasu <vbyravarasu@nvidia.com>
Benoit Goby91525d02011-03-09 16:28:55 -08009 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21#include <linux/resource.h>
22#include <linux/delay.h>
23#include <linux/slab.h>
24#include <linux/err.h>
Arnd Bergmann4265cbf2012-03-02 15:58:42 -050025#include <linux/export.h>
Stephen Warren587376a2013-06-13 11:24:08 -060026#include <linux/module.h>
Benoit Goby91525d02011-03-09 16:28:55 -080027#include <linux/platform_device.h>
28#include <linux/io.h>
29#include <linux/gpio.h>
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +000030#include <linux/of.h>
Stephen Warrenaa607eb2012-04-12 15:46:49 -060031#include <linux/of_gpio.h>
Benoit Goby91525d02011-03-09 16:28:55 -080032#include <linux/usb/otg.h>
33#include <linux/usb/ulpi.h>
34#include <asm/mach-types.h>
Venu Byravarasu1ba82162012-09-05 18:50:23 +053035#include <linux/usb/tegra_usb_phy.h>
Venu Byravarasu2d22b422013-05-16 19:43:02 +053036#include <linux/module.h>
Benoit Goby91525d02011-03-09 16:28:55 -080037
38#define ULPI_VIEWPORT 0x170
39
Benoit Goby91525d02011-03-09 16:28:55 -080040#define USB_SUSP_CTRL 0x400
41#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
42#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
43#define USB_SUSP_CLR (1 << 5)
44#define USB_PHY_CLK_VALID (1 << 7)
45#define UTMIP_RESET (1 << 11)
46#define UHSIC_RESET (1 << 11)
47#define UTMIP_PHY_ENABLE (1 << 12)
48#define ULPI_PHY_ENABLE (1 << 13)
49#define USB_SUSP_SET (1 << 14)
50#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
51
52#define USB1_LEGACY_CTRL 0x410
53#define USB1_NO_LEGACY_MODE (1 << 0)
54#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
55#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
56#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
57 (1 << 1)
58#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
59#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
60
61#define ULPI_TIMING_CTRL_0 0x424
62#define ULPI_OUTPUT_PINMUX_BYP (1 << 10)
63#define ULPI_CLKOUT_PINMUX_BYP (1 << 11)
64
65#define ULPI_TIMING_CTRL_1 0x428
66#define ULPI_DATA_TRIMMER_LOAD (1 << 0)
67#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
68#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16)
69#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
70#define ULPI_DIR_TRIMMER_LOAD (1 << 24)
71#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
72
73#define UTMIP_PLL_CFG1 0x804
74#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
75#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
76
77#define UTMIP_XCVR_CFG0 0x808
78#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
79#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
80#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
81#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
82#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
83#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
84#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25)
85
86#define UTMIP_BIAS_CFG0 0x80c
87#define UTMIP_OTGPD (1 << 11)
88#define UTMIP_BIASPD (1 << 10)
89
90#define UTMIP_HSRX_CFG0 0x810
91#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
92#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
93
94#define UTMIP_HSRX_CFG1 0x814
95#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
96
97#define UTMIP_TX_CFG0 0x820
98#define UTMIP_FS_PREABMLE_J (1 << 19)
99#define UTMIP_HS_DISCON_DISABLE (1 << 8)
100
101#define UTMIP_MISC_CFG0 0x824
102#define UTMIP_DPDM_OBSERVE (1 << 26)
103#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
104#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
105#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
106#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
107#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
108#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
109
110#define UTMIP_MISC_CFG1 0x828
111#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
112#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
113
114#define UTMIP_DEBOUNCE_CFG0 0x82c
115#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
116
117#define UTMIP_BAT_CHRG_CFG0 0x830
118#define UTMIP_PD_CHRG (1 << 0)
119
120#define UTMIP_SPARE_CFG0 0x834
121#define FUSE_SETUP_SEL (1 << 3)
122
123#define UTMIP_XCVR_CFG1 0x838
124#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
125#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
126#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
127#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
128
129#define UTMIP_BIAS_CFG1 0x83c
130#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
131
132static DEFINE_SPINLOCK(utmip_pad_lock);
133static int utmip_pad_count;
134
135struct tegra_xtal_freq {
136 int freq;
137 u8 enable_delay;
138 u8 stable_count;
139 u8 active_delay;
140 u8 xtal_freq_count;
141 u16 debounce;
142};
143
144static const struct tegra_xtal_freq tegra_freq_table[] = {
145 {
146 .freq = 12000000,
147 .enable_delay = 0x02,
148 .stable_count = 0x2F,
149 .active_delay = 0x04,
150 .xtal_freq_count = 0x76,
151 .debounce = 0x7530,
152 },
153 {
154 .freq = 13000000,
155 .enable_delay = 0x02,
156 .stable_count = 0x33,
157 .active_delay = 0x05,
158 .xtal_freq_count = 0x7F,
159 .debounce = 0x7EF4,
160 },
161 {
162 .freq = 19200000,
163 .enable_delay = 0x03,
164 .stable_count = 0x4B,
165 .active_delay = 0x06,
166 .xtal_freq_count = 0xBB,
167 .debounce = 0xBB80,
168 },
169 {
170 .freq = 26000000,
171 .enable_delay = 0x04,
172 .stable_count = 0x66,
173 .active_delay = 0x09,
174 .xtal_freq_count = 0xFE,
175 .debounce = 0xFDE8,
176 },
177};
178
179static struct tegra_utmip_config utmip_default[] = {
180 [0] = {
181 .hssync_start_delay = 9,
182 .idle_wait_delay = 17,
183 .elastic_limit = 16,
184 .term_range_adj = 6,
185 .xcvr_setup = 9,
186 .xcvr_lsfslew = 1,
187 .xcvr_lsrslew = 1,
188 },
189 [2] = {
190 .hssync_start_delay = 9,
191 .idle_wait_delay = 17,
192 .elastic_limit = 16,
193 .term_range_adj = 6,
194 .xcvr_setup = 9,
195 .xcvr_lsfslew = 2,
196 .xcvr_lsrslew = 2,
197 },
198};
199
Benoit Goby91525d02011-03-09 16:28:55 -0800200static int utmip_pad_open(struct tegra_usb_phy *phy)
201{
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530202 phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads");
Benoit Goby91525d02011-03-09 16:28:55 -0800203 if (IS_ERR(phy->pad_clk)) {
204 pr_err("%s: can't get utmip pad clock\n", __func__);
205 return PTR_ERR(phy->pad_clk);
206 }
207
Benoit Goby91525d02011-03-09 16:28:55 -0800208 return 0;
209}
210
Benoit Goby91525d02011-03-09 16:28:55 -0800211static void utmip_pad_power_on(struct tegra_usb_phy *phy)
212{
213 unsigned long val, flags;
214 void __iomem *base = phy->pad_regs;
215
Prashant Gaikwad6a5278d2012-06-05 09:59:35 +0530216 clk_prepare_enable(phy->pad_clk);
Benoit Goby91525d02011-03-09 16:28:55 -0800217
218 spin_lock_irqsave(&utmip_pad_lock, flags);
219
220 if (utmip_pad_count++ == 0) {
221 val = readl(base + UTMIP_BIAS_CFG0);
222 val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
223 writel(val, base + UTMIP_BIAS_CFG0);
224 }
225
226 spin_unlock_irqrestore(&utmip_pad_lock, flags);
227
Prashant Gaikwad6a5278d2012-06-05 09:59:35 +0530228 clk_disable_unprepare(phy->pad_clk);
Benoit Goby91525d02011-03-09 16:28:55 -0800229}
230
231static int utmip_pad_power_off(struct tegra_usb_phy *phy)
232{
233 unsigned long val, flags;
234 void __iomem *base = phy->pad_regs;
235
236 if (!utmip_pad_count) {
237 pr_err("%s: utmip pad already powered off\n", __func__);
238 return -EINVAL;
239 }
240
Prashant Gaikwad6a5278d2012-06-05 09:59:35 +0530241 clk_prepare_enable(phy->pad_clk);
Benoit Goby91525d02011-03-09 16:28:55 -0800242
243 spin_lock_irqsave(&utmip_pad_lock, flags);
244
245 if (--utmip_pad_count == 0) {
246 val = readl(base + UTMIP_BIAS_CFG0);
247 val |= UTMIP_OTGPD | UTMIP_BIASPD;
248 writel(val, base + UTMIP_BIAS_CFG0);
249 }
250
251 spin_unlock_irqrestore(&utmip_pad_lock, flags);
252
Prashant Gaikwad6a5278d2012-06-05 09:59:35 +0530253 clk_disable_unprepare(phy->pad_clk);
Benoit Goby91525d02011-03-09 16:28:55 -0800254
255 return 0;
256}
257
258static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
259{
260 unsigned long timeout = 2000;
261 do {
262 if ((readl(reg) & mask) == result)
263 return 0;
264 udelay(1);
265 timeout--;
266 } while (timeout);
267 return -1;
268}
269
270static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
271{
272 unsigned long val;
273 void __iomem *base = phy->regs;
274
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +0000275 if (phy->is_legacy_phy) {
Benoit Goby91525d02011-03-09 16:28:55 -0800276 val = readl(base + USB_SUSP_CTRL);
277 val |= USB_SUSP_SET;
278 writel(val, base + USB_SUSP_CTRL);
279
280 udelay(10);
281
282 val = readl(base + USB_SUSP_CTRL);
283 val &= ~USB_SUSP_SET;
284 writel(val, base + USB_SUSP_CTRL);
Venu Byravarasubbdabdb2013-01-17 20:15:37 +0000285 } else
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530286 tegra_ehci_set_phcd(&phy->u_phy, true);
Benoit Goby91525d02011-03-09 16:28:55 -0800287
288 if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
289 pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
290}
291
292static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
293{
294 unsigned long val;
295 void __iomem *base = phy->regs;
296
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +0000297 if (phy->is_legacy_phy) {
Benoit Goby91525d02011-03-09 16:28:55 -0800298 val = readl(base + USB_SUSP_CTRL);
299 val |= USB_SUSP_CLR;
300 writel(val, base + USB_SUSP_CTRL);
301
302 udelay(10);
303
304 val = readl(base + USB_SUSP_CTRL);
305 val &= ~USB_SUSP_CLR;
306 writel(val, base + USB_SUSP_CTRL);
Venu Byravarasubbdabdb2013-01-17 20:15:37 +0000307 } else
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530308 tegra_ehci_set_phcd(&phy->u_phy, false);
Benoit Goby91525d02011-03-09 16:28:55 -0800309
310 if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
311 USB_PHY_CLK_VALID))
312 pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
313}
314
315static int utmi_phy_power_on(struct tegra_usb_phy *phy)
316{
317 unsigned long val;
318 void __iomem *base = phy->regs;
319 struct tegra_utmip_config *config = phy->config;
320
321 val = readl(base + USB_SUSP_CTRL);
322 val |= UTMIP_RESET;
323 writel(val, base + USB_SUSP_CTRL);
324
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +0000325 if (phy->is_legacy_phy) {
Benoit Goby91525d02011-03-09 16:28:55 -0800326 val = readl(base + USB1_LEGACY_CTRL);
327 val |= USB1_NO_LEGACY_MODE;
328 writel(val, base + USB1_LEGACY_CTRL);
329 }
330
331 val = readl(base + UTMIP_TX_CFG0);
332 val &= ~UTMIP_FS_PREABMLE_J;
333 writel(val, base + UTMIP_TX_CFG0);
334
335 val = readl(base + UTMIP_HSRX_CFG0);
336 val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
337 val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
338 val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
339 writel(val, base + UTMIP_HSRX_CFG0);
340
341 val = readl(base + UTMIP_HSRX_CFG1);
342 val &= ~UTMIP_HS_SYNC_START_DLY(~0);
343 val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
344 writel(val, base + UTMIP_HSRX_CFG1);
345
346 val = readl(base + UTMIP_DEBOUNCE_CFG0);
347 val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
348 val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
349 writel(val, base + UTMIP_DEBOUNCE_CFG0);
350
351 val = readl(base + UTMIP_MISC_CFG0);
352 val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
353 writel(val, base + UTMIP_MISC_CFG0);
354
355 val = readl(base + UTMIP_MISC_CFG1);
356 val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
357 val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
358 UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
359 writel(val, base + UTMIP_MISC_CFG1);
360
361 val = readl(base + UTMIP_PLL_CFG1);
362 val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
363 val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
364 UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
365 writel(val, base + UTMIP_PLL_CFG1);
366
367 if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
368 val = readl(base + USB_SUSP_CTRL);
369 val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
370 writel(val, base + USB_SUSP_CTRL);
371 }
372
373 utmip_pad_power_on(phy);
374
375 val = readl(base + UTMIP_XCVR_CFG0);
376 val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
377 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
378 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
379 UTMIP_XCVR_HSSLEW_MSB(~0));
380 val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
381 val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
382 val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
383 writel(val, base + UTMIP_XCVR_CFG0);
384
385 val = readl(base + UTMIP_XCVR_CFG1);
386 val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
387 UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
388 val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
389 writel(val, base + UTMIP_XCVR_CFG1);
390
391 val = readl(base + UTMIP_BAT_CHRG_CFG0);
392 val &= ~UTMIP_PD_CHRG;
393 writel(val, base + UTMIP_BAT_CHRG_CFG0);
394
395 val = readl(base + UTMIP_BIAS_CFG1);
396 val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
397 val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
398 writel(val, base + UTMIP_BIAS_CFG1);
399
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +0000400 if (phy->is_legacy_phy) {
Benoit Goby91525d02011-03-09 16:28:55 -0800401 val = readl(base + UTMIP_SPARE_CFG0);
402 if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
403 val &= ~FUSE_SETUP_SEL;
404 else
405 val |= FUSE_SETUP_SEL;
406 writel(val, base + UTMIP_SPARE_CFG0);
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +0000407 } else {
Benoit Goby91525d02011-03-09 16:28:55 -0800408 val = readl(base + USB_SUSP_CTRL);
409 val |= UTMIP_PHY_ENABLE;
410 writel(val, base + USB_SUSP_CTRL);
411 }
412
413 val = readl(base + USB_SUSP_CTRL);
414 val &= ~UTMIP_RESET;
415 writel(val, base + USB_SUSP_CTRL);
416
Venu Byravarasu3a55c6a2013-01-16 03:30:20 +0000417 if (phy->is_legacy_phy) {
Benoit Goby91525d02011-03-09 16:28:55 -0800418 val = readl(base + USB1_LEGACY_CTRL);
419 val &= ~USB1_VBUS_SENSE_CTL_MASK;
420 val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
421 writel(val, base + USB1_LEGACY_CTRL);
422
423 val = readl(base + USB_SUSP_CTRL);
424 val &= ~USB_SUSP_SET;
425 writel(val, base + USB_SUSP_CTRL);
426 }
427
428 utmi_phy_clk_enable(phy);
429
Venu Byravarasubbdabdb2013-01-17 20:15:37 +0000430 if (!phy->is_legacy_phy)
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530431 tegra_ehci_set_pts(&phy->u_phy, 0);
Benoit Goby91525d02011-03-09 16:28:55 -0800432
433 return 0;
434}
435
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530436static int utmi_phy_power_off(struct tegra_usb_phy *phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800437{
438 unsigned long val;
439 void __iomem *base = phy->regs;
440
441 utmi_phy_clk_disable(phy);
442
443 if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
444 val = readl(base + USB_SUSP_CTRL);
445 val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
446 val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
447 writel(val, base + USB_SUSP_CTRL);
448 }
449
450 val = readl(base + USB_SUSP_CTRL);
451 val |= UTMIP_RESET;
452 writel(val, base + USB_SUSP_CTRL);
453
454 val = readl(base + UTMIP_BAT_CHRG_CFG0);
455 val |= UTMIP_PD_CHRG;
456 writel(val, base + UTMIP_BAT_CHRG_CFG0);
457
458 val = readl(base + UTMIP_XCVR_CFG0);
459 val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
460 UTMIP_FORCE_PDZI_POWERDOWN;
461 writel(val, base + UTMIP_XCVR_CFG0);
462
463 val = readl(base + UTMIP_XCVR_CFG1);
464 val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
465 UTMIP_FORCE_PDDR_POWERDOWN;
466 writel(val, base + UTMIP_XCVR_CFG1);
467
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530468 return utmip_pad_power_off(phy);
Benoit Goby91525d02011-03-09 16:28:55 -0800469}
470
471static void utmi_phy_preresume(struct tegra_usb_phy *phy)
472{
473 unsigned long val;
474 void __iomem *base = phy->regs;
475
476 val = readl(base + UTMIP_TX_CFG0);
477 val |= UTMIP_HS_DISCON_DISABLE;
478 writel(val, base + UTMIP_TX_CFG0);
479}
480
481static void utmi_phy_postresume(struct tegra_usb_phy *phy)
482{
483 unsigned long val;
484 void __iomem *base = phy->regs;
485
486 val = readl(base + UTMIP_TX_CFG0);
487 val &= ~UTMIP_HS_DISCON_DISABLE;
488 writel(val, base + UTMIP_TX_CFG0);
489}
490
491static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
492 enum tegra_usb_phy_port_speed port_speed)
493{
494 unsigned long val;
495 void __iomem *base = phy->regs;
496
497 val = readl(base + UTMIP_MISC_CFG0);
498 val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
499 if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
500 val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
501 else
502 val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
503 writel(val, base + UTMIP_MISC_CFG0);
504 udelay(1);
505
506 val = readl(base + UTMIP_MISC_CFG0);
507 val |= UTMIP_DPDM_OBSERVE;
508 writel(val, base + UTMIP_MISC_CFG0);
509 udelay(10);
510}
511
512static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
513{
514 unsigned long val;
515 void __iomem *base = phy->regs;
516
517 val = readl(base + UTMIP_MISC_CFG0);
518 val &= ~UTMIP_DPDM_OBSERVE;
519 writel(val, base + UTMIP_MISC_CFG0);
520 udelay(10);
521}
522
523static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
524{
525 int ret;
526 unsigned long val;
527 void __iomem *base = phy->regs;
Benoit Goby91525d02011-03-09 16:28:55 -0800528
Venu Byravarasu6829f922013-05-16 19:43:01 +0530529 ret = gpio_direction_output(phy->reset_gpio, 0);
530 if (ret < 0) {
531 dev_err(phy->dev, "gpio %d not set to 0\n", phy->reset_gpio);
532 return ret;
533 }
Benoit Goby91525d02011-03-09 16:28:55 -0800534 msleep(5);
Venu Byravarasu6829f922013-05-16 19:43:01 +0530535 ret = gpio_direction_output(phy->reset_gpio, 1);
536 if (ret < 0) {
537 dev_err(phy->dev, "gpio %d not set to 1\n", phy->reset_gpio);
538 return ret;
539 }
Benoit Goby91525d02011-03-09 16:28:55 -0800540
Prashant Gaikwad6a5278d2012-06-05 09:59:35 +0530541 clk_prepare_enable(phy->clk);
Benoit Goby91525d02011-03-09 16:28:55 -0800542 msleep(1);
543
544 val = readl(base + USB_SUSP_CTRL);
545 val |= UHSIC_RESET;
546 writel(val, base + USB_SUSP_CTRL);
547
548 val = readl(base + ULPI_TIMING_CTRL_0);
549 val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
550 writel(val, base + ULPI_TIMING_CTRL_0);
551
552 val = readl(base + USB_SUSP_CTRL);
553 val |= ULPI_PHY_ENABLE;
554 writel(val, base + USB_SUSP_CTRL);
555
556 val = 0;
557 writel(val, base + ULPI_TIMING_CTRL_1);
558
559 val |= ULPI_DATA_TRIMMER_SEL(4);
560 val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
561 val |= ULPI_DIR_TRIMMER_SEL(4);
562 writel(val, base + ULPI_TIMING_CTRL_1);
563 udelay(10);
564
565 val |= ULPI_DATA_TRIMMER_LOAD;
566 val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
567 val |= ULPI_DIR_TRIMMER_LOAD;
568 writel(val, base + ULPI_TIMING_CTRL_1);
569
570 /* Fix VbusInvalid due to floating VBUS */
Heikki Krogerusb96d3b02012-02-13 13:24:18 +0200571 ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
Benoit Goby91525d02011-03-09 16:28:55 -0800572 if (ret) {
573 pr_err("%s: ulpi write failed\n", __func__);
574 return ret;
575 }
576
Heikki Krogerusb96d3b02012-02-13 13:24:18 +0200577 ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
Benoit Goby91525d02011-03-09 16:28:55 -0800578 if (ret) {
579 pr_err("%s: ulpi write failed\n", __func__);
580 return ret;
581 }
582
Benoit Goby91525d02011-03-09 16:28:55 -0800583 val = readl(base + USB_SUSP_CTRL);
584 val |= USB_SUSP_CLR;
585 writel(val, base + USB_SUSP_CTRL);
586 udelay(100);
587
588 val = readl(base + USB_SUSP_CTRL);
589 val &= ~USB_SUSP_CLR;
590 writel(val, base + USB_SUSP_CTRL);
591
592 return 0;
593}
594
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530595static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800596{
Benoit Goby91525d02011-03-09 16:28:55 -0800597 clk_disable(phy->clk);
Venu Byravarasu12ea18e2013-05-16 19:43:00 +0530598 return gpio_direction_output(phy->reset_gpio, 0);
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530599}
600
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530601static void tegra_usb_phy_close(struct usb_phy *x)
602{
603 struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
604
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530605 clk_disable_unprepare(phy->pll_u);
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530606}
607
608static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
609{
Venu Byravarasu3f9db1a2013-01-16 03:30:21 +0000610 if (phy->is_ulpi_phy)
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530611 return ulpi_phy_power_on(phy);
612 else
613 return utmi_phy_power_on(phy);
614}
615
616static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
617{
Venu Byravarasu3f9db1a2013-01-16 03:30:21 +0000618 if (phy->is_ulpi_phy)
Venu Byravarasu1ba82162012-09-05 18:50:23 +0530619 return ulpi_phy_power_off(phy);
620 else
621 return utmi_phy_power_off(phy);
622}
623
624static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
625{
626 struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
627 if (suspend)
628 return tegra_usb_phy_power_off(phy);
629 else
630 return tegra_usb_phy_power_on(phy);
Benoit Goby91525d02011-03-09 16:28:55 -0800631}
632
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530633static int ulpi_open(struct tegra_usb_phy *phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800634{
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530635 int err;
636
637 phy->clk = devm_clk_get(phy->dev, "ulpi-link");
638 if (IS_ERR(phy->clk)) {
639 pr_err("%s: can't get ulpi clock\n", __func__);
640 return PTR_ERR(phy->clk);
641 }
642
643 err = devm_gpio_request(phy->dev, phy->reset_gpio, "ulpi_phy_reset_b");
644 if (err < 0) {
645 dev_err(phy->dev, "request failed for gpio: %d\n",
646 phy->reset_gpio);
647 return err;
648 }
649
650 err = gpio_direction_output(phy->reset_gpio, 0);
651 if (err < 0) {
652 dev_err(phy->dev, "gpio %d direction not set to output\n",
653 phy->reset_gpio);
654 return err;
655 }
656
657 phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
658 if (!phy->ulpi) {
659 dev_err(phy->dev, "otg_ulpi_create returned NULL\n");
660 err = -ENOMEM;
661 return err;
662 }
663
664 phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
665 return 0;
666}
667
668static int tegra_usb_phy_init(struct tegra_usb_phy *phy)
669{
Benoit Goby91525d02011-03-09 16:28:55 -0800670 unsigned long parent_rate;
671 int i;
672 int err;
673
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530674 if (!phy->is_ulpi_phy) {
675 if (phy->is_legacy_phy)
676 phy->config = &utmip_default[0];
Venu Byravarasu9cd93842013-05-16 19:42:59 +0530677 else
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530678 phy->config = &utmip_default[2];
Benoit Goby91525d02011-03-09 16:28:55 -0800679 }
680
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530681 phy->pll_u = devm_clk_get(phy->dev, "pll_u");
Benoit Goby91525d02011-03-09 16:28:55 -0800682 if (IS_ERR(phy->pll_u)) {
683 pr_err("Can't get pll_u clock\n");
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530684 return PTR_ERR(phy->pll_u);
Benoit Goby91525d02011-03-09 16:28:55 -0800685 }
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530686
687 err = clk_prepare_enable(phy->pll_u);
688 if (err)
689 return err;
Benoit Goby91525d02011-03-09 16:28:55 -0800690
691 parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
692 for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
693 if (tegra_freq_table[i].freq == parent_rate) {
694 phy->freq = &tegra_freq_table[i];
695 break;
696 }
697 }
698 if (!phy->freq) {
699 pr_err("invalid pll_u parent rate %ld\n", parent_rate);
700 err = -EINVAL;
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530701 goto fail;
Benoit Goby91525d02011-03-09 16:28:55 -0800702 }
703
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530704 if (phy->is_ulpi_phy)
705 err = ulpi_open(phy);
706 else
707 err = utmip_pad_open(phy);
708 if (err < 0)
709 goto fail;
Benoit Goby91525d02011-03-09 16:28:55 -0800710
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530711 return 0;
Benoit Goby91525d02011-03-09 16:28:55 -0800712
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530713fail:
Prashant Gaikwad6a5278d2012-06-05 09:59:35 +0530714 clk_disable_unprepare(phy->pll_u);
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530715 return err;
Benoit Goby91525d02011-03-09 16:28:55 -0800716}
717
Venu Byravarasuab137d02013-01-24 15:57:03 +0530718void tegra_usb_phy_preresume(struct usb_phy *x)
Benoit Goby91525d02011-03-09 16:28:55 -0800719{
Venu Byravarasuab137d02013-01-24 15:57:03 +0530720 struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
721
Venu Byravarasu3f9db1a2013-01-16 03:30:21 +0000722 if (!phy->is_ulpi_phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800723 utmi_phy_preresume(phy);
724}
Arnd Bergmann4265cbf2012-03-02 15:58:42 -0500725EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
Benoit Goby91525d02011-03-09 16:28:55 -0800726
Venu Byravarasuab137d02013-01-24 15:57:03 +0530727void tegra_usb_phy_postresume(struct usb_phy *x)
Benoit Goby91525d02011-03-09 16:28:55 -0800728{
Venu Byravarasuab137d02013-01-24 15:57:03 +0530729 struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
730
Venu Byravarasu3f9db1a2013-01-16 03:30:21 +0000731 if (!phy->is_ulpi_phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800732 utmi_phy_postresume(phy);
733}
Arnd Bergmann4265cbf2012-03-02 15:58:42 -0500734EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
Benoit Goby91525d02011-03-09 16:28:55 -0800735
Venu Byravarasuab137d02013-01-24 15:57:03 +0530736void tegra_ehci_phy_restore_start(struct usb_phy *x,
Benoit Goby91525d02011-03-09 16:28:55 -0800737 enum tegra_usb_phy_port_speed port_speed)
738{
Venu Byravarasuab137d02013-01-24 15:57:03 +0530739 struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
740
Venu Byravarasu3f9db1a2013-01-16 03:30:21 +0000741 if (!phy->is_ulpi_phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800742 utmi_phy_restore_start(phy, port_speed);
743}
Arnd Bergmann4265cbf2012-03-02 15:58:42 -0500744EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
Benoit Goby91525d02011-03-09 16:28:55 -0800745
Venu Byravarasuab137d02013-01-24 15:57:03 +0530746void tegra_ehci_phy_restore_end(struct usb_phy *x)
Benoit Goby91525d02011-03-09 16:28:55 -0800747{
Venu Byravarasuab137d02013-01-24 15:57:03 +0530748 struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
749
Venu Byravarasu3f9db1a2013-01-16 03:30:21 +0000750 if (!phy->is_ulpi_phy)
Benoit Goby91525d02011-03-09 16:28:55 -0800751 utmi_phy_restore_end(phy);
752}
Arnd Bergmann4265cbf2012-03-02 15:58:42 -0500753EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
Benoit Goby91525d02011-03-09 16:28:55 -0800754
Venu Byravarasu2d22b422013-05-16 19:43:02 +0530755static int tegra_usb_phy_probe(struct platform_device *pdev)
756{
757 struct resource *res;
758 struct tegra_usb_phy *tegra_phy = NULL;
759 struct device_node *np = pdev->dev.of_node;
760 int err;
761
762 tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL);
763 if (!tegra_phy) {
764 dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
765 return -ENOMEM;
766 }
767
768 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
769 if (!res) {
770 dev_err(&pdev->dev, "Failed to get I/O memory\n");
771 return -ENXIO;
772 }
773
774 tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
775 resource_size(res));
776 if (!tegra_phy->regs) {
777 dev_err(&pdev->dev, "Failed to remap I/O memory\n");
778 return -ENOMEM;
779 }
780
781 tegra_phy->is_legacy_phy =
782 of_property_read_bool(np, "nvidia,has-legacy-mode");
783
784 err = of_property_match_string(np, "phy_type", "ulpi");
785 if (err < 0) {
786 tegra_phy->is_ulpi_phy = false;
787
788 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
789 if (!res) {
790 dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n");
791 return -ENXIO;
792 }
793
794 tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
795 resource_size(res));
796 if (!tegra_phy->regs) {
797 dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
798 return -ENOMEM;
799 }
800 } else {
801 tegra_phy->is_ulpi_phy = true;
802
803 tegra_phy->reset_gpio =
804 of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0);
805 if (!gpio_is_valid(tegra_phy->reset_gpio)) {
806 dev_err(&pdev->dev, "invalid gpio: %d\n",
807 tegra_phy->reset_gpio);
808 return tegra_phy->reset_gpio;
809 }
810 }
811
812 err = of_property_match_string(np, "dr_mode", "otg");
813 if (err < 0) {
814 err = of_property_match_string(np, "dr_mode", "peripheral");
815 if (err < 0)
816 tegra_phy->mode = TEGRA_USB_PHY_MODE_HOST;
817 else
818 tegra_phy->mode = TEGRA_USB_PHY_MODE_DEVICE;
819 } else
820 tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG;
821
822 tegra_phy->dev = &pdev->dev;
823 err = tegra_usb_phy_init(tegra_phy);
824 if (err < 0)
825 return err;
826
827 tegra_phy->u_phy.shutdown = tegra_usb_phy_close;
828 tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend;
829
830 dev_set_drvdata(&pdev->dev, tegra_phy);
831 return 0;
832}
833
834static struct of_device_id tegra_usb_phy_id_table[] = {
835 { .compatible = "nvidia,tegra20-usb-phy", },
836 { },
837};
838MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table);
839
840static struct platform_driver tegra_usb_phy_driver = {
841 .probe = tegra_usb_phy_probe,
842 .driver = {
843 .name = "tegra-phy",
844 .owner = THIS_MODULE,
845 .of_match_table = of_match_ptr(tegra_usb_phy_id_table),
846 },
847};
848module_platform_driver(tegra_usb_phy_driver);
849
850static int tegra_usb_phy_match(struct device *dev, void *data)
851{
852 struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev);
853 struct device_node *dn = data;
854
855 return (tegra_phy->dev->of_node == dn) ? 1 : 0;
856}
857
858struct usb_phy *tegra_usb_get_phy(struct device_node *dn)
859{
860 struct device *dev;
861 struct tegra_usb_phy *tegra_phy;
862
863 dev = driver_find_device(&tegra_usb_phy_driver.driver, NULL, dn,
864 tegra_usb_phy_match);
865 if (!dev)
866 return ERR_PTR(-EPROBE_DEFER);
867
868 tegra_phy = dev_get_drvdata(dev);
869
870 return &tegra_phy->u_phy;
871}
872EXPORT_SYMBOL_GPL(tegra_usb_get_phy);
Stephen Warren587376a2013-06-13 11:24:08 -0600873
874MODULE_DESCRIPTION("Tegra USB PHY driver");
875MODULE_LICENSE("GPL v2");