mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
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>
This commit is contained in:
parent
4c6e8971cb
commit
ab26d20f3e
2 changed files with 46 additions and 4 deletions
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
Loading…
Reference in a new issue