diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2009-01-25 02:56:42 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-03-24 19:20:26 -0400 |
commit | b799a7eb68082af620b7e37b6f41c98802e831f6 (patch) | |
tree | 3e03ef6d83eac47675ccb673432a862de29578f2 /drivers | |
parent | eb50702539f9be3765127d927d3e9ccfeb65f26e (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.c | 33 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa27x_udc.h | 1 |
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 | ||
1600 | static void udc_enable(struct pxa_udc *udc); | ||
1601 | static 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 | */ | ||
1613 | static 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 | |||
1595 | static const struct usb_gadget_ops pxa_udc_ops = { | 1626 | static 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; |