aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-01-05 16:21:43 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:35:01 -0500
commitf3db6e82034a6ea89191fdcc6b9a984dc0d5d533 (patch)
tree5ae328679bef284fc5fad4dd74137c1a52abcd61
parent4bde4a4c4ff53e67cde4b0fe630d6fc28106bff8 (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.c79
-rw-r--r--drivers/usb/gadget/at91_udc.h2
-rw-r--r--include/asm-arm/arch-at91/board.h3
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
582static struct usb_request * 581static struct usb_request *
583at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) 582at91_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 */
882static void pullup(struct at91_udc *udc, int is_on) 881static 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
1764fail3:
1765 if (udc->board.vbus_pin > 0)
1766 gpio_free(udc->board.vbus_pin);
1767fail2:
1768 free_irq(udc->udp_irq, udc);
1739fail1: 1769fail1:
1740 device_unregister(&udc->gadget.dev); 1770 device_unregister(&udc->gadget.dev);
1771fail0b:
1772 iounmap(udc->udp_baseaddr);
1773fail0a:
1774 if (cpu_is_at91rm9200())
1775 gpio_free(udc->board.pullup_pin);
1741fail0: 1776fail0:
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 */
41struct at91_udc_data { 41struct 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};
45extern void __init at91_add_device_udc(struct at91_udc_data *data); 46extern void __init at91_add_device_udc(struct at91_udc_data *data);
46 47