Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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.
+18 −1
Original line number Diff line number Diff line
@@ -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:
@@ -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);
@@ -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)) {
@@ -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);
+3 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/usb/otg.h>

/*
 * Register definitions
@@ -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
@@ -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;