aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-at91/include/mach/board.h2
-rw-r--r--drivers/usb/gadget/at91_udc.c66
-rw-r--r--drivers/usb/gadget/at91_udc.h2
3 files changed, 57 insertions, 13 deletions
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index df2ed848c9f8..58528aa9c8a8 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -44,6 +44,8 @@
44 /* USB Device */ 44 /* USB Device */
45struct at91_udc_data { 45struct at91_udc_data {
46 u8 vbus_pin; /* high == host powering us */ 46 u8 vbus_pin; /* high == host powering us */
47 u8 vbus_active_low; /* vbus polarity */
48 u8 vbus_polled; /* Use polling, not interrupt */
47 u8 pullup_pin; /* active == D+ pulled up */ 49 u8 pullup_pin; /* active == D+ pulled up */
48 u8 pullup_active_low; /* true == pullup_pin is active low */ 50 u8 pullup_active_low; /* true == pullup_pin is active low */
49}; 51};
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index fd6a7577ad25..93ead19507b6 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -76,6 +76,7 @@
76static const char driver_name [] = "at91_udc"; 76static const char driver_name [] = "at91_udc";
77static const char ep0name[] = "ep0"; 77static const char ep0name[] = "ep0";
78 78
79#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
79 80
80#define at91_udp_read(udc, reg) \ 81#define at91_udp_read(udc, reg) \
81 __raw_readl((udc)->udp_baseaddr + (reg)) 82 __raw_readl((udc)->udp_baseaddr + (reg))
@@ -1585,20 +1586,48 @@ static struct at91_udc controller = {
1585 /* ep6 and ep7 are also reserved (custom silicon might use them) */ 1586 /* ep6 and ep7 are also reserved (custom silicon might use them) */
1586}; 1587};
1587 1588
1589static void at91_vbus_update(struct at91_udc *udc, unsigned value)
1590{
1591 value ^= udc->board.vbus_active_low;
1592 if (value != udc->vbus)
1593 at91_vbus_session(&udc->gadget, value);
1594}
1595
1588static irqreturn_t at91_vbus_irq(int irq, void *_udc) 1596static irqreturn_t at91_vbus_irq(int irq, void *_udc)
1589{ 1597{
1590 struct at91_udc *udc = _udc; 1598 struct at91_udc *udc = _udc;
1591 unsigned value;
1592 1599
1593 /* vbus needs at least brief debouncing */ 1600 /* vbus needs at least brief debouncing */
1594 udelay(10); 1601 udelay(10);
1595 value = gpio_get_value(udc->board.vbus_pin); 1602 at91_vbus_update(udc, gpio_get_value(udc->board.vbus_pin));
1596 if (value != udc->vbus)
1597 at91_vbus_session(&udc->gadget, value);
1598 1603
1599 return IRQ_HANDLED; 1604 return IRQ_HANDLED;
1600} 1605}
1601 1606
1607static void at91_vbus_timer_work(struct work_struct *work)
1608{
1609 struct at91_udc *udc = container_of(work, struct at91_udc,
1610 vbus_timer_work);
1611
1612 at91_vbus_update(udc, gpio_get_value_cansleep(udc->board.vbus_pin));
1613
1614 if (!timer_pending(&udc->vbus_timer))
1615 mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT);
1616}
1617
1618static void at91_vbus_timer(unsigned long data)
1619{
1620 struct at91_udc *udc = (struct at91_udc *)data;
1621
1622 /*
1623 * If we are polling vbus it is likely that the gpio is on an
1624 * bus such as i2c or spi which may sleep, so schedule some work
1625 * to read the vbus gpio
1626 */
1627 if (!work_pending(&udc->vbus_timer_work))
1628 schedule_work(&udc->vbus_timer_work);
1629}
1630
1602int usb_gadget_register_driver (struct usb_gadget_driver *driver) 1631int usb_gadget_register_driver (struct usb_gadget_driver *driver)
1603{ 1632{
1604 struct at91_udc *udc = &controller; 1633 struct at91_udc *udc = &controller;
@@ -1800,13 +1829,23 @@ static int __init at91udc_probe(struct platform_device *pdev)
1800 * Get the initial state of VBUS - we cannot expect 1829 * Get the initial state of VBUS - we cannot expect
1801 * a pending interrupt. 1830 * a pending interrupt.
1802 */ 1831 */
1803 udc->vbus = gpio_get_value(udc->board.vbus_pin); 1832 udc->vbus = gpio_get_value_cansleep(udc->board.vbus_pin) ^
1804 if (request_irq(udc->board.vbus_pin, at91_vbus_irq, 1833 udc->board.vbus_active_low;
1805 IRQF_DISABLED, driver_name, udc)) { 1834
1806 DBG("request vbus irq %d failed\n", 1835 if (udc->board.vbus_polled) {
1807 udc->board.vbus_pin); 1836 INIT_WORK(&udc->vbus_timer_work, at91_vbus_timer_work);
1808 retval = -EBUSY; 1837 setup_timer(&udc->vbus_timer, at91_vbus_timer,
1809 goto fail3; 1838 (unsigned long)udc);
1839 mod_timer(&udc->vbus_timer,
1840 jiffies + VBUS_POLL_TIMEOUT);
1841 } else {
1842 if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
1843 IRQF_DISABLED, driver_name, udc)) {
1844 DBG("request vbus irq %d failed\n",
1845 udc->board.vbus_pin);
1846 retval = -EBUSY;
1847 goto fail3;
1848 }
1810 } 1849 }
1811 } else { 1850 } else {
1812 DBG("no VBUS detection, assuming always-on\n"); 1851 DBG("no VBUS detection, assuming always-on\n");
@@ -1898,7 +1937,7 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
1898 enable_irq_wake(udc->udp_irq); 1937 enable_irq_wake(udc->udp_irq);
1899 1938
1900 udc->active_suspend = wake; 1939 udc->active_suspend = wake;
1901 if (udc->board.vbus_pin > 0 && wake) 1940 if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled && wake)
1902 enable_irq_wake(udc->board.vbus_pin); 1941 enable_irq_wake(udc->board.vbus_pin);
1903 return 0; 1942 return 0;
1904} 1943}
@@ -1908,7 +1947,8 @@ static int at91udc_resume(struct platform_device *pdev)
1908 struct at91_udc *udc = platform_get_drvdata(pdev); 1947 struct at91_udc *udc = platform_get_drvdata(pdev);
1909 unsigned long flags; 1948 unsigned long flags;
1910 1949
1911 if (udc->board.vbus_pin > 0 && udc->active_suspend) 1950 if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled &&
1951 udc->active_suspend)
1912 disable_irq_wake(udc->board.vbus_pin); 1952 disable_irq_wake(udc->board.vbus_pin);
1913 1953
1914 /* maybe reconnect to host; if so, clocks on */ 1954 /* maybe reconnect to host; if so, clocks on */
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index bc76a39c2bb1..108ca54f9092 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -145,6 +145,8 @@ struct at91_udc {
145 void __iomem *udp_baseaddr; 145 void __iomem *udp_baseaddr;
146 int udp_irq; 146 int udp_irq;
147 spinlock_t lock; 147 spinlock_t lock;
148 struct timer_list vbus_timer;
149 struct work_struct vbus_timer_work;
148}; 150};
149 151
150static inline struct at91_udc *to_udc(struct usb_gadget *g) 152static inline struct at91_udc *to_udc(struct usb_gadget *g)