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

Commit ab26d20f authored by Philipp Zabel's avatar Philipp Zabel Committed by Greg Kroah-Hartman
Browse files

USB: gadget: pxa25x: basic transceiver support



This adds very basic otg_transceiver support, with vbus_session
and vbus_draw callbacks.

Now VBUS sensing can be handled by an external driver which registers
the otg_transceiver interface. It also allows gadget drivers to configure
the current drawn from VBUS. The UDC driver just passes their requests
along to the transceiver driver.

Signed-off-by: default avatarPhilipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4c6e8971
Loading
Loading
Loading
Loading
+45 −4
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@

#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>

/*
 * This driver is PXA25x only.  Grab the right register definitions.
@@ -1008,15 +1009,27 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
	return 0;
}

/* boards may consume current from VBUS, up to 100-500mA based on config.
 * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs
 * violate USB specs.
 */
static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
{
	struct pxa25x_udc	*udc;

	udc = container_of(_gadget, struct pxa25x_udc, gadget);

	if (udc->transceiver)
		return otg_set_power(udc->transceiver, mA);
	return -EOPNOTSUPP;
}

static const struct usb_gadget_ops pxa25x_udc_ops = {
	.get_frame	= pxa25x_udc_get_frame,
	.wakeup		= pxa25x_udc_wakeup,
	.vbus_session	= pxa25x_udc_vbus_session,
	.pullup		= pxa25x_udc_pullup,

	// .vbus_draw ... boards may consume current from VBUS, up to
	// 100-500mA based on config.  the 500uA suspend ceiling means
	// that exclusively vbus-powered PXA designs violate USB specs.
	.vbus_draw	= pxa25x_udc_vbus_draw,
};

/*-------------------------------------------------------------------------*/
@@ -1303,9 +1316,23 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
	 * for set_configuration as well as eventual disconnect.
	 */
	DMSG("registered gadget driver '%s'\n", driver->driver.name);

	/* connect to bus through transceiver */
	if (dev->transceiver) {
		retval = otg_set_peripheral(dev->transceiver, &dev->gadget);
		if (retval) {
			DMSG("can't bind to transceiver\n");
			if (driver->unbind)
				driver->unbind(&dev->gadget);
			goto bind_fail;
		}
	}

	pullup(dev);
	dump_state(dev);
	return 0;
bind_fail:
	return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);

@@ -1351,6 +1378,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
	stop_activity(dev, driver);
	local_irq_enable();

	if (dev->transceiver)
		(void) otg_set_peripheral(dev->transceiver, NULL);

	driver->unbind(&dev->gadget);
	dev->gadget.dev.driver = NULL;
	dev->driver = NULL;
@@ -2162,6 +2192,8 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
	dev->dev = &pdev->dev;
	dev->mach = pdev->dev.platform_data;

	dev->transceiver = otg_get_transceiver();

	if (gpio_is_valid(dev->mach->gpio_vbus)) {
		if ((retval = gpio_request(dev->mach->gpio_vbus,
				"pxa25x_udc GPIO VBUS"))) {
@@ -2264,6 +2296,10 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
	if (gpio_is_valid(dev->mach->gpio_vbus))
		gpio_free(dev->mach->gpio_vbus);
 err_gpio_vbus:
	if (dev->transceiver) {
		otg_put_transceiver(dev->transceiver);
		dev->transceiver = NULL;
	}
	clk_put(dev->clk);
 err_clk:
	return retval;
@@ -2305,6 +2341,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)

	clk_put(dev->clk);

	if (dev->transceiver) {
		otg_put_transceiver(dev->transceiver);
		dev->transceiver = NULL;
	}

	platform_set_drvdata(pdev, NULL);
	the_controller = NULL;
	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ struct pxa25x_udc {
	struct device				*dev;
	struct clk				*clk;
	struct pxa2xx_udc_mach_info		*mach;
	struct otg_transceiver			*transceiver;
	u64					dma_mask;
	struct pxa25x_ep			ep [PXA_UDC_NUM_ENDPOINTS];