Commit b799a7eb authored by Robert Jarzmik's avatar Robert Jarzmik Committed by Greg Kroah-Hartman

USB: pxa27x_udc: add vbus session handling

On vbus_session() call, optionally activate D+ pullup
resistor and enable the udc, or deactivate D+ pullup
resistor and disable the udc.

It is intentional to not handle any VBus sense related irq.
An external transceiver driver (like gpio_vbus) should
catch VBus sense signal, and call usb_gadget_vbus_connect()
or usb_gadget_vbus_disconnect().
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 eb507025
...@@ -1536,8 +1536,10 @@ static void udc_disable(struct pxa_udc *udc); ...@@ -1536,8 +1536,10 @@ static void udc_disable(struct pxa_udc *udc);
* Context: any * Context: any
* *
* The UDC should be enabled if : * The UDC should be enabled if :
* - the pullup resistor is connected * - the pullup resistor is connected
* - and a gadget driver is bound * - and a gadget driver is bound
* - and vbus is sensed (or no vbus sense is available)
* *
* Returns 1 if UDC should be enabled, 0 otherwise * Returns 1 if UDC should be enabled, 0 otherwise
*/ */
...@@ -1546,6 +1548,7 @@ static int should_enable_udc(struct pxa_udc *udc) ...@@ -1546,6 +1548,7 @@ static int should_enable_udc(struct pxa_udc *udc)
int put_on; int put_on;
put_on = ((udc->pullup_on) && (udc->driver)); put_on = ((udc->pullup_on) && (udc->driver));
put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
return put_on; return put_on;
} }
...@@ -1557,6 +1560,7 @@ static int should_enable_udc(struct pxa_udc *udc) ...@@ -1557,6 +1560,7 @@ static int should_enable_udc(struct pxa_udc *udc)
* The UDC should be disabled if : * The UDC should be disabled if :
* - the pullup resistor is not connected * - the pullup resistor is not connected
* - or no gadget driver is bound * - or no gadget driver is bound
* - or no vbus is sensed (when vbus sesing is available)
* *
* Returns 1 if UDC should be disabled * Returns 1 if UDC should be disabled
*/ */
...@@ -1565,6 +1569,7 @@ static int should_disable_udc(struct pxa_udc *udc) ...@@ -1565,6 +1569,7 @@ static int should_disable_udc(struct pxa_udc *udc)
int put_off; int put_off;
put_off = ((!udc->pullup_on) || (!udc->driver)); put_off = ((!udc->pullup_on) || (!udc->driver));
put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
return put_off; return put_off;
} }
...@@ -1592,10 +1597,37 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) ...@@ -1592,10 +1597,37 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
return 0; return 0;
} }
static void udc_enable(struct pxa_udc *udc);
static void udc_disable(struct pxa_udc *udc);
/**
* pxa_udc_vbus_session - Called by external transceiver to enable/disable udc
* @_gadget: usb gadget
* @is_active: 0 if should disable the udc, 1 if should enable
*
* Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the
* udc, and deactivates D+ pullup resistor.
*
* Returns 0
*/
static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{
struct pxa_udc *udc = to_gadget_udc(_gadget);
udc->vbus_sensed = is_active;
if (should_enable_udc(udc))
udc_enable(udc);
if (should_disable_udc(udc))
udc_disable(udc);
return 0;
}
static const struct usb_gadget_ops pxa_udc_ops = { static const struct usb_gadget_ops pxa_udc_ops = {
.get_frame = pxa_udc_get_frame, .get_frame = pxa_udc_get_frame,
.wakeup = pxa_udc_wakeup, .wakeup = pxa_udc_wakeup,
.pullup = pxa_udc_pullup, .pullup = pxa_udc_pullup,
.vbus_session = pxa_udc_vbus_session,
/* current versions must always be self-powered */ /* current versions must always be self-powered */
}; };
...@@ -2357,6 +2389,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) ...@@ -2357,6 +2389,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
device_initialize(&udc->gadget.dev); device_initialize(&udc->gadget.dev);
udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = NULL; udc->gadget.dev.dma_mask = NULL;
udc->vbus_sensed = 0;
the_controller = udc; the_controller = udc;
platform_set_drvdata(pdev, udc); platform_set_drvdata(pdev, udc);
......
...@@ -456,6 +456,7 @@ struct pxa_udc { ...@@ -456,6 +456,7 @@ struct pxa_udc {
unsigned enabled:1; unsigned enabled:1;
unsigned pullup_on:1; unsigned pullup_on:1;
unsigned pullup_resume:1; unsigned pullup_resume:1;
unsigned vbus_sensed:1;
unsigned config:2; unsigned config:2;
unsigned last_interface:3; unsigned last_interface:3;
unsigned last_alternate:3; unsigned last_alternate:3;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment