Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andrew Victor and committed by
Greg Kroah-Hartman
29ba4b53 ffd3326b

+42 -6
+39 -3
drivers/usb/gadget/at91_udc.c
··· 51 51 52 52 #include <asm/arch/gpio.h> 53 53 #include <asm/arch/board.h> 54 + #include <asm/arch/cpu.h> 55 + #include <asm/arch/at91sam9261_matrix.h> 54 56 55 57 #include "at91_udc.h" 56 58 ··· 911 909 if (is_on) { 912 910 clk_on(udc); 913 911 at91_udp_write(udc, AT91_UDP_TXVC, 0); 914 - at91_set_gpio_value(udc->board.pullup_pin, 1); 912 + if (cpu_is_at91rm9200()) 913 + at91_set_gpio_value(udc->board.pullup_pin, 1); 914 + else if (cpu_is_at91sam9260()) { 915 + u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); 916 + 917 + txvc |= AT91_UDP_TXVC_PUON; 918 + at91_udp_write(udc, AT91_UDP_TXVC, txvc); 919 + } else if (cpu_is_at91sam9261()) { 920 + u32 usbpucr; 921 + 922 + usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); 923 + usbpucr |= AT91_MATRIX_USBPUCR_PUON; 924 + at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); 925 + } 915 926 } else { 916 927 stop_activity(udc); 917 928 at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); 918 - at91_set_gpio_value(udc->board.pullup_pin, 0); 929 + if (cpu_is_at91rm9200()) 930 + at91_set_gpio_value(udc->board.pullup_pin, 0); 931 + else if (cpu_is_at91sam9260()) { 932 + u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); 933 + 934 + txvc &= ~AT91_UDP_TXVC_PUON; 935 + at91_udp_write(udc, AT91_UDP_TXVC, txvc); 936 + } else if (cpu_is_at91sam9261()) { 937 + u32 usbpucr; 938 + 939 + usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); 940 + usbpucr &= ~AT91_MATRIX_USBPUCR_PUON; 941 + at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); 942 + } 919 943 clk_off(udc); 920 944 } 921 945 } ··· 1696 1668 udc->fclk = clk_get(dev, "udpck"); 1697 1669 if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { 1698 1670 DBG("clocks missing\n"); 1699 - return -ENODEV; 1671 + retval = -ENODEV; 1672 + goto fail0; 1700 1673 } 1701 1674 1702 1675 retval = device_register(&udc->gadget.dev); ··· 1708 1679 clk_enable(udc->iclk); 1709 1680 at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); 1710 1681 at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff); 1682 + /* Clear all pending interrupts - UDP may be used by bootloader. */ 1683 + at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff); 1711 1684 clk_disable(udc->iclk); 1712 1685 1713 1686 /* request UDC and maybe VBUS irqs */ ··· 1721 1690 goto fail1; 1722 1691 } 1723 1692 if (udc->board.vbus_pin > 0) { 1693 + /* 1694 + * Get the initial state of VBUS - we cannot expect 1695 + * a pending interrupt. 1696 + */ 1697 + udc->vbus = at91_get_gpio_value(udc->board.vbus_pin); 1724 1698 if (request_irq(udc->board.vbus_pin, at91_vbus_irq, 1725 1699 IRQF_DISABLED, driver_name, udc)) { 1726 1700 DBG("request vbus irq %d failed\n",
+3 -3
drivers/usb/gadget/at91_udc.h
··· 51 51 #define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */ 52 52 #define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */ 53 53 #define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */ 54 - #define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */ 54 + #define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */ 55 55 #define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */ 56 56 #define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */ 57 - #define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */ 57 + #define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */ 58 58 59 59 #define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */ 60 60 #define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */ ··· 84 84 85 85 #define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */ 86 86 #define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */ 87 - 87 + #define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */ 88 88 89 89 /*-------------------------------------------------------------------------*/ 90 90