aboutsummaryrefslogtreecommitdiffstats
diff options
-rw-r--r--series16
-rw-r--r--tty/serial-max3107-abstract-out-the-platform-specific-bits.patch1158
-rw-r--r--tty/serial-max3107-introduce-a-max3107-driver.patch1860
-rw-r--r--tty/tty_io-remove-casts-from-void.patch73
-rw-r--r--usb/usb-core-hcd-pci-use-for_each_pci_dev.patch33
-rw-r--r--usb/usb-ehci_omap-fix-device-detect-issue-with-modules.patch83
-rw-r--r--usb/usb-gadget-compilation-issue-missing-task_interruptible.patch44
-rw-r--r--usb/usb-gadget-storage_common-comments-updated.patch159
-rw-r--r--usb/usb-musb-do-not-override-dma-mode-in-channel-program.patch39
-rw-r--r--usb/usb-musb-fix-compilation-warning-in-host-only-mode.patch45
-rw-r--r--usb/usb-musb-kill-board-specific-pinmux-from-driver-file.patch48
-rw-r--r--usb/usb-musb-use-correct-register-widths-in-register-dumps.patch72
-rw-r--r--usb/usb-serial-io_ti-don-t-return-0-if-writing-the-download-record-failed.patch28
-rw-r--r--usb/usb-ulpi-fix-compilation-warning.patch34
14 files changed, 3691 insertions, 1 deletions
diff --git a/series b/series
index 767b2db4288714..811bad414fc6fe 100644
--- a/series
+++ b/series
@@ -103,6 +103,10 @@ tty/tty-release-btm-while-sleeping-in-block_til_ready.patch
tty/8250-fix-set_ldisc-operation.patch
tty/tty-avoid-recursive-btm-in-pty_close.patch
+tty/serial-max3107-introduce-a-max3107-driver.patch
+tty/serial-max3107-abstract-out-the-platform-specific-bits.patch
+tty/tty_io-remove-casts-from-void.patch
+
###################################
# USB stuff for after 2.6.35 is out
@@ -170,7 +174,17 @@ usb/usb-drivers-usb-makefile-conditionally-descend-to-early.patch
usb/usb-xhci-trivial-use-array_size.patch
usb/usb-ehci-fix-null-pointer-dererence-in-hcds-that-use-hcd_local_mem.patch
usb/usb-musb-tusb6010-fix-compile-error-with-n8x0_defconfig.patch
-
+usb/usb-gadget-compilation-issue-missing-task_interruptible.patch
+usb/usb-gadget-storage_common-comments-updated.patch
+usb/usb-serial-io_ti-don-t-return-0-if-writing-the-download-record-failed.patch
+usb/usb-core-hcd-pci-use-for_each_pci_dev.patch
+usb/usb-musb-use-correct-register-widths-in-register-dumps.patch
+usb/usb-musb-fix-compilation-warning-in-host-only-mode.patch
+usb/usb-ulpi-fix-compilation-warning.patch
+usb/usb-ehci_omap-fix-device-detect-issue-with-modules.patch
+usb/usb-musb-kill-board-specific-pinmux-from-driver-file.patch
+usb/usb-musb-do-not-override-dma-mode-in-channel-program.patch
# staging stuff is now in the staging-next tree on git.kernel.org
+
diff --git a/tty/serial-max3107-abstract-out-the-platform-specific-bits.patch b/tty/serial-max3107-abstract-out-the-platform-specific-bits.patch
new file mode 100644
index 00000000000000..1bdce1ea0c6422
--- /dev/null
+++ b/tty/serial-max3107-abstract-out-the-platform-specific-bits.patch
@@ -0,0 +1,1158 @@
+From alan@linux.intel.com Thu Jul 8 11:28:08 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Wed, 30 Jun 2010 17:58:38 +0100
+Subject: serial: max3107: Abstract out the platform specific bits
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Message-ID: <20100630165831.8720.9189.stgit@localhost.localdomain>
+
+
+At the moment there is only one platform type supported and there is is
+hard wired, but with these changes the infrastructure is now there for
+anyone else to provide methods for their hardware.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/Kconfig | 21 +-
+ drivers/serial/Makefile | 1
+ drivers/serial/max3107-aava.c | 344 ++++++++++++++++++++++++++++++++++
+ drivers/serial/max3107.c | 413 ++++++++----------------------------------
+ drivers/serial/max3107.h | 85 ++++++++
+ include/linux/serial_core.h | 4
+ 6 files changed, 531 insertions(+), 337 deletions(-)
+
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -550,20 +550,29 @@ config SERIAL_S5PV210
+ help
+ Serial port support for Samsung's S5P Family of SoC's
+
++
++config SERIAL_MAX3100
++ tristate "MAX3100 support"
++ depends on SPI
++ select SERIAL_CORE
++ help
++ MAX3100 chip support
++
+ config SERIAL_MAX3107
+ tristate "MAX3107 support"
+- depends on SPI && GPIOLIB
++ depends on SPI
+ select SERIAL_CORE
+- default y
+ help
+ MAX3107 chip support
+
+-config SERIAL_MAX3100
+- tristate "MAX3100 support"
+- depends on SPI
++config SERIAL_MAX3107_AAVA
++ tristate "MAX3107 AAVA platform support"
++ depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB
+ select SERIAL_CORE
+ help
+- MAX3100 chip support
++ Support for the MAX3107 chip configuration found on the AAVA
++ platform. Includes the extra initialisation and GPIO support
++ neded for this device.
+
+ config SERIAL_DZ
+ bool "DECstation DZ serial driver"
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -47,6 +47,7 @@ obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.
+ obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
+ obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
+ obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
++obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
+ obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
+ obj-$(CONFIG_SERIAL_MUX) += mux.o
+ obj-$(CONFIG_SERIAL_68328) += 68328serial.o
+--- /dev/null
++++ b/drivers/serial/max3107-aava.c
+@@ -0,0 +1,344 @@
++/*
++ * max3107.c - spi uart protocol driver for Maxim 3107
++ * Based on max3100.c
++ * by Christian Pellegrin <chripell@evolware.org>
++ * and max3110.c
++ * by Feng Tang <feng.tang@intel.com>
++ *
++ * Copyright (C) Aavamobile 2009
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ */
++
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/serial_core.h>
++#include <linux/serial.h>
++#include <linux/spi/spi.h>
++#include <linux/freezer.h>
++#include <linux/platform_device.h>
++#include <linux/gpio.h>
++#include <linux/sfi.h>
++#include <asm/mrst.h>
++#include "max3107.h"
++
++/* GPIO direction to input function */
++static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[1]; /* Buffer for SPI transfer */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return -EINVAL;
++ }
++
++ /* Read current GPIO configuration register */
++ buf[0] = MAX3107_GPIOCFG_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
++ return -EIO;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++
++ /* Set GPIO to input */
++ buf[0] &= ~(0x0001 << offset);
++
++ /* Write new GPIO configuration register value */
++ buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
++ return -EIO;
++ }
++ return 0;
++}
++
++/* GPIO direction to output function */
++static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[2]; /* Buffer for SPI transfers */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return -EINVAL;
++ }
++
++ /* Read current GPIO configuration and data registers */
++ buf[0] = MAX3107_GPIOCFG_REG;
++ buf[1] = MAX3107_GPIODATA_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
++ dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
++ return -EIO;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++ buf[1] &= MAX3107_SPI_RX_DATA_MASK;
++
++ /* Set GPIO to output */
++ buf[0] |= (0x0001 << offset);
++ /* Set value */
++ if (value)
++ buf[1] |= (0x0001 << offset);
++ else
++ buf[1] &= ~(0x0001 << offset);
++
++ /* Write new GPIO configuration and data register values */
++ buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
++ buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
++ dev_err(&s->spi->dev,
++ "SPI transfer for GPIO conf data w failed\n");
++ return -EIO;
++ }
++ return 0;
++}
++
++/* GPIO value query function */
++static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[1]; /* Buffer for SPI transfer */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return -EINVAL;
++ }
++
++ /* Read current GPIO data register */
++ buf[0] = MAX3107_GPIODATA_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
++ return -EIO;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++
++ /* Return value */
++ return buf[0] & (0x0001 << offset);
++}
++
++/* GPIO value set function */
++static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[2]; /* Buffer for SPI transfers */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return;
++ }
++
++ /* Read current GPIO configuration registers*/
++ buf[0] = MAX3107_GPIODATA_REG;
++ buf[1] = MAX3107_GPIOCFG_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
++ dev_err(&s->spi->dev,
++ "SPI transfer for GPIO data and config read failed\n");
++ return;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++ buf[1] &= MAX3107_SPI_RX_DATA_MASK;
++
++ if (!(buf[1] & (0x0001 << offset))) {
++ /* Configured as input, can't set value */
++ dev_warn(&s->spi->dev,
++ "Trying to set value for input GPIO\n");
++ return;
++ }
++
++ /* Set value */
++ if (value)
++ buf[0] |= (0x0001 << offset);
++ else
++ buf[0] &= ~(0x0001 << offset);
++
++ /* Write new GPIO data register value */
++ buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 2))
++ dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
++}
++
++/* GPIO chip data */
++static struct gpio_chip max3107_gpio_chip = {
++ .owner = THIS_MODULE,
++ .direction_input = max3107_gpio_direction_in,
++ .direction_output = max3107_gpio_direction_out,
++ .get = max3107_gpio_get,
++ .set = max3107_gpio_set,
++ .can_sleep = 1,
++ .base = MAX3107_GPIO_BASE,
++ .ngpio = MAX3107_GPIO_COUNT,
++};
++
++/**
++ * max3107_aava_reset - reset on AAVA systems
++ * @spi: The SPI device we are probing
++ *
++ * Reset the device ready for probing.
++ */
++
++static int max3107_aava_reset(struct spi_device *spi)
++{
++ /* Reset the chip */
++ if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
++ pr_err("Requesting RESET GPIO failed\n");
++ return -EIO;
++ }
++ if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
++ pr_err("Setting RESET GPIO to 0 failed\n");
++ gpio_free(MAX3107_RESET_GPIO);
++ return -EIO;
++ }
++ msleep(MAX3107_RESET_DELAY);
++ if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
++ pr_err("Setting RESET GPIO to 1 failed\n");
++ gpio_free(MAX3107_RESET_GPIO);
++ return -EIO;
++ }
++ gpio_free(MAX3107_RESET_GPIO);
++ msleep(MAX3107_WAKEUP_DELAY);
++ return 0;
++}
++
++static int max3107_aava_configure(struct max3107_port *s)
++{
++ int retval;
++
++ /* Initialize GPIO chip data */
++ s->chip = max3107_gpio_chip;
++ s->chip.label = s->spi->modalias;
++ s->chip.dev = &s->spi->dev;
++
++ /* Add GPIO chip */
++ retval = gpiochip_add(&s->chip);
++ if (retval) {
++ dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
++ return retval;
++ }
++
++ /* Temporary fix for EV2 boot problems, set modem reset to 0 */
++ max3107_gpio_direction_out(&s->chip, 3, 0);
++ return 0;
++}
++
++#if 0
++/* This will get enabled once we have the board stuff merged for this
++ specific case */
++
++static const struct baud_table brg13_ext[] = {
++ { 300, MAX3107_BRG13_B300 },
++ { 600, MAX3107_BRG13_B600 },
++ { 1200, MAX3107_BRG13_B1200 },
++ { 2400, MAX3107_BRG13_B2400 },
++ { 4800, MAX3107_BRG13_B4800 },
++ { 9600, MAX3107_BRG13_B9600 },
++ { 19200, MAX3107_BRG13_B19200 },
++ { 57600, MAX3107_BRG13_B57600 },
++ { 115200, MAX3107_BRG13_B115200 },
++ { 230400, MAX3107_BRG13_B230400 },
++ { 460800, MAX3107_BRG13_B460800 },
++ { 921600, MAX3107_BRG13_B921600 },
++ { 0, 0 }
++};
++
++static void max3107_aava_init(struct max3107_port *s)
++{
++ /*override for AAVA SC specific*/
++ if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
++ if (get_koski_build_id() <= KOSKI_EV2)
++ if (s->ext_clk) {
++ s->brg_cfg = MAX3107_BRG13_B9600;
++ s->baud_tbl = (struct baud_table *)brg13_ext;
++ }
++ }
++}
++#endif
++
++static int __devexit max3107_aava_remove(struct spi_device *spi)
++{
++ struct max3107_port *s = dev_get_drvdata(&spi->dev);
++
++ /* Remove GPIO chip */
++ if (gpiochip_remove(&s->chip))
++ dev_warn(&spi->dev, "Removing GPIO chip failed\n");
++
++ /* Then do the default remove */
++ return max3107_remove(spi);
++}
++
++/* Platform data */
++static struct max3107_plat aava_plat_data = {
++ .loopback = 0,
++ .ext_clk = 1,
++/* .init = max3107_aava_init, */
++ .configure = max3107_aava_configure,
++ .hw_suspend = max3107_hw_susp,
++ .polled_mode = 0,
++ .poll_time = 0,
++};
++
++
++static int __devinit max3107_probe_aava(struct spi_device *spi)
++{
++ int err = max3107_aava_reset(spi);
++ if (err < 0)
++ return err;
++ return max3107_probe(spi, &aava_plat_data);
++}
++
++/* Spi driver data */
++static struct spi_driver max3107_driver = {
++ .driver = {
++ .name = "aava-max3107",
++ .bus = &spi_bus_type,
++ .owner = THIS_MODULE,
++ },
++ .probe = max3107_probe_aava,
++ .remove = __devexit_p(max3107_aava_remove),
++ .suspend = max3107_suspend,
++ .resume = max3107_resume,
++};
++
++/* Driver init function */
++static int __init max3107_init(void)
++{
++ return spi_register_driver(&max3107_driver);
++}
++
++/* Driver exit function */
++static void __exit max3107_exit(void)
++{
++ spi_unregister_driver(&max3107_driver);
++}
++
++module_init(max3107_init);
++module_exit(max3107_exit);
++
++MODULE_DESCRIPTION("MAX3107 driver");
++MODULE_AUTHOR("Aavamobile");
++MODULE_ALIAS("aava-max3107-spi");
++MODULE_LICENSE("GPL v2");
+--- a/drivers/serial/max3107.c
++++ b/drivers/serial/max3107.c
+@@ -31,98 +31,12 @@
+ #include <linux/device.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial.h>
++#include <linux/gpio.h>
+ #include <linux/spi/spi.h>
+ #include <linux/freezer.h>
+-#include <linux/platform_device.h>
+-#include <linux/gpio.h>
+-#include <linux/sfi.h>
+-#include <asm/mrst.h>
+ #include "max3107.h"
+
+-struct baud_table {
+- int baud;
+- u32 new_brg;
+-};
+-
+-struct max3107_port {
+- /* UART port structure */
+- struct uart_port port;
+-
+- /* SPI device structure */
+- struct spi_device *spi;
+-
+- /* GPIO chip stucture */
+- struct gpio_chip chip;
+-
+- /* Workqueue that does all the magic */
+- struct workqueue_struct *workqueue;
+- struct work_struct work;
+-
+- /* Lock for shared data */
+- spinlock_t data_lock;
+-
+- /* Device configuration */
+- int ext_clk; /* 1 if external clock used */
+- int loopback; /* Current loopback mode state */
+- int baud; /* Current baud rate */
+-
+- /* State flags */
+- int suspended; /* Indicates suspend mode */
+- int tx_fifo_empty; /* Flag for TX FIFO state */
+- int rx_enabled; /* Flag for receiver state */
+- int tx_enabled; /* Flag for transmitter state */
+-
+- u16 irqen_reg; /* Current IRQ enable register value */
+- /* Shared data */
+- u16 mode1_reg; /* Current mode1 register value*/
+- int mode1_commit; /* Flag for setting new mode1 register value */
+- u16 lcr_reg; /* Current LCR register value */
+- int lcr_commit; /* Flag for setting new LCR register value */
+- u32 brg_cfg; /* Current Baud rate generator config */
+- int brg_commit; /* Flag for setting new baud rate generator
+- * config
+- */
+- struct baud_table *baud_tbl;
+- int handle_irq; /* Indicates that IRQ should be handled */
+-
+- /* Rx buffer and str*/
+- u16 *rxbuf;
+- u8 *rxstr;
+- /* Tx buffer*/
+- u16 *txbuf;
+-};
+-
+-/* Platform data structure */
+-struct max3107_plat {
+- /* Loopback mode enable */
+- int loopback;
+- /* External clock enable */
+- int ext_clk;
+- /* HW suspend function */
+- void (*max3107_hw_suspend) (struct max3107_port *s, int suspend);
+- /* Polling mode enable */
+- int polled_mode;
+- /* Polling period if polling mode enabled */
+- int poll_time;
+-};
+-
+-static struct baud_table brg13_ext[] = {
+- { 300, MAX3107_BRG13_B300 },
+- { 600, MAX3107_BRG13_B600 },
+- { 1200, MAX3107_BRG13_B1200 },
+- { 2400, MAX3107_BRG13_B2400 },
+- { 4800, MAX3107_BRG13_B4800 },
+- { 9600, MAX3107_BRG13_B9600 },
+- { 19200, MAX3107_BRG13_B19200 },
+- { 57600, MAX3107_BRG13_B57600 },
+- { 115200, MAX3107_BRG13_B115200 },
+- { 230400, MAX3107_BRG13_B230400 },
+- { 460800, MAX3107_BRG13_B460800 },
+- { 921600, MAX3107_BRG13_B921600 },
+- { 0, 0 }
+-};
+-
+-static struct baud_table brg26_ext[] = {
++static const struct baud_table brg26_ext[] = {
+ { 300, MAX3107_BRG26_B300 },
+ { 600, MAX3107_BRG26_B600 },
+ { 1200, MAX3107_BRG26_B1200 },
+@@ -138,7 +52,7 @@ static struct baud_table brg26_ext[] = {
+ { 0, 0 }
+ };
+
+-static struct baud_table brg13_int[] = {
++static const struct baud_table brg13_int[] = {
+ { 300, MAX3107_BRG13_IB300 },
+ { 600, MAX3107_BRG13_IB600 },
+ { 1200, MAX3107_BRG13_IB1200 },
+@@ -157,7 +71,7 @@ static struct baud_table brg13_int[] = {
+ static u32 get_new_brg(int baud, struct max3107_port *s)
+ {
+ int i;
+- struct baud_table *baud_tbl = s->baud_tbl;
++ const struct baud_table *baud_tbl = s->baud_tbl;
+
+ for (i = 0; i < 13; i++) {
+ if (baud == baud_tbl[i].baud)
+@@ -168,7 +82,7 @@ static u32 get_new_brg(int baud, struct
+ }
+
+ /* Perform SPI transfer for write/read of device register(s) */
+-static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
++int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
+ {
+ struct spi_message spi_msg;
+ struct spi_transfer spi_xfer;
+@@ -213,6 +127,7 @@ static int max3107_rw(struct max3107_por
+ #endif
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(max3107_rw);
+
+ /* Puts received data to circular buffer */
+ static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
+@@ -611,16 +526,10 @@ static void max3107_register_init(struct
+ s->brg_cfg = MAX3107_BRG13_IB9600;
+ s->baud_tbl = (struct baud_table *)brg13_int;
+ }
+-#if 0
+- /*override for AAVA SC specific*/
+- if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
+- if (get_koski_build_id() <= KOSKI_EV2)
+- if (s->ext_clk) {
+- s->brg_cfg = MAX3107_BRG13_B9600;
+- s->baud_tbl = (struct baud_table *)brg13_ext;
+- }
+- }
+-#endif
++
++ if (s->pdata->init)
++ s->pdata->init(s);
++
+ buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG)
+ | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
+ buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG)
+@@ -734,7 +643,7 @@ static irqreturn_t max3107_irq(int irqno
+ * used but that would mess the GPIOs
+ *
+ */
+-static void max3107_hw_susp(struct max3107_port *s, int suspend)
++void max3107_hw_susp(struct max3107_port *s, int suspend)
+ {
+ pr_debug("enter, suspend %d\n", suspend);
+
+@@ -752,6 +661,7 @@ static void max3107_hw_susp(struct max31
+ max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
+ }
+ }
++EXPORT_SYMBOL_GPL(max3107_hw_susp);
+
+ /* Modem status IRQ enabling */
+ static void max3107_enable_ms(struct uart_port *port)
+@@ -899,10 +809,8 @@ static void max3107_shutdown(struct uart
+ {
+ struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+- if (s->suspended) {
+- /* Resume HW */
+- max3107_hw_susp(s, 0);
+- }
++ if (s->suspended && s->pdata->hw_suspend)
++ s->pdata->hw_suspend(s, 0);
+
+ /* Free the interrupt */
+ free_irq(s->spi->irq, s);
+@@ -915,7 +823,8 @@ static void max3107_shutdown(struct uart
+ }
+
+ /* Suspend HW */
+- max3107_hw_susp(s, 1);
++ if (s->pdata->hw_suspend)
++ s->pdata->hw_suspend(s, 1);
+ }
+
+ /* Port startup function */
+@@ -941,7 +850,8 @@ static int max3107_startup(struct uart_p
+ }
+
+ /* Resume HW */
+- max3107_hw_susp(s, 0);
++ if (s->pdata->hw_suspend)
++ s->pdata->hw_suspend(s, 0);
+
+ /* Init registers */
+ max3107_register_init(s);
+@@ -973,16 +883,14 @@ static int max3107_request_port(struct u
+ static void max3107_config_port(struct uart_port *port, int flags)
+ {
+ struct max3107_port *s = container_of(port, struct max3107_port, port);
+-
+- /* Use PORT_MAX3100 since we are at least int the same series */
+- s->port.type = PORT_MAX3100;
++ s->port.type = PORT_MAX3107;
+ }
+
+ /* Port verify function */
+ static int max3107_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+ {
+- if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
++ if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107)
+ return 0;
+
+ return -EINVAL;
+@@ -1000,157 +908,6 @@ static void max3107_break_ctl(struct uar
+ /* We don't support break control, do nothing */
+ }
+
+-/* GPIO direction to input function */
+-static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+-{
+- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+- u16 buf[1]; /* Buffer for SPI transfer */
+-
+- if (offset >= MAX3107_GPIO_COUNT) {
+- dev_err(&s->spi->dev, "Invalid GPIO\n");
+- return -EINVAL;
+- }
+-
+- /* Read current GPIO configuration register */
+- buf[0] = MAX3107_GPIOCFG_REG;
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+- dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
+- return -EIO;
+- }
+- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+-
+- /* Set GPIO to input */
+- buf[0] &= ~(0x0001 << offset);
+-
+- /* Write new GPIO configuration register value */
+- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
+- dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
+- return -EIO;
+- }
+- return 0;
+-}
+-
+-/* GPIO direction to output function */
+-static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
+- int value)
+-{
+- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+- u16 buf[2]; /* Buffer for SPI transfers */
+-
+- if (offset >= MAX3107_GPIO_COUNT) {
+- dev_err(&s->spi->dev, "Invalid GPIO\n");
+- return -EINVAL;
+- }
+-
+- /* Read current GPIO configuration and data registers */
+- buf[0] = MAX3107_GPIOCFG_REG;
+- buf[1] = MAX3107_GPIODATA_REG;
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
+- dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
+- return -EIO;
+- }
+- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
+-
+- /* Set GPIO to output */
+- buf[0] |= (0x0001 << offset);
+- /* Set value */
+- if (value)
+- buf[1] |= (0x0001 << offset);
+- else
+- buf[1] &= ~(0x0001 << offset);
+-
+- /* Write new GPIO configuration and data register values */
+- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
+- buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
+- dev_err(&s->spi->dev,
+- "SPI transfer for GPIO conf data w failed\n");
+- return -EIO;
+- }
+- return 0;
+-}
+-
+-/* GPIO value query function */
+-static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
+-{
+- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+- u16 buf[1]; /* Buffer for SPI transfer */
+-
+- if (offset >= MAX3107_GPIO_COUNT) {
+- dev_err(&s->spi->dev, "Invalid GPIO\n");
+- return -EINVAL;
+- }
+-
+- /* Read current GPIO data register */
+- buf[0] = MAX3107_GPIODATA_REG;
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+- dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
+- return -EIO;
+- }
+- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+-
+- /* Return value */
+- return buf[0] & (0x0001 << offset);
+-}
+-
+-/* GPIO value set function */
+-static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+-{
+- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+- u16 buf[2]; /* Buffer for SPI transfers */
+-
+- if (offset >= MAX3107_GPIO_COUNT) {
+- dev_err(&s->spi->dev, "Invalid GPIO\n");
+- return;
+- }
+-
+- /* Read current GPIO configuration registers*/
+- buf[0] = MAX3107_GPIODATA_REG;
+- buf[1] = MAX3107_GPIOCFG_REG;
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
+- dev_err(&s->spi->dev,
+- "SPI transfer for GPIO data and config read failed\n");
+- return;
+- }
+- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
+-
+- if (!(buf[1] & (0x0001 << offset))) {
+- /* Configured as input, can't set value */
+- dev_warn(&s->spi->dev,
+- "Trying to set value for input GPIO\n");
+- return;
+- }
+-
+- /* Set value */
+- if (value)
+- buf[0] |= (0x0001 << offset);
+- else
+- buf[0] &= ~(0x0001 << offset);
+-
+- /* Write new GPIO data register value */
+- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
+- /* Perform SPI transfer */
+- if (max3107_rw(s, (u8 *)buf, NULL, 2))
+- dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
+-}
+-
+-/* Platform data */
+-static struct max3107_plat max3107_plat_data = {
+- .loopback = 0,
+- .ext_clk = 1,
+- .max3107_hw_suspend = &max3107_hw_susp,
+- .polled_mode = 0,
+- .poll_time = 0,
+-};
+
+ /* Port functions */
+ static struct uart_ops max3107_ops = {
+@@ -1180,52 +937,48 @@ static struct uart_driver max3107_uart_d
+ .nr = 1,
+ };
+
+-/* GPIO chip data */
+-static struct gpio_chip max3107_gpio_chip = {
+- .owner = THIS_MODULE,
+- .direction_input = max3107_gpio_direction_in,
+- .direction_output = max3107_gpio_direction_out,
+- .get = max3107_gpio_get,
+- .set = max3107_gpio_set,
+- .can_sleep = 1,
+- .base = MAX3107_GPIO_BASE,
+- .ngpio = MAX3107_GPIO_COUNT,
++static int driver_registered = 0;
++
++
++
++/* 'Generic' platform data */
++static struct max3107_plat generic_plat_data = {
++ .loopback = 0,
++ .ext_clk = 1,
++ .hw_suspend = max3107_hw_susp,
++ .polled_mode = 0,
++ .poll_time = 0,
+ };
+-/* Device probe function */
+-static int __devinit max3107_probe(struct spi_device *spi)
++
++
++/*******************************************************************/
++
++/**
++ * max3107_probe - SPI bus probe entry point
++ * @spi: the spi device
++ *
++ * SPI wants us to probe this device and if appropriate claim it.
++ * Perform any platform specific requirements and then initialise
++ * the device.
++ */
++
++int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
+ {
+ struct max3107_port *s;
+- struct max3107_plat *pdata = &max3107_plat_data;
+ u16 buf[2]; /* Buffer for SPI transfers */
+ int retval;
+
+ pr_info("enter max3107 probe\n");
+
+- /* Reset the chip */
+- if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
+- pr_err("Requesting RESET GPIO failed\n");
+- return -EIO;
+- }
+- if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
+- pr_err("Setting RESET GPIO to 0 failed\n");
+- gpio_free(MAX3107_RESET_GPIO);
+- return -EIO;
+- }
+- msleep(MAX3107_RESET_DELAY);
+- if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
+- pr_err("Setting RESET GPIO to 1 failed\n");
+- gpio_free(MAX3107_RESET_GPIO);
+- return -EIO;
+- }
+- gpio_free(MAX3107_RESET_GPIO);
+- msleep(MAX3107_WAKEUP_DELAY);
+-
+ /* Allocate port structure */
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
+ if (!s) {
+ pr_err("Allocating port structure failed\n");
+ return -ENOMEM;
+ }
++
++ s->pdata = pdata;
++
+ /* SPI Rx buffer
+ * +2 for RX FIFO interrupt
+ * disabling and RX level query
+@@ -1298,10 +1051,13 @@ static int __devinit max3107_probe(struc
+ }
+
+ /* Register UART driver */
+- retval = uart_register_driver(&max3107_uart_driver);
+- if (retval) {
+- dev_err(&s->spi->dev, "Registering UART driver failed\n");
+- return retval;
++ if (!driver_registered) {
++ retval = uart_register_driver(&max3107_uart_driver);
++ if (retval) {
++ dev_err(&s->spi->dev, "Registering UART driver failed\n");
++ return retval;
++ }
++ driver_registered = 1;
+ }
+
+ /* Initialize UART port data */
+@@ -1312,8 +1068,7 @@ static int __devinit max3107_probe(struc
+ s->port.uartclk = 9600;
+ s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ s->port.irq = s->spi->irq;
+- /* Use PORT_MAX3100 since we are at least in the same series */
+- s->port.type = PORT_MAX3100;
++ s->port.type = PORT_MAX3107;
+
+ /* Add UART port */
+ retval = uart_add_one_port(&max3107_uart_driver, &s->port);
+@@ -1322,44 +1077,31 @@ static int __devinit max3107_probe(struc
+ return retval;
+ }
+
+- /* Initialize GPIO chip data */
+- s->chip = max3107_gpio_chip;
+- s->chip.label = spi->modalias;
+- s->chip.dev = &spi->dev;
+-
+- /* Add GPIO chip */
+- retval = gpiochip_add(&s->chip);
+- if (retval) {
+- dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
+- return retval;
++ if (pdata->configure) {
++ retval = pdata->configure(s);
++ if (retval < 0)
++ return retval;
+ }
+
+- /* Temporary fix for EV2 boot problems, set modem reset to 0 */
+- max3107_gpio_direction_out(&s->chip, 3, 0);
+-
+ /* Go to suspend mode */
+- max3107_hw_susp(s, 1);
++ if (pdata->hw_suspend)
++ pdata->hw_suspend(s, 1);
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(max3107_probe);
+
+ /* Driver remove function */
+-static int __devexit max3107_remove(struct spi_device *spi)
++int max3107_remove(struct spi_device *spi)
+ {
+ struct max3107_port *s = dev_get_drvdata(&spi->dev);
+
+ pr_info("enter max3107 remove\n");
+
+- /* Remove GPIO chip */
+- if (gpiochip_remove(&s->chip))
+- dev_warn(&s->spi->dev, "Removing GPIO chip failed\n");
+-
+ /* Remove port */
+ if (uart_remove_one_port(&max3107_uart_driver, &s->port))
+ dev_warn(&s->spi->dev, "Removing UART port failed\n");
+
+- /* Unregister UART driver */
+- uart_unregister_driver(&max3107_uart_driver);
+
+ /* Free TxRx buffer */
+ kfree(s->rxbuf);
+@@ -1371,9 +1113,10 @@ static int __devexit max3107_remove(stru
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(max3107_remove);
+
+ /* Driver suspend function */
+-static int max3107_suspend(struct spi_device *spi, pm_message_t state)
++int max3107_suspend(struct spi_device *spi, pm_message_t state)
+ {
+ #ifdef CONFIG_PM
+ struct max3107_port *s = dev_get_drvdata(&spi->dev);
+@@ -1384,13 +1127,15 @@ static int max3107_suspend(struct spi_de
+ uart_suspend_port(&max3107_uart_driver, &s->port);
+
+ /* Go to suspend mode */
+- max3107_hw_susp(s, 1);
++ if (s->pdata->hw_suspend)
++ s->pdata->hw_suspend(s, 1);
+ #endif /* CONFIG_PM */
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(max3107_suspend);
+
+ /* Driver resume function */
+-static int max3107_resume(struct spi_device *spi)
++int max3107_resume(struct spi_device *spi)
+ {
+ #ifdef CONFIG_PM
+ struct max3107_port *s = dev_get_drvdata(&spi->dev);
+@@ -1398,13 +1143,20 @@ static int max3107_resume(struct spi_dev
+ pr_debug("enter resume\n");
+
+ /* Resume from suspend */
+- max3107_hw_susp(s, 0);
++ if (s->pdata->hw_suspend)
++ s->pdata->hw_suspend(s, 0);
+
+ /* Resume UART port */
+ uart_resume_port(&max3107_uart_driver, &s->port);
+ #endif /* CONFIG_PM */
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(max3107_resume);
++
++static int max3107_probe_generic(struct spi_device *spi)
++{
++ return max3107_probe(spi, &generic_plat_data);
++}
+
+ /* Spi driver data */
+ static struct spi_driver max3107_driver = {
+@@ -1413,7 +1165,7 @@ static struct spi_driver max3107_driver
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+- .probe = max3107_probe,
++ .probe = max3107_probe_generic,
+ .remove = __devexit_p(max3107_remove),
+ .suspend = max3107_suspend,
+ .resume = max3107_resume,
+@@ -1430,6 +1182,9 @@ static int __init max3107_init(void)
+ static void __exit max3107_exit(void)
+ {
+ pr_info("enter max3107 exit\n");
++ /* Unregister UART driver */
++ if (driver_registered)
++ uart_unregister_driver(&max3107_uart_driver);
+ spi_unregister_driver(&max3107_driver);
+ }
+
+@@ -1438,5 +1193,5 @@ module_exit(max3107_exit);
+
+ MODULE_DESCRIPTION("MAX3107 driver");
+ MODULE_AUTHOR("Aavamobile");
+-MODULE_ALIAS("max3107-spi-uart");
+-MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("max3107-spi");
++MODULE_LICENSE("GPL v2");
+--- a/drivers/serial/max3107.h
++++ b/drivers/serial/max3107.h
+@@ -10,8 +10,8 @@
+ * (at your option) any later version.
+ */
+
+-#ifndef _LINUX_SERIAL_MAX3107_H
+-#define _LINUX_SERIAL_MAX3107_H
++#ifndef _MAX3107_H
++#define _MAX3107_H
+
+ /* Serial error status definitions */
+ #define MAX3107_PARITY_ERROR 1
+@@ -355,4 +355,85 @@
+ #define MAX3107_BRG13_IB460800 (0x000000 | 0x00)
+ #define MAX3107_BRG13_IB921600 (0x000000 | 0x00)
+
++
++struct baud_table {
++ int baud;
++ u32 new_brg;
++};
++
++struct max3107_port {
++ /* UART port structure */
++ struct uart_port port;
++
++ /* SPI device structure */
++ struct spi_device *spi;
++
++ /* GPIO chip stucture */
++ struct gpio_chip chip;
++
++ /* Workqueue that does all the magic */
++ struct workqueue_struct *workqueue;
++ struct work_struct work;
++
++ /* Lock for shared data */
++ spinlock_t data_lock;
++
++ /* Device configuration */
++ int ext_clk; /* 1 if external clock used */
++ int loopback; /* Current loopback mode state */
++ int baud; /* Current baud rate */
++
++ /* State flags */
++ int suspended; /* Indicates suspend mode */
++ int tx_fifo_empty; /* Flag for TX FIFO state */
++ int rx_enabled; /* Flag for receiver state */
++ int tx_enabled; /* Flag for transmitter state */
++
++ u16 irqen_reg; /* Current IRQ enable register value */
++ /* Shared data */
++ u16 mode1_reg; /* Current mode1 register value*/
++ int mode1_commit; /* Flag for setting new mode1 register value */
++ u16 lcr_reg; /* Current LCR register value */
++ int lcr_commit; /* Flag for setting new LCR register value */
++ u32 brg_cfg; /* Current Baud rate generator config */
++ int brg_commit; /* Flag for setting new baud rate generator
++ * config
++ */
++ struct baud_table *baud_tbl;
++ int handle_irq; /* Indicates that IRQ should be handled */
++
++ /* Rx buffer and str*/
++ u16 *rxbuf;
++ u8 *rxstr;
++ /* Tx buffer*/
++ u16 *txbuf;
++
++ struct max3107_plat *pdata; /* Platform data */
++};
++
++/* Platform data structure */
++struct max3107_plat {
++ /* Loopback mode enable */
++ int loopback;
++ /* External clock enable */
++ int ext_clk;
++ /* Called during the register initialisation */
++ void (*init)(struct max3107_port *s);
++ /* Called when the port is found and configured */
++ int (*configure)(struct max3107_port *s);
++ /* HW suspend function */
++ void (*hw_suspend) (struct max3107_port *s, int suspend);
++ /* Polling mode enable */
++ int polled_mode;
++ /* Polling period if polling mode enabled */
++ int poll_time;
++};
++
++extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len);
++extern void max3107_hw_susp(struct max3107_port *s, int suspend);
++extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata);
++extern int max3107_remove(struct spi_device *spi);
++extern int max3107_suspend(struct spi_device *spi, pm_message_t state);
++extern int max3107_resume(struct spi_device *spi);
++
+ #endif /* _LINUX_SERIAL_MAX3107_H */
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -186,6 +186,10 @@
+ #define PORT_ALTERA_JTAGUART 91
+ #define PORT_ALTERA_UART 92
+
++/* MAX3107 */
++#define PORT_MAX3107 94
++
++
+ #ifdef __KERNEL__
+
+ #include <linux/compiler.h>
diff --git a/tty/serial-max3107-introduce-a-max3107-driver.patch b/tty/serial-max3107-introduce-a-max3107-driver.patch
new file mode 100644
index 00000000000000..56b648f6d3850f
--- /dev/null
+++ b/tty/serial-max3107-introduce-a-max3107-driver.patch
@@ -0,0 +1,1860 @@
+From alan@linux.intel.com Thu Jul 8 11:27:42 2010
+From: jianwei.yang <jianwei.yang@intel.com>
+Date: Wed, 30 Jun 2010 17:57:12 +0100
+Subject: serial: max3107: introduce a max3107 driver
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Message-ID: <20100630165707.8519.16480.stgit@localhost.localdomain>
+
+
+From: jianwei.yang <jianwei.yang@intel.com>
+
+This device is used by some of the Intel MID platforms. It's not similar
+enough to the MAX3100 to use the same driver.
+
+At this point the driver is specific to the platform and not generalised.
+We will fix that later.
+
+Signed-off-by: jianwei.yang <jianwei.yang@intel.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/Kconfig | 8
+ drivers/serial/Makefile | 1
+ drivers/serial/max3107.c | 1442 +++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/serial/max3107.h | 358 +++++++++++
+ 4 files changed, 1809 insertions(+)
+
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -550,6 +550,14 @@ config SERIAL_S5PV210
+ help
+ Serial port support for Samsung's S5P Family of SoC's
+
++config SERIAL_MAX3107
++ tristate "MAX3107 support"
++ depends on SPI && GPIOLIB
++ select SERIAL_CORE
++ default y
++ help
++ MAX3107 chip support
++
+ config SERIAL_MAX3100
+ tristate "MAX3100 support"
+ depends on SPI
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.
+ obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
+ obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
+ obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
++obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
+ obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
+ obj-$(CONFIG_SERIAL_MUX) += mux.o
+ obj-$(CONFIG_SERIAL_68328) += 68328serial.o
+--- /dev/null
++++ b/drivers/serial/max3107.c
+@@ -0,0 +1,1442 @@
++/*
++ * max3107.c - spi uart protocol driver for Maxim 3107
++ * Based on max3100.c
++ * by Christian Pellegrin <chripell@evolware.org>
++ * and max3110.c
++ * by Feng Tang <feng.tang@intel.com>
++ *
++ * Copyright (C) Aavamobile 2009
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ */
++
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/serial_core.h>
++#include <linux/serial.h>
++#include <linux/spi/spi.h>
++#include <linux/freezer.h>
++#include <linux/platform_device.h>
++#include <linux/gpio.h>
++#include <linux/sfi.h>
++#include <asm/mrst.h>
++#include "max3107.h"
++
++struct baud_table {
++ int baud;
++ u32 new_brg;
++};
++
++struct max3107_port {
++ /* UART port structure */
++ struct uart_port port;
++
++ /* SPI device structure */
++ struct spi_device *spi;
++
++ /* GPIO chip stucture */
++ struct gpio_chip chip;
++
++ /* Workqueue that does all the magic */
++ struct workqueue_struct *workqueue;
++ struct work_struct work;
++
++ /* Lock for shared data */
++ spinlock_t data_lock;
++
++ /* Device configuration */
++ int ext_clk; /* 1 if external clock used */
++ int loopback; /* Current loopback mode state */
++ int baud; /* Current baud rate */
++
++ /* State flags */
++ int suspended; /* Indicates suspend mode */
++ int tx_fifo_empty; /* Flag for TX FIFO state */
++ int rx_enabled; /* Flag for receiver state */
++ int tx_enabled; /* Flag for transmitter state */
++
++ u16 irqen_reg; /* Current IRQ enable register value */
++ /* Shared data */
++ u16 mode1_reg; /* Current mode1 register value*/
++ int mode1_commit; /* Flag for setting new mode1 register value */
++ u16 lcr_reg; /* Current LCR register value */
++ int lcr_commit; /* Flag for setting new LCR register value */
++ u32 brg_cfg; /* Current Baud rate generator config */
++ int brg_commit; /* Flag for setting new baud rate generator
++ * config
++ */
++ struct baud_table *baud_tbl;
++ int handle_irq; /* Indicates that IRQ should be handled */
++
++ /* Rx buffer and str*/
++ u16 *rxbuf;
++ u8 *rxstr;
++ /* Tx buffer*/
++ u16 *txbuf;
++};
++
++/* Platform data structure */
++struct max3107_plat {
++ /* Loopback mode enable */
++ int loopback;
++ /* External clock enable */
++ int ext_clk;
++ /* HW suspend function */
++ void (*max3107_hw_suspend) (struct max3107_port *s, int suspend);
++ /* Polling mode enable */
++ int polled_mode;
++ /* Polling period if polling mode enabled */
++ int poll_time;
++};
++
++static struct baud_table brg13_ext[] = {
++ { 300, MAX3107_BRG13_B300 },
++ { 600, MAX3107_BRG13_B600 },
++ { 1200, MAX3107_BRG13_B1200 },
++ { 2400, MAX3107_BRG13_B2400 },
++ { 4800, MAX3107_BRG13_B4800 },
++ { 9600, MAX3107_BRG13_B9600 },
++ { 19200, MAX3107_BRG13_B19200 },
++ { 57600, MAX3107_BRG13_B57600 },
++ { 115200, MAX3107_BRG13_B115200 },
++ { 230400, MAX3107_BRG13_B230400 },
++ { 460800, MAX3107_BRG13_B460800 },
++ { 921600, MAX3107_BRG13_B921600 },
++ { 0, 0 }
++};
++
++static struct baud_table brg26_ext[] = {
++ { 300, MAX3107_BRG26_B300 },
++ { 600, MAX3107_BRG26_B600 },
++ { 1200, MAX3107_BRG26_B1200 },
++ { 2400, MAX3107_BRG26_B2400 },
++ { 4800, MAX3107_BRG26_B4800 },
++ { 9600, MAX3107_BRG26_B9600 },
++ { 19200, MAX3107_BRG26_B19200 },
++ { 57600, MAX3107_BRG26_B57600 },
++ { 115200, MAX3107_BRG26_B115200 },
++ { 230400, MAX3107_BRG26_B230400 },
++ { 460800, MAX3107_BRG26_B460800 },
++ { 921600, MAX3107_BRG26_B921600 },
++ { 0, 0 }
++};
++
++static struct baud_table brg13_int[] = {
++ { 300, MAX3107_BRG13_IB300 },
++ { 600, MAX3107_BRG13_IB600 },
++ { 1200, MAX3107_BRG13_IB1200 },
++ { 2400, MAX3107_BRG13_IB2400 },
++ { 4800, MAX3107_BRG13_IB4800 },
++ { 9600, MAX3107_BRG13_IB9600 },
++ { 19200, MAX3107_BRG13_IB19200 },
++ { 57600, MAX3107_BRG13_IB57600 },
++ { 115200, MAX3107_BRG13_IB115200 },
++ { 230400, MAX3107_BRG13_IB230400 },
++ { 460800, MAX3107_BRG13_IB460800 },
++ { 921600, MAX3107_BRG13_IB921600 },
++ { 0, 0 }
++};
++
++static u32 get_new_brg(int baud, struct max3107_port *s)
++{
++ int i;
++ struct baud_table *baud_tbl = s->baud_tbl;
++
++ for (i = 0; i < 13; i++) {
++ if (baud == baud_tbl[i].baud)
++ return baud_tbl[i].new_brg;
++ }
++
++ return 0;
++}
++
++/* Perform SPI transfer for write/read of device register(s) */
++static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
++{
++ struct spi_message spi_msg;
++ struct spi_transfer spi_xfer;
++
++ /* Initialize SPI ,message */
++ spi_message_init(&spi_msg);
++
++ /* Initialize SPI transfer */
++ memset(&spi_xfer, 0, sizeof spi_xfer);
++ spi_xfer.len = len;
++ spi_xfer.tx_buf = tx;
++ spi_xfer.rx_buf = rx;
++ spi_xfer.speed_hz = MAX3107_SPI_SPEED;
++
++ /* Add SPI transfer to SPI message */
++ spi_message_add_tail(&spi_xfer, &spi_msg);
++
++#ifdef DBG_TRACE_SPI_DATA
++ {
++ int i;
++ pr_info("tx len %d:\n", spi_xfer.len);
++ for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
++ pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]);
++ pr_info("\n");
++ }
++#endif
++
++ /* Perform synchronous SPI transfer */
++ if (spi_sync(s->spi, &spi_msg)) {
++ dev_err(&s->spi->dev, "spi_sync failure\n");
++ return -EIO;
++ }
++
++#ifdef DBG_TRACE_SPI_DATA
++ if (spi_xfer.rx_buf) {
++ int i;
++ pr_info("rx len %d:\n", spi_xfer.len);
++ for (i = 0 ; i < spi_xfer.len && i < 32 ; i++)
++ pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]);
++ pr_info("\n");
++ }
++#endif
++ return 0;
++}
++
++/* Puts received data to circular buffer */
++static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
++ int len)
++{
++ struct uart_port *port = &s->port;
++ struct tty_struct *tty;
++
++ if (!port->state)
++ return;
++
++ tty = port->state->port.tty;
++ if (!tty)
++ return;
++
++ /* Insert received data */
++ tty_insert_flip_string(tty, data, len);
++ /* Update RX counter */
++ port->icount.rx += len;
++}
++
++/* Handle data receiving */
++static void max3107_handlerx(struct max3107_port *s, u16 rxlvl)
++{
++ int i;
++ int j;
++ int len; /* SPI transfer buffer length */
++ u16 *buf;
++ u8 *valid_str;
++
++ if (!s->rx_enabled)
++ /* RX is disabled */
++ return;
++
++ if (rxlvl == 0) {
++ /* RX fifo is empty */
++ return;
++ } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) {
++ dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl);
++ /* Ensure sanity of RX level */
++ rxlvl = MAX3107_RX_FIFO_SIZE;
++ }
++ if ((s->rxbuf == 0) || (s->rxstr == 0)) {
++ dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n");
++ return;
++ }
++ buf = s->rxbuf;
++ valid_str = s->rxstr;
++ while (rxlvl) {
++ pr_debug("rxlvl %d\n", rxlvl);
++ /* Clear buffer */
++ memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2));
++ len = 0;
++ if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) {
++ /* First disable RX FIFO interrupt */
++ pr_debug("Disabling RX INT\n");
++ buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
++ s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT;
++ buf[0] |= s->irqen_reg;
++ len++;
++ }
++ /* Just increase the length by amount of words in FIFO since
++ * buffer was zeroed and SPI transfer of 0x0000 means reading
++ * from RX FIFO
++ */
++ len += rxlvl;
++ /* Append RX level query */
++ buf[len] = MAX3107_RXFIFOLVL_REG;
++ len++;
++
++ /* Perform the SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) {
++ dev_err(&s->spi->dev, "SPI transfer for RX h failed\n");
++ return;
++ }
++
++ /* Skip RX FIFO interrupt disabling word if it was added */
++ j = ((len - 1) - rxlvl);
++ /* Read received words */
++ for (i = 0; i < rxlvl; i++, j++)
++ valid_str[i] = (u8)buf[j];
++ put_data_to_circ_buf(s, valid_str, rxlvl);
++ /* Get new RX level */
++ rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK);
++ }
++
++ if (s->rx_enabled) {
++ /* RX still enabled, re-enable RX FIFO interrupt */
++ pr_debug("Enabling RX INT\n");
++ buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
++ s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
++ buf[0] |= s->irqen_reg;
++ if (max3107_rw(s, (u8 *)buf, NULL, 2))
++ dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n");
++ }
++
++ /* Push the received data to receivers */
++ if (s->port.state->port.tty)
++ tty_flip_buffer_push(s->port.state->port.tty);
++}
++
++
++/* Handle data sending */
++static void max3107_handletx(struct max3107_port *s)
++{
++ struct circ_buf *xmit = &s->port.state->xmit;
++ int i;
++ unsigned long flags;
++ int len; /* SPI transfer buffer length */
++ u16 *buf;
++
++ if (!s->tx_fifo_empty)
++ /* Don't send more data before previous data is sent */
++ return;
++
++ if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
++ /* No data to send or TX is stopped */
++ return;
++
++ if (!s->txbuf) {
++ dev_warn(&s->spi->dev, "Txbuf isn't ready\n");
++ return;
++ }
++ buf = s->txbuf;
++ /* Get length of data pending in circular buffer */
++ len = uart_circ_chars_pending(xmit);
++ if (len) {
++ /* Limit to size of TX FIFO */
++ if (len > MAX3107_TX_FIFO_SIZE)
++ len = MAX3107_TX_FIFO_SIZE;
++
++ pr_debug("txlen %d\n", len);
++
++ /* Update TX counter */
++ s->port.icount.tx += len;
++
++ /* TX FIFO will no longer be empty */
++ s->tx_fifo_empty = 0;
++
++ i = 0;
++ if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) {
++ /* First disable TX empty interrupt */
++ pr_debug("Disabling TE INT\n");
++ buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
++ s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT;
++ buf[i] |= s->irqen_reg;
++ i++;
++ len++;
++ }
++ /* Add data to send */
++ spin_lock_irqsave(&s->port.lock, flags);
++ for ( ; i < len ; i++) {
++ buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG);
++ buf[i] |= ((u16)xmit->buf[xmit->tail] &
++ MAX3107_SPI_TX_DATA_MASK);
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ }
++ spin_unlock_irqrestore(&s->port.lock, flags);
++ if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) {
++ /* Enable TX empty interrupt */
++ pr_debug("Enabling TE INT\n");
++ buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
++ s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT;
++ buf[i] |= s->irqen_reg;
++ i++;
++ len++;
++ }
++ if (!s->tx_enabled) {
++ /* Enable TX */
++ pr_debug("Enable TX\n");
++ buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
++ spin_lock_irqsave(&s->data_lock, flags);
++ s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT;
++ buf[i] |= s->mode1_reg;
++ spin_unlock_irqrestore(&s->data_lock, flags);
++ s->tx_enabled = 1;
++ i++;
++ len++;
++ }
++
++ /* Perform the SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, len*2)) {
++ dev_err(&s->spi->dev,
++ "SPI transfer TX handling failed\n");
++ return;
++ }
++ }
++
++ /* Indicate wake up if circular buffer is getting low on data */
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&s->port);
++
++}
++
++/* Handle interrupts
++ * Also reads and returns current RX FIFO level
++ */
++static u16 handle_interrupt(struct max3107_port *s)
++{
++ u16 buf[4]; /* Buffer for SPI transfers */
++ u8 irq_status;
++ u16 rx_level;
++ unsigned long flags;
++
++ /* Read IRQ status register */
++ buf[0] = MAX3107_IRQSTS_REG;
++ /* Read status IRQ status register */
++ buf[1] = MAX3107_STS_IRQSTS_REG;
++ /* Read LSR IRQ status register */
++ buf[2] = MAX3107_LSR_IRQSTS_REG;
++ /* Query RX level */
++ buf[3] = MAX3107_RXFIFOLVL_REG;
++
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) {
++ dev_err(&s->spi->dev,
++ "SPI transfer for INTR handling failed\n");
++ return 0;
++ }
++
++ irq_status = (u8)buf[0];
++ pr_debug("IRQSTS %x\n", irq_status);
++ rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK);
++
++ if (irq_status & MAX3107_IRQ_LSR_BIT) {
++ /* LSR interrupt */
++ if (buf[2] & MAX3107_LSR_RXTO_BIT)
++ /* RX timeout interrupt,
++ * handled by normal RX handling
++ */
++ pr_debug("RX TO INT\n");
++ }
++
++ if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) {
++ /* Tx empty interrupt,
++ * disable TX and set tx_fifo_empty flag
++ */
++ pr_debug("TE INT, disabling TX\n");
++ buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
++ spin_lock_irqsave(&s->data_lock, flags);
++ s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
++ buf[0] |= s->mode1_reg;
++ spin_unlock_irqrestore(&s->data_lock, flags);
++ if (max3107_rw(s, (u8 *)buf, NULL, 2))
++ dev_err(&s->spi->dev, "SPI transfer TX dis failed\n");
++ s->tx_enabled = 0;
++ s->tx_fifo_empty = 1;
++ }
++
++ if (irq_status & MAX3107_IRQ_RXFIFO_BIT)
++ /* RX FIFO interrupt,
++ * handled by normal RX handling
++ */
++ pr_debug("RFIFO INT\n");
++
++ /* Return RX level */
++ return rx_level;
++}
++
++/* Trigger work thread*/
++static void max3107_dowork(struct max3107_port *s)
++{
++ if (!work_pending(&s->work) && !freezing(current) && !s->suspended)
++ queue_work(s->workqueue, &s->work);
++ else
++ dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n");
++}
++
++/* Work thread */
++static void max3107_work(struct work_struct *w)
++{
++ struct max3107_port *s = container_of(w, struct max3107_port, work);
++ u16 rxlvl = 0;
++ int len; /* SPI transfer buffer length */
++ u16 buf[5]; /* Buffer for SPI transfers */
++ unsigned long flags;
++
++ /* Start by reading current RX FIFO level */
++ buf[0] = MAX3107_RXFIFOLVL_REG;
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer RX lev failed\n");
++ rxlvl = 0;
++ } else {
++ rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK);
++ }
++
++ do {
++ pr_debug("rxlvl %d\n", rxlvl);
++
++ /* Handle RX */
++ max3107_handlerx(s, rxlvl);
++ rxlvl = 0;
++
++ if (s->handle_irq) {
++ /* Handle pending interrupts
++ * We also get new RX FIFO level since new data may
++ * have been received while pushing received data to
++ * receivers
++ */
++ s->handle_irq = 0;
++ rxlvl = handle_interrupt(s);
++ }
++
++ /* Handle TX */
++ max3107_handletx(s);
++
++ /* Handle configuration changes */
++ len = 0;
++ spin_lock_irqsave(&s->data_lock, flags);
++ if (s->mode1_commit) {
++ pr_debug("mode1_commit\n");
++ buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
++ buf[len++] |= s->mode1_reg;
++ s->mode1_commit = 0;
++ }
++ if (s->lcr_commit) {
++ pr_debug("lcr_commit\n");
++ buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
++ buf[len++] |= s->lcr_reg;
++ s->lcr_commit = 0;
++ }
++ if (s->brg_commit) {
++ pr_debug("brg_commit\n");
++ buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
++ buf[len++] |= ((s->brg_cfg >> 16) &
++ MAX3107_SPI_TX_DATA_MASK);
++ buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
++ buf[len++] |= ((s->brg_cfg >> 8) &
++ MAX3107_SPI_TX_DATA_MASK);
++ buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
++ buf[len++] |= ((s->brg_cfg) & 0xff);
++ s->brg_commit = 0;
++ }
++ spin_unlock_irqrestore(&s->data_lock, flags);
++
++ if (len > 0) {
++ if (max3107_rw(s, (u8 *)buf, NULL, len * 2))
++ dev_err(&s->spi->dev,
++ "SPI transfer config failed\n");
++ }
++
++ /* Reloop if interrupt handling indicated data in RX FIFO */
++ } while (rxlvl);
++
++}
++
++/* Set sleep mode */
++static void max3107_set_sleep(struct max3107_port *s, int mode)
++{
++ u16 buf[1]; /* Buffer for SPI transfer */
++ unsigned long flags;
++ pr_debug("enter, mode %d\n", mode);
++
++ buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
++ spin_lock_irqsave(&s->data_lock, flags);
++ switch (mode) {
++ case MAX3107_DISABLE_FORCED_SLEEP:
++ s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT;
++ break;
++ case MAX3107_ENABLE_FORCED_SLEEP:
++ s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT;
++ break;
++ case MAX3107_DISABLE_AUTOSLEEP:
++ s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT;
++ break;
++ case MAX3107_ENABLE_AUTOSLEEP:
++ s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT;
++ break;
++ default:
++ spin_unlock_irqrestore(&s->data_lock, flags);
++ dev_warn(&s->spi->dev, "invalid sleep mode\n");
++ return;
++ }
++ buf[0] |= s->mode1_reg;
++ spin_unlock_irqrestore(&s->data_lock, flags);
++
++ if (max3107_rw(s, (u8 *)buf, NULL, 2))
++ dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n");
++
++ if (mode == MAX3107_DISABLE_AUTOSLEEP ||
++ mode == MAX3107_DISABLE_FORCED_SLEEP)
++ msleep(MAX3107_WAKEUP_DELAY);
++}
++
++/* Perform full register initialization */
++static void max3107_register_init(struct max3107_port *s)
++{
++ u16 buf[11]; /* Buffer for SPI transfers */
++
++ /* 1. Configure baud rate, 9600 as default */
++ s->baud = 9600;
++ /* the below is default*/
++ if (s->ext_clk) {
++ s->brg_cfg = MAX3107_BRG26_B9600;
++ s->baud_tbl = (struct baud_table *)brg26_ext;
++ } else {
++ s->brg_cfg = MAX3107_BRG13_IB9600;
++ s->baud_tbl = (struct baud_table *)brg13_int;
++ }
++#if 0
++ /*override for AAVA SC specific*/
++ if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
++ if (get_koski_build_id() <= KOSKI_EV2)
++ if (s->ext_clk) {
++ s->brg_cfg = MAX3107_BRG13_B9600;
++ s->baud_tbl = (struct baud_table *)brg13_ext;
++ }
++ }
++#endif
++ buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG)
++ | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
++ buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG)
++ | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK);
++ buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG)
++ | ((s->brg_cfg) & 0xff);
++
++ /* 2. Configure LCR register, 8N1 mode by default */
++ s->lcr_reg = MAX3107_LCR_WORD_LEN_8;
++ buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG)
++ | s->lcr_reg;
++
++ /* 3. Configure MODE 1 register */
++ s->mode1_reg = 0;
++ /* Enable IRQ pin */
++ s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT;
++ /* Disable TX */
++ s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
++ s->tx_enabled = 0;
++ /* RX is enabled */
++ s->rx_enabled = 1;
++ buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG)
++ | s->mode1_reg;
++
++ /* 4. Configure MODE 2 register */
++ buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
++ if (s->loopback) {
++ /* Enable loopback */
++ buf[5] |= MAX3107_MODE2_LOOPBACK_BIT;
++ }
++ /* Reset FIFOs */
++ buf[5] |= MAX3107_MODE2_FIFORST_BIT;
++ s->tx_fifo_empty = 1;
++
++ /* 5. Configure FIFO trigger level register */
++ buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG);
++ /* RX FIFO trigger for 16 words, TX FIFO trigger not used */
++ buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0));
++
++ /* 6. Configure flow control levels */
++ buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG);
++ /* Flow control halt level 96, resume level 48 */
++ buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96));
++
++ /* 7. Configure flow control */
++ buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG);
++ /* Enable auto CTS and auto RTS flow control */
++ buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT);
++
++ /* 8. Configure RX timeout register */
++ buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG);
++ /* Timeout after 48 character intervals */
++ buf[9] |= 0x0030;
++
++ /* 9. Configure LSR interrupt enable register */
++ buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG);
++ /* Enable RX timeout interrupt */
++ buf[10] |= MAX3107_LSR_RXTO_BIT;
++
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 22))
++ dev_err(&s->spi->dev, "SPI transfer for init failed\n");
++
++ /* 10. Clear IRQ status register by reading it */
++ buf[0] = MAX3107_IRQSTS_REG;
++
++ /* 11. Configure interrupt enable register */
++ /* Enable LSR interrupt */
++ s->irqen_reg = MAX3107_IRQ_LSR_BIT;
++ /* Enable RX FIFO interrupt */
++ s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
++ buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG)
++ | s->irqen_reg;
++
++ /* 12. Clear FIFO reset that was set in step 6 */
++ buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
++ if (s->loopback) {
++ /* Keep loopback enabled */
++ buf[2] |= MAX3107_MODE2_LOOPBACK_BIT;
++ }
++
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6))
++ dev_err(&s->spi->dev, "SPI transfer for init failed\n");
++
++}
++
++/* IRQ handler */
++static irqreturn_t max3107_irq(int irqno, void *dev_id)
++{
++ struct max3107_port *s = dev_id;
++
++ if (irqno != s->spi->irq) {
++ /* Unexpected IRQ */
++ return IRQ_NONE;
++ }
++
++ /* Indicate irq */
++ s->handle_irq = 1;
++
++ /* Trigger work thread */
++ max3107_dowork(s);
++
++ return IRQ_HANDLED;
++}
++
++/* HW suspension function
++ *
++ * Currently autosleep is used to decrease current consumption, alternative
++ * approach would be to set the chip to reset mode if UART is not being
++ * used but that would mess the GPIOs
++ *
++ */
++static void max3107_hw_susp(struct max3107_port *s, int suspend)
++{
++ pr_debug("enter, suspend %d\n", suspend);
++
++ if (suspend) {
++ /* Suspend requested,
++ * enable autosleep to decrease current consumption
++ */
++ s->suspended = 1;
++ max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP);
++ } else {
++ /* Resume requested,
++ * disable autosleep
++ */
++ s->suspended = 0;
++ max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
++ }
++}
++
++/* Modem status IRQ enabling */
++static void max3107_enable_ms(struct uart_port *port)
++{
++ /* Modem status not supported */
++}
++
++/* Data send function */
++static void max3107_start_tx(struct uart_port *port)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++
++ /* Trigger work thread for sending data */
++ max3107_dowork(s);
++}
++
++/* Function for checking that there is no pending transfers */
++static unsigned int max3107_tx_empty(struct uart_port *port)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++
++ pr_debug("returning %d\n",
++ (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit)));
++ return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit);
++}
++
++/* Function for stopping RX */
++static void max3107_stop_rx(struct uart_port *port)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++ unsigned long flags;
++
++ /* Set RX disabled in MODE 1 register */
++ spin_lock_irqsave(&s->data_lock, flags);
++ s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT;
++ s->mode1_commit = 1;
++ spin_unlock_irqrestore(&s->data_lock, flags);
++ /* Set RX disabled */
++ s->rx_enabled = 0;
++ /* Trigger work thread for doing the actual configuration change */
++ max3107_dowork(s);
++}
++
++/* Function for returning control pin states */
++static unsigned int max3107_get_mctrl(struct uart_port *port)
++{
++ /* DCD and DSR are not wired and CTS/RTS is handled automatically
++ * so just indicate DSR and CAR asserted
++ */
++ return TIOCM_DSR | TIOCM_CAR;
++}
++
++/* Function for setting control pin states */
++static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ /* DCD and DSR are not wired and CTS/RTS is hadnled automatically
++ * so do nothing
++ */
++}
++
++/* Function for configuring UART parameters */
++static void max3107_set_termios(struct uart_port *port,
++ struct ktermios *termios,
++ struct ktermios *old)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++ struct tty_struct *tty;
++ int baud;
++ u16 new_lcr = 0;
++ u32 new_brg = 0;
++ unsigned long flags;
++
++ if (!port->state)
++ return;
++
++ tty = port->state->port.tty;
++ if (!tty)
++ return;
++
++ /* Get new LCR register values */
++ /* Word size */
++ if ((termios->c_cflag & CSIZE) == CS7)
++ new_lcr |= MAX3107_LCR_WORD_LEN_7;
++ else
++ new_lcr |= MAX3107_LCR_WORD_LEN_8;
++
++ /* Parity */
++ if (termios->c_cflag & PARENB) {
++ new_lcr |= MAX3107_LCR_PARITY_BIT;
++ if (!(termios->c_cflag & PARODD))
++ new_lcr |= MAX3107_LCR_EVENPARITY_BIT;
++ }
++
++ /* Stop bits */
++ if (termios->c_cflag & CSTOPB) {
++ /* 2 stop bits */
++ new_lcr |= MAX3107_LCR_STOPLEN_BIT;
++ }
++
++ /* Mask termios capabilities we don't support */
++ termios->c_cflag &= ~CMSPAR;
++
++ /* Set status ignore mask */
++ s->port.ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ s->port.ignore_status_mask |= MAX3107_ALL_ERRORS;
++
++ /* Set low latency to immediately handle pushed data */
++ s->port.state->port.tty->low_latency = 1;
++
++ /* Get new baud rate generator configuration */
++ baud = tty_get_baud_rate(tty);
++
++ spin_lock_irqsave(&s->data_lock, flags);
++ new_brg = get_new_brg(baud, s);
++ /* if can't find the corrent config, use previous */
++ if (!new_brg) {
++ baud = s->baud;
++ new_brg = s->brg_cfg;
++ }
++ spin_unlock_irqrestore(&s->data_lock, flags);
++ tty_termios_encode_baud_rate(termios, baud, baud);
++ s->baud = baud;
++
++ /* Update timeout according to new baud rate */
++ uart_update_timeout(port, termios->c_cflag, baud);
++
++ spin_lock_irqsave(&s->data_lock, flags);
++ if (s->lcr_reg != new_lcr) {
++ s->lcr_reg = new_lcr;
++ s->lcr_commit = 1;
++ }
++ if (s->brg_cfg != new_brg) {
++ s->brg_cfg = new_brg;
++ s->brg_commit = 1;
++ }
++ spin_unlock_irqrestore(&s->data_lock, flags);
++
++ /* Trigger work thread for doing the actual configuration change */
++ max3107_dowork(s);
++}
++
++/* Port shutdown function */
++static void max3107_shutdown(struct uart_port *port)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++
++ if (s->suspended) {
++ /* Resume HW */
++ max3107_hw_susp(s, 0);
++ }
++
++ /* Free the interrupt */
++ free_irq(s->spi->irq, s);
++
++ if (s->workqueue) {
++ /* Flush and destroy work queue */
++ flush_workqueue(s->workqueue);
++ destroy_workqueue(s->workqueue);
++ s->workqueue = NULL;
++ }
++
++ /* Suspend HW */
++ max3107_hw_susp(s, 1);
++}
++
++/* Port startup function */
++static int max3107_startup(struct uart_port *port)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++
++ /* Initialize work queue */
++ s->workqueue = create_freezeable_workqueue("max3107");
++ if (!s->workqueue) {
++ dev_err(&s->spi->dev, "Workqueue creation failed\n");
++ return -EBUSY;
++ }
++ INIT_WORK(&s->work, max3107_work);
++
++ /* Setup IRQ */
++ if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING,
++ "max3107", s)) {
++ dev_err(&s->spi->dev, "IRQ reguest failed\n");
++ destroy_workqueue(s->workqueue);
++ s->workqueue = NULL;
++ return -EBUSY;
++ }
++
++ /* Resume HW */
++ max3107_hw_susp(s, 0);
++
++ /* Init registers */
++ max3107_register_init(s);
++
++ return 0;
++}
++
++/* Port type function */
++static const char *max3107_type(struct uart_port *port)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++ return s->spi->modalias;
++}
++
++/* Port release function */
++static void max3107_release_port(struct uart_port *port)
++{
++ /* Do nothing */
++}
++
++/* Port request function */
++static int max3107_request_port(struct uart_port *port)
++{
++ /* Do nothing */
++ return 0;
++}
++
++/* Port config function */
++static void max3107_config_port(struct uart_port *port, int flags)
++{
++ struct max3107_port *s = container_of(port, struct max3107_port, port);
++
++ /* Use PORT_MAX3100 since we are at least int the same series */
++ s->port.type = PORT_MAX3100;
++}
++
++/* Port verify function */
++static int max3107_verify_port(struct uart_port *port,
++ struct serial_struct *ser)
++{
++ if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
++ return 0;
++
++ return -EINVAL;
++}
++
++/* Port stop TX function */
++static void max3107_stop_tx(struct uart_port *port)
++{
++ /* Do nothing */
++}
++
++/* Port break control function */
++static void max3107_break_ctl(struct uart_port *port, int break_state)
++{
++ /* We don't support break control, do nothing */
++}
++
++/* GPIO direction to input function */
++static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[1]; /* Buffer for SPI transfer */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return -EINVAL;
++ }
++
++ /* Read current GPIO configuration register */
++ buf[0] = MAX3107_GPIOCFG_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
++ return -EIO;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++
++ /* Set GPIO to input */
++ buf[0] &= ~(0x0001 << offset);
++
++ /* Write new GPIO configuration register value */
++ buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
++ return -EIO;
++ }
++ return 0;
++}
++
++/* GPIO direction to output function */
++static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[2]; /* Buffer for SPI transfers */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return -EINVAL;
++ }
++
++ /* Read current GPIO configuration and data registers */
++ buf[0] = MAX3107_GPIOCFG_REG;
++ buf[1] = MAX3107_GPIODATA_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
++ dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
++ return -EIO;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++ buf[1] &= MAX3107_SPI_RX_DATA_MASK;
++
++ /* Set GPIO to output */
++ buf[0] |= (0x0001 << offset);
++ /* Set value */
++ if (value)
++ buf[1] |= (0x0001 << offset);
++ else
++ buf[1] &= ~(0x0001 << offset);
++
++ /* Write new GPIO configuration and data register values */
++ buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
++ buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
++ dev_err(&s->spi->dev,
++ "SPI transfer for GPIO conf data w failed\n");
++ return -EIO;
++ }
++ return 0;
++}
++
++/* GPIO value query function */
++static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[1]; /* Buffer for SPI transfer */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return -EINVAL;
++ }
++
++ /* Read current GPIO data register */
++ buf[0] = MAX3107_GPIODATA_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
++ return -EIO;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++
++ /* Return value */
++ return buf[0] & (0x0001 << offset);
++}
++
++/* GPIO value set function */
++static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct max3107_port *s = container_of(chip, struct max3107_port, chip);
++ u16 buf[2]; /* Buffer for SPI transfers */
++
++ if (offset >= MAX3107_GPIO_COUNT) {
++ dev_err(&s->spi->dev, "Invalid GPIO\n");
++ return;
++ }
++
++ /* Read current GPIO configuration registers*/
++ buf[0] = MAX3107_GPIODATA_REG;
++ buf[1] = MAX3107_GPIOCFG_REG;
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
++ dev_err(&s->spi->dev,
++ "SPI transfer for GPIO data and config read failed\n");
++ return;
++ }
++ buf[0] &= MAX3107_SPI_RX_DATA_MASK;
++ buf[1] &= MAX3107_SPI_RX_DATA_MASK;
++
++ if (!(buf[1] & (0x0001 << offset))) {
++ /* Configured as input, can't set value */
++ dev_warn(&s->spi->dev,
++ "Trying to set value for input GPIO\n");
++ return;
++ }
++
++ /* Set value */
++ if (value)
++ buf[0] |= (0x0001 << offset);
++ else
++ buf[0] &= ~(0x0001 << offset);
++
++ /* Write new GPIO data register value */
++ buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 2))
++ dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
++}
++
++/* Platform data */
++static struct max3107_plat max3107_plat_data = {
++ .loopback = 0,
++ .ext_clk = 1,
++ .max3107_hw_suspend = &max3107_hw_susp,
++ .polled_mode = 0,
++ .poll_time = 0,
++};
++
++/* Port functions */
++static struct uart_ops max3107_ops = {
++ .tx_empty = max3107_tx_empty,
++ .set_mctrl = max3107_set_mctrl,
++ .get_mctrl = max3107_get_mctrl,
++ .stop_tx = max3107_stop_tx,
++ .start_tx = max3107_start_tx,
++ .stop_rx = max3107_stop_rx,
++ .enable_ms = max3107_enable_ms,
++ .break_ctl = max3107_break_ctl,
++ .startup = max3107_startup,
++ .shutdown = max3107_shutdown,
++ .set_termios = max3107_set_termios,
++ .type = max3107_type,
++ .release_port = max3107_release_port,
++ .request_port = max3107_request_port,
++ .config_port = max3107_config_port,
++ .verify_port = max3107_verify_port,
++};
++
++/* UART driver data */
++static struct uart_driver max3107_uart_driver = {
++ .owner = THIS_MODULE,
++ .driver_name = "ttyMAX",
++ .dev_name = "ttyMAX",
++ .nr = 1,
++};
++
++/* GPIO chip data */
++static struct gpio_chip max3107_gpio_chip = {
++ .owner = THIS_MODULE,
++ .direction_input = max3107_gpio_direction_in,
++ .direction_output = max3107_gpio_direction_out,
++ .get = max3107_gpio_get,
++ .set = max3107_gpio_set,
++ .can_sleep = 1,
++ .base = MAX3107_GPIO_BASE,
++ .ngpio = MAX3107_GPIO_COUNT,
++};
++/* Device probe function */
++static int __devinit max3107_probe(struct spi_device *spi)
++{
++ struct max3107_port *s;
++ struct max3107_plat *pdata = &max3107_plat_data;
++ u16 buf[2]; /* Buffer for SPI transfers */
++ int retval;
++
++ pr_info("enter max3107 probe\n");
++
++ /* Reset the chip */
++ if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
++ pr_err("Requesting RESET GPIO failed\n");
++ return -EIO;
++ }
++ if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
++ pr_err("Setting RESET GPIO to 0 failed\n");
++ gpio_free(MAX3107_RESET_GPIO);
++ return -EIO;
++ }
++ msleep(MAX3107_RESET_DELAY);
++ if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
++ pr_err("Setting RESET GPIO to 1 failed\n");
++ gpio_free(MAX3107_RESET_GPIO);
++ return -EIO;
++ }
++ gpio_free(MAX3107_RESET_GPIO);
++ msleep(MAX3107_WAKEUP_DELAY);
++
++ /* Allocate port structure */
++ s = kzalloc(sizeof(*s), GFP_KERNEL);
++ if (!s) {
++ pr_err("Allocating port structure failed\n");
++ return -ENOMEM;
++ }
++ /* SPI Rx buffer
++ * +2 for RX FIFO interrupt
++ * disabling and RX level query
++ */
++ s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
++ if (!s->rxbuf) {
++ pr_err("Allocating RX buffer failed\n");
++ return -ENOMEM;
++ }
++ s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
++ if (!s->rxstr) {
++ pr_err("Allocating RX buffer failed\n");
++ return -ENOMEM;
++ }
++ /* SPI Tx buffer
++ * SPI transfer buffer
++ * +3 for TX FIFO empty
++ * interrupt disabling and
++ * enabling and TX enabling
++ */
++ s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
++ if (!s->txbuf) {
++ pr_err("Allocating TX buffer failed\n");
++ return -ENOMEM;
++ }
++ /* Initialize shared data lock */
++ spin_lock_init(&s->data_lock);
++
++ /* SPI intializations */
++ dev_set_drvdata(&spi->dev, s);
++ spi->mode = SPI_MODE_0;
++ spi->dev.platform_data = pdata;
++ spi->bits_per_word = 16;
++ s->ext_clk = pdata->ext_clk;
++ s->loopback = pdata->loopback;
++ spi_setup(spi);
++ s->spi = spi;
++
++ /* Check REV ID to ensure we are talking to what we expect */
++ buf[0] = MAX3107_REVID_REG;
++ if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
++ dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
++ return -EIO;
++ }
++ if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
++ (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
++ dev_err(&s->spi->dev, "REVID %x does not match\n",
++ (buf[0] & MAX3107_SPI_RX_DATA_MASK));
++ return -ENODEV;
++ }
++
++ /* Disable all interrupts */
++ buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000);
++ buf[0] |= 0x0000;
++
++ /* Configure clock source */
++ buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG);
++ if (s->ext_clk) {
++ /* External clock */
++ buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT;
++ }
++
++ /* PLL bypass ON */
++ buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT;
++
++ /* Perform SPI transfer */
++ if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
++ dev_err(&s->spi->dev, "SPI transfer for init failed\n");
++ return -EIO;
++ }
++
++ /* Register UART driver */
++ retval = uart_register_driver(&max3107_uart_driver);
++ if (retval) {
++ dev_err(&s->spi->dev, "Registering UART driver failed\n");
++ return retval;
++ }
++
++ /* Initialize UART port data */
++ s->port.fifosize = 128;
++ s->port.ops = &max3107_ops;
++ s->port.line = 0;
++ s->port.dev = &spi->dev;
++ s->port.uartclk = 9600;
++ s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
++ s->port.irq = s->spi->irq;
++ /* Use PORT_MAX3100 since we are at least in the same series */
++ s->port.type = PORT_MAX3100;
++
++ /* Add UART port */
++ retval = uart_add_one_port(&max3107_uart_driver, &s->port);
++ if (retval < 0) {
++ dev_err(&s->spi->dev, "Adding UART port failed\n");
++ return retval;
++ }
++
++ /* Initialize GPIO chip data */
++ s->chip = max3107_gpio_chip;
++ s->chip.label = spi->modalias;
++ s->chip.dev = &spi->dev;
++
++ /* Add GPIO chip */
++ retval = gpiochip_add(&s->chip);
++ if (retval) {
++ dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
++ return retval;
++ }
++
++ /* Temporary fix for EV2 boot problems, set modem reset to 0 */
++ max3107_gpio_direction_out(&s->chip, 3, 0);
++
++ /* Go to suspend mode */
++ max3107_hw_susp(s, 1);
++
++ return 0;
++}
++
++/* Driver remove function */
++static int __devexit max3107_remove(struct spi_device *spi)
++{
++ struct max3107_port *s = dev_get_drvdata(&spi->dev);
++
++ pr_info("enter max3107 remove\n");
++
++ /* Remove GPIO chip */
++ if (gpiochip_remove(&s->chip))
++ dev_warn(&s->spi->dev, "Removing GPIO chip failed\n");
++
++ /* Remove port */
++ if (uart_remove_one_port(&max3107_uart_driver, &s->port))
++ dev_warn(&s->spi->dev, "Removing UART port failed\n");
++
++ /* Unregister UART driver */
++ uart_unregister_driver(&max3107_uart_driver);
++
++ /* Free TxRx buffer */
++ kfree(s->rxbuf);
++ kfree(s->rxstr);
++ kfree(s->txbuf);
++
++ /* Free port structure */
++ kfree(s);
++
++ return 0;
++}
++
++/* Driver suspend function */
++static int max3107_suspend(struct spi_device *spi, pm_message_t state)
++{
++#ifdef CONFIG_PM
++ struct max3107_port *s = dev_get_drvdata(&spi->dev);
++
++ pr_debug("enter suspend\n");
++
++ /* Suspend UART port */
++ uart_suspend_port(&max3107_uart_driver, &s->port);
++
++ /* Go to suspend mode */
++ max3107_hw_susp(s, 1);
++#endif /* CONFIG_PM */
++ return 0;
++}
++
++/* Driver resume function */
++static int max3107_resume(struct spi_device *spi)
++{
++#ifdef CONFIG_PM
++ struct max3107_port *s = dev_get_drvdata(&spi->dev);
++
++ pr_debug("enter resume\n");
++
++ /* Resume from suspend */
++ max3107_hw_susp(s, 0);
++
++ /* Resume UART port */
++ uart_resume_port(&max3107_uart_driver, &s->port);
++#endif /* CONFIG_PM */
++ return 0;
++}
++
++/* Spi driver data */
++static struct spi_driver max3107_driver = {
++ .driver = {
++ .name = "max3107",
++ .bus = &spi_bus_type,
++ .owner = THIS_MODULE,
++ },
++ .probe = max3107_probe,
++ .remove = __devexit_p(max3107_remove),
++ .suspend = max3107_suspend,
++ .resume = max3107_resume,
++};
++
++/* Driver init function */
++static int __init max3107_init(void)
++{
++ pr_info("enter max3107 init\n");
++ return spi_register_driver(&max3107_driver);
++}
++
++/* Driver exit function */
++static void __exit max3107_exit(void)
++{
++ pr_info("enter max3107 exit\n");
++ spi_unregister_driver(&max3107_driver);
++}
++
++module_init(max3107_init);
++module_exit(max3107_exit);
++
++MODULE_DESCRIPTION("MAX3107 driver");
++MODULE_AUTHOR("Aavamobile");
++MODULE_ALIAS("max3107-spi-uart");
++MODULE_LICENSE("GPLv2");
+--- /dev/null
++++ b/drivers/serial/max3107.h
+@@ -0,0 +1,358 @@
++/*
++ * max3107.h - spi uart protocol driver header for Maxim 3107
++ *
++ * Copyright (C) Aavamobile 2009
++ * Based on serial_max3100.h by Christian Pellegrin
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#ifndef _LINUX_SERIAL_MAX3107_H
++#define _LINUX_SERIAL_MAX3107_H
++
++/* Serial error status definitions */
++#define MAX3107_PARITY_ERROR 1
++#define MAX3107_FRAME_ERROR 2
++#define MAX3107_OVERRUN_ERROR 4
++#define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \
++ MAX3107_FRAME_ERROR | \
++ MAX3107_OVERRUN_ERROR)
++
++/* GPIO definitions */
++#define MAX3107_GPIO_BASE 88
++#define MAX3107_GPIO_COUNT 4
++
++
++/* GPIO connected to chip's reset pin */
++#define MAX3107_RESET_GPIO 87
++
++
++/* Chip reset delay */
++#define MAX3107_RESET_DELAY 10
++
++/* Chip wakeup delay */
++#define MAX3107_WAKEUP_DELAY 50
++
++
++/* Sleep mode definitions */
++#define MAX3107_DISABLE_FORCED_SLEEP 0
++#define MAX3107_ENABLE_FORCED_SLEEP 1
++#define MAX3107_DISABLE_AUTOSLEEP 2
++#define MAX3107_ENABLE_AUTOSLEEP 3
++
++
++/* Definitions for register access with SPI transfers
++ *
++ * SPI transfer format:
++ *
++ * Master to slave bits xzzzzzzzyyyyyyyy
++ * Slave to master bits aaaaaaaabbbbbbbb
++ *
++ * where:
++ * x = 0 for reads, 1 for writes
++ * z = register address
++ * y = new register value if write, 0 if read
++ * a = unspecified
++ * b = register value if read, unspecified if write
++ */
++
++/* SPI speed */
++#define MAX3107_SPI_SPEED (3125000 * 2)
++
++/* Write bit */
++#define MAX3107_WRITE_BIT (1 << 15)
++
++/* SPI TX data mask */
++#define MAX3107_SPI_RX_DATA_MASK (0x00ff)
++
++/* SPI RX data mask */
++#define MAX3107_SPI_TX_DATA_MASK (0x00ff)
++
++/* Register access masks */
++#define MAX3107_RHR_REG (0x0000) /* RX FIFO */
++#define MAX3107_THR_REG (0x0000) /* TX FIFO */
++#define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */
++#define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */
++#define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */
++#define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */
++#define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */
++#define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */
++#define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */
++#define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */
++#define MAX3107_MODE1_REG (0x0900) /* MODE1 */
++#define MAX3107_MODE2_REG (0x0a00) /* MODE2 */
++#define MAX3107_LCR_REG (0x0b00) /* LCR */
++#define MAX3107_RXTO_REG (0x0c00) /* RX timeout */
++#define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */
++#define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */
++#define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */
++#define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */
++#define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */
++#define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */
++#define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */
++#define MAX3107_XON1_REG (0x1400) /* XON1 character */
++#define MAX3107_XON2_REG (0x1500) /* XON2 character */
++#define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */
++#define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */
++#define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */
++#define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */
++#define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */
++#define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */
++#define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */
++#define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */
++#define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */
++#define MAX3107_REVID_REG (0x1f00) /* Revision identification */
++
++/* IRQ register bits */
++#define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
++#define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
++#define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */
++#define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */
++#define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */
++#define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */
++#define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */
++#define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */
++
++/* LSR register bits */
++#define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */
++#define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */
++#define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */
++#define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */
++#define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */
++#define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */
++#define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
++#define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */
++
++/* Special character register bits */
++#define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */
++#define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */
++#define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */
++#define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */
++#define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */
++#define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */
++#define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
++#define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */
++
++/* Status register bits */
++#define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */
++#define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */
++#define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */
++#define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */
++#define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */
++#define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */
++#define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */
++#define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */
++
++/* MODE1 register bits */
++#define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */
++#define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */
++#define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */
++#define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */
++#define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */
++#define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */
++#define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */
++#define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */
++
++/* MODE2 register bits */
++#define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */
++#define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */
++#define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */
++#define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */
++#define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */
++#define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */
++#define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */
++#define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */
++
++/* LCR register bits */
++#define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */
++#define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1
++ *
++ * Word length bits table:
++ * 00 -> 5 bit words
++ * 01 -> 6 bit words
++ * 10 -> 7 bit words
++ * 11 -> 8 bit words
++ */
++#define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit
++ *
++ * STOP length bit table:
++ * 0 -> 1 stop bit
++ * 1 -> 1-1.5 stop bits if
++ * word length is 5,
++ * 2 stop bits otherwise
++ */
++#define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */
++#define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */
++#define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
++#define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
++#define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */
++#define MAX3107_LCR_WORD_LEN_5 (0x0000)
++#define MAX3107_LCR_WORD_LEN_6 (0x0001)
++#define MAX3107_LCR_WORD_LEN_7 (0x0002)
++#define MAX3107_LCR_WORD_LEN_8 (0x0003)
++
++
++/* IRDA register bits */
++#define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
++#define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
++#define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */
++#define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */
++#define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */
++#define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */
++#define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */
++#define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */
++
++/* Flow control trigger level register masks */
++#define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
++#define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */
++#define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f)
++#define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4)
++
++/* FIFO interrupt trigger level register masks */
++#define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */
++#define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */
++#define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f)
++#define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4)
++
++/* Flow control register bits */
++#define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */
++#define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */
++#define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs
++ * are used in conjunction with
++ * XOFF2 for definition of
++ * special character */
++#define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */
++#define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */
++#define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1
++ *
++ * SWFLOW bits 1 & 0 table:
++ * 00 -> no transmitter flow
++ * control
++ * 01 -> receiver compares
++ * XON2 and XOFF2
++ * and controls
++ * transmitter
++ * 10 -> receiver compares
++ * XON1 and XOFF1
++ * and controls
++ * transmitter
++ * 11 -> receiver compares
++ * XON1, XON2, XOFF1 and
++ * XOFF2 and controls
++ * transmitter
++ */
++#define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */
++#define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3
++ *
++ * SWFLOW bits 3 & 2 table:
++ * 00 -> no received flow
++ * control
++ * 01 -> transmitter generates
++ * XON2 and XOFF2
++ * 10 -> transmitter generates
++ * XON1 and XOFF1
++ * 11 -> transmitter generates
++ * XON1, XON2, XOFF1 and
++ * XOFF2
++ */
++
++/* GPIO configuration register bits */
++#define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */
++#define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */
++#define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */
++#define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */
++#define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */
++#define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */
++#define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */
++#define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */
++
++/* GPIO DATA register bits */
++#define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */
++#define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */
++#define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */
++#define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */
++#define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */
++#define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */
++#define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */
++#define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */
++
++/* PLL configuration register masks */
++#define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */
++#define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */
++
++/* Baud rate generator configuration register masks and bits */
++#define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of
++ * Baud rate generator divisor
++ */
++#define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */
++#define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */
++#define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */
++#define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */
++
++/* Clock source register bits */
++#define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */
++#define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */
++#define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */
++#define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */
++#define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */
++#define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */
++#define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */
++#define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */
++
++
++/* HW definitions */
++#define MAX3107_RX_FIFO_SIZE 128
++#define MAX3107_TX_FIFO_SIZE 128
++#define MAX3107_REVID1 0x00a0
++#define MAX3107_REVID2 0x00a1
++
++
++/* Baud rate generator configuration values for external clock 13MHz */
++#define MAX3107_BRG13_B300 (0x0A9400 | 0x05)
++#define MAX3107_BRG13_B600 (0x054A00 | 0x03)
++#define MAX3107_BRG13_B1200 (0x02A500 | 0x01)
++#define MAX3107_BRG13_B2400 (0x015200 | 0x09)
++#define MAX3107_BRG13_B4800 (0x00A900 | 0x04)
++#define MAX3107_BRG13_B9600 (0x005400 | 0x0A)
++#define MAX3107_BRG13_B19200 (0x002A00 | 0x05)
++#define MAX3107_BRG13_B38400 (0x001500 | 0x03)
++#define MAX3107_BRG13_B57600 (0x000E00 | 0x02)
++#define MAX3107_BRG13_B115200 (0x000700 | 0x01)
++#define MAX3107_BRG13_B230400 (0x000300 | 0x08)
++#define MAX3107_BRG13_B460800 (0x000100 | 0x0c)
++#define MAX3107_BRG13_B921600 (0x000100 | 0x1c)
++
++/* Baud rate generator configuration values for external clock 26MHz */
++#define MAX3107_BRG26_B300 (0x152800 | 0x0A)
++#define MAX3107_BRG26_B600 (0x0A9400 | 0x05)
++#define MAX3107_BRG26_B1200 (0x054A00 | 0x03)
++#define MAX3107_BRG26_B2400 (0x02A500 | 0x01)
++#define MAX3107_BRG26_B4800 (0x015200 | 0x09)
++#define MAX3107_BRG26_B9600 (0x00A900 | 0x04)
++#define MAX3107_BRG26_B19200 (0x005400 | 0x0A)
++#define MAX3107_BRG26_B38400 (0x002A00 | 0x05)
++#define MAX3107_BRG26_B57600 (0x001C00 | 0x03)
++#define MAX3107_BRG26_B115200 (0x000E00 | 0x02)
++#define MAX3107_BRG26_B230400 (0x000700 | 0x01)
++#define MAX3107_BRG26_B460800 (0x000300 | 0x08)
++#define MAX3107_BRG26_B921600 (0x000100 | 0x0C)
++
++/* Baud rate generator configuration values for internal clock */
++#define MAX3107_BRG13_IB300 (0x008000 | 0x00)
++#define MAX3107_BRG13_IB600 (0x004000 | 0x00)
++#define MAX3107_BRG13_IB1200 (0x002000 | 0x00)
++#define MAX3107_BRG13_IB2400 (0x001000 | 0x00)
++#define MAX3107_BRG13_IB4800 (0x000800 | 0x00)
++#define MAX3107_BRG13_IB9600 (0x000400 | 0x00)
++#define MAX3107_BRG13_IB19200 (0x000200 | 0x00)
++#define MAX3107_BRG13_IB38400 (0x000100 | 0x00)
++#define MAX3107_BRG13_IB57600 (0x000000 | 0x0B)
++#define MAX3107_BRG13_IB115200 (0x000000 | 0x05)
++#define MAX3107_BRG13_IB230400 (0x000000 | 0x03)
++#define MAX3107_BRG13_IB460800 (0x000000 | 0x00)
++#define MAX3107_BRG13_IB921600 (0x000000 | 0x00)
++
++#endif /* _LINUX_SERIAL_MAX3107_H */
diff --git a/tty/tty_io-remove-casts-from-void.patch b/tty/tty_io-remove-casts-from-void.patch
new file mode 100644
index 00000000000000..2fcdfdca6d2581
--- /dev/null
+++ b/tty/tty_io-remove-casts-from-void.patch
@@ -0,0 +1,73 @@
+From segooon@gmail.com Thu Jul 8 11:39:12 2010
+From: Kulikov Vasiliy <segooon@gmail.com>
+Date: Tue, 29 Jun 2010 14:15:09 +0400
+Subject: tty_io: remove casts from void*
+Cc: Greg Kroah-Hartman <gregkh@suse.de>, Alan Cox <alan@linux.intel.com>, "Eric W. Biederman" <ebiederm@xmission.com>, Dave Young <hidave.darkstar@gmail.com>, Jiri Kosina <jkosina@suse.cz>, linux-kernel@vger.kernel.org
+Message-ID: <1277806510-30840-1-git-send-email-segooon@gmail.com>
+
+
+Remove unnesessary casts from void*.
+
+Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/tty_io.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -893,7 +893,7 @@ static ssize_t tty_read(struct file *fil
+ struct inode *inode;
+ struct tty_ldisc *ld;
+
+- tty = (struct tty_struct *)file->private_data;
++ tty = file->private_data;
+ inode = file->f_path.dentry->d_inode;
+ if (tty_paranoia_check(tty, inode, "tty_read"))
+ return -EIO;
+@@ -1070,7 +1070,7 @@ static ssize_t tty_write(struct file *fi
+ ssize_t ret;
+ struct tty_ldisc *ld;
+
+- tty = (struct tty_struct *)file->private_data;
++ tty = file->private_data;
+ if (tty_paranoia_check(tty, inode, "tty_write"))
+ return -EIO;
+ if (!tty || !tty->ops->write ||
+@@ -1513,7 +1513,7 @@ int tty_release(struct inode *inode, str
+ int idx;
+ char buf[64];
+
+- tty = (struct tty_struct *)filp->private_data;
++ tty = filp->private_data;
+ if (tty_paranoia_check(tty, inode, "tty_release_dev"))
+ return 0;
+
+@@ -1920,7 +1920,7 @@ static unsigned int tty_poll(struct file
+ struct tty_ldisc *ld;
+ int ret = 0;
+
+- tty = (struct tty_struct *)filp->private_data;
++ tty = filp->private_data;
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
+ return 0;
+
+@@ -1937,7 +1937,7 @@ static int __tty_fasync(int fd, struct f
+ unsigned long flags;
+ int retval = 0;
+
+- tty = (struct tty_struct *)filp->private_data;
++ tty = filp->private_data;
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
+ goto out;
+
+@@ -2497,7 +2497,7 @@ long tty_ioctl(struct file *file, unsign
+ struct tty_ldisc *ld;
+ struct inode *inode = file->f_dentry->d_inode;
+
+- tty = (struct tty_struct *)file->private_data;
++ tty = file->private_data;
+ if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+ return -EINVAL;
+
diff --git a/usb/usb-core-hcd-pci-use-for_each_pci_dev.patch b/usb/usb-core-hcd-pci-use-for_each_pci_dev.patch
new file mode 100644
index 00000000000000..a7dc30a68feb09
--- /dev/null
+++ b/usb/usb-core-hcd-pci-use-for_each_pci_dev.patch
@@ -0,0 +1,33 @@
+From segooon@gmail.com Thu Jul 8 11:37:17 2010
+From: Kulikov Vasiliy <segooon@gmail.com>
+Date: Sat, 3 Jul 2010 20:04:47 +0400
+Subject: USB: core: hcd-pci: use for_each_pci_dev()
+To: Kernel Janitors <kernel-janitors@vger.kernel.org>
+Cc: Greg Kroah-Hartman <gregkh@suse.de>, Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, Alexey Dobriyan <adobriyan@gmail.com>, "Rafael J. Wysocki" <rjw@sisk.pl>, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
+Message-ID: <1278173088-12051-1-git-send-email-segooon@gmail.com>
+
+
+Use for_each_pci_dev() to simplify the code.
+
+Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd-pci.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -66,10 +66,7 @@ static void companion_common(struct pci_
+ * vice versa.
+ */
+ companion = NULL;
+- for (;;) {
+- companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion);
+- if (!companion)
+- break;
++ for_each_pci_dev(companion) {
+ if (companion->bus != pdev->bus ||
+ PCI_SLOT(companion->devfn) != slot)
+ continue;
diff --git a/usb/usb-ehci_omap-fix-device-detect-issue-with-modules.patch b/usb/usb-ehci_omap-fix-device-detect-issue-with-modules.patch
new file mode 100644
index 00000000000000..17ebcb359d0ae2
--- /dev/null
+++ b/usb/usb-ehci_omap-fix-device-detect-issue-with-modules.patch
@@ -0,0 +1,83 @@
+From ajay.gupta@ti.com Thu Jul 8 11:40:51 2010
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 8 Jul 2010 14:03:02 +0530
+Subject: USB: ehci_omap: fix device detect issue with modules
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, felipe.balbi@nokia.com, gregkh@suse.de, Ajay Kumar Gupta <ajay.gupta@ti.com>
+Message-ID: <1278577982-30046-5-git-send-email-ajay.gupta@ti.com>
+
+
+Currently devices don't get detected automatically if the ehci
+module is inserted 2nd time onward. We need to disconnect and
+reconnect the device for it to get detected and enumerated.
+
+Resetting the USB PHY using PHY reset comamnd over ULPI fixes
+this issue. Tested on OMAP3EVM.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Acked-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-omap.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -38,6 +38,7 @@
+ #include <linux/gpio.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
++#include <linux/usb/ulpi.h>
+ #include <plat/usb.h>
+
+ /*
+@@ -236,6 +237,35 @@ static void omap_usb_utmi_init(struct eh
+
+ /*-------------------------------------------------------------------------*/
+
++static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
++{
++ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
++ unsigned reg = 0;
++
++ reg = ULPI_FUNC_CTRL_RESET
++ /* FUNCTION_CTRL_SET register */
++ | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
++ /* Write */
++ | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
++ /* PORTn */
++ | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
++ /* start ULPI access*/
++ | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
++
++ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg);
++
++ /* Wait for ULPI access completion */
++ while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI)
++ & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout)) {
++ dev_dbg(omap->dev, "phy reset operation timed out\n");
++ break;
++ }
++ }
++}
++
+ /* omap_start_ehc
+ * - Start the TI USBHOST controller
+ */
+@@ -425,6 +455,12 @@ static int omap_start_ehc(struct ehci_hc
+ gpio_set_value(omap->reset_gpio_port[1], 1);
+ }
+
++ /* Soft reset the PHY using PHY reset command over ULPI */
++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
++ omap_ehci_soft_phy_reset(omap, 0);
++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
++ omap_ehci_soft_phy_reset(omap, 1);
++
+ return 0;
+
+ err_sys_status:
diff --git a/usb/usb-gadget-compilation-issue-missing-task_interruptible.patch b/usb/usb-gadget-compilation-issue-missing-task_interruptible.patch
new file mode 100644
index 00000000000000..9642be9f5ac8a9
--- /dev/null
+++ b/usb/usb-gadget-compilation-issue-missing-task_interruptible.patch
@@ -0,0 +1,44 @@
+From stephane.duverger@gmail.com Thu Jul 8 11:23:40 2010
+From: stephane duverger <stephane.duverger@gmail.com>
+Date: Tue, 29 Jun 2010 16:57:25 +0200
+Subject: USB: gadget: compilation issue: missing TASK_INTERRUPTIBLE
+To: Greg KH <greg@kroah.com>
+Cc: dbrownell@users.sourceforge.net, linux-usb@vger.kernel.org
+Message-ID: <20100629165725.24e64a2b@riot.ssi.corp>
+
+
+Here is the patch for the following issue:
+
+drivers/usb/gadget/u_serial.c: In function ‘gs_start_tx’:
+drivers/usb/gadget/u_serial.c:369: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
+drivers/usb/gadget/u_serial.c:369: error: (Each undeclared identifier is reported only once
+drivers/usb/gadget/u_serial.c:369: error: for each function it appears in.)
+drivers/usb/gadget/u_serial.c: In function ‘gs_rx_push’:
+drivers/usb/gadget/u_serial.c:546: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
+drivers/usb/gadget/u_serial.c: In function ‘gs_close’:
+drivers/usb/gadget/u_serial.c:857: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
+drivers/usb/gadget/u_serial.c:857: error: implicit declaration of function ‘signal_pending’
+drivers/usb/gadget/u_serial.c:857: error: implicit declaration of function ‘schedule_timeout’
+drivers/usb/gadget/u_serial.c: In function ‘gserial_cleanup’:
+drivers/usb/gadget/u_serial.c:1190: error: ‘TASK_UNINTERRUPTIBLE’ undeclared (first use in this function)
+drivers/usb/gadget/u_serial.c:1190: error: implicit declaration of function ‘schedule’
+drivers/usb/gadget/u_serial.c: In function ‘gserial_disconnect’:
+drivers/usb/gadget/u_serial.c:1311: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
+
+Signed-off-by: Stephane Duverger <stephane.duverger@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/u_serial.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/gadget/u_serial.c
++++ b/drivers/usb/gadget/u_serial.c
+@@ -18,6 +18,7 @@
+ /* #define VERBOSE_DEBUG */
+
+ #include <linux/kernel.h>
++#include <linux/sched.h>
+ #include <linux/interrupt.h>
+ #include <linux/device.h>
+ #include <linux/delay.h>
diff --git a/usb/usb-gadget-storage_common-comments-updated.patch b/usb/usb-gadget-storage_common-comments-updated.patch
new file mode 100644
index 00000000000000..7b0740432d7427
--- /dev/null
+++ b/usb/usb-gadget-storage_common-comments-updated.patch
@@ -0,0 +1,159 @@
+From m.nazarewicz@samsung.com Thu Jul 8 11:30:03 2010
+From: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Date: Mon, 05 Jul 2010 16:38:04 +0200
+Subject: USB: gadget: storage_common: comments updated
+To: linux-usb@vger.kernel.org
+Cc: Sergei Shtylyov <sshtylyov@mvista.com>, Greg KH <greg@kroah.com>, linux-kernel@vger.kernel.org
+Message-ID: <dd71cb106d8ded3a1d204102ffbe67f089fff923.1278324780.git.m.nazarewicz@samsung.com>
+
+
+Updated comment to describe why printing macros are needed even
+thought they are copied form the composite.h. Also, made multiline
+comments follow the coding standard.
+
+Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/storage_common.c | 69 +++++++++++++++++++++++++-----------
+ 1 file changed, 48 insertions(+), 21 deletions(-)
+
+--- a/drivers/usb/gadget/storage_common.c
++++ b/drivers/usb/gadget/storage_common.c
+@@ -57,10 +57,12 @@
+ #include <asm/unaligned.h>
+
+
+-/* Thanks to NetChip Technologies for donating this product ID.
++/*
++ * Thanks to NetChip Technologies for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with any other driver!! Ever!!
+- * Instead: allocate your own, using normal USB-IF procedures. */
++ * Instead: allocate your own, using normal USB-IF procedures.
++ */
+ #define FSG_VENDOR_ID 0x0525 /* NetChip */
+ #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */
+
+@@ -84,14 +86,27 @@
+ #define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
+ #define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
+
+-/* Keep those macros in sync with thos in
+- * include/linux/ubs/composite.h or else GCC will complain. If they
++/*
++ * Keep those macros in sync with those in
++ * include/linux/usb/composite.h or else GCC will complain. If they
+ * are identical (the same names of arguments, white spaces in the
+ * same places) GCC will allow redefinition otherwise (even if some
+- * white space is removed or added) warning will be issued. No
+- * checking if those symbols is defined is performed because warning
+- * is desired when those macros were defined by someone else to mean
+- * something else. */
++ * white space is removed or added) warning will be issued.
++ *
++ * Those macros are needed here because File Storage Gadget does not
++ * include the composite.h header. For composite gadgets those macros
++ * are redundant since composite.h is included any way.
++ *
++ * One could check whether those macros are already defined (which
++ * would indicate composite.h had been included) or not (which would
++ * indicate we were in FSG) but this is not done because a warning is
++ * desired if definitions here differ from the ones in composite.h.
++ *
++ * We want the definitions to match and be the same in File Storage
++ * Gadget as well as Mass Storage Function (and so composite gadgets
++ * using MSF). If someone changes them in composite.h it will produce
++ * a warning in this file when building MSF.
++ */
+ #define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args)
+ #define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args)
+ #define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args)
+@@ -313,9 +328,11 @@ struct fsg_buffhd {
+ enum fsg_buffer_state state;
+ struct fsg_buffhd *next;
+
+- /* The NetChip 2280 is faster, and handles some protocol faults
++ /*
++ * The NetChip 2280 is faster, and handles some protocol faults
+ * better, if we don't submit any short bulk-out read requests.
+- * So we will record the intended request length here. */
++ * So we will record the intended request length here.
++ */
+ unsigned int bulk_out_intended_length;
+
+ struct usb_request *inreq;
+@@ -395,8 +412,10 @@ fsg_intf_desc = {
+ .iInterface = FSG_STRING_INTERFACE,
+ };
+
+-/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
+- * and interrupt-in. */
++/*
++ * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
++ * interrupt-in.
++ */
+
+ static struct usb_endpoint_descriptor
+ fsg_fs_bulk_in_desc = {
+@@ -459,7 +478,7 @@ static struct usb_descriptor_header *fsg
+ *
+ * That means alternate endpoint descriptors (bigger packets)
+ * and a "device qualifier" ... plus more construction options
+- * for the config descriptor.
++ * for the configuration descriptor.
+ */
+ static struct usb_endpoint_descriptor
+ fsg_hs_bulk_in_desc = {
+@@ -547,8 +566,10 @@ static struct usb_gadget_strings fsg_str
+
+ /*-------------------------------------------------------------------------*/
+
+-/* If the next two routines are called while the gadget is registered,
+- * the caller must own fsg->filesem for writing. */
++/*
++ * If the next two routines are called while the gadget is registered,
++ * the caller must own fsg->filesem for writing.
++ */
+
+ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
+ {
+@@ -587,8 +608,10 @@ static int fsg_lun_open(struct fsg_lun *
+ goto out;
+ }
+
+- /* If we can't read the file, it's no good.
+- * If we can't write the file, use it read-only. */
++ /*
++ * If we can't read the file, it's no good.
++ * If we can't write the file, use it read-only.
++ */
+ if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
+ LINFO(curlun, "file not readable: %s\n", filename);
+ goto out;
+@@ -646,8 +669,10 @@ static void fsg_lun_close(struct fsg_lun
+
+ /*-------------------------------------------------------------------------*/
+
+-/* Sync the file data, don't bother with the metadata.
+- * This code was copied from fs/buffer.c:sys_fdatasync(). */
++/*
++ * Sync the file data, don't bother with the metadata.
++ * This code was copied from fs/buffer.c:sys_fdatasync().
++ */
+ static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
+ {
+ struct file *filp = curlun->filp;
+@@ -728,8 +753,10 @@ static ssize_t fsg_store_ro(struct devic
+ if (sscanf(buf, "%d", &i) != 1)
+ return -EINVAL;
+
+- /* Allow the write-enable status to change only while the backing file
+- * is closed. */
++ /*
++ * Allow the write-enable status to change only while the
++ * backing file is closed.
++ */
+ down_read(filesem);
+ if (fsg_lun_is_open(curlun)) {
+ LDBG(curlun, "read-only status change prevented\n");
diff --git a/usb/usb-musb-do-not-override-dma-mode-in-channel-program.patch b/usb/usb-musb-do-not-override-dma-mode-in-channel-program.patch
new file mode 100644
index 00000000000000..3da3fdbbe3866b
--- /dev/null
+++ b/usb/usb-musb-do-not-override-dma-mode-in-channel-program.patch
@@ -0,0 +1,39 @@
+From ajay.gupta@ti.com Thu Jul 8 11:41:23 2010
+From: Anand Gadiyar <gadiyar@ti.com>
+Date: Thu, 8 Jul 2010 16:34:55 +0530
+Subject: USB: musb: do not override DMA mode in channel program
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, felipe.balbi@nokia.com, gregkh@suse.de, Anand Gadiyar <gadiyar@ti.com>, Ajay Kumar Gupta <ajay.gupta@ti.com>
+Message-ID: <1278587095-16978-3-git-send-email-ajay.gupta@ti.com>
+
+
+From: Anand Gadiyar <gadiyar@ti.com>
+
+There is no reason for the DMA channel program to override the
+DMA mode passed down by its caller. Use the passed parameter
+directly, and let the caller handle the decision on which mode
+is to be used.
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Acked-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musbhsdma.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/usb/musb/musbhsdma.c
++++ b/drivers/usb/musb/musbhsdma.c
+@@ -173,10 +173,7 @@ static int dma_channel_program(struct dm
+ musb_channel->max_packet_sz = packet_sz;
+ channel->status = MUSB_DMA_STATUS_BUSY;
+
+- if ((mode == 1) && (len >= packet_sz))
+- configure_channel(channel, packet_sz, 1, dma_addr, len);
+- else
+- configure_channel(channel, packet_sz, 0, dma_addr, len);
++ configure_channel(channel, packet_sz, mode, dma_addr, len);
+
+ return true;
+ }
diff --git a/usb/usb-musb-fix-compilation-warning-in-host-only-mode.patch b/usb/usb-musb-fix-compilation-warning-in-host-only-mode.patch
new file mode 100644
index 00000000000000..c8852ebce1f389
--- /dev/null
+++ b/usb/usb-musb-fix-compilation-warning-in-host-only-mode.patch
@@ -0,0 +1,45 @@
+From ajay.gupta@ti.com Thu Jul 8 11:40:30 2010
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 8 Jul 2010 14:03:00 +0530
+Subject: USB: musb: fix compilation warning in host only mode
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, felipe.balbi@nokia.com, gregkh@suse.de, Ajay Kumar Gupta <ajay.gupta@ti.com>
+Message-ID: <1278577982-30046-3-git-send-email-ajay.gupta@ti.com>
+
+
+Fixes below compilation warning when host only configuration is
+selected.
+drivers/usb/musb/musb_core.c: In function 'musb_stage0_irq':
+drivers/usb/musb/musb_core.c:711: warning: unused variable 'mbase'
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Acked-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_core.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -704,7 +704,6 @@ static irqreturn_t musb_stage0_irq(struc
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+ if (int_usb & MUSB_INTR_CONNECT) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+- void __iomem *mbase = musb->mregs;
+
+ handled = IRQ_HANDLED;
+ musb->is_active = 1;
+@@ -717,9 +716,9 @@ static irqreturn_t musb_stage0_irq(struc
+ if (is_peripheral_active(musb)) {
+ /* REVISIT HNP; just force disconnect */
+ }
+- musb_writew(mbase, MUSB_INTRTXE, musb->epmask);
+- musb_writew(mbase, MUSB_INTRRXE, musb->epmask & 0xfffe);
+- musb_writeb(mbase, MUSB_INTRUSBE, 0xf7);
++ musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
++ musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
++ musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
+ #endif
+ musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
+ |USB_PORT_STAT_HIGH_SPEED
diff --git a/usb/usb-musb-kill-board-specific-pinmux-from-driver-file.patch b/usb/usb-musb-kill-board-specific-pinmux-from-driver-file.patch
new file mode 100644
index 00000000000000..17a0d08f23a597
--- /dev/null
+++ b/usb/usb-musb-kill-board-specific-pinmux-from-driver-file.patch
@@ -0,0 +1,48 @@
+From ajay.gupta@ti.com Thu Jul 8 11:41:07 2010
+From: Anand Gadiyar <gadiyar@ti.com>
+Date: Thu, 8 Jul 2010 16:34:54 +0530
+Subject: USB: musb: Kill board specific pinmux from driver file
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, felipe.balbi@nokia.com, gregkh@suse.de, Anand Gadiyar <gadiyar@ti.com>, Ajay Kumar Gupta <ajay.gupta@ti.com>
+Message-ID: <1278587095-16978-2-git-send-email-ajay.gupta@ti.com>
+
+
+From: Anand Gadiyar <gadiyar@ti.com>
+
+This pin-muxing is best done in the board files. The driver should
+not do this explicitly.
+
+Also, this code causes a warning to be thrown when OMAP2430 and OMAP3/4
+support are enabled in the same kernel.
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Acked-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/omap2430.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -32,8 +32,6 @@
+ #include <linux/clk.h>
+ #include <linux/io.h>
+
+-#include <plat/mux.h>
+-
+ #include "musb_core.h"
+ #include "omap2430.h"
+
+@@ -194,10 +192,6 @@ int __init musb_platform_init(struct mus
+ u32 l;
+ struct omap_musb_board_data *data = board_data;
+
+-#if defined(CONFIG_ARCH_OMAP2430)
+- omap_cfg_reg(AE5_2430_USB0HS_STP);
+-#endif
+-
+ /* We require some kind of external transceiver, hooked
+ * up through ULPI. TWL4030-family PMICs include one,
+ * which needs a driver, drivers aren't always needed.
diff --git a/usb/usb-musb-use-correct-register-widths-in-register-dumps.patch b/usb/usb-musb-use-correct-register-widths-in-register-dumps.patch
new file mode 100644
index 00000000000000..02e487f9f4454a
--- /dev/null
+++ b/usb/usb-musb-use-correct-register-widths-in-register-dumps.patch
@@ -0,0 +1,72 @@
+From ajay.gupta@ti.com Thu Jul 8 11:40:11 2010
+From: Anand Gadiyar <gadiyar@ti.com>
+Date: Thu, 8 Jul 2010 14:02:59 +0530
+Subject: USB: musb: use correct register widths in register dumps
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, felipe.balbi@nokia.com, gregkh@suse.de, Anand Gadiyar <gadiyar@ti.com>, Ajay Kumar Gupta <ajay.gupta@ti.com>
+Message-ID: <1278577982-30046-2-git-send-email-ajay.gupta@ti.com>
+
+From: Anand Gadiyar <gadiyar@ti.com>
+
+DMA_ADDR and DMA_COUNT are 32-bit registers, not 16-bit.
+
+Marking them as 16-bit in the table causes only the lower
+16-bits to be dumped and this is misleading.
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Acked-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_debugfs.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/usb/musb/musb_debugfs.c
++++ b/drivers/usb/musb/musb_debugfs.c
+@@ -92,29 +92,29 @@ static const struct musb_register_map mu
+ { "LS_EOF1", 0x7E, 8 },
+ { "SOFT_RST", 0x7F, 8 },
+ { "DMA_CNTLch0", 0x204, 16 },
+- { "DMA_ADDRch0", 0x208, 16 },
+- { "DMA_COUNTch0", 0x20C, 16 },
++ { "DMA_ADDRch0", 0x208, 32 },
++ { "DMA_COUNTch0", 0x20C, 32 },
+ { "DMA_CNTLch1", 0x214, 16 },
+- { "DMA_ADDRch1", 0x218, 16 },
+- { "DMA_COUNTch1", 0x21C, 16 },
++ { "DMA_ADDRch1", 0x218, 32 },
++ { "DMA_COUNTch1", 0x21C, 32 },
+ { "DMA_CNTLch2", 0x224, 16 },
+- { "DMA_ADDRch2", 0x228, 16 },
+- { "DMA_COUNTch2", 0x22C, 16 },
++ { "DMA_ADDRch2", 0x228, 32 },
++ { "DMA_COUNTch2", 0x22C, 32 },
+ { "DMA_CNTLch3", 0x234, 16 },
+- { "DMA_ADDRch3", 0x238, 16 },
+- { "DMA_COUNTch3", 0x23C, 16 },
++ { "DMA_ADDRch3", 0x238, 32 },
++ { "DMA_COUNTch3", 0x23C, 32 },
+ { "DMA_CNTLch4", 0x244, 16 },
+- { "DMA_ADDRch4", 0x248, 16 },
+- { "DMA_COUNTch4", 0x24C, 16 },
++ { "DMA_ADDRch4", 0x248, 32 },
++ { "DMA_COUNTch4", 0x24C, 32 },
+ { "DMA_CNTLch5", 0x254, 16 },
+- { "DMA_ADDRch5", 0x258, 16 },
+- { "DMA_COUNTch5", 0x25C, 16 },
++ { "DMA_ADDRch5", 0x258, 32 },
++ { "DMA_COUNTch5", 0x25C, 32 },
+ { "DMA_CNTLch6", 0x264, 16 },
+- { "DMA_ADDRch6", 0x268, 16 },
+- { "DMA_COUNTch6", 0x26C, 16 },
++ { "DMA_ADDRch6", 0x268, 32 },
++ { "DMA_COUNTch6", 0x26C, 32 },
+ { "DMA_CNTLch7", 0x274, 16 },
+- { "DMA_ADDRch7", 0x278, 16 },
+- { "DMA_COUNTch7", 0x27C, 16 },
++ { "DMA_ADDRch7", 0x278, 32 },
++ { "DMA_COUNTch7", 0x27C, 32 },
+ { } /* Terminating Entry */
+ };
+
diff --git a/usb/usb-serial-io_ti-don-t-return-0-if-writing-the-download-record-failed.patch b/usb/usb-serial-io_ti-don-t-return-0-if-writing-the-download-record-failed.patch
new file mode 100644
index 00000000000000..8e3bf339ddbb82
--- /dev/null
+++ b/usb/usb-serial-io_ti-don-t-return-0-if-writing-the-download-record-failed.patch
@@ -0,0 +1,28 @@
+From roel.kluin@gmail.com Thu Jul 8 11:35:42 2010
+From: Roel Kluin <roel.kluin@gmail.com>
+Date: Fri, 02 Jul 2010 00:36:43 +0200
+Subject: USB: serial: io_ti: Don't return 0 if writing the download record failed
+To: Greg Kroah-Hartman <gregkh@suse.de>, linux-usb@vger.kernel.org, Andrew Morton <akpm@linux-foundation.org>, LKML <linux-kernel@vger.kernel.org>
+Message-ID: <4C2D187B.4020109@gmail.com>
+
+
+If the write download record failed we shouldn't return 0.
+
+Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/io_ti.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -1321,7 +1321,7 @@ static int download_fw(struct edgeport_s
+ kfree(header);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
+- return status;
++ return -EINVAL;
+ }
+
+ kfree(vheader);
diff --git a/usb/usb-ulpi-fix-compilation-warning.patch b/usb/usb-ulpi-fix-compilation-warning.patch
new file mode 100644
index 00000000000000..7cc79693b3c6bb
--- /dev/null
+++ b/usb/usb-ulpi-fix-compilation-warning.patch
@@ -0,0 +1,34 @@
+From ajay.gupta@ti.com Thu Jul 8 11:40:41 2010
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 8 Jul 2010 14:03:01 +0530
+Subject: USB: ulpi: fix compilation warning
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, felipe.balbi@nokia.com, gregkh@suse.de, Ajay Kumar Gupta <ajay.gupta@ti.com>
+Message-ID: <1278577982-30046-4-git-send-email-ajay.gupta@ti.com>
+
+
+Fixes below compilation warning from ulpi.h
+
+include/linux/usb/ulpi.h:145:
+ warning: 'struct otg_io_access_ops' declared inside parameter list
+include/linux/usb/ulpi.h:145:
+ warning: its scope is only this definition or declaration,
+ which is probably not what you want
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/usb/ulpi.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/linux/usb/ulpi.h
++++ b/include/linux/usb/ulpi.h
+@@ -11,6 +11,7 @@
+ #ifndef __LINUX_USB_ULPI_H
+ #define __LINUX_USB_ULPI_H
+
++#include <linux/usb/otg.h>
+ /*-------------------------------------------------------------------------*/
+
+ /*