diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-01-05 16:21:43 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-01 17:35:01 -0500 |
commit | f3db6e82034a6ea89191fdcc6b9a984dc0d5d533 (patch) | |
tree | 5ae328679bef284fc5fad4dd74137c1a52abcd61 | |
parent | 4bde4a4c4ff53e67cde4b0fe630d6fc28106bff8 (diff) |
USB: at91_udc uses generic GPIO calls; minor cleanup
Various small at91_udc cleanups:
- Use generic GPIO calls, not older platform-specific ones
- Use gpio_request()/gpio_free()
- Use VERBOSE_DEBUG convention, not older VERBOSE
- Fix sparse complaint about parameter type (changed to gfp_t)
- Add missing newline to some rarely-seen debug messages
- Fix some old cleanup bugs on probe() fault paths
Also add a mechanism whereby rm9200 gpios can drive the D+ pullup
through an inverting transistor, based on a patch from Steve Birtles.
Most UDC drivers supporting a GPIO based pullup should probably have
such an option, but testing it requries such a board in hand!
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Steve Birtles <arm_kernel_development@micromark.net.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/gadget/at91_udc.c | 79 | ||||
-rw-r--r-- | drivers/usb/gadget/at91_udc.h | 2 | ||||
-rw-r--r-- | include/asm-arm/arch-at91/board.h | 3 |
3 files changed, 63 insertions, 21 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 305db36a3b1c..a83e8b798ec9 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
@@ -21,8 +21,7 @@ | |||
21 | * Boston, MA 02111-1307, USA. | 21 | * Boston, MA 02111-1307, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #undef DEBUG | 24 | #undef VERBOSE_DEBUG |
25 | #undef VERBOSE | ||
26 | #undef PACKET_TRACE | 25 | #undef PACKET_TRACE |
27 | 26 | ||
28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
@@ -46,8 +45,8 @@ | |||
46 | #include <asm/irq.h> | 45 | #include <asm/irq.h> |
47 | #include <asm/system.h> | 46 | #include <asm/system.h> |
48 | #include <asm/mach-types.h> | 47 | #include <asm/mach-types.h> |
48 | #include <asm/gpio.h> | ||
49 | 49 | ||
50 | #include <asm/arch/gpio.h> | ||
51 | #include <asm/arch/board.h> | 50 | #include <asm/arch/board.h> |
52 | #include <asm/arch/cpu.h> | 51 | #include <asm/arch/cpu.h> |
53 | #include <asm/arch/at91sam9261_matrix.h> | 52 | #include <asm/arch/at91sam9261_matrix.h> |
@@ -580,7 +579,7 @@ static int at91_ep_disable (struct usb_ep * _ep) | |||
580 | */ | 579 | */ |
581 | 580 | ||
582 | static struct usb_request * | 581 | static struct usb_request * |
583 | at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) | 582 | at91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) |
584 | { | 583 | { |
585 | struct at91_request *req; | 584 | struct at91_request *req; |
586 | 585 | ||
@@ -881,6 +880,8 @@ static void clk_off(struct at91_udc *udc) | |||
881 | */ | 880 | */ |
882 | static void pullup(struct at91_udc *udc, int is_on) | 881 | static void pullup(struct at91_udc *udc, int is_on) |
883 | { | 882 | { |
883 | int active = !udc->board.pullup_active_low; | ||
884 | |||
884 | if (!udc->enabled || !udc->vbus) | 885 | if (!udc->enabled || !udc->vbus) |
885 | is_on = 0; | 886 | is_on = 0; |
886 | DBG("%sactive\n", is_on ? "" : "in"); | 887 | DBG("%sactive\n", is_on ? "" : "in"); |
@@ -890,7 +891,7 @@ static void pullup(struct at91_udc *udc, int is_on) | |||
890 | at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); | 891 | at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); |
891 | at91_udp_write(udc, AT91_UDP_TXVC, 0); | 892 | at91_udp_write(udc, AT91_UDP_TXVC, 0); |
892 | if (cpu_is_at91rm9200()) | 893 | if (cpu_is_at91rm9200()) |
893 | at91_set_gpio_value(udc->board.pullup_pin, 1); | 894 | gpio_set_value(udc->board.pullup_pin, active); |
894 | else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { | 895 | else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { |
895 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); | 896 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); |
896 | 897 | ||
@@ -908,7 +909,7 @@ static void pullup(struct at91_udc *udc, int is_on) | |||
908 | at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); | 909 | at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); |
909 | at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); | 910 | at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); |
910 | if (cpu_is_at91rm9200()) | 911 | if (cpu_is_at91rm9200()) |
911 | at91_set_gpio_value(udc->board.pullup_pin, 0); | 912 | gpio_set_value(udc->board.pullup_pin, !active); |
912 | else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { | 913 | else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { |
913 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); | 914 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); |
914 | 915 | ||
@@ -1551,7 +1552,7 @@ static irqreturn_t at91_vbus_irq(int irq, void *_udc) | |||
1551 | 1552 | ||
1552 | /* vbus needs at least brief debouncing */ | 1553 | /* vbus needs at least brief debouncing */ |
1553 | udelay(10); | 1554 | udelay(10); |
1554 | value = at91_get_gpio_value(udc->board.vbus_pin); | 1555 | value = gpio_get_value(udc->board.vbus_pin); |
1555 | if (value != udc->vbus) | 1556 | if (value != udc->vbus) |
1556 | at91_vbus_session(&udc->gadget, value); | 1557 | at91_vbus_session(&udc->gadget, value); |
1557 | 1558 | ||
@@ -1647,12 +1648,12 @@ static int __init at91udc_probe(struct platform_device *pdev) | |||
1647 | } | 1648 | } |
1648 | 1649 | ||
1649 | if (pdev->num_resources != 2) { | 1650 | if (pdev->num_resources != 2) { |
1650 | DBG("invalid num_resources"); | 1651 | DBG("invalid num_resources\n"); |
1651 | return -ENODEV; | 1652 | return -ENODEV; |
1652 | } | 1653 | } |
1653 | if ((pdev->resource[0].flags != IORESOURCE_MEM) | 1654 | if ((pdev->resource[0].flags != IORESOURCE_MEM) |
1654 | || (pdev->resource[1].flags != IORESOURCE_IRQ)) { | 1655 | || (pdev->resource[1].flags != IORESOURCE_IRQ)) { |
1655 | DBG("invalid resource type"); | 1656 | DBG("invalid resource type\n"); |
1656 | return -ENODEV; | 1657 | return -ENODEV; |
1657 | } | 1658 | } |
1658 | 1659 | ||
@@ -1674,10 +1675,26 @@ static int __init at91udc_probe(struct platform_device *pdev) | |||
1674 | udc->pdev = pdev; | 1675 | udc->pdev = pdev; |
1675 | udc->enabled = 0; | 1676 | udc->enabled = 0; |
1676 | 1677 | ||
1678 | /* rm9200 needs manual D+ pullup; off by default */ | ||
1679 | if (cpu_is_at91rm9200()) { | ||
1680 | if (udc->board.pullup_pin <= 0) { | ||
1681 | DBG("no D+ pullup?\n"); | ||
1682 | retval = -ENODEV; | ||
1683 | goto fail0; | ||
1684 | } | ||
1685 | retval = gpio_request(udc->board.pullup_pin, "udc_pullup"); | ||
1686 | if (retval) { | ||
1687 | DBG("D+ pullup is busy\n"); | ||
1688 | goto fail0; | ||
1689 | } | ||
1690 | gpio_direction_output(udc->board.pullup_pin, | ||
1691 | udc->board.pullup_active_low); | ||
1692 | } | ||
1693 | |||
1677 | udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1); | 1694 | udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1); |
1678 | if (!udc->udp_baseaddr) { | 1695 | if (!udc->udp_baseaddr) { |
1679 | release_mem_region(res->start, res->end - res->start + 1); | 1696 | retval = -ENOMEM; |
1680 | return -ENOMEM; | 1697 | goto fail0a; |
1681 | } | 1698 | } |
1682 | 1699 | ||
1683 | udc_reinit(udc); | 1700 | udc_reinit(udc); |
@@ -1688,12 +1705,13 @@ static int __init at91udc_probe(struct platform_device *pdev) | |||
1688 | if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { | 1705 | if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { |
1689 | DBG("clocks missing\n"); | 1706 | DBG("clocks missing\n"); |
1690 | retval = -ENODEV; | 1707 | retval = -ENODEV; |
1691 | goto fail0; | 1708 | /* NOTE: we "know" here that refcounts on these are NOPs */ |
1709 | goto fail0b; | ||
1692 | } | 1710 | } |
1693 | 1711 | ||
1694 | retval = device_register(&udc->gadget.dev); | 1712 | retval = device_register(&udc->gadget.dev); |
1695 | if (retval < 0) | 1713 | if (retval < 0) |
1696 | goto fail0; | 1714 | goto fail0b; |
1697 | 1715 | ||
1698 | /* don't do anything until we have both gadget driver and VBUS */ | 1716 | /* don't do anything until we have both gadget driver and VBUS */ |
1699 | clk_enable(udc->iclk); | 1717 | clk_enable(udc->iclk); |
@@ -1705,25 +1723,32 @@ static int __init at91udc_probe(struct platform_device *pdev) | |||
1705 | 1723 | ||
1706 | /* request UDC and maybe VBUS irqs */ | 1724 | /* request UDC and maybe VBUS irqs */ |
1707 | udc->udp_irq = platform_get_irq(pdev, 0); | 1725 | udc->udp_irq = platform_get_irq(pdev, 0); |
1708 | if (request_irq(udc->udp_irq, at91_udc_irq, | 1726 | retval = request_irq(udc->udp_irq, at91_udc_irq, |
1709 | IRQF_DISABLED, driver_name, udc)) { | 1727 | IRQF_DISABLED, driver_name, udc); |
1728 | if (retval < 0) { | ||
1710 | DBG("request irq %d failed\n", udc->udp_irq); | 1729 | DBG("request irq %d failed\n", udc->udp_irq); |
1711 | retval = -EBUSY; | ||
1712 | goto fail1; | 1730 | goto fail1; |
1713 | } | 1731 | } |
1714 | if (udc->board.vbus_pin > 0) { | 1732 | if (udc->board.vbus_pin > 0) { |
1733 | retval = gpio_request(udc->board.vbus_pin, "udc_vbus"); | ||
1734 | if (retval < 0) { | ||
1735 | DBG("request vbus pin failed\n"); | ||
1736 | goto fail2; | ||
1737 | } | ||
1738 | gpio_direction_input(udc->board.vbus_pin); | ||
1739 | |||
1715 | /* | 1740 | /* |
1716 | * Get the initial state of VBUS - we cannot expect | 1741 | * Get the initial state of VBUS - we cannot expect |
1717 | * a pending interrupt. | 1742 | * a pending interrupt. |
1718 | */ | 1743 | */ |
1719 | udc->vbus = at91_get_gpio_value(udc->board.vbus_pin); | 1744 | udc->vbus = gpio_get_value(udc->board.vbus_pin); |
1720 | if (request_irq(udc->board.vbus_pin, at91_vbus_irq, | 1745 | if (request_irq(udc->board.vbus_pin, at91_vbus_irq, |
1721 | IRQF_DISABLED, driver_name, udc)) { | 1746 | IRQF_DISABLED, driver_name, udc)) { |
1722 | DBG("request vbus irq %d failed\n", | 1747 | DBG("request vbus irq %d failed\n", |
1723 | udc->board.vbus_pin); | 1748 | udc->board.vbus_pin); |
1724 | free_irq(udc->udp_irq, udc); | 1749 | free_irq(udc->udp_irq, udc); |
1725 | retval = -EBUSY; | 1750 | retval = -EBUSY; |
1726 | goto fail1; | 1751 | goto fail3; |
1727 | } | 1752 | } |
1728 | } else { | 1753 | } else { |
1729 | DBG("no VBUS detection, assuming always-on\n"); | 1754 | DBG("no VBUS detection, assuming always-on\n"); |
@@ -1736,8 +1761,18 @@ static int __init at91udc_probe(struct platform_device *pdev) | |||
1736 | INFO("%s version %s\n", driver_name, DRIVER_VERSION); | 1761 | INFO("%s version %s\n", driver_name, DRIVER_VERSION); |
1737 | return 0; | 1762 | return 0; |
1738 | 1763 | ||
1764 | fail3: | ||
1765 | if (udc->board.vbus_pin > 0) | ||
1766 | gpio_free(udc->board.vbus_pin); | ||
1767 | fail2: | ||
1768 | free_irq(udc->udp_irq, udc); | ||
1739 | fail1: | 1769 | fail1: |
1740 | device_unregister(&udc->gadget.dev); | 1770 | device_unregister(&udc->gadget.dev); |
1771 | fail0b: | ||
1772 | iounmap(udc->udp_baseaddr); | ||
1773 | fail0a: | ||
1774 | if (cpu_is_at91rm9200()) | ||
1775 | gpio_free(udc->board.pullup_pin); | ||
1741 | fail0: | 1776 | fail0: |
1742 | release_mem_region(res->start, res->end - res->start + 1); | 1777 | release_mem_region(res->start, res->end - res->start + 1); |
1743 | DBG("%s probe failed, %d\n", driver_name, retval); | 1778 | DBG("%s probe failed, %d\n", driver_name, retval); |
@@ -1758,12 +1793,18 @@ static int __exit at91udc_remove(struct platform_device *pdev) | |||
1758 | 1793 | ||
1759 | device_init_wakeup(&pdev->dev, 0); | 1794 | device_init_wakeup(&pdev->dev, 0); |
1760 | remove_debug_file(udc); | 1795 | remove_debug_file(udc); |
1761 | if (udc->board.vbus_pin > 0) | 1796 | if (udc->board.vbus_pin > 0) { |
1762 | free_irq(udc->board.vbus_pin, udc); | 1797 | free_irq(udc->board.vbus_pin, udc); |
1798 | gpio_free(udc->board.vbus_pin); | ||
1799 | } | ||
1763 | free_irq(udc->udp_irq, udc); | 1800 | free_irq(udc->udp_irq, udc); |
1764 | device_unregister(&udc->gadget.dev); | 1801 | device_unregister(&udc->gadget.dev); |
1765 | 1802 | ||
1766 | iounmap(udc->udp_baseaddr); | 1803 | iounmap(udc->udp_baseaddr); |
1804 | |||
1805 | if (cpu_is_at91rm9200()) | ||
1806 | gpio_free(udc->board.pullup_pin); | ||
1807 | |||
1767 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1808 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1768 | release_mem_region(res->start, res->end - res->start + 1); | 1809 | release_mem_region(res->start, res->end - res->start + 1); |
1769 | 1810 | ||
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index f3095a90a0ee..a973f2a50fb9 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h | |||
@@ -158,7 +158,7 @@ struct at91_request { | |||
158 | 158 | ||
159 | /*-------------------------------------------------------------------------*/ | 159 | /*-------------------------------------------------------------------------*/ |
160 | 160 | ||
161 | #ifdef VERBOSE | 161 | #ifdef VERBOSE_DEBUG |
162 | # define VDBG DBG | 162 | # define VDBG DBG |
163 | #else | 163 | #else |
164 | # define VDBG(stuff...) do{}while(0) | 164 | # define VDBG(stuff...) do{}while(0) |
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index 55b07bd5316c..dc189f01c5b3 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h | |||
@@ -40,7 +40,8 @@ | |||
40 | /* USB Device */ | 40 | /* USB Device */ |
41 | struct at91_udc_data { | 41 | struct at91_udc_data { |
42 | u8 vbus_pin; /* high == host powering us */ | 42 | u8 vbus_pin; /* high == host powering us */ |
43 | u8 pullup_pin; /* high == D+ pulled up */ | 43 | u8 pullup_pin; /* active == D+ pulled up */ |
44 | u8 pullup_active_low; /* true == pullup_pin is active low */ | ||
44 | }; | 45 | }; |
45 | extern void __init at91_add_device_udc(struct at91_udc_data *data); | 46 | extern void __init at91_add_device_udc(struct at91_udc_data *data); |
46 | 47 | ||