Commit 7fec3c25 authored by Robert Jarzmik's avatar Robert Jarzmik Committed by Greg Kroah-Hartman

USB: pxa27x_udc: add otg transceiver support

When a transceiver driver is used, no automatic udc enable
is done. The transceiver (OTG or not) should :
 - take care of VBus sensing
 - call usb_gadget_vbus_connect()
 - call usb_gadget_vbus_disconnect()

The pullup should remain within this driver's management,
either by gpio_pullup of udc_command() fields.
Signed-off-by: default avatarRobert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b799a7eb
...@@ -254,6 +254,7 @@ config USB_PXA25X_SMALL ...@@ -254,6 +254,7 @@ config USB_PXA25X_SMALL
config USB_GADGET_PXA27X config USB_GADGET_PXA27X
boolean "PXA 27x" boolean "PXA 27x"
depends on ARCH_PXA && PXA27x depends on ARCH_PXA && PXA27x
select USB_OTG_UTILS
help help
Intel's PXA 27x series XScale ARM v5TE processors include Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller. an integrated full speed USB 1.1 device controller.
......
...@@ -1779,10 +1779,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) ...@@ -1779,10 +1779,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev_dbg(udc->dev, "registered gadget driver '%s'\n", dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name); driver->driver.name);
if (udc->transceiver) {
retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
if (retval) {
dev_err(udc->dev, "can't bind to transceiver\n");
goto transceiver_fail;
}
}
if (should_enable_udc(udc)) if (should_enable_udc(udc))
udc_enable(udc); udc_enable(udc);
return 0; return 0;
transceiver_fail:
if (driver->unbind)
driver->unbind(&udc->gadget);
bind_fail: bind_fail:
device_del(&udc->gadget.dev); device_del(&udc->gadget.dev);
add_fail: add_fail:
...@@ -1840,9 +1851,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ...@@ -1840,9 +1851,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc->driver = NULL; udc->driver = NULL;
device_del(&udc->gadget.dev); device_del(&udc->gadget.dev);
dev_info(udc->dev, "unregistered gadget driver '%s'\n", dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name); driver->driver.name);
if (udc->transceiver)
return otg_set_peripheral(udc->transceiver, NULL);
return 0; return 0;
} }
EXPORT_SYMBOL(usb_gadget_unregister_driver); EXPORT_SYMBOL(usb_gadget_unregister_driver);
...@@ -2359,6 +2372,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) ...@@ -2359,6 +2372,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
udc->dev = &pdev->dev; udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data; udc->mach = pdev->dev.platform_data;
udc->transceiver = otg_get_transceiver();
gpio = udc->mach->gpio_pullup; gpio = udc->mach->gpio_pullup;
if (gpio_is_valid(gpio)) { if (gpio_is_valid(gpio)) {
...@@ -2431,6 +2445,9 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) ...@@ -2431,6 +2445,9 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
if (gpio_is_valid(gpio)) if (gpio_is_valid(gpio))
gpio_free(gpio); gpio_free(gpio);
otg_put_transceiver(udc->transceiver);
udc->transceiver = NULL;
platform_set_drvdata(_dev, NULL); platform_set_drvdata(_dev, NULL);
the_controller = NULL; the_controller = NULL;
clk_put(udc->clk); clk_put(udc->clk);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/usb/otg.h>
/* /*
* Register definitions * Register definitions
...@@ -421,6 +422,7 @@ struct udc_stats { ...@@ -421,6 +422,7 @@ struct udc_stats {
* @driver: bound gadget (zero, g_ether, g_file_storage, ...) * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
* @dev: device * @dev: device
* @mach: machine info, used to activate specific GPIO * @mach: machine info, used to activate specific GPIO
* @transceiver: external transceiver to handle vbus sense and D+ pullup
* @ep0state: control endpoint state machine state * @ep0state: control endpoint state machine state
* @stats: statistics on udc usage * @stats: statistics on udc usage
* @udc_usb_ep: array of usb endpoints offered by the gadget * @udc_usb_ep: array of usb endpoints offered by the gadget
...@@ -446,6 +448,7 @@ struct pxa_udc { ...@@ -446,6 +448,7 @@ struct pxa_udc {
struct usb_gadget_driver *driver; struct usb_gadget_driver *driver;
struct device *dev; struct device *dev;
struct pxa2xx_udc_mach_info *mach; struct pxa2xx_udc_mach_info *mach;
struct otg_transceiver *transceiver;
enum ep0_state ep0state; enum ep0_state ep0state;
struct udc_stats stats; struct udc_stats stats;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment