diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2009-04-21 23:34:44 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:42 -0400 |
commit | 9f5351b743716c796d13235651699fb4ec7aa64f (patch) | |
tree | d8cfe409a56f89e3753fd6f82cd38beddb3d4244 | |
parent | f6d529f936672d341fab14ffb0d8eebeee2d8cd3 (diff) |
USB: pxa27x_udc: compatibility with pxa320 SoC
Got pxa27x_udc working on the pxa320 Nomad platform. The
problem was that the pxa3xx UDC is not quite compatible with
the pxa27x UDC in how it handles back-to-back control
packets. The pxa27x probably drops them by default, but the
pxa320 does not, and you have to detect it and set the OPC
bit to clear the zero-length packet.
Signed-off-by: Aric Blumer <aric@sdgsystems.com>
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/gadget/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa27x_udc.c | 13 |
2 files changed, 13 insertions, 2 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 080bb1e4b847..772dd3b9bab9 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -253,7 +253,7 @@ config USB_PXA25X_SMALL | |||
253 | 253 | ||
254 | config USB_GADGET_PXA27X | 254 | config USB_GADGET_PXA27X |
255 | boolean "PXA 27x" | 255 | boolean "PXA 27x" |
256 | depends on ARCH_PXA && PXA27x | 256 | depends on ARCH_PXA && (PXA27x || PXA3xx) |
257 | select USB_OTG_UTILS | 257 | select USB_OTG_UTILS |
258 | help | 258 | help |
259 | Intel's PXA 27x series XScale ARM v5TE processors include | 259 | Intel's PXA 27x series XScale ARM v5TE processors include |
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index ffe6e0afc2ee..51790b06b8ca 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c | |||
@@ -1892,6 +1892,15 @@ static void handle_ep0_ctrl_req(struct pxa_udc *udc, | |||
1892 | 1892 | ||
1893 | nuke(ep, -EPROTO); | 1893 | nuke(ep, -EPROTO); |
1894 | 1894 | ||
1895 | /* | ||
1896 | * In the PXA320 manual, in the section about Back-to-Back setup | ||
1897 | * packets, it describes this situation. The solution is to set OPC to | ||
1898 | * get rid of the status packet, and then continue with the setup | ||
1899 | * packet. Generalize to pxa27x CPUs. | ||
1900 | */ | ||
1901 | if (epout_has_pkt(ep) && (ep_count_bytes_remain(ep) == 0)) | ||
1902 | udc_ep_writel(ep, UDCCSR, UDCCSR0_OPC); | ||
1903 | |||
1895 | /* read SETUP packet */ | 1904 | /* read SETUP packet */ |
1896 | for (i = 0; i < 2; i++) { | 1905 | for (i = 0; i < 2; i++) { |
1897 | if (unlikely(ep_is_empty(ep))) | 1906 | if (unlikely(ep_is_empty(ep))) |
@@ -1965,6 +1974,8 @@ stall: | |||
1965 | * cleared by software. | 1974 | * cleared by software. |
1966 | * - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it | 1975 | * - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it |
1967 | * before reading ep0. | 1976 | * before reading ep0. |
1977 | * This is true only for PXA27x. This is not true anymore for PXA3xx family | ||
1978 | * (check Back-to-Back setup packet in developers guide). | ||
1968 | * - irq can be called on a "packet complete" event (opc_irq=1), while | 1979 | * - irq can be called on a "packet complete" event (opc_irq=1), while |
1969 | * UDCCSR0_OPC is not yet raised (delta can be as big as 100ms | 1980 | * UDCCSR0_OPC is not yet raised (delta can be as big as 100ms |
1970 | * from experimentation). | 1981 | * from experimentation). |
@@ -2575,7 +2586,7 @@ static struct platform_driver udc_driver = { | |||
2575 | 2586 | ||
2576 | static int __init udc_init(void) | 2587 | static int __init udc_init(void) |
2577 | { | 2588 | { |
2578 | if (!cpu_is_pxa27x()) | 2589 | if (!cpu_is_pxa27x() && !cpu_is_pxa3xx()) |
2579 | return -ENODEV; | 2590 | return -ENODEV; |
2580 | 2591 | ||
2581 | printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); | 2592 | printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); |