aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2009-01-25 02:55:34 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-24 19:20:26 -0400
commiteb50702539f9be3765127d927d3e9ccfeb65f26e (patch)
treedcb3885aa1c037c2a2113d2451a28bd5a5c18537 /drivers/usb/gadget
parentc2344f13b59e007d782a3e591ebc551bc583a8b7 (diff)
USB: pxa27x_udc: factor pullup code to prepare otg transceiver
Prepare pxa27x_udc to handle usb D+ pullup properly : it should connect the pullup resistor and disconnect it only if no external transceiver is handling it. [ dbrownell@users.sourceforge.net: kerneldoc and gpio fixes ] 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/usb/gadget')
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c140
-rw-r--r--drivers/usb/gadget/pxa27x_udc.h6
2 files changed, 138 insertions, 8 deletions
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 990f40f988d4..f8145590944f 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -30,6 +30,7 @@
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/clk.h> 31#include <linux/clk.h>
32#include <linux/irq.h> 32#include <linux/irq.h>
33#include <linux/gpio.h>
33 34
34#include <asm/byteorder.h> 35#include <asm/byteorder.h>
35#include <mach/hardware.h> 36#include <mach/hardware.h>
@@ -1471,6 +1472,32 @@ static struct usb_ep_ops pxa_ep_ops = {
1471 .fifo_flush = pxa_ep_fifo_flush, 1472 .fifo_flush = pxa_ep_fifo_flush,
1472}; 1473};
1473 1474
1475/**
1476 * dplus_pullup - Connect or disconnect pullup resistor to D+ pin
1477 * @udc: udc device
1478 * @on: 0 if disconnect pullup resistor, 1 otherwise
1479 * Context: any
1480 *
1481 * Handle D+ pullup resistor, make the device visible to the usb bus, and
1482 * declare it as a full speed usb device
1483 */
1484static void dplus_pullup(struct pxa_udc *udc, int on)
1485{
1486 if (on) {
1487 if (gpio_is_valid(udc->mach->gpio_pullup))
1488 gpio_set_value(udc->mach->gpio_pullup,
1489 !udc->mach->gpio_pullup_inverted);
1490 if (udc->mach->udc_command)
1491 udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
1492 } else {
1493 if (gpio_is_valid(udc->mach->gpio_pullup))
1494 gpio_set_value(udc->mach->gpio_pullup,
1495 udc->mach->gpio_pullup_inverted);
1496 if (udc->mach->udc_command)
1497 udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
1498 }
1499 udc->pullup_on = on;
1500}
1474 1501
1475/** 1502/**
1476 * pxa_udc_get_frame - Returns usb frame number 1503 * pxa_udc_get_frame - Returns usb frame number
@@ -1500,21 +1527,91 @@ static int pxa_udc_wakeup(struct usb_gadget *_gadget)
1500 return 0; 1527 return 0;
1501} 1528}
1502 1529
1530static void udc_enable(struct pxa_udc *udc);
1531static void udc_disable(struct pxa_udc *udc);
1532
1533/**
1534 * should_enable_udc - Tells if UDC should be enabled
1535 * @udc: udc device
1536 * Context: any
1537 *
1538 * The UDC should be enabled if :
1539 * - the pullup resistor is connected
1540 * - and a gadget driver is bound
1541 *
1542 * Returns 1 if UDC should be enabled, 0 otherwise
1543 */
1544static int should_enable_udc(struct pxa_udc *udc)
1545{
1546 int put_on;
1547
1548 put_on = ((udc->pullup_on) && (udc->driver));
1549 return put_on;
1550}
1551
1552/**
1553 * should_disable_udc - Tells if UDC should be disabled
1554 * @udc: udc device
1555 * Context: any
1556 *
1557 * The UDC should be disabled if :
1558 * - the pullup resistor is not connected
1559 * - or no gadget driver is bound
1560 *
1561 * Returns 1 if UDC should be disabled
1562 */
1563static int should_disable_udc(struct pxa_udc *udc)
1564{
1565 int put_off;
1566
1567 put_off = ((!udc->pullup_on) || (!udc->driver));
1568 return put_off;
1569}
1570
1571/**
1572 * pxa_udc_pullup - Offer manual D+ pullup control
1573 * @_gadget: usb gadget using the control
1574 * @is_active: 0 if disconnect, else connect D+ pullup resistor
1575 * Context: !in_interrupt()
1576 *
1577 * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
1578 */
1579static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
1580{
1581 struct pxa_udc *udc = to_gadget_udc(_gadget);
1582
1583 if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
1584 return -EOPNOTSUPP;
1585
1586 dplus_pullup(udc, is_active);
1587
1588 if (should_enable_udc(udc))
1589 udc_enable(udc);
1590 if (should_disable_udc(udc))
1591 udc_disable(udc);
1592 return 0;
1593}
1594
1503static const struct usb_gadget_ops pxa_udc_ops = { 1595static const struct usb_gadget_ops pxa_udc_ops = {
1504 .get_frame = pxa_udc_get_frame, 1596 .get_frame = pxa_udc_get_frame,
1505 .wakeup = pxa_udc_wakeup, 1597 .wakeup = pxa_udc_wakeup,
1598 .pullup = pxa_udc_pullup,
1506 /* current versions must always be self-powered */ 1599 /* current versions must always be self-powered */
1507}; 1600};
1508 1601
1509/** 1602/**
1510 * udc_disable - disable udc device controller 1603 * udc_disable - disable udc device controller
1511 * @udc: udc device 1604 * @udc: udc device
1605 * Context: any
1512 * 1606 *
1513 * Disables the udc device : disables clocks, udc interrupts, control endpoint 1607 * Disables the udc device : disables clocks, udc interrupts, control endpoint
1514 * interrupts. 1608 * interrupts.
1515 */ 1609 */
1516static void udc_disable(struct pxa_udc *udc) 1610static void udc_disable(struct pxa_udc *udc)
1517{ 1611{
1612 if (!udc->enabled)
1613 return;
1614
1518 udc_writel(udc, UDCICR0, 0); 1615 udc_writel(udc, UDCICR0, 0);
1519 udc_writel(udc, UDCICR1, 0); 1616 udc_writel(udc, UDCICR1, 0);
1520 1617
@@ -1523,8 +1620,8 @@ static void udc_disable(struct pxa_udc *udc)
1523 1620
1524 ep0_idle(udc); 1621 ep0_idle(udc);
1525 udc->gadget.speed = USB_SPEED_UNKNOWN; 1622 udc->gadget.speed = USB_SPEED_UNKNOWN;
1526 if (udc->mach->udc_command) 1623
1527 udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); 1624 udc->enabled = 0;
1528} 1625}
1529 1626
1530/** 1627/**
@@ -1570,6 +1667,9 @@ static __init void udc_init_data(struct pxa_udc *dev)
1570 */ 1667 */
1571static void udc_enable(struct pxa_udc *udc) 1668static void udc_enable(struct pxa_udc *udc)
1572{ 1669{
1670 if (udc->enabled)
1671 return;
1672
1573 udc_writel(udc, UDCICR0, 0); 1673 udc_writel(udc, UDCICR0, 0);
1574 udc_writel(udc, UDCICR1, 0); 1674 udc_writel(udc, UDCICR1, 0);
1575 udc_clear_mask_UDCCR(udc, UDCCR_UDE); 1675 udc_clear_mask_UDCCR(udc, UDCCR_UDE);
@@ -1598,9 +1698,7 @@ static void udc_enable(struct pxa_udc *udc)
1598 /* enable ep0 irqs */ 1698 /* enable ep0 irqs */
1599 pio_irq_enable(&udc->pxa_ep[0]); 1699 pio_irq_enable(&udc->pxa_ep[0]);
1600 1700
1601 dev_info(udc->dev, "UDC connecting\n"); 1701 udc->enabled = 1;
1602 if (udc->mach->udc_command)
1603 udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
1604} 1702}
1605 1703
1606/** 1704/**
@@ -1612,6 +1710,9 @@ static void udc_enable(struct pxa_udc *udc)
1612 * usb traffic follows until a disconnect is reported. Then a host may connect 1710 * usb traffic follows until a disconnect is reported. Then a host may connect
1613 * again, or the driver might get unbound. 1711 * again, or the driver might get unbound.
1614 * 1712 *
1713 * Note that the udc is not automatically enabled. Check function
1714 * should_enable_udc().
1715 *
1615 * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise 1716 * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
1616 */ 1717 */
1617int usb_gadget_register_driver(struct usb_gadget_driver *driver) 1718int usb_gadget_register_driver(struct usb_gadget_driver *driver)
@@ -1630,6 +1731,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
1630 /* first hook up the driver ... */ 1731 /* first hook up the driver ... */
1631 udc->driver = driver; 1732 udc->driver = driver;
1632 udc->gadget.dev.driver = &driver->driver; 1733 udc->gadget.dev.driver = &driver->driver;
1734 dplus_pullup(udc, 1);
1633 1735
1634 retval = device_add(&udc->gadget.dev); 1736 retval = device_add(&udc->gadget.dev);
1635 if (retval) { 1737 if (retval) {
@@ -1645,7 +1747,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
1645 dev_dbg(udc->dev, "registered gadget driver '%s'\n", 1747 dev_dbg(udc->dev, "registered gadget driver '%s'\n",
1646 driver->driver.name); 1748 driver->driver.name);
1647 1749
1648 udc_enable(udc); 1750 if (should_enable_udc(udc))
1751 udc_enable(udc);
1649 return 0; 1752 return 0;
1650 1753
1651bind_fail: 1754bind_fail:
@@ -1699,6 +1802,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1699 1802
1700 stop_activity(udc, driver); 1803 stop_activity(udc, driver);
1701 udc_disable(udc); 1804 udc_disable(udc);
1805 dplus_pullup(udc, 0);
1702 1806
1703 driver->unbind(&udc->gadget); 1807 driver->unbind(&udc->gadget);
1704 udc->driver = NULL; 1808 udc->driver = NULL;
@@ -2212,7 +2316,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
2212{ 2316{
2213 struct resource *regs; 2317 struct resource *regs;
2214 struct pxa_udc *udc = &memory; 2318 struct pxa_udc *udc = &memory;
2215 int retval; 2319 int retval = 0, gpio;
2216 2320
2217 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2321 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2218 if (!regs) 2322 if (!regs)
@@ -2224,6 +2328,19 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
2224 udc->dev = &pdev->dev; 2328 udc->dev = &pdev->dev;
2225 udc->mach = pdev->dev.platform_data; 2329 udc->mach = pdev->dev.platform_data;
2226 2330
2331 gpio = udc->mach->gpio_pullup;
2332 if (gpio_is_valid(gpio)) {
2333 retval = gpio_request(gpio, "USB D+ pullup");
2334 if (retval == 0)
2335 gpio_direction_output(gpio,
2336 udc->mach->gpio_pullup_inverted);
2337 }
2338 if (retval) {
2339 dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n",
2340 gpio, retval);
2341 return retval;
2342 }
2343
2227 udc->clk = clk_get(&pdev->dev, NULL); 2344 udc->clk = clk_get(&pdev->dev, NULL);
2228 if (IS_ERR(udc->clk)) { 2345 if (IS_ERR(udc->clk)) {
2229 retval = PTR_ERR(udc->clk); 2346 retval = PTR_ERR(udc->clk);
@@ -2273,10 +2390,13 @@ err_clk:
2273static int __exit pxa_udc_remove(struct platform_device *_dev) 2390static int __exit pxa_udc_remove(struct platform_device *_dev)
2274{ 2391{
2275 struct pxa_udc *udc = platform_get_drvdata(_dev); 2392 struct pxa_udc *udc = platform_get_drvdata(_dev);
2393 int gpio = udc->mach->gpio_pullup;
2276 2394
2277 usb_gadget_unregister_driver(udc->driver); 2395 usb_gadget_unregister_driver(udc->driver);
2278 free_irq(udc->irq, udc); 2396 free_irq(udc->irq, udc);
2279 pxa_cleanup_debugfs(udc); 2397 pxa_cleanup_debugfs(udc);
2398 if (gpio_is_valid(gpio))
2399 gpio_free(gpio);
2280 2400
2281 platform_set_drvdata(_dev, NULL); 2401 platform_set_drvdata(_dev, NULL);
2282 the_controller = NULL; 2402 the_controller = NULL;
@@ -2319,6 +2439,8 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
2319 } 2439 }
2320 2440
2321 udc_disable(udc); 2441 udc_disable(udc);
2442 udc->pullup_resume = udc->pullup_on;
2443 dplus_pullup(udc, 0);
2322 2444
2323 return 0; 2445 return 0;
2324} 2446}
@@ -2346,7 +2468,9 @@ static int pxa_udc_resume(struct platform_device *_dev)
2346 ep->udccsr_value, ep->udccr_value); 2468 ep->udccsr_value, ep->udccr_value);
2347 } 2469 }
2348 2470
2349 udc_enable(udc); 2471 dplus_pullup(udc, udc->pullup_resume);
2472 if (should_enable_udc(udc))
2473 udc_enable(udc);
2350 /* 2474 /*
2351 * We do not handle OTG yet. 2475 * We do not handle OTG yet.
2352 * 2476 *
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index 1d1b7936ee11..6f5234dff8a5 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -425,6 +425,9 @@ struct udc_stats {
425 * @stats: statistics on udc usage 425 * @stats: statistics on udc usage
426 * @udc_usb_ep: array of usb endpoints offered by the gadget 426 * @udc_usb_ep: array of usb endpoints offered by the gadget
427 * @pxa_ep: array of pxa available endpoints 427 * @pxa_ep: array of pxa available endpoints
428 * @enabled: UDC was enabled by a previous udc_enable()
429 * @pullup_on: if pullup resistor connected to D+ pin
430 * @pullup_resume: if pullup resistor should be connected to D+ pin on resume
428 * @config: UDC active configuration 431 * @config: UDC active configuration
429 * @last_interface: UDC interface of the last SET_INTERFACE host request 432 * @last_interface: UDC interface of the last SET_INTERFACE host request
430 * @last_alternate: UDC altsetting of the last SET_INTERFACE host request 433 * @last_alternate: UDC altsetting of the last SET_INTERFACE host request
@@ -450,6 +453,9 @@ struct pxa_udc {
450 struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS]; 453 struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS];
451 struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS]; 454 struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS];
452 455
456 unsigned enabled:1;
457 unsigned pullup_on:1;
458 unsigned pullup_resume:1;
453 unsigned config:2; 459 unsigned config:2;
454 unsigned last_interface:3; 460 unsigned last_interface:3;
455 unsigned last_alternate:3; 461 unsigned last_alternate:3;