diff options
| -rw-r--r-- | series | 8 | ||||
| -rw-r--r-- | tty/serial-abstraction-for-8250-legacy-ports.patch | 78 | ||||
| -rw-r--r-- | tty/serial-bfin_sport_uart-speed-up-sport-rx-sample-rate-to-be-3-faster.patch | 43 | ||||
| -rw-r--r-- | usb/mxc_udc-add-workaround-for-engcm09152-for-i.mx35.patch | 86 | ||||
| -rw-r--r-- | usb/usb-am35x-add-musb-support.patch | 137 | ||||
| -rw-r--r-- | usb/usb-driver-for-meywa-denki-kayac-yurex.patch | 4 | ||||
| -rw-r--r-- | usb/usb-ftdi_sio-add-device-ids-for-sciencescope.patch | 40 | ||||
| -rw-r--r-- | usb/usb-musb-add-musb-support-for-am35x.patch | 590 | ||||
| -rw-r--r-- | usb/usb-musb-am35x-workaround-for-fifo-read-issue.patch | 75 |
9 files changed, 1059 insertions, 2 deletions
@@ -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 */ + |
