aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/Kconfig6
-rw-r--r--drivers/usb/host/uhci-grlib.c194
-rw-r--r--drivers/usb/host/uhci-hcd.c41
3 files changed, 234 insertions, 7 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 8045988f57a1..8898505af429 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -396,7 +396,7 @@ config USB_OHCI_LITTLE_ENDIAN
396 396
397config USB_UHCI_HCD 397config USB_UHCI_HCD
398 tristate "UHCI HCD (most Intel and VIA) support" 398 tristate "UHCI HCD (most Intel and VIA) support"
399 depends on USB && PCI 399 depends on USB && (PCI || SPARC_LEON)
400 ---help--- 400 ---help---
401 The Universal Host Controller Interface is a standard by Intel for 401 The Universal Host Controller Interface is a standard by Intel for
402 accessing the USB hardware in the PC (which is also called the USB 402 accessing the USB hardware in the PC (which is also called the USB
@@ -405,7 +405,8 @@ config USB_UHCI_HCD
405 with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX, 405 with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
406 i810, i820) conform to this standard. Also all VIA PCI chipsets 406 i810, i820) conform to this standard. Also all VIA PCI chipsets
407 (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro 407 (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
408 133). If unsure, say Y. 408 133) and LEON/GRLIB SoCs with the GRUSBHC controller.
409 If unsure, say Y.
409 410
410 To compile this driver as a module, choose M here: the 411 To compile this driver as a module, choose M here: the
411 module will be called uhci-hcd. 412 module will be called uhci-hcd.
@@ -413,6 +414,7 @@ config USB_UHCI_HCD
413config USB_UHCI_SUPPORT_NON_PCI_HC 414config USB_UHCI_SUPPORT_NON_PCI_HC
414 bool 415 bool
415 depends on USB_UHCI_HCD 416 depends on USB_UHCI_HCD
417 default y if SPARC_LEON
416 418
417config USB_FHCI_HCD 419config USB_FHCI_HCD
418 tristate "Freescale QE USB Host Controller support" 420 tristate "Freescale QE USB Host Controller support"
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
new file mode 100644
index 000000000000..b1addd60a1ef
--- /dev/null
+++ b/drivers/usb/host/uhci-grlib.c
@@ -0,0 +1,194 @@
1/*
2 * UHCI HCD (Host Controller Driver) for GRLIB GRUSBHC
3 *
4 * Copyright (c) 2011 Jan Andersson <jan@gaisler.com>
5 *
6 * This file is based on UHCI PCI HCD:
7 * (C) Copyright 1999 Linus Torvalds
8 * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
9 * (C) Copyright 1999 Randy Dunlap
10 * (C) Copyright 1999 Georg Acher, acher@in.tum.de
11 * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
12 * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
13 * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
14 * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
15 * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
16 * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
17 * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
18 */
19
20#include <linux/of_irq.h>
21#include <linux/of_address.h>
22#include <linux/of_platform.h>
23
24static int uhci_grlib_init(struct usb_hcd *hcd)
25{
26 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
27
28 uhci->rh_numports = uhci_count_ports(hcd);
29
30 /* Set up pointers to to generic functions */
31 uhci->reset_hc = uhci_generic_reset_hc;
32 uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc;
33 /* No special actions need to be taken for the functions below */
34 uhci->configure_hc = NULL;
35 uhci->resume_detect_interrupts_are_broken = NULL;
36 uhci->global_suspend_mode_is_broken = NULL;
37
38 /* Reset if the controller isn't already safely quiescent. */
39 check_and_reset_hc(uhci);
40 return 0;
41}
42
43static const struct hc_driver uhci_grlib_hc_driver = {
44 .description = hcd_name,
45 .product_desc = "GRLIB GRUSBHC UHCI Host Controller",
46 .hcd_priv_size = sizeof(struct uhci_hcd),
47
48 /* Generic hardware linkage */
49 .irq = uhci_irq,
50 .flags = HCD_MEMORY | HCD_USB11,
51
52 /* Basic lifecycle operations */
53 .reset = uhci_grlib_init,
54 .start = uhci_start,
55#ifdef CONFIG_PM
56 .pci_suspend = NULL,
57 .pci_resume = NULL,
58 .bus_suspend = uhci_rh_suspend,
59 .bus_resume = uhci_rh_resume,
60#endif
61 .stop = uhci_stop,
62
63 .urb_enqueue = uhci_urb_enqueue,
64 .urb_dequeue = uhci_urb_dequeue,
65
66 .endpoint_disable = uhci_hcd_endpoint_disable,
67 .get_frame_number = uhci_hcd_get_frame_number,
68
69 .hub_status_data = uhci_hub_status_data,
70 .hub_control = uhci_hub_control,
71};
72
73
74static int __devinit uhci_hcd_grlib_probe(struct platform_device *op)
75{
76 struct device_node *dn = op->dev.of_node;
77 struct usb_hcd *hcd;
78 struct uhci_hcd *uhci = NULL;
79 struct resource res;
80 int irq;
81 int rv;
82
83 if (usb_disabled())
84 return -ENODEV;
85
86 dev_dbg(&op->dev, "initializing GRUSBHC UHCI USB Controller\n");
87
88 rv = of_address_to_resource(dn, 0, &res);
89 if (rv)
90 return rv;
91
92 /* usb_create_hcd requires dma_mask != NULL */
93 op->dev.dma_mask = &op->dev.coherent_dma_mask;
94 hcd = usb_create_hcd(&uhci_grlib_hc_driver, &op->dev,
95 "GRUSBHC UHCI USB");
96 if (!hcd)
97 return -ENOMEM;
98
99 hcd->rsrc_start = res.start;
100 hcd->rsrc_len = res.end - res.start + 1;
101
102 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
103 printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
104 rv = -EBUSY;
105 goto err_rmr;
106 }
107
108 irq = irq_of_parse_and_map(dn, 0);
109 if (irq == NO_IRQ) {
110 printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
111 rv = -EBUSY;
112 goto err_irq;
113 }
114
115 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
116 if (!hcd->regs) {
117 printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
118 rv = -ENOMEM;
119 goto err_ioremap;
120 }
121
122 uhci = hcd_to_uhci(hcd);
123
124 uhci->regs = hcd->regs;
125
126 rv = usb_add_hcd(hcd, irq, 0);
127 if (rv)
128 goto err_uhci;
129
130 return 0;
131
132err_uhci:
133 iounmap(hcd->regs);
134err_ioremap:
135 irq_dispose_mapping(irq);
136err_irq:
137 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
138err_rmr:
139 usb_put_hcd(hcd);
140
141 return rv;
142}
143
144static int uhci_hcd_grlib_remove(struct platform_device *op)
145{
146 struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
147
148 dev_set_drvdata(&op->dev, NULL);
149
150 dev_dbg(&op->dev, "stopping GRLIB GRUSBHC UHCI USB Controller\n");
151
152 usb_remove_hcd(hcd);
153
154 iounmap(hcd->regs);
155 irq_dispose_mapping(hcd->irq);
156 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
157
158 usb_put_hcd(hcd);
159
160 return 0;
161}
162
163/* Make sure the controller is quiescent and that we're not using it
164 * any more. This is mainly for the benefit of programs which, like kexec,
165 * expect the hardware to be idle: not doing DMA or generating IRQs.
166 *
167 * This routine may be called in a damaged or failing kernel. Hence we
168 * do not acquire the spinlock before shutting down the controller.
169 */
170static void uhci_hcd_grlib_shutdown(struct platform_device *op)
171{
172 struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
173
174 uhci_hc_died(hcd_to_uhci(hcd));
175}
176
177static const struct of_device_id uhci_hcd_grlib_of_match[] = {
178 { .name = "GAISLER_UHCI", },
179 { .name = "01_027", },
180 {},
181};
182MODULE_DEVICE_TABLE(of, uhci_hcd_grlib_of_match);
183
184
185static struct platform_driver uhci_grlib_driver = {
186 .probe = uhci_hcd_grlib_probe,
187 .remove = uhci_hcd_grlib_remove,
188 .shutdown = uhci_hcd_grlib_shutdown,
189 .driver = {
190 .name = "grlib-uhci",
191 .owner = THIS_MODULE,
192 .of_match_table = uhci_hcd_grlib_of_match,
193 },
194};
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index cd482fcc05da..79dd822e58d1 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -831,7 +831,19 @@ static int uhci_count_ports(struct usb_hcd *hcd)
831 831
832static const char hcd_name[] = "uhci_hcd"; 832static const char hcd_name[] = "uhci_hcd";
833 833
834#ifdef CONFIG_PCI
834#include "uhci-pci.c" 835#include "uhci-pci.c"
836#define PCI_DRIVER uhci_pci_driver
837#endif
838
839#ifdef CONFIG_SPARC_LEON
840#include "uhci-grlib.c"
841#define PLATFORM_DRIVER uhci_grlib_driver
842#endif
843
844#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER)
845#error "missing bus glue for uhci-hcd"
846#endif
835 847
836static int __init uhci_hcd_init(void) 848static int __init uhci_hcd_init(void)
837{ 849{
@@ -858,13 +870,27 @@ static int __init uhci_hcd_init(void)
858 if (!uhci_up_cachep) 870 if (!uhci_up_cachep)
859 goto up_failed; 871 goto up_failed;
860 872
861 retval = pci_register_driver(&uhci_pci_driver); 873#ifdef PLATFORM_DRIVER
862 if (retval) 874 retval = platform_driver_register(&PLATFORM_DRIVER);
863 goto init_failed; 875 if (retval < 0)
876 goto clean0;
877#endif
878
879#ifdef PCI_DRIVER
880 retval = pci_register_driver(&PCI_DRIVER);
881 if (retval < 0)
882 goto clean1;
883#endif
864 884
865 return 0; 885 return 0;
866 886
867init_failed: 887#ifdef PCI_DRIVER
888clean1:
889#endif
890#ifdef PLATFORM_DRIVER
891 platform_driver_unregister(&PLATFORM_DRIVER);
892clean0:
893#endif
868 kmem_cache_destroy(uhci_up_cachep); 894 kmem_cache_destroy(uhci_up_cachep);
869 895
870up_failed: 896up_failed:
@@ -881,7 +907,12 @@ errbuf_failed:
881 907
882static void __exit uhci_hcd_cleanup(void) 908static void __exit uhci_hcd_cleanup(void)
883{ 909{
884 pci_unregister_driver(&uhci_pci_driver); 910#ifdef PLATFORM_DRIVER
911 platform_driver_unregister(&PLATFORM_DRIVER);
912#endif
913#ifdef PCI_DRIVER
914 pci_unregister_driver(&PCI_DRIVER);
915#endif
885 kmem_cache_destroy(uhci_up_cachep); 916 kmem_cache_destroy(uhci_up_cachep);
886 debugfs_remove(uhci_debugfs_root); 917 debugfs_remove(uhci_debugfs_root);
887 kfree(errbuf); 918 kfree(errbuf);