aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorPhilipp Zabel <philipp.zabel@gmail.com>2009-07-01 06:46:25 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:23 -0400
commitab26d20f3ef1105d889f702cd01fba8c6fb32f73 (patch)
treeafe07b1938e05f83b5824feaa3a4d8e6d8bdce64 /drivers/usb/gadget
parent4c6e8971cbe0148085fcf6fd30eaa3c39f8a8cce (diff)
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: Philipp Zabel <philipp.zabel@gmail.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c49
-rw-r--r--drivers/usb/gadget/pxa25x_udc.h1
2 files changed, 46 insertions, 4 deletions
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index ed21e263f832..e6fedbd5a654 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -56,6 +56,7 @@
56 56
57#include <linux/usb/ch9.h> 57#include <linux/usb/ch9.h>
58#include <linux/usb/gadget.h> 58#include <linux/usb/gadget.h>
59#include <linux/usb/otg.h>
59 60
60/* 61/*
61 * This driver is PXA25x only. Grab the right register definitions. 62 * 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)
1008 return 0; 1009 return 0;
1009} 1010}
1010 1011
1012/* boards may consume current from VBUS, up to 100-500mA based on config.
1013 * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs
1014 * violate USB specs.
1015 */
1016static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
1017{
1018 struct pxa25x_udc *udc;
1019
1020 udc = container_of(_gadget, struct pxa25x_udc, gadget);
1021
1022 if (udc->transceiver)
1023 return otg_set_power(udc->transceiver, mA);
1024 return -EOPNOTSUPP;
1025}
1026
1011static const struct usb_gadget_ops pxa25x_udc_ops = { 1027static const struct usb_gadget_ops pxa25x_udc_ops = {
1012 .get_frame = pxa25x_udc_get_frame, 1028 .get_frame = pxa25x_udc_get_frame,
1013 .wakeup = pxa25x_udc_wakeup, 1029 .wakeup = pxa25x_udc_wakeup,
1014 .vbus_session = pxa25x_udc_vbus_session, 1030 .vbus_session = pxa25x_udc_vbus_session,
1015 .pullup = pxa25x_udc_pullup, 1031 .pullup = pxa25x_udc_pullup,
1016 1032 .vbus_draw = pxa25x_udc_vbus_draw,
1017 // .vbus_draw ... boards may consume current from VBUS, up to
1018 // 100-500mA based on config. the 500uA suspend ceiling means
1019 // that exclusively vbus-powered PXA designs violate USB specs.
1020}; 1033};
1021 1034
1022/*-------------------------------------------------------------------------*/ 1035/*-------------------------------------------------------------------------*/
@@ -1303,9 +1316,23 @@ fail:
1303 * for set_configuration as well as eventual disconnect. 1316 * for set_configuration as well as eventual disconnect.
1304 */ 1317 */
1305 DMSG("registered gadget driver '%s'\n", driver->driver.name); 1318 DMSG("registered gadget driver '%s'\n", driver->driver.name);
1319
1320 /* connect to bus through transceiver */
1321 if (dev->transceiver) {
1322 retval = otg_set_peripheral(dev->transceiver, &dev->gadget);
1323 if (retval) {
1324 DMSG("can't bind to transceiver\n");
1325 if (driver->unbind)
1326 driver->unbind(&dev->gadget);
1327 goto bind_fail;
1328 }
1329 }
1330
1306 pullup(dev); 1331 pullup(dev);
1307 dump_state(dev); 1332 dump_state(dev);
1308 return 0; 1333 return 0;
1334bind_fail:
1335 return retval;
1309} 1336}
1310EXPORT_SYMBOL(usb_gadget_register_driver); 1337EXPORT_SYMBOL(usb_gadget_register_driver);
1311 1338
@@ -1351,6 +1378,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1351 stop_activity(dev, driver); 1378 stop_activity(dev, driver);
1352 local_irq_enable(); 1379 local_irq_enable();
1353 1380
1381 if (dev->transceiver)
1382 (void) otg_set_peripheral(dev->transceiver, NULL);
1383
1354 driver->unbind(&dev->gadget); 1384 driver->unbind(&dev->gadget);
1355 dev->gadget.dev.driver = NULL; 1385 dev->gadget.dev.driver = NULL;
1356 dev->driver = NULL; 1386 dev->driver = NULL;
@@ -2162,6 +2192,8 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
2162 dev->dev = &pdev->dev; 2192 dev->dev = &pdev->dev;
2163 dev->mach = pdev->dev.platform_data; 2193 dev->mach = pdev->dev.platform_data;
2164 2194
2195 dev->transceiver = otg_get_transceiver();
2196
2165 if (gpio_is_valid(dev->mach->gpio_vbus)) { 2197 if (gpio_is_valid(dev->mach->gpio_vbus)) {
2166 if ((retval = gpio_request(dev->mach->gpio_vbus, 2198 if ((retval = gpio_request(dev->mach->gpio_vbus,
2167 "pxa25x_udc GPIO VBUS"))) { 2199 "pxa25x_udc GPIO VBUS"))) {
@@ -2264,6 +2296,10 @@ lubbock_fail0:
2264 if (gpio_is_valid(dev->mach->gpio_vbus)) 2296 if (gpio_is_valid(dev->mach->gpio_vbus))
2265 gpio_free(dev->mach->gpio_vbus); 2297 gpio_free(dev->mach->gpio_vbus);
2266 err_gpio_vbus: 2298 err_gpio_vbus:
2299 if (dev->transceiver) {
2300 otg_put_transceiver(dev->transceiver);
2301 dev->transceiver = NULL;
2302 }
2267 clk_put(dev->clk); 2303 clk_put(dev->clk);
2268 err_clk: 2304 err_clk:
2269 return retval; 2305 return retval;
@@ -2305,6 +2341,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
2305 2341
2306 clk_put(dev->clk); 2342 clk_put(dev->clk);
2307 2343
2344 if (dev->transceiver) {
2345 otg_put_transceiver(dev->transceiver);
2346 dev->transceiver = NULL;
2347 }
2348
2308 platform_set_drvdata(pdev, NULL); 2349 platform_set_drvdata(pdev, NULL);
2309 the_controller = NULL; 2350 the_controller = NULL;
2310 return 0; 2351 return 0;
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
index 1d51aa21e6eb..f572c5617462 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -128,6 +128,7 @@ struct pxa25x_udc {
128 struct device *dev; 128 struct device *dev;
129 struct clk *clk; 129 struct clk *clk;
130 struct pxa2xx_udc_mach_info *mach; 130 struct pxa2xx_udc_mach_info *mach;
131 struct otg_transceiver *transceiver;
131 u64 dma_mask; 132 u64 dma_mask;
132 struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; 133 struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS];
133 134