aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/at91_udc.c
diff options
context:
space:
mode:
authorAndrew Victor <andrew@sanpeople.com>2006-12-08 01:44:38 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-20 13:14:27 -0500
commit29ba4b533b677f3cd7f2fc901d51054555a8f243 (patch)
tree159f814dcf4b500cd0dca369bd39af9cfdcec266 /drivers/usb/gadget/at91_udc.c
parentffd3326bf6282b9f606e92ae57e8f47f2e10e6b5 (diff)
USB: at91_udc, misc fixes
This is an update to the AT91 USB Device (Gadget) driver. Adds support for the Atmel AT91SAM9260 and AT91SAM9261 processors. The only difference is how they handle the pullup pin. [Patch from Patrice Vilchez] Need to clear any pending USB Device interrupts before registering the interrupt handler. The bootloader might have been using the USB Device port. [Patch from Peer Georgi] VBUS detection is handled by a GPIO interrupt which only triggers on a change. Is is therefore necessary to read the current VBUS state explicitly at startup. [Patch from Peer Georgi] Signed-off-by: Andrew Victor <andrew@sanpeople.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/at91_udc.c')
-rw-r--r--drivers/usb/gadget/at91_udc.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index b53b93700ca8..c8954a6ddf8c 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -51,6 +51,8 @@
51 51
52#include <asm/arch/gpio.h> 52#include <asm/arch/gpio.h>
53#include <asm/arch/board.h> 53#include <asm/arch/board.h>
54#include <asm/arch/cpu.h>
55#include <asm/arch/at91sam9261_matrix.h>
54 56
55#include "at91_udc.h" 57#include "at91_udc.h"
56 58
@@ -909,11 +911,37 @@ static void pullup(struct at91_udc *udc, int is_on)
909 if (is_on) { 911 if (is_on) {
910 clk_on(udc); 912 clk_on(udc);
911 at91_udp_write(udc, AT91_UDP_TXVC, 0); 913 at91_udp_write(udc, AT91_UDP_TXVC, 0);
912 at91_set_gpio_value(udc->board.pullup_pin, 1); 914 if (cpu_is_at91rm9200())
915 at91_set_gpio_value(udc->board.pullup_pin, 1);
916 else if (cpu_is_at91sam9260()) {
917 u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
918
919 txvc |= AT91_UDP_TXVC_PUON;
920 at91_udp_write(udc, AT91_UDP_TXVC, txvc);
921 } else if (cpu_is_at91sam9261()) {
922 u32 usbpucr;
923
924 usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
925 usbpucr |= AT91_MATRIX_USBPUCR_PUON;
926 at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
927 }
913 } else { 928 } else {
914 stop_activity(udc); 929 stop_activity(udc);
915 at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); 930 at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
916 at91_set_gpio_value(udc->board.pullup_pin, 0); 931 if (cpu_is_at91rm9200())
932 at91_set_gpio_value(udc->board.pullup_pin, 0);
933 else if (cpu_is_at91sam9260()) {
934 u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
935
936 txvc &= ~AT91_UDP_TXVC_PUON;
937 at91_udp_write(udc, AT91_UDP_TXVC, txvc);
938 } else if (cpu_is_at91sam9261()) {
939 u32 usbpucr;
940
941 usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
942 usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
943 at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
944 }
917 clk_off(udc); 945 clk_off(udc);
918 } 946 }
919} 947}
@@ -1668,7 +1696,8 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
1668 udc->fclk = clk_get(dev, "udpck"); 1696 udc->fclk = clk_get(dev, "udpck");
1669 if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { 1697 if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
1670 DBG("clocks missing\n"); 1698 DBG("clocks missing\n");
1671 return -ENODEV; 1699 retval = -ENODEV;
1700 goto fail0;
1672 } 1701 }
1673 1702
1674 retval = device_register(&udc->gadget.dev); 1703 retval = device_register(&udc->gadget.dev);
@@ -1679,6 +1708,8 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
1679 clk_enable(udc->iclk); 1708 clk_enable(udc->iclk);
1680 at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); 1709 at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
1681 at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff); 1710 at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
1711 /* Clear all pending interrupts - UDP may be used by bootloader. */
1712 at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
1682 clk_disable(udc->iclk); 1713 clk_disable(udc->iclk);
1683 1714
1684 /* request UDC and maybe VBUS irqs */ 1715 /* request UDC and maybe VBUS irqs */
@@ -1690,6 +1721,11 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
1690 goto fail1; 1721 goto fail1;
1691 } 1722 }
1692 if (udc->board.vbus_pin > 0) { 1723 if (udc->board.vbus_pin > 0) {
1724 /*
1725 * Get the initial state of VBUS - we cannot expect
1726 * a pending interrupt.
1727 */
1728 udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
1693 if (request_irq(udc->board.vbus_pin, at91_vbus_irq, 1729 if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
1694 IRQF_DISABLED, driver_name, udc)) { 1730 IRQF_DISABLED, driver_name, udc)) {
1695 DBG("request vbus irq %d failed\n", 1731 DBG("request vbus irq %d failed\n",