aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorStelian Pop <stelian@popies.net>2008-04-05 16:25:47 -0400
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-04-06 17:25:06 -0400
commit16a45bc82e61891daec1ffcd057679bdf962aeb8 (patch)
tree9b7527cbe92525a56361ad64be1c2d960b2d6021 /drivers/usb/gadget
parent5275653fa12b30cea6e309cc03e518bfd00073a5 (diff)
atmel_usba_udc: Add support for AT91CAP9 UDPHS
This patch is part of the series adding support for the USB High Speed Device Port on the AT91CAP9 system on chip. The AT91CAP9 uses the same UDPHS IP as the AVR32 and the AT91SAM9RL. The only differences between the AVR32 and the AT91 version of the device are in the enable/disable and suspend/wakeup sequences: the AT91 version needs to toggle the USB bias and pulldown explicitly. Signed-off-by: Stelian Pop <stelian@popies.net> Acked-by: Andrew Victor <linux@maxim.org.za> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Kconfig4
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c41
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h9
3 files changed, 46 insertions, 8 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 6f45dd669b33..d681bb27fa58 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -118,10 +118,10 @@ config USB_AMD5536UDC
118config USB_GADGET_ATMEL_USBA 118config USB_GADGET_ATMEL_USBA
119 boolean "Atmel USBA" 119 boolean "Atmel USBA"
120 select USB_GADGET_DUALSPEED 120 select USB_GADGET_DUALSPEED
121 depends on AVR32 121 depends on AVR32 || ARCH_AT91CAP9
122 help 122 help
123 USBA is the integrated high-speed USB Device controller on 123 USBA is the integrated high-speed USB Device controller on
124 the AT32AP700x processors from Atmel. 124 the AT32AP700x and AT91CAP9 processors from Atmel.
125 125
126config USB_ATMEL_USBA 126config USB_ATMEL_USBA
127 tristate 127 tristate
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index ddb7301a0138..c9a3c2a462c4 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -326,6 +326,28 @@ static int vbus_is_present(struct usba_udc *udc)
326 return 1; 326 return 1;
327} 327}
328 328
329#if defined(CONFIG_AVR32)
330
331static void toggle_bias(int is_on)
332{
333}
334
335#elif defined(CONFIG_ARCH_AT91)
336
337#include <asm/arch/at91_pmc.h>
338
339static void toggle_bias(int is_on)
340{
341 unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
342
343 if (is_on)
344 at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
345 else
346 at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
347}
348
349#endif /* CONFIG_ARCH_AT91 */
350
329static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req) 351static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
330{ 352{
331 unsigned int transaction_len; 353 unsigned int transaction_len;
@@ -1457,7 +1479,7 @@ restart:
1457 DBG(DBG_HW, "Packet length: %u\n", pkt_len); 1479 DBG(DBG_HW, "Packet length: %u\n", pkt_len);
1458 if (pkt_len != sizeof(crq)) { 1480 if (pkt_len != sizeof(crq)) {
1459 pr_warning("udc: Invalid packet length %u " 1481 pr_warning("udc: Invalid packet length %u "
1460 "(expected %lu)\n", pkt_len, sizeof(crq)); 1482 "(expected %zu)\n", pkt_len, sizeof(crq));
1461 set_protocol_stall(udc, ep); 1483 set_protocol_stall(udc, ep);
1462 return; 1484 return;
1463 } 1485 }
@@ -1615,6 +1637,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
1615 DBG(DBG_INT, "irq, status=%#08x\n", status); 1637 DBG(DBG_INT, "irq, status=%#08x\n", status);
1616 1638
1617 if (status & USBA_DET_SUSPEND) { 1639 if (status & USBA_DET_SUSPEND) {
1640 toggle_bias(0);
1618 usba_writel(udc, INT_CLR, USBA_DET_SUSPEND); 1641 usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
1619 DBG(DBG_BUS, "Suspend detected\n"); 1642 DBG(DBG_BUS, "Suspend detected\n");
1620 if (udc->gadget.speed != USB_SPEED_UNKNOWN 1643 if (udc->gadget.speed != USB_SPEED_UNKNOWN
@@ -1626,6 +1649,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
1626 } 1649 }
1627 1650
1628 if (status & USBA_WAKE_UP) { 1651 if (status & USBA_WAKE_UP) {
1652 toggle_bias(1);
1629 usba_writel(udc, INT_CLR, USBA_WAKE_UP); 1653 usba_writel(udc, INT_CLR, USBA_WAKE_UP);
1630 DBG(DBG_BUS, "Wake Up CPU detected\n"); 1654 DBG(DBG_BUS, "Wake Up CPU detected\n");
1631 } 1655 }
@@ -1719,12 +1743,14 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
1719 vbus = gpio_get_value(udc->vbus_pin); 1743 vbus = gpio_get_value(udc->vbus_pin);
1720 if (vbus != udc->vbus_prev) { 1744 if (vbus != udc->vbus_prev) {
1721 if (vbus) { 1745 if (vbus) {
1722 usba_writel(udc, CTRL, USBA_EN_USBA); 1746 toggle_bias(1);
1747 usba_writel(udc, CTRL, USBA_ENABLE_MASK);
1723 usba_writel(udc, INT_ENB, USBA_END_OF_RESET); 1748 usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
1724 } else { 1749 } else {
1725 udc->gadget.speed = USB_SPEED_UNKNOWN; 1750 udc->gadget.speed = USB_SPEED_UNKNOWN;
1726 reset_all_endpoints(udc); 1751 reset_all_endpoints(udc);
1727 usba_writel(udc, CTRL, 0); 1752 toggle_bias(0);
1753 usba_writel(udc, CTRL, USBA_DISABLE_MASK);
1728 spin_unlock(&udc->lock); 1754 spin_unlock(&udc->lock);
1729 udc->driver->disconnect(&udc->gadget); 1755 udc->driver->disconnect(&udc->gadget);
1730 spin_lock(&udc->lock); 1756 spin_lock(&udc->lock);
@@ -1777,7 +1803,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
1777 /* If Vbus is present, enable the controller and wait for reset */ 1803 /* If Vbus is present, enable the controller and wait for reset */
1778 spin_lock_irqsave(&udc->lock, flags); 1804 spin_lock_irqsave(&udc->lock, flags);
1779 if (vbus_is_present(udc) && udc->vbus_prev == 0) { 1805 if (vbus_is_present(udc) && udc->vbus_prev == 0) {
1780 usba_writel(udc, CTRL, USBA_EN_USBA); 1806 toggle_bias(1);
1807 usba_writel(udc, CTRL, USBA_ENABLE_MASK);
1781 usba_writel(udc, INT_ENB, USBA_END_OF_RESET); 1808 usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
1782 } 1809 }
1783 spin_unlock_irqrestore(&udc->lock, flags); 1810 spin_unlock_irqrestore(&udc->lock, flags);
@@ -1810,7 +1837,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1810 spin_unlock_irqrestore(&udc->lock, flags); 1837 spin_unlock_irqrestore(&udc->lock, flags);
1811 1838
1812 /* This will also disable the DP pullup */ 1839 /* This will also disable the DP pullup */
1813 usba_writel(udc, CTRL, 0); 1840 toggle_bias(0);
1841 usba_writel(udc, CTRL, USBA_DISABLE_MASK);
1814 1842
1815 driver->unbind(&udc->gadget); 1843 driver->unbind(&udc->gadget);
1816 udc->gadget.dev.driver = NULL; 1844 udc->gadget.dev.driver = NULL;
@@ -1880,7 +1908,8 @@ static int __init usba_udc_probe(struct platform_device *pdev)
1880 1908
1881 /* Make sure we start from a clean slate */ 1909 /* Make sure we start from a clean slate */
1882 clk_enable(pclk); 1910 clk_enable(pclk);
1883 usba_writel(udc, CTRL, 0); 1911 toggle_bias(0);
1912 usba_writel(udc, CTRL, USBA_DISABLE_MASK);
1884 clk_disable(pclk); 1913 clk_disable(pclk);
1885 1914
1886 usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep, 1915 usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep,
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 08bf6f9aaf7e..f7baea307f0d 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -41,6 +41,15 @@
41#define USBA_EN_USBA (1 << 8) 41#define USBA_EN_USBA (1 << 8)
42#define USBA_DETACH (1 << 9) 42#define USBA_DETACH (1 << 9)
43#define USBA_REMOTE_WAKE_UP (1 << 10) 43#define USBA_REMOTE_WAKE_UP (1 << 10)
44#define USBA_PULLD_DIS (1 << 11)
45
46#if defined(CONFIG_AVR32)
47#define USBA_ENABLE_MASK USBA_EN_USBA
48#define USBA_DISABLE_MASK 0
49#elif defined(CONFIG_ARCH_AT91)
50#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS)
51#define USBA_DISABLE_MASK USBA_DETACH
52#endif /* CONFIG_ARCH_AT91 */
44 53
45/* Bitfields in FNUM */ 54/* Bitfields in FNUM */
46#define USBA_MICRO_FRAME_NUM_OFFSET 0 55#define USBA_MICRO_FRAME_NUM_OFFSET 0