aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulie Zhu <julie.zhu@xilinx.com>2009-09-21 18:08:19 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:55:13 -0500
commit08d3c18e6674c5d46e4333a462b1e2e4c4ded1d4 (patch)
tree2efb48ceb2b86784b1966d696bd38c03a71ab7a4
parent9eb66f71318df6ab73bad2fb924a36777cf0220e (diff)
USB: Add support for Xilinx USB host controller
Add bus glue driver for Xilinx USB host controller. The controller can be configured as HS only or HS/FS hybrid. The driver uses the device tree file to configure the driver according to the setting in the hardware system. This driver has been tested with usbtest using the NET2280 PCI card. Signed-off-by: Julie Zhu <julie.zhu@xilinx.com> Signed-off-by: John Linn <john.linn@xilinx.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/powerpc/dts-bindings/xilinx.txt11
-rw-r--r--drivers/usb/host/Kconfig15
-rw-r--r--drivers/usb/host/ehci-hcd.c5
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c300
4 files changed, 329 insertions, 2 deletions
diff --git a/Documentation/powerpc/dts-bindings/xilinx.txt b/Documentation/powerpc/dts-bindings/xilinx.txt
index 80339fe4300b..ea68046bb9cb 100644
--- a/Documentation/powerpc/dts-bindings/xilinx.txt
+++ b/Documentation/powerpc/dts-bindings/xilinx.txt
@@ -292,4 +292,15 @@
292 - reg-offset : A value of 3 is required 292 - reg-offset : A value of 3 is required
293 - reg-shift : A value of 2 is required 293 - reg-shift : A value of 2 is required
294 294
295 vii) Xilinx USB Host controller
296
297 The Xilinx USB host controller is EHCI compatible but with a different
298 base address for the EHCI registers, and it is always a big-endian
299 USB Host controller. The hardware can be configured as high speed only,
300 or high speed/full speed hybrid.
301
302 Required properties:
303 - xlnx,support-usb-fs: A value 0 means the core is built as high speed
304 only. A value 1 means the core also supports
305 full speed devices.
295 306
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 9b43b226817f..6d97e039cdbb 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -90,14 +90,25 @@ config USB_EHCI_TT_NEWSCHED
90 90
91config USB_EHCI_BIG_ENDIAN_MMIO 91config USB_EHCI_BIG_ENDIAN_MMIO
92 bool 92 bool
93 depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX) 93 depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
94 default y 94 default y
95 95
96config USB_EHCI_BIG_ENDIAN_DESC 96config USB_EHCI_BIG_ENDIAN_DESC
97 bool 97 bool
98 depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) 98 depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
99 default y 99 default y
100 100
101config XPS_USB_HCD_XILINX
102 bool "Use Xilinx usb host EHCI controller core"
103 depends on USB_EHCI_HCD && (PPC32 || MICROBLAZE)
104 select USB_EHCI_BIG_ENDIAN_DESC
105 select USB_EHCI_BIG_ENDIAN_MMIO
106 ---help---
107 Xilinx xps USB host controller core is EHCI compilant and has
108 transaction translator built-in. It can be configured to either
109 support both high speed and full speed devices, or high speed
110 devices only.
111
101config USB_EHCI_FSL 112config USB_EHCI_FSL
102 bool "Support for Freescale on-chip EHCI USB controller" 113 bool "Support for Freescale on-chip EHCI USB controller"
103 depends on USB_EHCI_HCD && FSL_SOC 114 depends on USB_EHCI_HCD && FSL_SOC
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d8f4aaa616f2..e2afb2b5faf8 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1120,6 +1120,11 @@ MODULE_LICENSE ("GPL");
1120#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver 1120#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
1121#endif 1121#endif
1122 1122
1123#ifdef CONFIG_XPS_USB_HCD_XILINX
1124#include "ehci-xilinx-of.c"
1125#define OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
1126#endif
1127
1123#ifdef CONFIG_PLAT_ORION 1128#ifdef CONFIG_PLAT_ORION
1124#include "ehci-orion.c" 1129#include "ehci-orion.c"
1125#define PLATFORM_DRIVER ehci_orion_driver 1130#define PLATFORM_DRIVER ehci_orion_driver
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
new file mode 100644
index 000000000000..a5861531ad3e
--- /dev/null
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -0,0 +1,300 @@
1/*
2 * EHCI HCD (Host Controller Driver) for USB.
3 *
4 * Bus Glue for Xilinx EHCI core on the of_platform bus
5 *
6 * Copyright (c) 2009 Xilinx, Inc.
7 *
8 * Based on "ehci-ppc-of.c" by Valentine Barshak <vbarshak@ru.mvista.com>
9 * and "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
10 * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 */
27
28#include <linux/signal.h>
29
30#include <linux/of.h>
31#include <linux/of_platform.h>
32
33/**
34 * ehci_xilinx_of_setup - Initialize the device for ehci_reset()
35 * @hcd: Pointer to the usb_hcd device to which the host controller bound
36 *
37 * called during probe() after chip reset completes.
38 */
39static int ehci_xilinx_of_setup(struct usb_hcd *hcd)
40{
41 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
42 int retval;
43
44 retval = ehci_halt(ehci);
45 if (retval)
46 return retval;
47
48 retval = ehci_init(hcd);
49 if (retval)
50 return retval;
51
52 ehci->sbrn = 0x20;
53
54 return ehci_reset(ehci);
55}
56
57/**
58 * ehci_xilinx_port_handed_over - hand the port out if failed to enable it
59 * @hcd: Pointer to the usb_hcd device to which the host controller bound
60 * @portnum:Port number to which the device is attached.
61 *
62 * This function is used as a place to tell the user that the Xilinx USB host
63 * controller does support LS devices. And in an HS only configuration, it
64 * does not support FS devices either. It is hoped that this can help a
65 * confused user.
66 *
67 * There are cases when the host controller fails to enable the port due to,
68 * for example, insufficient power that can be supplied to the device from
69 * the USB bus. In those cases, the messages printed here are not helpful.
70 */
71static int ehci_xilinx_port_handed_over(struct usb_hcd *hcd, int portnum)
72{
73 dev_warn(hcd->self.controller, "port %d cannot be enabled\n", portnum);
74 if (hcd->has_tt) {
75 dev_warn(hcd->self.controller,
76 "Maybe you have connected a low speed device?\n");
77
78 dev_warn(hcd->self.controller,
79 "We do not support low speed devices\n");
80 } else {
81 dev_warn(hcd->self.controller,
82 "Maybe your device is not a high speed device?\n");
83 dev_warn(hcd->self.controller,
84 "The USB host controller does not support full speed "
85 "nor low speed devices\n");
86 dev_warn(hcd->self.controller,
87 "You can reconfigure the host controller to have "
88 "full speed support\n");
89 }
90
91 return 0;
92}
93
94
95static const struct hc_driver ehci_xilinx_of_hc_driver = {
96 .description = hcd_name,
97 .product_desc = "OF EHCI",
98 .hcd_priv_size = sizeof(struct ehci_hcd),
99
100 /*
101 * generic hardware linkage
102 */
103 .irq = ehci_irq,
104 .flags = HCD_MEMORY | HCD_USB2,
105
106 /*
107 * basic lifecycle operations
108 */
109 .reset = ehci_xilinx_of_setup,
110 .start = ehci_run,
111 .stop = ehci_stop,
112 .shutdown = ehci_shutdown,
113
114 /*
115 * managing i/o requests and associated device resources
116 */
117 .urb_enqueue = ehci_urb_enqueue,
118 .urb_dequeue = ehci_urb_dequeue,
119 .endpoint_disable = ehci_endpoint_disable,
120
121 /*
122 * scheduling support
123 */
124 .get_frame_number = ehci_get_frame,
125
126 /*
127 * root hub support
128 */
129 .hub_status_data = ehci_hub_status_data,
130 .hub_control = ehci_hub_control,
131#ifdef CONFIG_PM
132 .bus_suspend = ehci_bus_suspend,
133 .bus_resume = ehci_bus_resume,
134#endif
135 .relinquish_port = NULL,
136 .port_handed_over = ehci_xilinx_port_handed_over,
137
138 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
139};
140
141/**
142 * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller
143 * @op: pointer to the of_device to which the host controller bound
144 * @match: pointer to of_device_id structure, not used
145 *
146 * This function requests resources and sets up appropriate properties for the
147 * host controller. Because the Xilinx USB host controller can be configured
148 * as HS only or HS/FS only, it checks the configuration in the device tree
149 * entry, and sets an appropriate value for hcd->has_tt.
150 */
151static int __devinit
152ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match)
153{
154 struct device_node *dn = op->node;
155 struct usb_hcd *hcd;
156 struct ehci_hcd *ehci;
157 struct resource res;
158 int irq;
159 int rv;
160 int *value;
161
162 if (usb_disabled())
163 return -ENODEV;
164
165 dev_dbg(&op->dev, "initializing XILINX-OF USB Controller\n");
166
167 rv = of_address_to_resource(dn, 0, &res);
168 if (rv)
169 return rv;
170
171 hcd = usb_create_hcd(&ehci_xilinx_of_hc_driver, &op->dev,
172 "XILINX-OF USB");
173 if (!hcd)
174 return -ENOMEM;
175
176 hcd->rsrc_start = res.start;
177 hcd->rsrc_len = res.end - res.start + 1;
178
179 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
180 printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
181 rv = -EBUSY;
182 goto err_rmr;
183 }
184
185 irq = irq_of_parse_and_map(dn, 0);
186 if (irq == NO_IRQ) {
187 printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
188 rv = -EBUSY;
189 goto err_irq;
190 }
191
192 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
193 if (!hcd->regs) {
194 printk(KERN_ERR __FILE__ ": ioremap failed\n");
195 rv = -ENOMEM;
196 goto err_ioremap;
197 }
198
199 ehci = hcd_to_ehci(hcd);
200
201 /* This core always has big-endian register interface and uses
202 * big-endian memory descriptors.
203 */
204 ehci->big_endian_mmio = 1;
205 ehci->big_endian_desc = 1;
206
207 /* Check whether the FS support option is selected in the hardware.
208 */
209 value = (int *)of_get_property(dn, "xlnx,support-usb-fs", NULL);
210 if (value && (*value == 1)) {
211 ehci_dbg(ehci, "USB host controller supports FS devices\n");
212 hcd->has_tt = 1;
213 } else {
214 ehci_dbg(ehci,
215 "USB host controller is HS only\n");
216 hcd->has_tt = 0;
217 }
218
219 /* Debug registers are at the first 0x100 region
220 */
221 ehci->caps = hcd->regs + 0x100;
222 ehci->regs = hcd->regs + 0x100 +
223 HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
224
225 /* cache this readonly data; minimize chip reads */
226 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
227
228 rv = usb_add_hcd(hcd, irq, 0);
229 if (rv == 0)
230 return 0;
231
232 iounmap(hcd->regs);
233
234err_ioremap:
235err_irq:
236 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
237err_rmr:
238 usb_put_hcd(hcd);
239
240 return rv;
241}
242
243/**
244 * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources
245 * @op: pointer to of_device structure that is to be removed
246 *
247 * Remove the hcd structure, and release resources that has been requested
248 * during probe.
249 */
250static int ehci_hcd_xilinx_of_remove(struct of_device *op)
251{
252 struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
253 dev_set_drvdata(&op->dev, NULL);
254
255 dev_dbg(&op->dev, "stopping XILINX-OF USB Controller\n");
256
257 usb_remove_hcd(hcd);
258
259 iounmap(hcd->regs);
260 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
261
262 usb_put_hcd(hcd);
263
264 return 0;
265}
266
267/**
268 * ehci_hcd_xilinx_of_shutdown - shutdown the hcd
269 * @op: pointer to of_device structure that is to be removed
270 *
271 * Properly shutdown the hcd, call driver's shutdown routine.
272 */
273static int ehci_hcd_xilinx_of_shutdown(struct of_device *op)
274{
275 struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
276
277 if (hcd->driver->shutdown)
278 hcd->driver->shutdown(hcd);
279
280 return 0;
281}
282
283
284static struct of_device_id ehci_hcd_xilinx_of_match[] = {
285 {.compatible = "xlnx,xps-usb-host-1.00.a",},
286 {},
287};
288MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
289
290static struct of_platform_driver ehci_hcd_xilinx_of_driver = {
291 .name = "xilinx-of-ehci",
292 .match_table = ehci_hcd_xilinx_of_match,
293 .probe = ehci_hcd_xilinx_of_probe,
294 .remove = ehci_hcd_xilinx_of_remove,
295 .shutdown = ehci_hcd_xilinx_of_shutdown,
296 .driver = {
297 .name = "xilinx-of-ehci",
298 .owner = THIS_MODULE,
299 },
300};