aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/Kconfig3
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h86
-rw-r--r--arch/arm/mach-tegra/usb_phy.c795
4 files changed, 885 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index acd9552f8ada..394b3c76be83 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -10,6 +10,9 @@ config ARCH_TEGRA_2x_SOC
10 select CPU_V7 10 select CPU_V7
11 select ARM_GIC 11 select ARM_GIC
12 select ARCH_REQUIRE_GPIOLIB 12 select ARCH_REQUIRE_GPIOLIB
13 select USB_ARCH_HAS_EHCI if USB_SUPPORT
14 select USB_ULPI if USB_SUPPORT
15 select USB_ULPI_VIEWPORT if USB_SUPPORT
13 help 16 help
14 Support for NVIDIA Tegra AP20 and T20 processors, based on the 17 Support for NVIDIA Tegra AP20 and T20 processors, based on the
15 ARM CortexA9MP CPU and the ARM PL310 L2 cache controller 18 ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index cdbc68e4c0ca..38b66a85ac28 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
15obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o 15obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o
16obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o 16obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
17obj-$(CONFIG_TEGRA_PCI) += pcie.o 17obj-$(CONFIG_TEGRA_PCI) += pcie.o
18obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
18 19
19obj-${CONFIG_MACH_HARMONY} += board-harmony.o 20obj-${CONFIG_MACH_HARMONY} += board-harmony.o
20obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o 21obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
new file mode 100644
index 000000000000..d4b8f9e298a8
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -0,0 +1,86 @@
1/*
2 * arch/arm/mach-tegra/include/mach/usb_phy.h
3 *
4 * Copyright (C) 2010 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __MACH_USB_PHY_H
18#define __MACH_USB_PHY_H
19
20#include <linux/clk.h>
21#include <linux/usb/otg.h>
22
23struct tegra_utmip_config {
24 u8 hssync_start_delay;
25 u8 elastic_limit;
26 u8 idle_wait_delay;
27 u8 term_range_adj;
28 u8 xcvr_setup;
29 u8 xcvr_lsfslew;
30 u8 xcvr_lsrslew;
31};
32
33struct tegra_ulpi_config {
34 int reset_gpio;
35 const char *clk;
36};
37
38enum tegra_usb_phy_port_speed {
39 TEGRA_USB_PHY_PORT_SPEED_FULL = 0,
40 TEGRA_USB_PHY_PORT_SPEED_LOW,
41 TEGRA_USB_PHY_PORT_SPEED_HIGH,
42};
43
44enum tegra_usb_phy_mode {
45 TEGRA_USB_PHY_MODE_DEVICE,
46 TEGRA_USB_PHY_MODE_HOST,
47};
48
49struct tegra_xtal_freq;
50
51struct tegra_usb_phy {
52 int instance;
53 const struct tegra_xtal_freq *freq;
54 void __iomem *regs;
55 void __iomem *pad_regs;
56 struct clk *clk;
57 struct clk *pll_u;
58 struct clk *pad_clk;
59 enum tegra_usb_phy_mode mode;
60 void *config;
61 struct otg_transceiver *ulpi;
62};
63
64struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
65 void *config, enum tegra_usb_phy_mode phy_mode);
66
67int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
68
69void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
70
71void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
72
73void tegra_usb_phy_power_off(struct tegra_usb_phy *phy);
74
75void tegra_usb_phy_preresume(struct tegra_usb_phy *phy);
76
77void tegra_usb_phy_postresume(struct tegra_usb_phy *phy);
78
79void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
80 enum tegra_usb_phy_port_speed port_speed);
81
82void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
83
84void tegra_usb_phy_close(struct tegra_usb_phy *phy);
85
86#endif /* __MACH_USB_PHY_H */
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
new file mode 100644
index 000000000000..88081bb3ec52
--- /dev/null
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -0,0 +1,795 @@
1/*
2 * arch/arm/mach-tegra/usb_phy.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 *
6 * Author:
7 * Erik Gilling <konkers@google.com>
8 * Benoit Goby <benoit@android.com>
9 *
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>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/gpio.h>
28#include <linux/usb/otg.h>
29#include <linux/usb/ulpi.h>
30#include <asm/mach-types.h>
31#include <mach/usb_phy.h>
32#include <mach/iomap.h>
33
34#define ULPI_VIEWPORT 0x170
35
36#define USB_PORTSC1 0x184
37#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
38#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26)
39#define USB_PORTSC1_PHCD (1 << 23)
40#define USB_PORTSC1_WKOC (1 << 22)
41#define USB_PORTSC1_WKDS (1 << 21)
42#define USB_PORTSC1_WKCN (1 << 20)
43#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16)
44#define USB_PORTSC1_PP (1 << 12)
45#define USB_PORTSC1_SUSP (1 << 7)
46#define USB_PORTSC1_PE (1 << 2)
47#define USB_PORTSC1_CCS (1 << 0)
48
49#define USB_SUSP_CTRL 0x400
50#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
51#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
52#define USB_SUSP_CLR (1 << 5)
53#define USB_PHY_CLK_VALID (1 << 7)
54#define UTMIP_RESET (1 << 11)
55#define UHSIC_RESET (1 << 11)
56#define UTMIP_PHY_ENABLE (1 << 12)
57#define ULPI_PHY_ENABLE (1 << 13)
58#define USB_SUSP_SET (1 << 14)
59#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
60
61#define USB1_LEGACY_CTRL 0x410
62#define USB1_NO_LEGACY_MODE (1 << 0)
63#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
64#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
65#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
66 (1 << 1)
67#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
68#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
69
70#define ULPI_TIMING_CTRL_0 0x424
71#define ULPI_OUTPUT_PINMUX_BYP (1 << 10)
72#define ULPI_CLKOUT_PINMUX_BYP (1 << 11)
73
74#define ULPI_TIMING_CTRL_1 0x428
75#define ULPI_DATA_TRIMMER_LOAD (1 << 0)
76#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
77#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16)
78#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
79#define ULPI_DIR_TRIMMER_LOAD (1 << 24)
80#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
81
82#define UTMIP_PLL_CFG1 0x804
83#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
84#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
85
86#define UTMIP_XCVR_CFG0 0x808
87#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
88#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
89#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
90#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
91#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
92#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
93#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25)
94
95#define UTMIP_BIAS_CFG0 0x80c
96#define UTMIP_OTGPD (1 << 11)
97#define UTMIP_BIASPD (1 << 10)
98
99#define UTMIP_HSRX_CFG0 0x810
100#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
101#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
102
103#define UTMIP_HSRX_CFG1 0x814
104#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
105
106#define UTMIP_TX_CFG0 0x820
107#define UTMIP_FS_PREABMLE_J (1 << 19)
108#define UTMIP_HS_DISCON_DISABLE (1 << 8)
109
110#define UTMIP_MISC_CFG0 0x824
111#define UTMIP_DPDM_OBSERVE (1 << 26)
112#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
113#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
114#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
115#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
116#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
117#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
118
119#define UTMIP_MISC_CFG1 0x828
120#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
121#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
122
123#define UTMIP_DEBOUNCE_CFG0 0x82c
124#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
125
126#define UTMIP_BAT_CHRG_CFG0 0x830
127#define UTMIP_PD_CHRG (1 << 0)
128
129#define UTMIP_SPARE_CFG0 0x834
130#define FUSE_SETUP_SEL (1 << 3)
131
132#define UTMIP_XCVR_CFG1 0x838
133#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
134#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
135#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
136#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
137
138#define UTMIP_BIAS_CFG1 0x83c
139#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
140
141static DEFINE_SPINLOCK(utmip_pad_lock);
142static int utmip_pad_count;
143
144struct tegra_xtal_freq {
145 int freq;
146 u8 enable_delay;
147 u8 stable_count;
148 u8 active_delay;
149 u8 xtal_freq_count;
150 u16 debounce;
151};
152
153static const struct tegra_xtal_freq tegra_freq_table[] = {
154 {
155 .freq = 12000000,
156 .enable_delay = 0x02,
157 .stable_count = 0x2F,
158 .active_delay = 0x04,
159 .xtal_freq_count = 0x76,
160 .debounce = 0x7530,
161 },
162 {
163 .freq = 13000000,
164 .enable_delay = 0x02,
165 .stable_count = 0x33,
166 .active_delay = 0x05,
167 .xtal_freq_count = 0x7F,
168 .debounce = 0x7EF4,
169 },
170 {
171 .freq = 19200000,
172 .enable_delay = 0x03,
173 .stable_count = 0x4B,
174 .active_delay = 0x06,
175 .xtal_freq_count = 0xBB,
176 .debounce = 0xBB80,
177 },
178 {
179 .freq = 26000000,
180 .enable_delay = 0x04,
181 .stable_count = 0x66,
182 .active_delay = 0x09,
183 .xtal_freq_count = 0xFE,
184 .debounce = 0xFDE8,
185 },
186};
187
188static struct tegra_utmip_config utmip_default[] = {
189 [0] = {
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 = 1,
196 .xcvr_lsrslew = 1,
197 },
198 [2] = {
199 .hssync_start_delay = 9,
200 .idle_wait_delay = 17,
201 .elastic_limit = 16,
202 .term_range_adj = 6,
203 .xcvr_setup = 9,
204 .xcvr_lsfslew = 2,
205 .xcvr_lsrslew = 2,
206 },
207};
208
209static inline bool phy_is_ulpi(struct tegra_usb_phy *phy)
210{
211 return (phy->instance == 1);
212}
213
214static int utmip_pad_open(struct tegra_usb_phy *phy)
215{
216 phy->pad_clk = clk_get_sys("utmip-pad", NULL);
217 if (IS_ERR(phy->pad_clk)) {
218 pr_err("%s: can't get utmip pad clock\n", __func__);
219 return PTR_ERR(phy->pad_clk);
220 }
221
222 if (phy->instance == 0) {
223 phy->pad_regs = phy->regs;
224 } else {
225 phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
226 if (!phy->pad_regs) {
227 pr_err("%s: can't remap usb registers\n", __func__);
228 clk_put(phy->pad_clk);
229 return -ENOMEM;
230 }
231 }
232 return 0;
233}
234
235static void utmip_pad_close(struct tegra_usb_phy *phy)
236{
237 if (phy->instance != 0)
238 iounmap(phy->pad_regs);
239 clk_put(phy->pad_clk);
240}
241
242static void utmip_pad_power_on(struct tegra_usb_phy *phy)
243{
244 unsigned long val, flags;
245 void __iomem *base = phy->pad_regs;
246
247 clk_enable(phy->pad_clk);
248
249 spin_lock_irqsave(&utmip_pad_lock, flags);
250
251 if (utmip_pad_count++ == 0) {
252 val = readl(base + UTMIP_BIAS_CFG0);
253 val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
254 writel(val, base + UTMIP_BIAS_CFG0);
255 }
256
257 spin_unlock_irqrestore(&utmip_pad_lock, flags);
258
259 clk_disable(phy->pad_clk);
260}
261
262static int utmip_pad_power_off(struct tegra_usb_phy *phy)
263{
264 unsigned long val, flags;
265 void __iomem *base = phy->pad_regs;
266
267 if (!utmip_pad_count) {
268 pr_err("%s: utmip pad already powered off\n", __func__);
269 return -EINVAL;
270 }
271
272 clk_enable(phy->pad_clk);
273
274 spin_lock_irqsave(&utmip_pad_lock, flags);
275
276 if (--utmip_pad_count == 0) {
277 val = readl(base + UTMIP_BIAS_CFG0);
278 val |= UTMIP_OTGPD | UTMIP_BIASPD;
279 writel(val, base + UTMIP_BIAS_CFG0);
280 }
281
282 spin_unlock_irqrestore(&utmip_pad_lock, flags);
283
284 clk_disable(phy->pad_clk);
285
286 return 0;
287}
288
289static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
290{
291 unsigned long timeout = 2000;
292 do {
293 if ((readl(reg) & mask) == result)
294 return 0;
295 udelay(1);
296 timeout--;
297 } while (timeout);
298 return -1;
299}
300
301static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
302{
303 unsigned long val;
304 void __iomem *base = phy->regs;
305
306 if (phy->instance == 0) {
307 val = readl(base + USB_SUSP_CTRL);
308 val |= USB_SUSP_SET;
309 writel(val, base + USB_SUSP_CTRL);
310
311 udelay(10);
312
313 val = readl(base + USB_SUSP_CTRL);
314 val &= ~USB_SUSP_SET;
315 writel(val, base + USB_SUSP_CTRL);
316 }
317
318 if (phy->instance == 2) {
319 val = readl(base + USB_PORTSC1);
320 val |= USB_PORTSC1_PHCD;
321 writel(val, base + USB_PORTSC1);
322 }
323
324 if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
325 pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
326}
327
328static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
329{
330 unsigned long val;
331 void __iomem *base = phy->regs;
332
333 if (phy->instance == 0) {
334 val = readl(base + USB_SUSP_CTRL);
335 val |= USB_SUSP_CLR;
336 writel(val, base + USB_SUSP_CTRL);
337
338 udelay(10);
339
340 val = readl(base + USB_SUSP_CTRL);
341 val &= ~USB_SUSP_CLR;
342 writel(val, base + USB_SUSP_CTRL);
343 }
344
345 if (phy->instance == 2) {
346 val = readl(base + USB_PORTSC1);
347 val &= ~USB_PORTSC1_PHCD;
348 writel(val, base + USB_PORTSC1);
349 }
350
351 if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
352 USB_PHY_CLK_VALID))
353 pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
354}
355
356static int utmi_phy_power_on(struct tegra_usb_phy *phy)
357{
358 unsigned long val;
359 void __iomem *base = phy->regs;
360 struct tegra_utmip_config *config = phy->config;
361
362 val = readl(base + USB_SUSP_CTRL);
363 val |= UTMIP_RESET;
364 writel(val, base + USB_SUSP_CTRL);
365
366 if (phy->instance == 0) {
367 val = readl(base + USB1_LEGACY_CTRL);
368 val |= USB1_NO_LEGACY_MODE;
369 writel(val, base + USB1_LEGACY_CTRL);
370 }
371
372 val = readl(base + UTMIP_TX_CFG0);
373 val &= ~UTMIP_FS_PREABMLE_J;
374 writel(val, base + UTMIP_TX_CFG0);
375
376 val = readl(base + UTMIP_HSRX_CFG0);
377 val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
378 val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
379 val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
380 writel(val, base + UTMIP_HSRX_CFG0);
381
382 val = readl(base + UTMIP_HSRX_CFG1);
383 val &= ~UTMIP_HS_SYNC_START_DLY(~0);
384 val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
385 writel(val, base + UTMIP_HSRX_CFG1);
386
387 val = readl(base + UTMIP_DEBOUNCE_CFG0);
388 val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
389 val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
390 writel(val, base + UTMIP_DEBOUNCE_CFG0);
391
392 val = readl(base + UTMIP_MISC_CFG0);
393 val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
394 writel(val, base + UTMIP_MISC_CFG0);
395
396 val = readl(base + UTMIP_MISC_CFG1);
397 val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
398 val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
399 UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
400 writel(val, base + UTMIP_MISC_CFG1);
401
402 val = readl(base + UTMIP_PLL_CFG1);
403 val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
404 val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
405 UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
406 writel(val, base + UTMIP_PLL_CFG1);
407
408 if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
409 val = readl(base + USB_SUSP_CTRL);
410 val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
411 writel(val, base + USB_SUSP_CTRL);
412 }
413
414 utmip_pad_power_on(phy);
415
416 val = readl(base + UTMIP_XCVR_CFG0);
417 val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
418 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
419 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
420 UTMIP_XCVR_HSSLEW_MSB(~0));
421 val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
422 val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
423 val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
424 writel(val, base + UTMIP_XCVR_CFG0);
425
426 val = readl(base + UTMIP_XCVR_CFG1);
427 val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
428 UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
429 val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
430 writel(val, base + UTMIP_XCVR_CFG1);
431
432 val = readl(base + UTMIP_BAT_CHRG_CFG0);
433 val &= ~UTMIP_PD_CHRG;
434 writel(val, base + UTMIP_BAT_CHRG_CFG0);
435
436 val = readl(base + UTMIP_BIAS_CFG1);
437 val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
438 val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
439 writel(val, base + UTMIP_BIAS_CFG1);
440
441 if (phy->instance == 0) {
442 val = readl(base + UTMIP_SPARE_CFG0);
443 if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
444 val &= ~FUSE_SETUP_SEL;
445 else
446 val |= FUSE_SETUP_SEL;
447 writel(val, base + UTMIP_SPARE_CFG0);
448 }
449
450 if (phy->instance == 2) {
451 val = readl(base + USB_SUSP_CTRL);
452 val |= UTMIP_PHY_ENABLE;
453 writel(val, base + USB_SUSP_CTRL);
454 }
455
456 val = readl(base + USB_SUSP_CTRL);
457 val &= ~UTMIP_RESET;
458 writel(val, base + USB_SUSP_CTRL);
459
460 if (phy->instance == 0) {
461 val = readl(base + USB1_LEGACY_CTRL);
462 val &= ~USB1_VBUS_SENSE_CTL_MASK;
463 val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
464 writel(val, base + USB1_LEGACY_CTRL);
465
466 val = readl(base + USB_SUSP_CTRL);
467 val &= ~USB_SUSP_SET;
468 writel(val, base + USB_SUSP_CTRL);
469 }
470
471 utmi_phy_clk_enable(phy);
472
473 if (phy->instance == 2) {
474 val = readl(base + USB_PORTSC1);
475 val &= ~USB_PORTSC1_PTS(~0);
476 writel(val, base + USB_PORTSC1);
477 }
478
479 return 0;
480}
481
482static void utmi_phy_power_off(struct tegra_usb_phy *phy)
483{
484 unsigned long val;
485 void __iomem *base = phy->regs;
486
487 utmi_phy_clk_disable(phy);
488
489 if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
490 val = readl(base + USB_SUSP_CTRL);
491 val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
492 val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
493 writel(val, base + USB_SUSP_CTRL);
494 }
495
496 val = readl(base + USB_SUSP_CTRL);
497 val |= UTMIP_RESET;
498 writel(val, base + USB_SUSP_CTRL);
499
500 val = readl(base + UTMIP_BAT_CHRG_CFG0);
501 val |= UTMIP_PD_CHRG;
502 writel(val, base + UTMIP_BAT_CHRG_CFG0);
503
504 val = readl(base + UTMIP_XCVR_CFG0);
505 val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
506 UTMIP_FORCE_PDZI_POWERDOWN;
507 writel(val, base + UTMIP_XCVR_CFG0);
508
509 val = readl(base + UTMIP_XCVR_CFG1);
510 val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
511 UTMIP_FORCE_PDDR_POWERDOWN;
512 writel(val, base + UTMIP_XCVR_CFG1);
513
514 utmip_pad_power_off(phy);
515}
516
517static void utmi_phy_preresume(struct tegra_usb_phy *phy)
518{
519 unsigned long val;
520 void __iomem *base = phy->regs;
521
522 val = readl(base + UTMIP_TX_CFG0);
523 val |= UTMIP_HS_DISCON_DISABLE;
524 writel(val, base + UTMIP_TX_CFG0);
525}
526
527static void utmi_phy_postresume(struct tegra_usb_phy *phy)
528{
529 unsigned long val;
530 void __iomem *base = phy->regs;
531
532 val = readl(base + UTMIP_TX_CFG0);
533 val &= ~UTMIP_HS_DISCON_DISABLE;
534 writel(val, base + UTMIP_TX_CFG0);
535}
536
537static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
538 enum tegra_usb_phy_port_speed port_speed)
539{
540 unsigned long val;
541 void __iomem *base = phy->regs;
542
543 val = readl(base + UTMIP_MISC_CFG0);
544 val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
545 if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
546 val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
547 else
548 val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
549 writel(val, base + UTMIP_MISC_CFG0);
550 udelay(1);
551
552 val = readl(base + UTMIP_MISC_CFG0);
553 val |= UTMIP_DPDM_OBSERVE;
554 writel(val, base + UTMIP_MISC_CFG0);
555 udelay(10);
556}
557
558static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
559{
560 unsigned long val;
561 void __iomem *base = phy->regs;
562
563 val = readl(base + UTMIP_MISC_CFG0);
564 val &= ~UTMIP_DPDM_OBSERVE;
565 writel(val, base + UTMIP_MISC_CFG0);
566 udelay(10);
567}
568
569static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
570{
571 int ret;
572 unsigned long val;
573 void __iomem *base = phy->regs;
574 struct tegra_ulpi_config *config = phy->config;
575
576 gpio_direction_output(config->reset_gpio, 0);
577 msleep(5);
578 gpio_direction_output(config->reset_gpio, 1);
579
580 clk_enable(phy->clk);
581 msleep(1);
582
583 val = readl(base + USB_SUSP_CTRL);
584 val |= UHSIC_RESET;
585 writel(val, base + USB_SUSP_CTRL);
586
587 val = readl(base + ULPI_TIMING_CTRL_0);
588 val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
589 writel(val, base + ULPI_TIMING_CTRL_0);
590
591 val = readl(base + USB_SUSP_CTRL);
592 val |= ULPI_PHY_ENABLE;
593 writel(val, base + USB_SUSP_CTRL);
594
595 val = 0;
596 writel(val, base + ULPI_TIMING_CTRL_1);
597
598 val |= ULPI_DATA_TRIMMER_SEL(4);
599 val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
600 val |= ULPI_DIR_TRIMMER_SEL(4);
601 writel(val, base + ULPI_TIMING_CTRL_1);
602 udelay(10);
603
604 val |= ULPI_DATA_TRIMMER_LOAD;
605 val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
606 val |= ULPI_DIR_TRIMMER_LOAD;
607 writel(val, base + ULPI_TIMING_CTRL_1);
608
609 /* Fix VbusInvalid due to floating VBUS */
610 ret = otg_io_write(phy->ulpi, 0x40, 0x08);
611 if (ret) {
612 pr_err("%s: ulpi write failed\n", __func__);
613 return ret;
614 }
615
616 ret = otg_io_write(phy->ulpi, 0x80, 0x0B);
617 if (ret) {
618 pr_err("%s: ulpi write failed\n", __func__);
619 return ret;
620 }
621
622 val = readl(base + USB_PORTSC1);
623 val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
624 writel(val, base + USB_PORTSC1);
625
626 val = readl(base + USB_SUSP_CTRL);
627 val |= USB_SUSP_CLR;
628 writel(val, base + USB_SUSP_CTRL);
629 udelay(100);
630
631 val = readl(base + USB_SUSP_CTRL);
632 val &= ~USB_SUSP_CLR;
633 writel(val, base + USB_SUSP_CTRL);
634
635 return 0;
636}
637
638static void ulpi_phy_power_off(struct tegra_usb_phy *phy)
639{
640 unsigned long val;
641 void __iomem *base = phy->regs;
642 struct tegra_ulpi_config *config = phy->config;
643
644 /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
645 * Controller to immediately bring the ULPI PHY out of low power
646 */
647 val = readl(base + USB_PORTSC1);
648 val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
649 writel(val, base + USB_PORTSC1);
650
651 gpio_direction_output(config->reset_gpio, 0);
652 clk_disable(phy->clk);
653}
654
655struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
656 void *config, enum tegra_usb_phy_mode phy_mode)
657{
658 struct tegra_usb_phy *phy;
659 struct tegra_ulpi_config *ulpi_config;
660 unsigned long parent_rate;
661 int i;
662 int err;
663
664 phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
665 if (!phy)
666 return ERR_PTR(-ENOMEM);
667
668 phy->instance = instance;
669 phy->regs = regs;
670 phy->config = config;
671 phy->mode = phy_mode;
672
673 if (!phy->config) {
674 if (phy_is_ulpi(phy)) {
675 pr_err("%s: ulpi phy configuration missing", __func__);
676 err = -EINVAL;
677 goto err0;
678 } else {
679 phy->config = &utmip_default[instance];
680 }
681 }
682
683 phy->pll_u = clk_get_sys(NULL, "pll_u");
684 if (IS_ERR(phy->pll_u)) {
685 pr_err("Can't get pll_u clock\n");
686 err = PTR_ERR(phy->pll_u);
687 goto err0;
688 }
689 clk_enable(phy->pll_u);
690
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;
701 goto err1;
702 }
703
704 if (phy_is_ulpi(phy)) {
705 ulpi_config = config;
706 phy->clk = clk_get_sys(NULL, ulpi_config->clk);
707 if (IS_ERR(phy->clk)) {
708 pr_err("%s: can't get ulpi clock\n", __func__);
709 err = -ENXIO;
710 goto err1;
711 }
712 tegra_gpio_enable(ulpi_config->reset_gpio);
713 gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
714 gpio_direction_output(ulpi_config->reset_gpio, 0);
715 phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
716 phy->ulpi->io_priv = regs + ULPI_VIEWPORT;
717 } else {
718 err = utmip_pad_open(phy);
719 if (err < 0)
720 goto err1;
721 }
722
723 return phy;
724
725err1:
726 clk_disable(phy->pll_u);
727 clk_put(phy->pll_u);
728err0:
729 kfree(phy);
730 return ERR_PTR(err);
731}
732
733int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
734{
735 if (phy_is_ulpi(phy))
736 return ulpi_phy_power_on(phy);
737 else
738 return utmi_phy_power_on(phy);
739}
740
741void tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
742{
743 if (phy_is_ulpi(phy))
744 ulpi_phy_power_off(phy);
745 else
746 utmi_phy_power_off(phy);
747}
748
749void tegra_usb_phy_preresume(struct tegra_usb_phy *phy)
750{
751 if (!phy_is_ulpi(phy))
752 utmi_phy_preresume(phy);
753}
754
755void tegra_usb_phy_postresume(struct tegra_usb_phy *phy)
756{
757 if (!phy_is_ulpi(phy))
758 utmi_phy_postresume(phy);
759}
760
761void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
762 enum tegra_usb_phy_port_speed port_speed)
763{
764 if (!phy_is_ulpi(phy))
765 utmi_phy_restore_start(phy, port_speed);
766}
767
768void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy)
769{
770 if (!phy_is_ulpi(phy))
771 utmi_phy_restore_end(phy);
772}
773
774void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
775{
776 if (!phy_is_ulpi(phy))
777 utmi_phy_clk_disable(phy);
778}
779
780void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
781{
782 if (!phy_is_ulpi(phy))
783 utmi_phy_clk_enable(phy);
784}
785
786void tegra_usb_phy_close(struct tegra_usb_phy *phy)
787{
788 if (phy_is_ulpi(phy))
789 clk_put(phy->clk);
790 else
791 utmip_pad_close(phy);
792 clk_disable(phy->pll_u);
793 clk_put(phy->pll_u);
794 kfree(phy);
795}