aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2009-01-25 02:56:42 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-24 19:20:26 -0400
commitb799a7eb68082af620b7e37b6f41c98802e831f6 (patch)
tree3e03ef6d83eac47675ccb673432a862de29578f2 /drivers
parenteb50702539f9be3765127d927d3e9ccfeb65f26e (diff)
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: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c33
-rw-r--r--drivers/usb/gadget/pxa27x_udc.h1
2 files changed, 34 insertions, 0 deletions
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index f8145590944f..0c9307118b54 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1536,8 +1536,10 @@ static void udc_disable(struct pxa_udc *udc);
1536 * Context: any 1536 * Context: any
1537 * 1537 *
1538 * The UDC should be enabled if : 1538 * The UDC should be enabled if :
1539
1539 * - the pullup resistor is connected 1540 * - the pullup resistor is connected
1540 * - and a gadget driver is bound 1541 * - and a gadget driver is bound
1542 * - and vbus is sensed (or no vbus sense is available)
1541 * 1543 *
1542 * Returns 1 if UDC should be enabled, 0 otherwise 1544 * Returns 1 if UDC should be enabled, 0 otherwise
1543 */ 1545 */
@@ -1546,6 +1548,7 @@ static int should_enable_udc(struct pxa_udc *udc)
1546 int put_on; 1548 int put_on;
1547 1549
1548 put_on = ((udc->pullup_on) && (udc->driver)); 1550 put_on = ((udc->pullup_on) && (udc->driver));
1551 put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
1549 return put_on; 1552 return put_on;
1550} 1553}
1551 1554
@@ -1557,6 +1560,7 @@ static int should_enable_udc(struct pxa_udc *udc)
1557 * The UDC should be disabled if : 1560 * The UDC should be disabled if :
1558 * - the pullup resistor is not connected 1561 * - the pullup resistor is not connected
1559 * - or no gadget driver is bound 1562 * - or no gadget driver is bound
1563 * - or no vbus is sensed (when vbus sesing is available)
1560 * 1564 *
1561 * Returns 1 if UDC should be disabled 1565 * Returns 1 if UDC should be disabled
1562 */ 1566 */
@@ -1565,6 +1569,7 @@ static int should_disable_udc(struct pxa_udc *udc)
1565 int put_off; 1569 int put_off;
1566 1570
1567 put_off = ((!udc->pullup_on) || (!udc->driver)); 1571 put_off = ((!udc->pullup_on) || (!udc->driver));
1572 put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
1568 return put_off; 1573 return put_off;
1569} 1574}
1570 1575
@@ -1592,10 +1597,37 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
1592 return 0; 1597 return 0;
1593} 1598}
1594 1599
1600static void udc_enable(struct pxa_udc *udc);
1601static void udc_disable(struct pxa_udc *udc);
1602
1603/**
1604 * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc
1605 * @_gadget: usb gadget
1606 * @is_active: 0 if should disable the udc, 1 if should enable
1607 *
1608 * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the
1609 * udc, and deactivates D+ pullup resistor.
1610 *
1611 * Returns 0
1612 */
1613static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1614{
1615 struct pxa_udc *udc = to_gadget_udc(_gadget);
1616
1617 udc->vbus_sensed = is_active;
1618 if (should_enable_udc(udc))
1619 udc_enable(udc);
1620 if (should_disable_udc(udc))
1621 udc_disable(udc);
1622
1623 return 0;
1624}
1625
1595static const struct usb_gadget_ops pxa_udc_ops = { 1626static const struct usb_gadget_ops pxa_udc_ops = {
1596 .get_frame = pxa_udc_get_frame, 1627 .get_frame = pxa_udc_get_frame,
1597 .wakeup = pxa_udc_wakeup, 1628 .wakeup = pxa_udc_wakeup,
1598 .pullup = pxa_udc_pullup, 1629 .pullup = pxa_udc_pullup,
1630 .vbus_session = pxa_udc_vbus_session,
1599 /* current versions must always be self-powered */ 1631 /* current versions must always be self-powered */
1600}; 1632};
1601 1633
@@ -2357,6 +2389,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
2357 device_initialize(&udc->gadget.dev); 2389 device_initialize(&udc->gadget.dev);
2358 udc->gadget.dev.parent = &pdev->dev; 2390 udc->gadget.dev.parent = &pdev->dev;
2359 udc->gadget.dev.dma_mask = NULL; 2391 udc->gadget.dev.dma_mask = NULL;
2392 udc->vbus_sensed = 0;
2360 2393
2361 the_controller = udc; 2394 the_controller = udc;
2362 platform_set_drvdata(pdev, udc); 2395 platform_set_drvdata(pdev, udc);
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index 6f5234dff8a5..64741e199204 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -456,6 +456,7 @@ struct pxa_udc {
456 unsigned enabled:1; 456 unsigned enabled:1;
457 unsigned pullup_on:1; 457 unsigned pullup_on:1;
458 unsigned pullup_resume:1; 458 unsigned pullup_resume:1;
459 unsigned vbus_sensed:1;
459 unsigned config:2; 460 unsigned config:2;
460 unsigned last_interface:3; 461 unsigned last_interface:3;
461 unsigned last_alternate:3; 462 unsigned last_alternate:3;