[PATCH 041/142] USB: gadget: pxa25x: basic transceiver support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Philipp Zabel <philipp.zabel@xxxxxxxxx>

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: Philipp Zabel <philipp.zabel@xxxxxxxxx>
Signed-off-by: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/gadget/pxa25x_udc.c |   49 +++++++++++++++++++++++++++++++++++---
 drivers/usb/gadget/pxa25x_udc.h |    1 +
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index ed21e26..e6fedbd 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -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 @@ fail:
 	 * 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 @@ lubbock_fail0:
 	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;
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
index 1d51aa2..f572c56 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -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];
 
-- 
1.6.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux