Skip to content

Commit

Permalink
USB: pxa27x_udc: add otg transceiver support
Browse files Browse the repository at this point in the history
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: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Robert Jarzmik authored and Greg Kroah-Hartman committed Mar 24, 2009
1 parent b799a7e commit 7fec3c2
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/usb/gadget/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ config USB_PXA25X_SMALL
config USB_GADGET_PXA27X
boolean "PXA 27x"
depends on ARCH_PXA && PXA27x
select USB_OTG_UTILS
help
Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller.
Expand Down
19 changes: 18 additions & 1 deletion drivers/usb/gadget/pxa27x_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1779,10 +1779,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
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))
udc_enable(udc);
return 0;

transceiver_fail:
if (driver->unbind)
driver->unbind(&udc->gadget);
bind_fail:
device_del(&udc->gadget.dev);
add_fail:
Expand Down Expand Up @@ -1840,9 +1851,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc->driver = NULL;

device_del(&udc->gadget.dev);

dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);

if (udc->transceiver)
return otg_set_peripheral(udc->transceiver, NULL);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
Expand Down Expand Up @@ -2359,6 +2372,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)

udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data;
udc->transceiver = otg_get_transceiver();

gpio = udc->mach->gpio_pullup;
if (gpio_is_valid(gpio)) {
Expand Down Expand Up @@ -2431,6 +2445,9 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
if (gpio_is_valid(gpio))
gpio_free(gpio);

otg_put_transceiver(udc->transceiver);

udc->transceiver = NULL;
platform_set_drvdata(_dev, NULL);
the_controller = NULL;
clk_put(udc->clk);
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/gadget/pxa27x_udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/usb/otg.h>

/*
* Register definitions
Expand Down Expand Up @@ -421,6 +422,7 @@ struct udc_stats {
* @driver: bound gadget (zero, g_ether, g_file_storage, ...)
* @dev: device
* @mach: machine info, used to activate specific GPIO
* @transceiver: external transceiver to handle vbus sense and D+ pullup
* @ep0state: control endpoint state machine state
* @stats: statistics on udc usage
* @udc_usb_ep: array of usb endpoints offered by the gadget
Expand All @@ -446,6 +448,7 @@ struct pxa_udc {
struct usb_gadget_driver *driver;
struct device *dev;
struct pxa2xx_udc_mach_info *mach;
struct otg_transceiver *transceiver;

enum ep0_state ep0state;
struct udc_stats stats;
Expand Down

0 comments on commit 7fec3c2

Please sign in to comment.