aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/ehci-hcd.c5
-rw-r--r--drivers/usb/host/ehci-tegra.c625
-rw-r--r--include/linux/platform_data/tegra_usb.h31
-rw-r--r--include/linux/usb/ehci_def.h4
5 files changed, 672 insertions, 1 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b5a908eacb82..9483acdf2e9e 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -165,6 +165,14 @@ config USB_EHCI_MSM
165 This driver is not supported on boards like trout which 165 This driver is not supported on boards like trout which
166 has an external PHY. 166 has an external PHY.
167 167
168config USB_EHCI_TEGRA
169 boolean "NVIDIA Tegra HCD support"
170 depends on USB_EHCI_HCD && ARCH_TEGRA
171 select USB_EHCI_ROOT_HUB_TT
172 help
173 This driver enables support for the internal USB Host Controllers
174 found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
175
168config USB_EHCI_HCD_PPC_OF 176config USB_EHCI_HCD_PPC_OF
169 bool "EHCI support for PPC USB controller on OF platform bus" 177 bool "EHCI support for PPC USB controller on OF platform bus"
170 depends on USB_EHCI_HCD && PPC_OF 178 depends on USB_EHCI_HCD && PPC_OF
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index cfeb24b3ee09..d30c4e08c137 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1260,6 +1260,11 @@ MODULE_LICENSE ("GPL");
1260#define PLATFORM_DRIVER ehci_hcd_msp_driver 1260#define PLATFORM_DRIVER ehci_hcd_msp_driver
1261#endif 1261#endif
1262 1262
1263#ifdef CONFIG_USB_EHCI_TEGRA
1264#include "ehci-tegra.c"
1265#define PLATFORM_DRIVER tegra_ehci_driver
1266#endif
1267
1263#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ 1268#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
1264 !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ 1269 !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
1265 !defined(XILINX_OF_PLATFORM_DRIVER) 1270 !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
new file mode 100644
index 000000000000..6202102a6d75
--- /dev/null
+++ b/drivers/usb/host/ehci-tegra.c
@@ -0,0 +1,625 @@
1/*
2 * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2009 NVIDIA Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 */
18
19#include <linux/clk.h>
20#include <linux/platform_device.h>
21#include <linux/platform_data/tegra_usb.h>
22#include <linux/irq.h>
23#include <linux/usb/otg.h>
24#include <mach/usb_phy.h>
25
26struct tegra_ehci_hcd {
27 struct ehci_hcd *ehci;
28 struct tegra_usb_phy *phy;
29 struct clk *clk;
30 struct clk *emc_clk;
31 struct otg_transceiver *transceiver;
32 int host_resumed;
33 int bus_suspended;
34 int port_resuming;
35 int power_down_on_bus_suspend;
36 enum tegra_usb_phy_port_speed port_speed;
37};
38
39static void tegra_ehci_power_up(struct usb_hcd *hcd)
40{
41 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
42
43 clk_enable(tegra->emc_clk);
44 clk_enable(tegra->clk);
45 tegra_usb_phy_power_on(tegra->phy);
46 tegra->host_resumed = 1;
47}
48
49static void tegra_ehci_power_down(struct usb_hcd *hcd)
50{
51 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
52
53 tegra->host_resumed = 0;
54 tegra_usb_phy_power_off(tegra->phy);
55 clk_disable(tegra->clk);
56 clk_disable(tegra->emc_clk);
57}
58
59static int tegra_ehci_hub_control(
60 struct usb_hcd *hcd,
61 u16 typeReq,
62 u16 wValue,
63 u16 wIndex,
64 char *buf,
65 u16 wLength
66)
67{
68 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
69 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
70 u32 __iomem *status_reg;
71 u32 temp;
72 unsigned long flags;
73 int retval = 0;
74
75 status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
76
77 spin_lock_irqsave(&ehci->lock, flags);
78
79 /*
80 * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
81 * that are write on clear, by writing back the register read value, so
82 * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
83 */
84 if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
85 temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
86 ehci_writel(ehci, temp & ~PORT_PE, status_reg);
87 goto done;
88 }
89
90 else if (typeReq == GetPortStatus) {
91 temp = ehci_readl(ehci, status_reg);
92 if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
93 /* Resume completed, re-enable disconnect detection */
94 tegra->port_resuming = 0;
95 tegra_usb_phy_postresume(tegra->phy);
96 }
97 }
98
99 else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
100 temp = ehci_readl(ehci, status_reg);
101 if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
102 retval = -EPIPE;
103 goto done;
104 }
105
106 temp &= ~PORT_WKCONN_E;
107 temp |= PORT_WKDISC_E | PORT_WKOC_E;
108 ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
109
110 /*
111 * If a transaction is in progress, there may be a delay in
112 * suspending the port. Poll until the port is suspended.
113 */
114 if (handshake(ehci, status_reg, PORT_SUSPEND,
115 PORT_SUSPEND, 5000))
116 pr_err("%s: timeout waiting for SUSPEND\n", __func__);
117
118 set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
119 goto done;
120 }
121
122 /*
123 * Tegra host controller will time the resume operation to clear the bit
124 * when the port control state switches to HS or FS Idle. This behavior
125 * is different from EHCI where the host controller driver is required
126 * to set this bit to a zero after the resume duration is timed in the
127 * driver.
128 */
129 else if (typeReq == ClearPortFeature &&
130 wValue == USB_PORT_FEAT_SUSPEND) {
131 temp = ehci_readl(ehci, status_reg);
132 if ((temp & PORT_RESET) || !(temp & PORT_PE)) {
133 retval = -EPIPE;
134 goto done;
135 }
136
137 if (!(temp & PORT_SUSPEND))
138 goto done;
139
140 /* Disable disconnect detection during port resume */
141 tegra_usb_phy_preresume(tegra->phy);
142
143 ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
144
145 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
146 /* start resume signalling */
147 ehci_writel(ehci, temp | PORT_RESUME, status_reg);
148
149 spin_unlock_irqrestore(&ehci->lock, flags);
150 msleep(20);
151 spin_lock_irqsave(&ehci->lock, flags);
152
153 /* Poll until the controller clears RESUME and SUSPEND */
154 if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
155 pr_err("%s: timeout waiting for RESUME\n", __func__);
156 if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
157 pr_err("%s: timeout waiting for SUSPEND\n", __func__);
158
159 ehci->reset_done[wIndex-1] = 0;
160
161 tegra->port_resuming = 1;
162 goto done;
163 }
164
165 spin_unlock_irqrestore(&ehci->lock, flags);
166
167 /* Handle the hub control events here */
168 return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
169done:
170 spin_unlock_irqrestore(&ehci->lock, flags);
171 return retval;
172}
173
174static void tegra_ehci_restart(struct usb_hcd *hcd)
175{
176 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
177
178 ehci_reset(ehci);
179
180 /* setup the frame list and Async q heads */
181 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
182 ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
183 /* setup the command register and set the controller in RUN mode */
184 ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
185 ehci->command |= CMD_RUN;
186 ehci_writel(ehci, ehci->command, &ehci->regs->command);
187
188 down_write(&ehci_cf_port_reset_rwsem);
189 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
190 /* flush posted writes */
191 ehci_readl(ehci, &ehci->regs->command);
192 up_write(&ehci_cf_port_reset_rwsem);
193}
194
195static int tegra_usb_suspend(struct usb_hcd *hcd)
196{
197 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
198 struct ehci_regs __iomem *hw = tegra->ehci->regs;
199 unsigned long flags;
200
201 spin_lock_irqsave(&tegra->ehci->lock, flags);
202
203 tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
204 ehci_halt(tegra->ehci);
205 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
206
207 spin_unlock_irqrestore(&tegra->ehci->lock, flags);
208
209 tegra_ehci_power_down(hcd);
210 return 0;
211}
212
213static int tegra_usb_resume(struct usb_hcd *hcd)
214{
215 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
216 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
217 struct ehci_regs __iomem *hw = ehci->regs;
218 unsigned long val;
219
220 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
221 tegra_ehci_power_up(hcd);
222
223 if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
224 /* Wait for the phy to detect new devices
225 * before we restart the controller */
226 msleep(10);
227 goto restart;
228 }
229
230 /* Force the phy to keep data lines in suspend state */
231 tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
232
233 /* Enable host mode */
234 tdi_reset(ehci);
235
236 /* Enable Port Power */
237 val = readl(&hw->port_status[0]);
238 val |= PORT_POWER;
239 writel(val, &hw->port_status[0]);
240 udelay(10);
241
242 /* Check if the phy resume from LP0. When the phy resume from LP0
243 * USB register will be reset. */
244 if (!readl(&hw->async_next)) {
245 /* Program the field PTC based on the saved speed mode */
246 val = readl(&hw->port_status[0]);
247 val &= ~PORT_TEST(~0);
248 if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
249 val |= PORT_TEST_FORCE;
250 else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
251 val |= PORT_TEST(6);
252 else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
253 val |= PORT_TEST(7);
254 writel(val, &hw->port_status[0]);
255 udelay(10);
256
257 /* Disable test mode by setting PTC field to NORMAL_OP */
258 val = readl(&hw->port_status[0]);
259 val &= ~PORT_TEST(~0);
260 writel(val, &hw->port_status[0]);
261 udelay(10);
262 }
263
264 /* Poll until CCS is enabled */
265 if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
266 PORT_CONNECT, 2000)) {
267 pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
268 goto restart;
269 }
270
271 /* Poll until PE is enabled */
272 if (handshake(ehci, &hw->port_status[0], PORT_PE,
273 PORT_PE, 2000)) {
274 pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
275 goto restart;
276 }
277
278 /* Clear the PCI status, to avoid an interrupt taken upon resume */
279 val = readl(&hw->status);
280 val |= STS_PCD;
281 writel(val, &hw->status);
282
283 /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
284 val = readl(&hw->port_status[0]);
285 if ((val & PORT_POWER) && (val & PORT_PE)) {
286 val |= PORT_SUSPEND;
287 writel(val, &hw->port_status[0]);
288
289 /* Wait until port suspend completes */
290 if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
291 PORT_SUSPEND, 1000)) {
292 pr_err("%s: timeout waiting for PORT_SUSPEND\n",
293 __func__);
294 goto restart;
295 }
296 }
297
298 tegra_ehci_phy_restore_end(tegra->phy);
299 return 0;
300
301restart:
302 if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
303 tegra_ehci_phy_restore_end(tegra->phy);
304
305 tegra_ehci_restart(hcd);
306 return 0;
307}
308
309static void tegra_ehci_shutdown(struct usb_hcd *hcd)
310{
311 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
312
313 /* ehci_shutdown touches the USB controller registers, make sure
314 * controller has clocks to it */
315 if (!tegra->host_resumed)
316 tegra_ehci_power_up(hcd);
317
318 ehci_shutdown(hcd);
319}
320
321static int tegra_ehci_setup(struct usb_hcd *hcd)
322{
323 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
324 int retval;
325
326 /* EHCI registers start at offset 0x100 */
327 ehci->caps = hcd->regs + 0x100;
328 ehci->regs = hcd->regs + 0x100 +
329 HC_LENGTH(readl(&ehci->caps->hc_capbase));
330
331 dbg_hcs_params(ehci, "reset");
332 dbg_hcc_params(ehci, "reset");
333
334 /* cache this readonly data; minimize chip reads */
335 ehci->hcs_params = readl(&ehci->caps->hcs_params);
336
337 /* switch to host mode */
338 hcd->has_tt = 1;
339 ehci_reset(ehci);
340
341 retval = ehci_halt(ehci);
342 if (retval)
343 return retval;
344
345 /* data structure init */
346 retval = ehci_init(hcd);
347 if (retval)
348 return retval;
349
350 ehci->sbrn = 0x20;
351
352 ehci_port_power(ehci, 1);
353 return retval;
354}
355
356#ifdef CONFIG_PM
357static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
358{
359 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
360 int error_status = 0;
361
362 error_status = ehci_bus_suspend(hcd);
363 if (!error_status && tegra->power_down_on_bus_suspend) {
364 tegra_usb_suspend(hcd);
365 tegra->bus_suspended = 1;
366 }
367
368 return error_status;
369}
370
371static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
372{
373 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
374
375 if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
376 tegra_usb_resume(hcd);
377 tegra->bus_suspended = 0;
378 }
379
380 tegra_usb_phy_preresume(tegra->phy);
381 tegra->port_resuming = 1;
382 return ehci_bus_resume(hcd);
383}
384#endif
385
386static const struct hc_driver tegra_ehci_hc_driver = {
387 .description = hcd_name,
388 .product_desc = "Tegra EHCI Host Controller",
389 .hcd_priv_size = sizeof(struct ehci_hcd),
390
391 .flags = HCD_USB2 | HCD_MEMORY,
392
393 .reset = tegra_ehci_setup,
394 .irq = ehci_irq,
395
396 .start = ehci_run,
397 .stop = ehci_stop,
398 .shutdown = tegra_ehci_shutdown,
399 .urb_enqueue = ehci_urb_enqueue,
400 .urb_dequeue = ehci_urb_dequeue,
401 .endpoint_disable = ehci_endpoint_disable,
402 .endpoint_reset = ehci_endpoint_reset,
403 .get_frame_number = ehci_get_frame,
404 .hub_status_data = ehci_hub_status_data,
405 .hub_control = tegra_ehci_hub_control,
406 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
407#ifdef CONFIG_PM
408 .bus_suspend = tegra_ehci_bus_suspend,
409 .bus_resume = tegra_ehci_bus_resume,
410#endif
411 .relinquish_port = ehci_relinquish_port,
412 .port_handed_over = ehci_port_handed_over,
413};
414
415static int tegra_ehci_probe(struct platform_device *pdev)
416{
417 struct resource *res;
418 struct usb_hcd *hcd;
419 struct tegra_ehci_hcd *tegra;
420 struct tegra_ehci_platform_data *pdata;
421 int err = 0;
422 int irq;
423 int instance = pdev->id;
424
425 pdata = pdev->dev.platform_data;
426 if (!pdata) {
427 dev_err(&pdev->dev, "Platform data missing\n");
428 return -EINVAL;
429 }
430
431 tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
432 if (!tegra)
433 return -ENOMEM;
434
435 hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
436 dev_name(&pdev->dev));
437 if (!hcd) {
438 dev_err(&pdev->dev, "Unable to create HCD\n");
439 err = -ENOMEM;
440 goto fail_hcd;
441 }
442
443 platform_set_drvdata(pdev, tegra);
444
445 tegra->clk = clk_get(&pdev->dev, NULL);
446 if (IS_ERR(tegra->clk)) {
447 dev_err(&pdev->dev, "Can't get ehci clock\n");
448 err = PTR_ERR(tegra->clk);
449 goto fail_clk;
450 }
451
452 err = clk_enable(tegra->clk);
453 if (err)
454 goto fail_clken;
455
456 tegra->emc_clk = clk_get(&pdev->dev, "emc");
457 if (IS_ERR(tegra->emc_clk)) {
458 dev_err(&pdev->dev, "Can't get emc clock\n");
459 err = PTR_ERR(tegra->emc_clk);
460 goto fail_emc_clk;
461 }
462
463 clk_enable(tegra->emc_clk);
464 clk_set_rate(tegra->emc_clk, 400000000);
465
466 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
467 if (!res) {
468 dev_err(&pdev->dev, "Failed to get I/O memory\n");
469 err = -ENXIO;
470 goto fail_io;
471 }
472 hcd->rsrc_start = res->start;
473 hcd->rsrc_len = resource_size(res);
474 hcd->regs = ioremap(res->start, resource_size(res));
475 if (!hcd->regs) {
476 dev_err(&pdev->dev, "Failed to remap I/O memory\n");
477 err = -ENOMEM;
478 goto fail_io;
479 }
480
481 tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
482 TEGRA_USB_PHY_MODE_HOST);
483 if (IS_ERR(tegra->phy)) {
484 dev_err(&pdev->dev, "Failed to open USB phy\n");
485 err = -ENXIO;
486 goto fail_phy;
487 }
488
489 err = tegra_usb_phy_power_on(tegra->phy);
490 if (err) {
491 dev_err(&pdev->dev, "Failed to power on the phy\n");
492 goto fail;
493 }
494
495 tegra->host_resumed = 1;
496 tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
497 tegra->ehci = hcd_to_ehci(hcd);
498
499 irq = platform_get_irq(pdev, 0);
500 if (!irq) {
501 dev_err(&pdev->dev, "Failed to get IRQ\n");
502 err = -ENODEV;
503 goto fail;
504 }
505 set_irq_flags(irq, IRQF_VALID);
506
507#ifdef CONFIG_USB_OTG_UTILS
508 if (pdata->operating_mode == TEGRA_USB_OTG) {
509 tegra->transceiver = otg_get_transceiver();
510 if (tegra->transceiver)
511 otg_set_host(tegra->transceiver, &hcd->self);
512 }
513#endif
514
515 err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
516 if (err) {
517 dev_err(&pdev->dev, "Failed to add USB HCD\n");
518 goto fail;
519 }
520
521 return err;
522
523fail:
524#ifdef CONFIG_USB_OTG_UTILS
525 if (tegra->transceiver) {
526 otg_set_host(tegra->transceiver, NULL);
527 otg_put_transceiver(tegra->transceiver);
528 }
529#endif
530 tegra_usb_phy_close(tegra->phy);
531fail_phy:
532 iounmap(hcd->regs);
533fail_io:
534 clk_disable(tegra->emc_clk);
535 clk_put(tegra->emc_clk);
536fail_emc_clk:
537 clk_disable(tegra->clk);
538fail_clken:
539 clk_put(tegra->clk);
540fail_clk:
541 usb_put_hcd(hcd);
542fail_hcd:
543 kfree(tegra);
544 return err;
545}
546
547#ifdef CONFIG_PM
548static int tegra_ehci_resume(struct platform_device *pdev)
549{
550 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
551 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
552
553 if (tegra->bus_suspended)
554 return 0;
555
556 return tegra_usb_resume(hcd);
557}
558
559static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
560{
561 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
562 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
563
564 if (tegra->bus_suspended)
565 return 0;
566
567 if (time_before(jiffies, tegra->ehci->next_statechange))
568 msleep(10);
569
570 return tegra_usb_suspend(hcd);
571}
572#endif
573
574static int tegra_ehci_remove(struct platform_device *pdev)
575{
576 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
577 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
578
579 if (tegra == NULL || hcd == NULL)
580 return -EINVAL;
581
582#ifdef CONFIG_USB_OTG_UTILS
583 if (tegra->transceiver) {
584 otg_set_host(tegra->transceiver, NULL);
585 otg_put_transceiver(tegra->transceiver);
586 }
587#endif
588
589 usb_remove_hcd(hcd);
590 usb_put_hcd(hcd);
591
592 tegra_usb_phy_close(tegra->phy);
593 iounmap(hcd->regs);
594
595 clk_disable(tegra->clk);
596 clk_put(tegra->clk);
597
598 clk_disable(tegra->emc_clk);
599 clk_put(tegra->emc_clk);
600
601 kfree(tegra);
602 return 0;
603}
604
605static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
606{
607 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
608 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
609
610 if (hcd->driver->shutdown)
611 hcd->driver->shutdown(hcd);
612}
613
614static struct platform_driver tegra_ehci_driver = {
615 .probe = tegra_ehci_probe,
616 .remove = tegra_ehci_remove,
617#ifdef CONFIG_PM
618 .suspend = tegra_ehci_suspend,
619 .resume = tegra_ehci_resume,
620#endif
621 .shutdown = tegra_ehci_hcd_shutdown,
622 .driver = {
623 .name = "tegra-ehci",
624 }
625};
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
new file mode 100644
index 000000000000..6bca5b569acb
--- /dev/null
+++ b/include/linux/platform_data/tegra_usb.h
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#ifndef _TEGRA_USB_H_
16#define _TEGRA_USB_H_
17
18enum tegra_usb_operating_modes {
19 TEGRA_USB_DEVICE,
20 TEGRA_USB_HOST,
21 TEGRA_USB_OTG,
22};
23
24struct tegra_ehci_platform_data {
25 enum tegra_usb_operating_modes operating_mode;
26 /* power down the phy on bus suspend */
27 int power_down_on_bus_suspend;
28 void *phy_config;
29};
30
31#endif /* _TEGRA_USB_H_ */
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index 2e262cb15425..656380245198 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -127,7 +127,9 @@ struct ehci_regs {
127#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ 127#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */
128#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ 128#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */
129/* 19:16 for port testing */ 129/* 19:16 for port testing */
130#define PORT_TEST_PKT (0x4<<16) /* Port Test Control - packet test */ 130#define PORT_TEST(x) (((x)&0xf)<<16) /* Port Test Control */
131#define PORT_TEST_PKT PORT_TEST(0x4) /* Port Test Control - packet test */
132#define PORT_TEST_FORCE PORT_TEST(0x5) /* Port Test Control - force enable */
131#define PORT_LED_OFF (0<<14) 133#define PORT_LED_OFF (0<<14)
132#define PORT_LED_AMBER (1<<14) 134#define PORT_LED_AMBER (1<<14)
133#define PORT_LED_GREEN (2<<14) 135#define PORT_LED_GREEN (2<<14)