aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-02-04 09:51:49 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-02-04 09:51:49 -0500
commit2fb20e2e35cd1455d022ab7a553d7f1663ffbdeb (patch)
tree4b3bb0f76c15264fe7d4cced91127f3d96ff31f5 /drivers/usb/host
parent9cb543124a2d31af42ce61a4c30765ecc8e5f1fa (diff)
parent5b91ab0abc957145c3ff6be03eb9a3901797019f (diff)
Merge branch 'for-rmk/broadcast' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into devel-stable
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-hcd.c12
-rw-r--r--drivers/usb/host/ehci-mxc.c120
-rw-r--r--drivers/usb/host/ehci.h7
-rw-r--r--drivers/usb/host/uhci-hcd.c15
6 files changed, 70 insertions, 87 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d6bb128ce21e..3a21c5d683c0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -148,7 +148,7 @@ config USB_EHCI_FSL
148 Variation of ARC USB block used in some Freescale chips. 148 Variation of ARC USB block used in some Freescale chips.
149 149
150config USB_EHCI_MXC 150config USB_EHCI_MXC
151 bool "Support for Freescale i.MX on-chip EHCI USB controller" 151 tristate "Support for Freescale i.MX on-chip EHCI USB controller"
152 depends on USB_EHCI_HCD && ARCH_MXC 152 depends on USB_EHCI_HCD && ARCH_MXC
153 select USB_EHCI_ROOT_HUB_TT 153 select USB_EHCI_ROOT_HUB_TT
154 ---help--- 154 ---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 1eb4c3006e9e..001fbff2fdef 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_PCI) += pci-quirks.o
26obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o 26obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
27obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o 27obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
28obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o 28obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
29obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
29 30
30obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o 31obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
31obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o 32obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c97503bb0b0e..09537b2f1002 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -74,10 +74,6 @@ static const char hcd_name [] = "ehci_hcd";
74#undef VERBOSE_DEBUG 74#undef VERBOSE_DEBUG
75#undef EHCI_URB_TRACE 75#undef EHCI_URB_TRACE
76 76
77#ifdef DEBUG
78#define EHCI_STATS
79#endif
80
81/* magic numbers that can affect system performance */ 77/* magic numbers that can affect system performance */
82#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ 78#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
83#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ 79#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
@@ -1250,11 +1246,6 @@ MODULE_LICENSE ("GPL");
1250#define PLATFORM_DRIVER ehci_fsl_driver 1246#define PLATFORM_DRIVER ehci_fsl_driver
1251#endif 1247#endif
1252 1248
1253#ifdef CONFIG_USB_EHCI_MXC
1254#include "ehci-mxc.c"
1255#define PLATFORM_DRIVER ehci_mxc_driver
1256#endif
1257
1258#ifdef CONFIG_USB_EHCI_SH 1249#ifdef CONFIG_USB_EHCI_SH
1259#include "ehci-sh.c" 1250#include "ehci-sh.c"
1260#define PLATFORM_DRIVER ehci_hcd_sh_driver 1251#define PLATFORM_DRIVER ehci_hcd_sh_driver
@@ -1352,7 +1343,8 @@ MODULE_LICENSE ("GPL");
1352 1343
1353#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ 1344#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
1354 !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ 1345 !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
1355 !defined(CONFIG_USB_CHIPIDEA_HOST) && \ 1346 !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
1347 !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
1356 !defined(PLATFORM_DRIVER) && \ 1348 !defined(PLATFORM_DRIVER) && \
1357 !defined(PS3_SYSTEM_BUS_DRIVER) && \ 1349 !defined(PS3_SYSTEM_BUS_DRIVER) && \
1358 !defined(OF_PLATFORM_DRIVER) && \ 1350 !defined(OF_PLATFORM_DRIVER) && \
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index ec7f5d2c90de..dedb80bb8d40 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -17,75 +17,38 @@
17 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */ 18 */
19 19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/io.h>
20#include <linux/platform_device.h> 23#include <linux/platform_device.h>
21#include <linux/clk.h> 24#include <linux/clk.h>
22#include <linux/delay.h> 25#include <linux/delay.h>
23#include <linux/usb/otg.h> 26#include <linux/usb/otg.h>
24#include <linux/usb/ulpi.h> 27#include <linux/usb/ulpi.h>
25#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/usb.h>
30#include <linux/usb/hcd.h>
26 31
27#include <linux/platform_data/usb-ehci-mxc.h> 32#include <linux/platform_data/usb-ehci-mxc.h>
28 33
29#include <asm/mach-types.h> 34#include <asm/mach-types.h>
30 35
36#include "ehci.h"
37
38#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
39
40static const char hcd_name[] = "ehci-mxc";
41
31#define ULPI_VIEWPORT_OFFSET 0x170 42#define ULPI_VIEWPORT_OFFSET 0x170
32 43
33struct ehci_mxc_priv { 44struct ehci_mxc_priv {
34 struct clk *usbclk, *ahbclk, *phyclk; 45 struct clk *usbclk, *ahbclk, *phyclk;
35 struct usb_hcd *hcd;
36}; 46};
37 47
38/* called during probe() after chip reset completes */ 48static struct hc_driver __read_mostly ehci_mxc_hc_driver;
39static int ehci_mxc_setup(struct usb_hcd *hcd)
40{
41 hcd->has_tt = 1;
42
43 return ehci_setup(hcd);
44}
45 49
46static const struct hc_driver ehci_mxc_hc_driver = { 50static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
47 .description = hcd_name, 51 .extra_priv_size = sizeof(struct ehci_mxc_priv),
48 .product_desc = "Freescale On-Chip EHCI Host Controller",
49 .hcd_priv_size = sizeof(struct ehci_hcd),
50
51 /*
52 * generic hardware linkage
53 */
54 .irq = ehci_irq,
55 .flags = HCD_USB2 | HCD_MEMORY,
56
57 /*
58 * basic lifecycle operations
59 */
60 .reset = ehci_mxc_setup,
61 .start = ehci_run,
62 .stop = ehci_stop,
63 .shutdown = ehci_shutdown,
64
65 /*
66 * managing i/o requests and associated device resources
67 */
68 .urb_enqueue = ehci_urb_enqueue,
69 .urb_dequeue = ehci_urb_dequeue,
70 .endpoint_disable = ehci_endpoint_disable,
71 .endpoint_reset = ehci_endpoint_reset,
72
73 /*
74 * scheduling support
75 */
76 .get_frame_number = ehci_get_frame,
77
78 /*
79 * root hub support
80 */
81 .hub_status_data = ehci_hub_status_data,
82 .hub_control = ehci_hub_control,
83 .bus_suspend = ehci_bus_suspend,
84 .bus_resume = ehci_bus_resume,
85 .relinquish_port = ehci_relinquish_port,
86 .port_handed_over = ehci_port_handed_over,
87
88 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
89}; 52};
90 53
91static int ehci_mxc_drv_probe(struct platform_device *pdev) 54static int ehci_mxc_drv_probe(struct platform_device *pdev)
@@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
112 if (!hcd) 75 if (!hcd)
113 return -ENOMEM; 76 return -ENOMEM;
114 77
115 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
116 if (!priv) {
117 ret = -ENOMEM;
118 goto err_alloc;
119 }
120
121 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 78 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
122 if (!res) { 79 if (!res) {
123 dev_err(dev, "Found HC with no register addr. Check setup!\n"); 80 dev_err(dev, "Found HC with no register addr. Check setup!\n");
@@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
135 goto err_alloc; 92 goto err_alloc;
136 } 93 }
137 94
95 hcd->has_tt = 1;
96 ehci = hcd_to_ehci(hcd);
97 priv = (struct ehci_mxc_priv *) ehci->priv;
98
138 /* enable clocks */ 99 /* enable clocks */
139 priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); 100 priv->usbclk = devm_clk_get(&pdev->dev, "ipg");
140 if (IS_ERR(priv->usbclk)) { 101 if (IS_ERR(priv->usbclk)) {
@@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
169 mdelay(10); 130 mdelay(10);
170 } 131 }
171 132
172 ehci = hcd_to_ehci(hcd);
173
174 /* EHCI registers start at offset 0x100 */ 133 /* EHCI registers start at offset 0x100 */
175 ehci->caps = hcd->regs + 0x100; 134 ehci->caps = hcd->regs + 0x100;
176 ehci->regs = hcd->regs + 0x100 + 135 ehci->regs = hcd->regs + 0x100 +
@@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
198 } 157 }
199 } 158 }
200 159
201 priv->hcd = hcd; 160 platform_set_drvdata(pdev, hcd);
202 platform_set_drvdata(pdev, priv);
203 161
204 ret = usb_add_hcd(hcd, irq, IRQF_SHARED); 162 ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
205 if (ret) 163 if (ret)
@@ -244,8 +202,11 @@ err_alloc:
244static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) 202static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
245{ 203{
246 struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; 204 struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
247 struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); 205 struct usb_hcd *hcd = platform_get_drvdata(pdev);
248 struct usb_hcd *hcd = priv->hcd; 206 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
207 struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
208
209 usb_remove_hcd(hcd);
249 210
250 if (pdata && pdata->exit) 211 if (pdata && pdata->exit)
251 pdata->exit(pdev); 212 pdata->exit(pdev);
@@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
253 if (pdata->otg) 214 if (pdata->otg)
254 usb_phy_shutdown(pdata->otg); 215 usb_phy_shutdown(pdata->otg);
255 216
256 usb_remove_hcd(hcd);
257 usb_put_hcd(hcd);
258 platform_set_drvdata(pdev, NULL);
259
260 clk_disable_unprepare(priv->usbclk); 217 clk_disable_unprepare(priv->usbclk);
261 clk_disable_unprepare(priv->ahbclk); 218 clk_disable_unprepare(priv->ahbclk);
262 219
263 if (priv->phyclk) 220 if (priv->phyclk)
264 clk_disable_unprepare(priv->phyclk); 221 clk_disable_unprepare(priv->phyclk);
265 222
223 usb_put_hcd(hcd);
224 platform_set_drvdata(pdev, NULL);
266 return 0; 225 return 0;
267} 226}
268 227
269static void ehci_mxc_drv_shutdown(struct platform_device *pdev) 228static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
270{ 229{
271 struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); 230 struct usb_hcd *hcd = platform_get_drvdata(pdev);
272 struct usb_hcd *hcd = priv->hcd;
273 231
274 if (hcd->driver->shutdown) 232 if (hcd->driver->shutdown)
275 hcd->driver->shutdown(hcd); 233 hcd->driver->shutdown(hcd);
@@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci");
279 237
280static struct platform_driver ehci_mxc_driver = { 238static struct platform_driver ehci_mxc_driver = {
281 .probe = ehci_mxc_drv_probe, 239 .probe = ehci_mxc_drv_probe,
282 .remove = __exit_p(ehci_mxc_drv_remove), 240 .remove = ehci_mxc_drv_remove,
283 .shutdown = ehci_mxc_drv_shutdown, 241 .shutdown = ehci_mxc_drv_shutdown,
284 .driver = { 242 .driver = {
285 .name = "mxc-ehci", 243 .name = "mxc-ehci",
286 }, 244 },
287}; 245};
246
247static int __init ehci_mxc_init(void)
248{
249 if (usb_disabled())
250 return -ENODEV;
251
252 pr_info("%s: " DRIVER_DESC "\n", hcd_name);
253
254 ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides);
255 return platform_driver_register(&ehci_mxc_driver);
256}
257module_init(ehci_mxc_init);
258
259static void __exit ehci_mxc_cleanup(void)
260{
261 platform_driver_unregister(&ehci_mxc_driver);
262}
263module_exit(ehci_mxc_cleanup);
264
265MODULE_DESCRIPTION(DRIVER_DESC);
266MODULE_AUTHOR("Sascha Hauer");
267MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 9dadc7118d68..36c3a8210595 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16;
38#endif 38#endif
39 39
40/* statistics can be kept for tuning/monitoring */ 40/* statistics can be kept for tuning/monitoring */
41#ifdef DEBUG
42#define EHCI_STATS
43#endif
44
41struct ehci_stats { 45struct ehci_stats {
42 /* irq usage */ 46 /* irq usage */
43 unsigned long normal; 47 unsigned long normal;
@@ -221,6 +225,9 @@ struct ehci_hcd { /* one per controller */
221#ifdef DEBUG 225#ifdef DEBUG
222 struct dentry *debug_dir; 226 struct dentry *debug_dir;
223#endif 227#endif
228
229 /* platform-specific data -- must come last */
230 unsigned long priv[0] __aligned(sizeof(s64));
224}; 231};
225 232
226/* convert between an HCD pointer and the corresponding EHCI_HCD */ 233/* convert between an HCD pointer and the corresponding EHCI_HCD */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 4b9e9aba2665..4f64d24eebc8 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
447 return IRQ_NONE; 447 return IRQ_NONE;
448 uhci_writew(uhci, status, USBSTS); /* Clear it */ 448 uhci_writew(uhci, status, USBSTS); /* Clear it */
449 449
450 spin_lock(&uhci->lock);
451 if (unlikely(!uhci->is_initialized)) /* not yet configured */
452 goto done;
453
450 if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { 454 if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
451 if (status & USBSTS_HSE) 455 if (status & USBSTS_HSE)
452 dev_err(uhci_dev(uhci), "host system error, " 456 dev_err(uhci_dev(uhci), "host system error, "
@@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
455 dev_err(uhci_dev(uhci), "host controller process " 459 dev_err(uhci_dev(uhci), "host controller process "
456 "error, something bad happened!\n"); 460 "error, something bad happened!\n");
457 if (status & USBSTS_HCH) { 461 if (status & USBSTS_HCH) {
458 spin_lock(&uhci->lock);
459 if (uhci->rh_state >= UHCI_RH_RUNNING) { 462 if (uhci->rh_state >= UHCI_RH_RUNNING) {
460 dev_err(uhci_dev(uhci), 463 dev_err(uhci_dev(uhci),
461 "host controller halted, " 464 "host controller halted, "
@@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
473 * pending unlinks */ 476 * pending unlinks */
474 mod_timer(&hcd->rh_timer, jiffies); 477 mod_timer(&hcd->rh_timer, jiffies);
475 } 478 }
476 spin_unlock(&uhci->lock);
477 } 479 }
478 } 480 }
479 481
480 if (status & USBSTS_RD) 482 if (status & USBSTS_RD) {
483 spin_unlock(&uhci->lock);
481 usb_hcd_poll_rh_status(hcd); 484 usb_hcd_poll_rh_status(hcd);
482 else { 485 } else {
483 spin_lock(&uhci->lock);
484 uhci_scan_schedule(uhci); 486 uhci_scan_schedule(uhci);
487 done:
485 spin_unlock(&uhci->lock); 488 spin_unlock(&uhci->lock);
486 } 489 }
487 490
@@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd)
662 */ 665 */
663 mb(); 666 mb();
664 667
668 spin_lock_irq(&uhci->lock);
665 configure_hc(uhci); 669 configure_hc(uhci);
666 uhci->is_initialized = 1; 670 uhci->is_initialized = 1;
667 spin_lock_irq(&uhci->lock);
668 start_rh(uhci); 671 start_rh(uhci);
669 spin_unlock_irq(&uhci->lock); 672 spin_unlock_irq(&uhci->lock);
670 return 0; 673 return 0;