aboutsummaryrefslogtreecommitdiffstats
diff options
-rw-r--r--series8
-rw-r--r--tty/serial-abstraction-for-8250-legacy-ports.patch78
-rw-r--r--tty/serial-bfin_sport_uart-speed-up-sport-rx-sample-rate-to-be-3-faster.patch43
-rw-r--r--usb/mxc_udc-add-workaround-for-engcm09152-for-i.mx35.patch86
-rw-r--r--usb/usb-am35x-add-musb-support.patch137
-rw-r--r--usb/usb-driver-for-meywa-denki-kayac-yurex.patch4
-rw-r--r--usb/usb-ftdi_sio-add-device-ids-for-sciencescope.patch40
-rw-r--r--usb/usb-musb-add-musb-support-for-am35x.patch590
-rw-r--r--usb/usb-musb-am35x-workaround-for-fifo-read-issue.patch75
9 files changed, 1059 insertions, 2 deletions
diff --git a/series b/series
index 5e88c3329e65c6..f91cdf04d8f166 100644
--- a/series
+++ b/series
@@ -112,6 +112,8 @@ tty/alchemy-add-uart-pm-methods.patch
tty/jsm-remove-the-uart-port-on-errors.patch
tty/serial-mfd-add-more-baud-rates-support.patch
tty/serial-imx-check-that-the-buffer-is-non-empty-before-sending-it-out.patch
+tty/serial-abstraction-for-8250-legacy-ports.patch
+tty/serial-bfin_sport_uart-speed-up-sport-rx-sample-rate-to-be-3-faster.patch
###################################
# USB stuff for after 2.6.36 is out
@@ -248,8 +250,14 @@ usb/usb-isp116x-hcd-use-resource_size-instead-of-defining-its-own-resource_len-m
usb/usb-isp1362-hcd-use-resource_size-instead-of-defining-its-own-resource_len-macro.patch
usb/usb-ohci-sh-use-resource_size-instead-of-defining-its-own-resource_len-macro.patch
usb/usb-fix-linker-errors-with-config_pm-n.patch
+usb/usb-am35x-add-musb-support.patch
+usb/usb-musb-add-musb-support-for-am35x.patch
+usb/usb-musb-am35x-workaround-for-fifo-read-issue.patch
+usb/usb-ftdi_sio-add-device-ids-for-sciencescope.patch
+usb/mxc_udc-add-workaround-for-engcm09152-for-i.mx35.patch
# staging stuff for next is now in the staging-next tree on git.kernel.org
+
diff --git a/tty/serial-abstraction-for-8250-legacy-ports.patch b/tty/serial-abstraction-for-8250-legacy-ports.patch
new file mode 100644
index 00000000000000..331de4920efee0
--- /dev/null
+++ b/tty/serial-abstraction-for-8250-legacy-ports.patch
@@ -0,0 +1,78 @@
+From linux-serial-owner@vger.kernel.org Tue Oct 19 09:03:48 2010
+From: Alan Cox <alan@linux.intel.com>
+To: linux-serial@vger.kernel.org
+Cc: Alan Cox <alan@linux.intel.com>, gregkh@suse.de,
+ dirk.brandewie@gmail.com, sodaville@linutronix.de
+Subject: serial: abstraction for 8250 legacy ports
+Date: Mon, 18 Oct 2010 11:38:02 -0700
+Message-Id: <6858904d0c5c5eb42bedf92a093817252dc85549.1287426968.git.dirk.brandewie@gmail.com>
+To: linux-serial@vger.kernel.org
+
+From: Alan Cox <alan@linux.intel.com>
+
+Not every platform that has generic legacy 8250 ports manages to have them
+clocked the right way or without errata. Provide a generic interface to
+allow platforms to override the default behaviour in a manner that dumps
+the complexity in *their* code not the 8250 driver.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c | 17 +++++++++++++++++
+ include/linux/serial_8250.h | 4 ++++
+ 2 files changed, 21 insertions(+)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -2672,6 +2672,16 @@ static struct uart_ops serial8250_pops =
+
+ static struct uart_8250_port serial8250_ports[UART_NR];
+
++static void (*serial8250_isa_config)(int port, struct uart_port *up,
++ unsigned short *capabilities);
++
++void serial8250_set_isa_configurator(
++ void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
++{
++ serial8250_isa_config = v;
++}
++EXPORT_SYMBOL(serial8250_set_isa_configurator);
++
+ static void __init serial8250_isa_init_ports(void)
+ {
+ struct uart_8250_port *up;
+@@ -2717,6 +2727,9 @@ static void __init serial8250_isa_init_p
+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ set_io_from_upio(&up->port);
+ up->port.irqflags |= irqflag;
++ if (serial8250_isa_config != NULL)
++ serial8250_isa_config(i, &up->port, &up->capabilities);
++
+ }
+ }
+
+@@ -3178,6 +3191,10 @@ int serial8250_register_port(struct uart
+ if (port->pm)
+ uart->port.pm = port->pm;
+
++ if (serial8250_isa_config != NULL)
++ serial8250_isa_config(0, &uart->port,
++ &uart->capabilities);
++
+ ret = uart_add_one_port(&serial8250_reg, &uart->port);
+ if (ret == 0)
+ ret = uart->port.line;
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -81,4 +81,8 @@ extern void serial8250_do_set_termios(st
+ extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate);
+
++extern void serial8250_set_isa_configurator(void (*v)
++ (int port, struct uart_port *up,
++ unsigned short *capabilities));
++
+ #endif
diff --git a/tty/serial-bfin_sport_uart-speed-up-sport-rx-sample-rate-to-be-3-faster.patch b/tty/serial-bfin_sport_uart-speed-up-sport-rx-sample-rate-to-be-3-faster.patch
new file mode 100644
index 00000000000000..55b8d514759d0d
--- /dev/null
+++ b/tty/serial-bfin_sport_uart-speed-up-sport-rx-sample-rate-to-be-3-faster.patch
@@ -0,0 +1,43 @@
+From vapier@gentoo.org Tue Oct 19 09:08:41 2010
+From: Mike Frysinger <vapier@gentoo.org>
+To: linux-serial@vger.kernel.org,
+ Greg Kroah-Hartman <gregkh@suse.de>,
+ Alan Cox <alan@lxorguk.ukuu.org.uk>
+Cc: uclinux-dist-devel@blackfin.uclinux.org,
+ Sonic Zhang <sonic.zhang@analog.com>
+Subject: serial: bfin_sport_uart: speed up sport RX sample rate to be 3% faster
+Date: Sat, 16 Oct 2010 18:22:34 -0400
+Message-Id: <1287267754-9298-1-git-send-email-vapier@gentoo.org>
+
+From: Sonic Zhang <sonic.zhang@analog.com>
+
+The actual uart baud rate of devices vary between +/-2% of what is
+asked. The SPORT RX sample rate should be faster than double of the
+worst case. Otherwise, wrong data may be received. So set SPORT RX
+clock to be 3% faster in general.
+
+Reported-by: Olivier STOCK <ostockemer@ereca.fr>
+Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
+Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/bfin_sport_uart.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/serial/bfin_sport_uart.c
++++ b/drivers/serial/bfin_sport_uart.c
+@@ -131,7 +131,12 @@ static int sport_uart_setup(struct sport
+ pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
+
+ tclkdiv = sclk / (2 * baud_rate) - 1;
+- rclkdiv = sclk / (2 * baud_rate * 2) - 1;
++ /* The actual uart baud rate of devices vary between +/-2%. The sport
++ * RX sample rate should be faster than the double of the worst case,
++ * otherwise, wrong data are received. So, set sport RX clock to be
++ * 3% faster.
++ */
++ rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1;
+ SPORT_PUT_TCLKDIV(up, tclkdiv);
+ SPORT_PUT_RCLKDIV(up, rclkdiv);
+ SSYNC();
diff --git a/usb/mxc_udc-add-workaround-for-engcm09152-for-i.mx35.patch b/usb/mxc_udc-add-workaround-for-engcm09152-for-i.mx35.patch
new file mode 100644
index 00000000000000..fb0b96fd89a022
--- /dev/null
+++ b/usb/mxc_udc-add-workaround-for-engcm09152-for-i.mx35.patch
@@ -0,0 +1,86 @@
+From eric@eukrea.com Tue Oct 19 09:09:34 2010
+From: =?UTF-8?q?Eric=20B=C3=A9nard?= <eric@eukrea.com>
+To: linux-usb@vger.kernel.org
+Cc: linux-arm-kernel@lists.infradead.org, s.hauer@pengutronix.de,
+ Dinh.Nguyen@freescale.com, leoli@freescale.com,
+ dbrownell@users.sourceforge.net, gregkh@suse.de,
+ linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
+Subject: mxc_udc: add workaround for ENGcm09152 for i.MX35
+Date: Fri, 15 Oct 2010 14:30:58 +0200
+Message-Id: <1287145858-10239-1-git-send-email-eric@eukrea.com>
+
+this patch gives the possibility to workaround bug ENGcm09152
+on i.MX35 when the hardware workaround is also implemented on
+the board.
+It covers the workaround described on page 25 of the following Errata :
+http://cache.freescale.com/files/dsp/doc/errata/IMX35CE.pdf
+
+Signed-off-by: Eric Bénard <eric@eukrea.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/mach-mx3/mach-cpuimx35.c | 1 +
+ drivers/usb/gadget/fsl_mxc_udc.c | 15 +++++++++++++++
+ include/linux/fsl_devices.h | 3 +++
+ 3 files changed, 19 insertions(+)
+
+--- a/arch/arm/mach-mx3/mach-cpuimx35.c
++++ b/arch/arm/mach-mx3/mach-cpuimx35.c
+@@ -155,6 +155,7 @@ static struct mxc_usbh_platform_data usb
+ static struct fsl_usb2_platform_data otg_device_pdata = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_UTMI,
++ .workaround = FLS_USB2_WORKAROUND_ENGCM09152,
+ };
+
+ static int otg_mode_host;
+--- a/drivers/usb/gadget/fsl_mxc_udc.c
++++ b/drivers/usb/gadget/fsl_mxc_udc.c
+@@ -22,6 +22,10 @@
+ static struct clk *mxc_ahb_clk;
+ static struct clk *mxc_usb_clk;
+
++/* workaround ENGcm09152 for i.MX35 */
++#define USBPHYCTRL_OTGBASE_OFFSET 0x608
++#define USBPHYCTRL_EVDO (1 << 23)
++
+ int fsl_udc_clk_init(struct platform_device *pdev)
+ {
+ struct fsl_usb2_platform_data *pdata;
+@@ -84,6 +88,17 @@ eenahb:
+ void fsl_udc_clk_finalize(struct platform_device *pdev)
+ {
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
++#if defined(CONFIG_ARCH_MX35)
++ unsigned int v;
++
++ /* workaround ENGcm09152 for i.MX35 */
++ if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
++ v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
++ USBPHYCTRL_OTGBASE_OFFSET));
++ writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
++ USBPHYCTRL_OTGBASE_OFFSET));
++ }
++#endif
+
+ /* ULPI transceivers don't need usbpll */
+ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -66,6 +66,7 @@ struct fsl_usb2_platform_data {
+ enum fsl_usb2_operating_modes operating_mode;
+ enum fsl_usb2_phy_modes phy_mode;
+ unsigned int port_enables;
++ unsigned int workaround;
+
+ int (*init)(struct platform_device *);
+ void (*exit)(struct platform_device *);
+@@ -84,6 +85,8 @@ struct fsl_usb2_platform_data {
+ #define FSL_USB2_PORT0_ENABLED 0x00000001
+ #define FSL_USB2_PORT1_ENABLED 0x00000002
+
++#define FLS_USB2_WORKAROUND_ENGCM09152 (1 << 0)
++
+ struct spi_device;
+
+ struct fsl_spi_platform_data {
diff --git a/usb/usb-am35x-add-musb-support.patch b/usb/usb-am35x-add-musb-support.patch
new file mode 100644
index 00000000000000..88b3b97e09a115
--- /dev/null
+++ b/usb/usb-am35x-add-musb-support.patch
@@ -0,0 +1,137 @@
+From balbi@ti.com Tue Oct 19 08:59:45 2010
+From: Felipe Balbi <balbi@ti.com>
+To: Greg KH <greg@kroah.com>
+Subject: USB: AM35x: Add musb support
+Date: Tue, 19 Oct 2010 10:08:11 +0300
+Message-Id: <1287472093-20454-2-git-send-email-balbi@ti.com>
+
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+
+AM35x has musb interface (version 1.8) and uses CPPI41 DMA engine.
+It has USB phy built inside the IP itself.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-omap@vger.kernel.org
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/mach-omap2/board-am3517evm.c | 31 +++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/usb-musb.c | 4 ++++
+ arch/arm/plat-omap/include/plat/usb.h | 21 +++++++++++++++++++++
+ 3 files changed, 56 insertions(+)
+
+--- a/arch/arm/mach-omap2/board-am3517evm.c
++++ b/arch/arm/mach-omap2/board-am3517evm.c
+@@ -35,6 +35,7 @@
+ #include <plat/control.h>
+ #include <plat/usb.h>
+ #include <plat/display.h>
++#include <plat/control.h>
+
+ #include "mux.h"
+
+@@ -375,6 +376,31 @@ static void __init am3517_evm_init_irq(v
+ omap_gpio_init();
+ }
+
++static struct omap_musb_board_data musb_board_data = {
++ .interface_type = MUSB_INTERFACE_ULPI,
++ .mode = MUSB_OTG,
++ .power = 500,
++};
++
++static __init void am3517_evm_musb_init(void)
++{
++ u32 devconf2;
++
++ /*
++ * Set up USB clock/mode in the DEVCONF2 register.
++ */
++ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
++
++ /* USB2.0 PHY reference clock is 13 MHz */
++ devconf2 &= ~(CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE);
++ devconf2 |= CONF2_REFFREQ_13MHZ | CONF2_SESENDEN | CONF2_VBDTCTEN
++ | CONF2_DATPOL;
++
++ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
++
++ usb_musb_init(&musb_board_data);
++}
++
+ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+ .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+ #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
+@@ -393,6 +419,8 @@ static const struct ehci_hcd_omap_platfo
+
+ #ifdef CONFIG_OMAP_MUX
+ static struct omap_board_mux board_mux[] __initdata = {
++ /* USB OTG DRVVBUS offset = 0x212 */
++ OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+ { .reg_offset = OMAP_MUX_TERMINATOR },
+ };
+ #else
+@@ -459,6 +487,9 @@ static void __init am3517_evm_init(void)
+ ARRAY_SIZE(am3517evm_i2c1_boardinfo));
+ /*Ethernet*/
+ am3517_evm_ethernet_init(&am3517_evm_emac_pdata);
++
++ /* MUSB */
++ am3517_evm_musb_init();
+ }
+
+ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
+--- a/arch/arm/mach-omap2/usb-musb.c
++++ b/arch/arm/mach-omap2/usb-musb.c
+@@ -28,6 +28,7 @@
+
+ #include <mach/hardware.h>
+ #include <mach/irqs.h>
++#include <mach/am35xx.h>
+ #include <plat/usb.h>
+
+ #ifdef CONFIG_USB_MUSB_SOC
+@@ -89,6 +90,9 @@ void __init usb_musb_init(struct omap_mu
+ {
+ if (cpu_is_omap243x()) {
+ musb_resources[0].start = OMAP243X_HS_BASE;
++ } else if (cpu_is_omap3517() || cpu_is_omap3505()) {
++ musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
++ musb_resources[1].start = INT_35XX_USBOTG_IRQ;
+ } else if (cpu_is_omap34xx()) {
+ musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
+ } else if (cpu_is_omap44xx()) {
+--- a/arch/arm/plat-omap/include/plat/usb.h
++++ b/arch/arm/plat-omap/include/plat/usb.h
+@@ -218,6 +218,27 @@ static inline omap2_usbfs_init(struct om
+ # define USBT2TLL5PI (1 << 17)
+ # define USB0PUENACTLOI (1 << 16)
+ # define USBSTANDBYCTRL (1 << 15)
++/* AM35x */
++/* USB 2.0 PHY Control */
++#define CONF2_PHY_GPIOMODE (1 << 23)
++#define CONF2_OTGMODE (3 << 14)
++#define CONF2_NO_OVERRIDE (0 << 14)
++#define CONF2_FORCE_HOST (1 << 14)
++#define CONF2_FORCE_DEVICE (2 << 14)
++#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
++#define CONF2_SESENDEN (1 << 13)
++#define CONF2_VBDTCTEN (1 << 12)
++#define CONF2_REFFREQ_24MHZ (2 << 8)
++#define CONF2_REFFREQ_26MHZ (7 << 8)
++#define CONF2_REFFREQ_13MHZ (6 << 8)
++#define CONF2_REFFREQ (0xf << 8)
++#define CONF2_PHYCLKGD (1 << 7)
++#define CONF2_VBUSSENSE (1 << 6)
++#define CONF2_PHY_PLLON (1 << 5)
++#define CONF2_RESET (1 << 4)
++#define CONF2_PHYPWRDN (1 << 3)
++#define CONF2_OTGPWRDN (1 << 2)
++#define CONF2_DATPOL (1 << 1)
+
+ #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB)
+ u32 omap1_usb0_init(unsigned nwires, unsigned is_device);
diff --git a/usb/usb-driver-for-meywa-denki-kayac-yurex.patch b/usb/usb-driver-for-meywa-denki-kayac-yurex.patch
index 598b4014d9cb4a..fa23dac52e4f8a 100644
--- a/usb/usb-driver-for-meywa-denki-kayac-yurex.patch
+++ b/usb/usb-driver-for-meywa-denki-kayac-yurex.patch
@@ -27,7 +27,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
-@@ -1661,6 +1661,7 @@ static const struct hid_device_id hid_ig
+@@ -1662,6 +1662,7 @@ static const struct hid_device_id hid_ig
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
@@ -37,7 +37,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
-@@ -303,6 +303,9 @@
+@@ -304,6 +304,9 @@
#define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
diff --git a/usb/usb-ftdi_sio-add-device-ids-for-sciencescope.patch b/usb/usb-ftdi_sio-add-device-ids-for-sciencescope.patch
new file mode 100644
index 00000000000000..9349e79b7b80fa
--- /dev/null
+++ b/usb/usb-ftdi_sio-add-device-ids-for-sciencescope.patch
@@ -0,0 +1,40 @@
+From foo@baz Tue Oct 19 09:05:43 PDT 2010
+Date: Tue, 19 Oct 2010 09:05:43 -0700
+To: Greg KH <greg@kroah.com>
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: USB: ftdi_sio: add device ids for ScienceScope
+
+This adds the requested device ids to the ftdi_sio driver.
+
+Reported-by: Ewan Bingham <ewan@auc.co.uk>
+Cc: Kuba Ober <kuba@mareimbrium.org>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/ftdi_sio.c | 3 +++
+ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -791,6 +791,9 @@ static struct usb_device_id id_table_com
+ { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+ { }, /* Optional parameter entry */
+ { } /* Terminating entry */
+ };
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -1095,3 +1095,8 @@
+ * Accesio USB Data Acquisition products (http://www.accesio.com/)
+ */
+ #define ACCESIO_COM4SM_PID 0xD578
++
++/* www.sciencescope.co.uk educational dataloggers */
++#define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18
++#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C
++#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D
diff --git a/usb/usb-musb-add-musb-support-for-am35x.patch b/usb/usb-musb-add-musb-support-for-am35x.patch
new file mode 100644
index 00000000000000..5b27c8341b997a
--- /dev/null
+++ b/usb/usb-musb-add-musb-support-for-am35x.patch
@@ -0,0 +1,590 @@
+From balbi@ti.com Tue Oct 19 09:00:12 2010
+From: Felipe Balbi <balbi@ti.com>
+To: Greg KH <greg@kroah.com>
+Subject: USB: musb: add musb support for AM35x
+Date: Tue, 19 Oct 2010 10:08:12 +0300
+Message-Id: <1287472093-20454-3-git-send-email-balbi@ti.com>
+
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+
+AM35x has musb interface and uses CPPI4.1 DMA engine.
+Current patch supports only PIO mode. DMA support can be
+added later once basic CPPI4.1 DMA patch is accepted.
+
+Also added USB_MUSB_AM35X which is required to differentiate musb ips
+between OMAP3x and AM35x. This config would be used to for below
+purposes,
+ - Select am35x.c instead of omap2430.c for compilation
+ at drivers/usb/musb directory. Please note there are
+ significant differneces in these two files as musb ip
+ in quite different on AM35x.
+
+ Please note that in multi omap configuration only omap2430.c
+ file will get compiled and we would require to select only
+ AM35x based board config to compile am35x.c
+
+ - Select workaround codes applicable for AM35x musb issues.
+ one such workaround is for bytewise read issue on AM35x.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/Kconfig | 13 +
+ drivers/usb/musb/Makefile | 6
+ drivers/usb/musb/am35x.c | 494 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/musb/musb_core.h | 1
+ 4 files changed, 512 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/musb/Kconfig
++++ b/drivers/usb/musb/Kconfig
+@@ -60,6 +60,17 @@ comment "OMAP 44xx high speed USB suppor
+ comment "Blackfin high speed USB Support"
+ depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523))
+
++config USB_MUSB_AM35X
++ bool
++ depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4
++ select NOP_USB_XCEIV
++ default MACH_OMAP3517EVM
++ help
++ Select this option if your platform is based on AM35x. As
++ AM35x has an updated MUSB with CPPI4.1 DMA so this config
++ is introduced to differentiate musb ip between OMAP3x and
++ AM35x platforms.
++
+ config USB_TUSB6010
+ boolean "TUSB 6010 support"
+ depends on USB_MUSB_HDRC && !USB_MUSB_SOC
+@@ -147,7 +158,7 @@ config USB_MUSB_HDRC_HCD
+ config MUSB_PIO_ONLY
+ bool 'Disable DMA (always use PIO)'
+ depends on USB_MUSB_HDRC
+- default USB_TUSB6010 || ARCH_DAVINCI_DA8XX
++ default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X
+ help
+ All data is copied between memory and FIFO by the CPU.
+ DMA controllers are ignored.
+--- a/drivers/usb/musb/Makefile
++++ b/drivers/usb/musb/Makefile
+@@ -12,7 +12,11 @@ musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx) +=
+ musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx.o
+ musb_hdrc-$(CONFIG_USB_TUSB6010) += tusb6010.o
+ musb_hdrc-$(CONFIG_ARCH_OMAP2430) += omap2430.o
+-musb_hdrc-$(CONFIG_ARCH_OMAP3430) += omap2430.o
++ifeq ($(CONFIG_USB_MUSB_AM35X),y)
++ musb_hdrc-$(CONFIG_ARCH_OMAP3430) += am35x.o
++else
++ musb_hdrc-$(CONFIG_ARCH_OMAP3430) += omap2430.o
++endif
+ musb_hdrc-$(CONFIG_ARCH_OMAP4) += omap2430.o
+ musb_hdrc-$(CONFIG_BF54x) += blackfin.o
+ musb_hdrc-$(CONFIG_BF52x) += blackfin.o
+--- /dev/null
++++ b/drivers/usb/musb/am35x.c
+@@ -0,0 +1,494 @@
++/*
++ * Texas Instruments AM35x "glue layer"
++ *
++ * Copyright (c) 2010, by Texas Instruments
++ *
++ * Based on the DA8xx "glue layer" code.
++ * Copyright (c) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
++ *
++ * This file is part of the Inventra Controller Driver for Linux.
++ *
++ * The Inventra Controller Driver for Linux is free software; you
++ * can redistribute it and/or modify it under the terms of the GNU
++ * General Public License version 2 as published by the Free Software
++ * Foundation.
++ *
++ * The Inventra Controller Driver for Linux is distributed in
++ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
++ * License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with The Inventra Controller Driver for Linux ; if not,
++ * write to the Free Software Foundation, Inc., 59 Temple Place,
++ * Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++#include <plat/control.h>
++#include <plat/usb.h>
++
++#include "musb_core.h"
++
++/*
++ * AM35x specific definitions
++ */
++/* USB 2.0 OTG module registers */
++#define USB_REVISION_REG 0x00
++#define USB_CTRL_REG 0x04
++#define USB_STAT_REG 0x08
++#define USB_EMULATION_REG 0x0c
++/* 0x10 Reserved */
++#define USB_AUTOREQ_REG 0x14
++#define USB_SRP_FIX_TIME_REG 0x18
++#define USB_TEARDOWN_REG 0x1c
++#define EP_INTR_SRC_REG 0x20
++#define EP_INTR_SRC_SET_REG 0x24
++#define EP_INTR_SRC_CLEAR_REG 0x28
++#define EP_INTR_MASK_REG 0x2c
++#define EP_INTR_MASK_SET_REG 0x30
++#define EP_INTR_MASK_CLEAR_REG 0x34
++#define EP_INTR_SRC_MASKED_REG 0x38
++#define CORE_INTR_SRC_REG 0x40
++#define CORE_INTR_SRC_SET_REG 0x44
++#define CORE_INTR_SRC_CLEAR_REG 0x48
++#define CORE_INTR_MASK_REG 0x4c
++#define CORE_INTR_MASK_SET_REG 0x50
++#define CORE_INTR_MASK_CLEAR_REG 0x54
++#define CORE_INTR_SRC_MASKED_REG 0x58
++/* 0x5c Reserved */
++#define USB_END_OF_INTR_REG 0x60
++
++/* Control register bits */
++#define AM35X_SOFT_RESET_MASK 1
++
++/* USB interrupt register bits */
++#define AM35X_INTR_USB_SHIFT 16
++#define AM35X_INTR_USB_MASK (0x1ff << AM35X_INTR_USB_SHIFT)
++#define AM35X_INTR_DRVVBUS 0x100
++#define AM35X_INTR_RX_SHIFT 16
++#define AM35X_INTR_TX_SHIFT 0
++#define AM35X_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */
++#define AM35X_RX_EP_MASK 0xfffe /* 15 Rx EPs */
++#define AM35X_TX_INTR_MASK (AM35X_TX_EP_MASK << AM35X_INTR_TX_SHIFT)
++#define AM35X_RX_INTR_MASK (AM35X_RX_EP_MASK << AM35X_INTR_RX_SHIFT)
++
++#define USB_MENTOR_CORE_OFFSET 0x400
++
++static inline void phy_on(void)
++{
++ unsigned long timeout = jiffies + msecs_to_jiffies(100);
++ u32 devconf2;
++
++ /*
++ * Start the on-chip PHY and its PLL.
++ */
++ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
++
++ devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
++ devconf2 |= CONF2_PHY_PLLON;
++
++ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
++
++ DBG(1, "Waiting for PHY clock good...\n");
++ while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
++ & CONF2_PHYCLKGD)) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout)) {
++ DBG(1, "musb PHY clock good timed out\n");
++ break;
++ }
++ }
++}
++
++static inline void phy_off(void)
++{
++ u32 devconf2;
++
++ /*
++ * Power down the on-chip PHY.
++ */
++ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
++
++ devconf2 &= ~CONF2_PHY_PLLON;
++ devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
++ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
++}
++
++/*
++ * musb_platform_enable - enable interrupts
++ */
++void musb_platform_enable(struct musb *musb)
++{
++ void __iomem *reg_base = musb->ctrl_base;
++ u32 epmask;
++
++ /* Workaround: setup IRQs through both register sets. */
++ epmask = ((musb->epmask & AM35X_TX_EP_MASK) << AM35X_INTR_TX_SHIFT) |
++ ((musb->epmask & AM35X_RX_EP_MASK) << AM35X_INTR_RX_SHIFT);
++
++ musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
++ musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK);
++
++ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
++ if (is_otg_enabled(musb))
++ musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
++ AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
++}
++
++/*
++ * musb_platform_disable - disable HDRC and flush interrupts
++ */
++void musb_platform_disable(struct musb *musb)
++{
++ void __iomem *reg_base = musb->ctrl_base;
++
++ musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, AM35X_INTR_USB_MASK);
++ musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG,
++ AM35X_TX_INTR_MASK | AM35X_RX_INTR_MASK);
++ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
++ musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
++}
++
++#ifdef CONFIG_USB_MUSB_HDRC_HCD
++#define portstate(stmt) stmt
++#else
++#define portstate(stmt)
++#endif
++
++static void am35x_set_vbus(struct musb *musb, int is_on)
++{
++ WARN_ON(is_on && is_peripheral_active(musb));
++}
++
++#define POLL_SECONDS 2
++
++static struct timer_list otg_workaround;
++
++static void otg_timer(unsigned long _musb)
++{
++ struct musb *musb = (void *)_musb;
++ void __iomem *mregs = musb->mregs;
++ u8 devctl;
++ unsigned long flags;
++
++ /*
++ * We poll because AM35x's won't expose several OTG-critical
++ * status change events (from the transceiver) otherwise.
++ */
++ devctl = musb_readb(mregs, MUSB_DEVCTL);
++ DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
++
++ spin_lock_irqsave(&musb->lock, flags);
++ switch (musb->xceiv->state) {
++ case OTG_STATE_A_WAIT_BCON:
++ devctl &= ~MUSB_DEVCTL_SESSION;
++ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
++
++ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
++ if (devctl & MUSB_DEVCTL_BDEVICE) {
++ musb->xceiv->state = OTG_STATE_B_IDLE;
++ MUSB_DEV_MODE(musb);
++ } else {
++ musb->xceiv->state = OTG_STATE_A_IDLE;
++ MUSB_HST_MODE(musb);
++ }
++ break;
++ case OTG_STATE_A_WAIT_VFALL:
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
++ musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
++ MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
++ break;
++ case OTG_STATE_B_IDLE:
++ if (!is_peripheral_enabled(musb))
++ break;
++
++ devctl = musb_readb(mregs, MUSB_DEVCTL);
++ if (devctl & MUSB_DEVCTL_BDEVICE)
++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
++ else
++ musb->xceiv->state = OTG_STATE_A_IDLE;
++ break;
++ default:
++ break;
++ }
++ spin_unlock_irqrestore(&musb->lock, flags);
++}
++
++void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
++{
++ static unsigned long last_timer;
++
++ if (!is_otg_enabled(musb))
++ return;
++
++ if (timeout == 0)
++ timeout = jiffies + msecs_to_jiffies(3);
++
++ /* Never idle if active, or when VBUS timeout is not set as host */
++ if (musb->is_active || (musb->a_wait_bcon == 0 &&
++ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
++ DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
++ del_timer(&otg_workaround);
++ last_timer = jiffies;
++ return;
++ }
++
++ if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
++ DBG(4, "Longer idle timer already pending, ignoring...\n");
++ return;
++ }
++ last_timer = timeout;
++
++ DBG(4, "%s inactive, starting idle timer for %u ms\n",
++ otg_state_string(musb), jiffies_to_msecs(timeout - jiffies));
++ mod_timer(&otg_workaround, timeout);
++}
++
++static irqreturn_t am35x_interrupt(int irq, void *hci)
++{
++ struct musb *musb = hci;
++ void __iomem *reg_base = musb->ctrl_base;
++ unsigned long flags;
++ irqreturn_t ret = IRQ_NONE;
++ u32 epintr, usbintr, lvl_intr;
++
++ spin_lock_irqsave(&musb->lock, flags);
++
++ /* Get endpoint interrupts */
++ epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG);
++
++ if (epintr) {
++ musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr);
++
++ musb->int_rx =
++ (epintr & AM35X_RX_INTR_MASK) >> AM35X_INTR_RX_SHIFT;
++ musb->int_tx =
++ (epintr & AM35X_TX_INTR_MASK) >> AM35X_INTR_TX_SHIFT;
++ }
++
++ /* Get usb core interrupts */
++ usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG);
++ if (!usbintr && !epintr)
++ goto eoi;
++
++ if (usbintr) {
++ musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr);
++
++ musb->int_usb =
++ (usbintr & AM35X_INTR_USB_MASK) >> AM35X_INTR_USB_SHIFT;
++ }
++ /*
++ * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
++ * AM35x's missing ID change IRQ. We need an ID change IRQ to
++ * switch appropriately between halves of the OTG state machine.
++ * Managing DEVCTL.SESSION per Mentor docs requires that we know its
++ * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
++ * Also, DRVVBUS pulses for SRP (but not at 5V) ...
++ */
++ if (usbintr & (AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT)) {
++ int drvvbus = musb_readl(reg_base, USB_STAT_REG);
++ void __iomem *mregs = musb->mregs;
++ u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
++ int err;
++
++ err = is_host_enabled(musb) && (musb->int_usb &
++ MUSB_INTR_VBUSERROR);
++ if (err) {
++ /*
++ * The Mentor core doesn't debounce VBUS as needed
++ * to cope with device connect current spikes. This
++ * means it's not uncommon for bus-powered devices
++ * to get VBUS errors during enumeration.
++ *
++ * This is a workaround, but newer RTL from Mentor
++ * seems to allow a better one: "re"-starting sessions
++ * without waiting for VBUS to stop registering in
++ * devctl.
++ */
++ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
++ WARNING("VBUS error workaround (delay coming)\n");
++ } else if (is_host_enabled(musb) && drvvbus) {
++ MUSB_HST_MODE(musb);
++ musb->xceiv->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
++ portstate(musb->port1_status |= USB_PORT_STAT_POWER);
++ del_timer(&otg_workaround);
++ } else {
++ musb->is_active = 0;
++ MUSB_DEV_MODE(musb);
++ musb->xceiv->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
++ portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
++ }
++
++ /* NOTE: this must complete power-on within 100 ms. */
++ DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
++ drvvbus ? "on" : "off",
++ otg_state_string(musb),
++ err ? " ERROR" : "",
++ devctl);
++ ret = IRQ_HANDLED;
++ }
++
++ if (musb->int_tx || musb->int_rx || musb->int_usb)
++ ret |= musb_interrupt(musb);
++
++eoi:
++ /* EOI needs to be written for the IRQ to be re-asserted. */
++ if (ret == IRQ_HANDLED || epintr || usbintr) {
++ /* clear level interrupt */
++ lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
++ lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
++ omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
++ /* write EOI */
++ musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
++ }
++
++ /* Poll for ID change */
++ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
++
++ spin_unlock_irqrestore(&musb->lock, flags);
++
++ return ret;
++}
++
++int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
++{
++ u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
++
++ devconf2 &= ~CONF2_OTGMODE;
++ switch (musb_mode) {
++#ifdef CONFIG_USB_MUSB_HDRC_HCD
++ case MUSB_HOST: /* Force VBUS valid, ID = 0 */
++ devconf2 |= CONF2_FORCE_HOST;
++ break;
++#endif
++#ifdef CONFIG_USB_GADGET_MUSB_HDRC
++ case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
++ devconf2 |= CONF2_FORCE_DEVICE;
++ break;
++#endif
++#ifdef CONFIG_USB_MUSB_OTG
++ case MUSB_OTG: /* Don't override the VBUS/ID comparators */
++ devconf2 |= CONF2_NO_OVERRIDE;
++ break;
++#endif
++ default:
++ DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
++ }
++
++ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
++ return 0;
++}
++
++int __init musb_platform_init(struct musb *musb, void *board_data)
++{
++ void __iomem *reg_base = musb->ctrl_base;
++ u32 rev, lvl_intr, sw_reset;
++ int status;
++
++ musb->mregs += USB_MENTOR_CORE_OFFSET;
++
++ clk_enable(musb->clock);
++ DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock));
++
++ musb->phy_clock = clk_get(musb->controller, "fck");
++ if (IS_ERR(musb->phy_clock)) {
++ status = PTR_ERR(musb->phy_clock);
++ goto exit0;
++ }
++ clk_enable(musb->phy_clock);
++ DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock));
++
++ /* Returns zero if e.g. not clocked */
++ rev = musb_readl(reg_base, USB_REVISION_REG);
++ if (!rev) {
++ status = -ENODEV;
++ goto exit1;
++ }
++
++ usb_nop_xceiv_register();
++ musb->xceiv = otg_get_transceiver();
++ if (!musb->xceiv) {
++ status = -ENODEV;
++ goto exit1;
++ }
++
++ if (is_host_enabled(musb))
++ setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
++
++ musb->board_set_vbus = am35x_set_vbus;
++
++ /* Global reset */
++ sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
++
++ sw_reset |= AM35XX_USBOTGSS_SW_RST;
++ omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
++
++ sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
++ omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
++
++ /* Reset the controller */
++ musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
++
++ /* Start the on-chip PHY and its PLL. */
++ phy_on();
++
++ msleep(5);
++
++ musb->isr = am35x_interrupt;
++
++ /* clear level interrupt */
++ lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
++ lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
++ omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
++ return 0;
++exit1:
++ clk_disable(musb->phy_clock);
++ clk_put(musb->phy_clock);
++exit0:
++ clk_disable(musb->clock);
++ return status;
++}
++
++int musb_platform_exit(struct musb *musb)
++{
++ if (is_host_enabled(musb))
++ del_timer_sync(&otg_workaround);
++
++ phy_off();
++
++ otg_put_transceiver(musb->xceiv);
++ usb_nop_xceiv_unregister();
++
++ clk_disable(musb->clock);
++
++ clk_disable(musb->phy_clock);
++ clk_put(musb->phy_clock);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++void musb_platform_save_context(struct musb *musb,
++ struct musb_context_registers *musb_context)
++{
++ phy_off();
++}
++
++void musb_platform_restore_context(struct musb *musb,
++ struct musb_context_registers *musb_context)
++{
++ phy_on();
++}
++#endif
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -330,6 +330,7 @@ struct musb {
+ /* device lock */
+ spinlock_t lock;
+ struct clk *clock;
++ struct clk *phy_clock;
+ irqreturn_t (*isr)(int, void *);
+ struct work_struct irq_work;
+ u16 hwvers;
diff --git a/usb/usb-musb-am35x-workaround-for-fifo-read-issue.patch b/usb/usb-musb-am35x-workaround-for-fifo-read-issue.patch
new file mode 100644
index 00000000000000..ad33752ee3162e
--- /dev/null
+++ b/usb/usb-musb-am35x-workaround-for-fifo-read-issue.patch
@@ -0,0 +1,75 @@
+From balbi@ti.com Tue Oct 19 09:03:10 2010
+From: Felipe Balbi <balbi@ti.com>
+To: Greg KH <greg@kroah.com>
+Subject: USB: musb: AM35x: Workaround for fifo read issue
+Date: Tue, 19 Oct 2010 10:08:13 +0300
+Message-Id: <1287472093-20454-4-git-send-email-balbi@ti.com>
+
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+
+AM35x supports only 32bit read operations so we need to have
+workaround for 8bit and 16bit read operations.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/am35x.c | 30 ++++++++++++++++++++++++++++++
+ drivers/usb/musb/musb_core.c | 2 ++
+ 2 files changed, 32 insertions(+)
+
+--- a/drivers/usb/musb/am35x.c
++++ b/drivers/usb/musb/am35x.c
+@@ -492,3 +492,33 @@ void musb_platform_restore_context(struc
+ phy_on();
+ }
+ #endif
++
++/* AM35x supports only 32bit read operation */
++void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
++{
++ void __iomem *fifo = hw_ep->fifo;
++ u32 val;
++ int i;
++
++ /* Read for 32bit-aligned destination address */
++ if (likely((0x03 & (unsigned long) dst) == 0) && len >= 4) {
++ readsl(fifo, dst, len >> 2);
++ dst += len & ~0x03;
++ len &= 0x03;
++ }
++ /*
++ * Now read the remaining 1 to 3 byte or complete length if
++ * unaligned address.
++ */
++ if (len > 4) {
++ for (i = 0; i < (len >> 2); i++) {
++ *(u32 *) dst = musb_readl(fifo, 0);
++ dst += 4;
++ }
++ len &= 0x03;
++ }
++ if (len > 0) {
++ val = musb_readl(fifo, 0);
++ memcpy(dst, &val, len);
++ }
++}
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -272,6 +272,7 @@ void musb_write_fifo(struct musb_hw_ep *
+ }
+ }
+
++#if !defined(CONFIG_USB_MUSB_AM35X)
+ /*
+ * Unload an endpoint's FIFO
+ */
+@@ -309,6 +310,7 @@ void musb_read_fifo(struct musb_hw_ep *h
+ readsb(fifo, dst, len);
+ }
+ }
++#endif
+
+ #endif /* normal PIO */
+