aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-07-26 14:44:39 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-07-26 14:44:39 -0700
commit05eb87b12a0ff0b645dcf70ccc91942638f84802 (patch)
treed108e0bf3f90aae0e59dd715e31636b9fbd19aba
parentba9d216e7d22ef8010eeef5deacbb37bc9e58f67 (diff)
downloadpatches-05eb87b12a0ff0b645dcf70ccc91942638f84802.tar.gz
more patches
-rw-r--r--driver-core/driver-core-add-bus_notify_bind_driver.patch71
-rw-r--r--series11
-rw-r--r--tty/hsu-add-a-periodic-timer-to-check-dma-rx-channel.patch142
-rw-r--r--tty/hsu-call-pci-pm-hooks-in-suspend-resume-function.patch69
-rw-r--r--tty/hsu-driver-for-medfield-high-speed-uart-device.patch1596
-rw-r--r--tty/hsu-some-code-cleanup.patch282
-rw-r--r--tty/mxser-remove-unnesesary-null-check.patch33
-rw-r--r--tty/serial-add-support-for-ox16pci958-card.patch65
-rw-r--r--usb/usb-gadget-file_storage-serial-parameter-even-if-not-test-mode.patch104
-rw-r--r--usb/usb-imx21-hcd-set-task-state-with-schedule_timeout_uninterruptible.patch32
-rw-r--r--usb/usb-serial-enabling-support-for-segway-rmp-in-ftdi_sio.patch49
-rw-r--r--usb/usb-uvc-move-constants-and-structures-definitions-to-linux-usb-video.h.patch1044
12 files changed, 2453 insertions, 1045 deletions
diff --git a/driver-core/driver-core-add-bus_notify_bind_driver.patch b/driver-core/driver-core-add-bus_notify_bind_driver.patch
new file mode 100644
index 00000000000000..ba46fc3d39125d
--- /dev/null
+++ b/driver-core/driver-core-add-bus_notify_bind_driver.patch
@@ -0,0 +1,71 @@
+From magnus.damm@gmail.com Mon Jul 26 14:18:23 2010
+From: Magnus Damm <magnus.damm@gmail.com>
+To: linux-kernel@vger.kernel.org
+Cc: Magnus Damm <magnus.damm@gmail.com>, gregkh@suse.de
+Date: Fri, 23 Jul 2010 19:56:18 +0900
+Message-Id: <20100723105618.11690.75431.sendpatchset@t400s>
+Subject: Driver core: Add BUS_NOTIFY_BIND_DRIVER
+
+From: Magnus Damm <damm@opensource.se>
+
+Add BUS_NOTIFY_BIND_DRIVER as a bus notifier event.
+
+For driver binding/unbinding we with this in
+place have the following bus notifier events:
+ - BUS_NOTIFY_BIND_DRIVER - before ->probe()
+ - BUS_NOTIFY_BOUND_DRIVER - after ->probe()
+ - BUS_NOTIFY_UNBIND_DRIVER - before ->remove()
+ - BUS_NOTIFY_UNBOUND_DRIVER - after ->remove()
+
+The event BUS_NOTIFY_BIND_DRIVER allows bus code
+to be notified that ->probe() is about to be called.
+
+Useful for bus code that needs to setup hardware before
+the driver gets to run. With this in place platform
+drivers can be loaded and unloaded as modules and the
+new BIND event allows bus code to control for instance
+device clocks that must be enabled before the driver
+can be executed.
+
+Without this patch there is no way for the bus code to
+get notified that a modular driver is about to be probed.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/base/dd.c | 4 ++++
+ include/linux/device.h | 8 +++++---
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -51,6 +51,10 @@ static int driver_sysfs_add(struct devic
+ {
+ int ret;
+
++ if (dev->bus)
++ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
++ BUS_NOTIFY_BIND_DRIVER, dev);
++
+ ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+ if (ret == 0) {
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -109,10 +109,12 @@ extern int bus_unregister_notifier(struc
+ */
+ #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
+ #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
+-#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */
+-#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be
++#define BUS_NOTIFY_BIND_DRIVER 0x00000003 /* driver about to be
++ bound */
++#define BUS_NOTIFY_BOUND_DRIVER 0x00000004 /* driver bound to device */
++#define BUS_NOTIFY_UNBIND_DRIVER 0x00000005 /* driver about to be
+ unbound */
+-#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000005 /* driver is unbound
++#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000006 /* driver is unbound
+ from the device */
+
+ extern struct kset *bus_get_kset(struct bus_type *bus);
diff --git a/series b/series
index a9a8fe3026565c..a872183b096e64 100644
--- a/series
+++ b/series
@@ -47,6 +47,7 @@ driver-core/sysfs-fix-discrepancies-between-implementation-and-documentation.pat
driver-core/sysfs-fix-one-more-signature-discrepancy-between-sysfs-implementation-and-docs.patch
driver-core/debugfs-no-longer-needs-to-depend-on-sysfs.patch
driver-core/driver-core-fix-memory-leak-one-one-error-path-in-bus_register.patch
+driver-core/driver-core-add-bus_notify_bind_driver.patch
# can we really drop it? (nope, not yet...)
#driver-core/driver-core-remove-config_sysfs_deprecated.patch
@@ -115,6 +116,12 @@ tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch
tty/serial-mmio32-support-for-8250_early.c.patch
tty/timbuart-use-__devinit-and-__devexit-macros-for-probe-and-remove.patch
tty/serial-68328serial.c-remove-dead-alma_ans-dragonixvz-m68ez328ads.patch
+tty/serial-add-support-for-ox16pci958-card.patch
+tty/hsu-driver-for-medfield-high-speed-uart-device.patch
+tty/hsu-add-a-periodic-timer-to-check-dma-rx-channel.patch
+tty/hsu-some-code-cleanup.patch
+tty/hsu-call-pci-pm-hooks-in-suspend-resume-function.patch
+tty/mxser-remove-unnesesary-null-check.patch
###################################
@@ -139,7 +146,6 @@ usb/usb-otg.h-fix-the-mixup-in-parameters-order.patch
usb/usb-host-eliminate-null-dereference.patch
usb/usb-isd200.c-remove-unnecessary-kmalloc-cast.patch
usb/usb-throw-away-custom-hex-digit-methods.patch
-usb/usb-uvc-move-constants-and-structures-definitions-to-linux-usb-video.h.patch
usb/usb-ehci-ehci-1.1-addendum-preparation.patch
usb/usb-ehci-ehci-1.1-addendum-basic-lpm-feature-support.patch
usb/usb-ehci-ehci-1.1-addendum-enable-per-port-change-detect-bits.patch
@@ -246,6 +252,9 @@ usb/usb-s3c-hsotg-add-support-for-clock-gating.patch
usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch
usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch
usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch
+usb/usb-serial-enabling-support-for-segway-rmp-in-ftdi_sio.patch
+usb/usb-imx21-hcd-set-task-state-with-schedule_timeout_uninterruptible.patch
+usb/usb-gadget-file_storage-serial-parameter-even-if-not-test-mode.patch
# staging stuff is now in the staging-next tree on git.kernel.org
diff --git a/tty/hsu-add-a-periodic-timer-to-check-dma-rx-channel.patch b/tty/hsu-add-a-periodic-timer-to-check-dma-rx-channel.patch
new file mode 100644
index 00000000000000..6553a6dc05b74c
--- /dev/null
+++ b/tty/hsu-add-a-periodic-timer-to-check-dma-rx-channel.patch
@@ -0,0 +1,142 @@
+From alan@linux.intel.com Mon Jul 26 14:23:17 2010
+From: Alan Cox <alan@linux.intel.com>
+Subject: hsu: add a periodic timer to check dma rx channel
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Date: Mon, 26 Jul 2010 10:18:21 +0100
+Message-ID: <20100726091818.21579.67436.stgit@localhost.localdomain>
+
+From: Feng Tang <feng.tang@intel.com>
+
+A general problem for uart rx dma channel is you never know when
+and how much data will be received, so usually preset it a DMA
+descriptor with a big size, and rely on DMA RX timeout IRQ to
+know there is some data in rx channel.
+
+For a RX data size of multiple of MOTSR, there will be no timeout
+IRQ issued, thus OS will never be notified about that.
+
+This is a work around for that, current timer frequency is 5 times
+per second, it should vary according to the baud rate
+
+When future silicon version fix the problem, this workaround need
+be removed
+
+Signed-off-by: Feng Tang <feng.tang@intel.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/mfd.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 47 insertions(+), 3 deletions(-)
+
+--- a/drivers/serial/mfd.c
++++ b/drivers/serial/mfd.c
+@@ -64,6 +64,8 @@
+ #define mfd_readl(obj, offset) readl(obj->reg + offset)
+ #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset)
+
++#define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10)
++
+ struct hsu_dma_buffer {
+ u8 *buf;
+ dma_addr_t dma_addr;
+@@ -75,7 +77,8 @@ struct hsu_dma_chan {
+ u32 id;
+ u32 dirt; /* to or from device */
+ struct uart_hsu_port *uport;
+- void __iomem *reg;
++ void __iomem *reg;
++ struct timer_list rx_timer; /* only needed by RX channel */
+ };
+
+ struct uart_hsu_port {
+@@ -377,6 +380,8 @@ void hsu_dma_start_rx_chan(struct hsu_dm
+ | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
+ );
+ chan_writel(rxc, HSU_CH_CR, 0x3);
++
++ mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
+ }
+
+ /* Protected by spin_lock_irqsave(port->lock) */
+@@ -437,8 +442,13 @@ void hsu_dma_rx(struct uart_hsu_port *up
+ /* We can use 2 ways to calc the actual transfer len */
+ count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
+
+- if (!count)
++ if (!count) {
++ /* restart the channel before we leave */
++ chan_writel(chan, HSU_CH_CR, 0x3);
+ return;
++ }
++
++ del_timer(&chan->rx_timer);
+
+ dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
+ dbuf->dma_size, DMA_FROM_DEVICE);
+@@ -463,9 +473,12 @@ void hsu_dma_rx(struct uart_hsu_port *up
+ | (0x1 << 16)
+ | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
+ );
++ tty_flip_buffer_push(tty);
++
+ chan_writel(chan, HSU_CH_CR, 0x3);
++ chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ;
++ add_timer(&chan->rx_timer);
+
+- tty_flip_buffer_push(tty);
+ }
+
+ static void serial_hsu_stop_rx(struct uart_port *port)
+@@ -893,6 +906,8 @@ static void serial_hsu_shutdown(struct u
+ container_of(port, struct uart_hsu_port, port);
+ unsigned long flags;
+
++ del_timer_sync(&up->rxc->rx_timer);
++
+ /* Disable interrupts from this port */
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+@@ -1348,6 +1363,28 @@ err_disable:
+ return ret;
+ }
+
++static void hsu_dma_rx_timeout(unsigned long data)
++{
++ struct hsu_dma_chan *chan = (void *)data;
++ struct uart_hsu_port *up = chan->uport;
++ struct hsu_dma_buffer *dbuf = &up->rxbuf;
++ int count = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
++
++ if (!count) {
++ mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
++ goto exit;
++ }
++
++ hsu_dma_rx(up, 0);
++exit:
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
+ static void hsu_global_init(void)
+ {
+ struct hsu_port *hsu;
+@@ -1409,6 +1446,13 @@ static void hsu_global_init(void)
+ dchan->uport = &hsu->port[i/2];
+ dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
+ i * HSU_DMA_CHANS_REG_LENGTH;
++
++ /* Work around for RX */
++ if (dchan->dirt == DMA_FROM_DEVICE) {
++ init_timer(&dchan->rx_timer);
++ dchan->rx_timer.function = hsu_dma_rx_timeout;
++ dchan->rx_timer.data = (unsigned long)dchan;
++ }
+ dchan++;
+ }
+
diff --git a/tty/hsu-call-pci-pm-hooks-in-suspend-resume-function.patch b/tty/hsu-call-pci-pm-hooks-in-suspend-resume-function.patch
new file mode 100644
index 00000000000000..956724458e6ef7
--- /dev/null
+++ b/tty/hsu-call-pci-pm-hooks-in-suspend-resume-function.patch
@@ -0,0 +1,69 @@
+From alan@linux.intel.com Mon Jul 26 14:23:51 2010
+From: Alan Cox <alan@linux.intel.com>
+Subject: hsu: call PCI pm hooks in suspend/resume function
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Date: Mon, 26 Jul 2010 10:18:46 +0100
+Message-ID: <20100726091839.21579.4983.stgit@localhost.localdomain>
+
+From: Feng Tang <feng.tang@intel.com>
+
+Also add check for dma controller or the uart ports.
+
+Signed-off-by: Feng Tang <feng.tang@intel.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/mfd.c | 31 ++++++++++++++++++++++---------
+ 1 file changed, 22 insertions(+), 9 deletions(-)
+
+--- a/drivers/serial/mfd.c
++++ b/drivers/serial/mfd.c
+@@ -1217,25 +1217,38 @@ static struct uart_driver serial_hsu_reg
+ #ifdef CONFIG_PM
+ static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
++ void *priv = pci_get_drvdata(pdev);
+ struct uart_hsu_port *up;
+
+- up = pci_get_drvdata(pdev);
+- if (!up)
+- return 0;
+-
+- uart_suspend_port(&serial_hsu_reg, &up->port);
++ /* Make sure this is not the internal dma controller */
++ if (priv && (pdev->device != 0x081E)) {
++ up = priv;
++ uart_suspend_port(&serial_hsu_reg, &up->port);
++ }
+
++ pci_save_state(pdev);
++ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+ }
+
+ static int serial_hsu_resume(struct pci_dev *pdev)
+ {
++ void *priv = pci_get_drvdata(pdev);
+ struct uart_hsu_port *up;
++ int ret;
++
++ pci_set_power_state(pdev, PCI_D0);
++ pci_restore_state(pdev);
++
++ ret = pci_enable_device(pdev);
++ if (ret)
++ dev_warn(&pdev->dev,
++ "HSU: can't re-enable device, try to continue\n");
+
+- up = pci_get_drvdata(pdev);
+- if (!up)
+- return 0;
+- uart_resume_port(&serial_hsu_reg, &up->port);
++ if (priv && (pdev->device != 0x081E)) {
++ up = priv;
++ uart_resume_port(&serial_hsu_reg, &up->port);
++ }
+ return 0;
+ }
+ #else
diff --git a/tty/hsu-driver-for-medfield-high-speed-uart-device.patch b/tty/hsu-driver-for-medfield-high-speed-uart-device.patch
new file mode 100644
index 00000000000000..fe3e1747abf3b7
--- /dev/null
+++ b/tty/hsu-driver-for-medfield-high-speed-uart-device.patch
@@ -0,0 +1,1596 @@
+From alan@linux.intel.com Mon Jul 26 14:22:51 2010
+From: Alan Cox <alan@linux.intel.com>
+Subject: hsu: driver for Medfield High Speed UART device
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Date: Mon, 26 Jul 2010 10:18:10 +0100
+Message-ID: <20100726091803.21579.750.stgit@localhost.localdomain>
+
+From: Feng Tang <feng.tang@intel.com>
+
+This is a PCI & UART driver, which suppors both PIO and DMA mode
+UART operation. It has 3 identical UART ports and one internal
+DMA controller.
+
+Current FW will export 4 pci devices for hsu: 3 uart ports and 1
+dma controller, each has one IRQ line. And we need to discuss the
+device model, one PCI device covering whole HSU should be a better
+model, but there is a problem of how to export the 4 IRQs info
+
+Current driver set the highest baud rate to 2746800bps, which is
+easy to scale down to 115200/230400.... To suport higher baud rate,
+we need add special process, change DLAB/DLH/PS/DIV/MUL registers
+all together.
+
+921600 is the highest baud rate that has been tested with Bluetooth
+modem connected to HSU port 0. Will test more when there is right
+BT firmware.
+
+Current version contains several work around for A0's Silicon bugs
+
+Signed-off-by: Feng Tang <feng.tang@intel.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/Kconfig | 10
+ drivers/serial/Makefile | 1
+ drivers/serial/mfd.c | 1488 ++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/serial_core.h | 2
+ include/linux/serial_reg.h | 16
+ 5 files changed, 1517 insertions(+)
+
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -732,6 +732,16 @@ config MRST_MAX3110_IRQ
+ help
+ This has to be enabled after Moorestown GPIO driver is loaded
+
++config SERIAL_MFD_HSU
++ tristate "Medfield High Speed UART support"
++ depends on PCI
++ select SERIAL_CORE
++
++config SERIAL_MFD_HSU_CONSOLE
++ boolean "Medfile HSU serial console support"
++ depends on SERIAL_MFD_HSU=y
++ select SERIAL_CORE_CONSOLE
++
+ config SERIAL_BFIN
+ tristate "Blackfin serial port support"
+ depends on BLACKFIN
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -87,3 +87,4 @@ obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUAR
+ obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
+ obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+ obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
++obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
+--- /dev/null
++++ b/drivers/serial/mfd.c
+@@ -0,0 +1,1488 @@
++/*
++ * mfd.c: driver for High Speed UART device of Intel Medfield platform
++ *
++ * Refer pxa.c, 8250.c and some other drivers in drivers/serial/
++ *
++ * (C) Copyright 2009 Intel Corporation
++ *
++ * 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; version 2
++ * of the License.
++ */
++
++
++/* Notes:
++ * 1. there should be 2 types of register access method, one for
++ * UART ports, the other for the general purpose registers
++ *
++ * 2. It used to have a Irda port, but was defeatured recently
++ *
++ * 3. Based on the info from HSU MAS, 0/1 channel are assigned to
++ * port0, 2/3 chan to port 1, 4/5 chan to port 3. Even number
++ * chan will be read, odd chan for write
++ *
++ * 4. HUS supports both the 64B and 16B FIFO version, but this driver
++ * will only use 64B version
++ *
++ * 5. In A0 stepping, UART will not support TX half empty flag, thus
++ * need add a #ifdef judgement
++ *
++ * 6. One more bug for A0, the loopback mode won't support AFC
++ * auto-flow control
++ *
++ * 7. HSU has some special FCR control bits, we add it to serial_reg.h
++ *
++ * 8. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always asserted,
++ * only when the HW is reset the DDCD and DDSR will be triggered
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <linux/serial_reg.h>
++#include <linux/circ_buf.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial_core.h>
++#include <linux/serial_mfd.h>
++#include <linux/dma-mapping.h>
++#include <linux/pci.h>
++#include <linux/io.h>
++#include <linux/debugfs.h>
++
++#define MFD_HSU_A0_STEPPING 1
++
++#define HSU_DMA_BUF_SIZE 2048
++
++#define chan_readl(chan, offset) readl(chan->reg + offset)
++#define chan_writel(chan, offset, val) writel(val, chan->reg + offset)
++
++#define mfd_readl(obj, offset) readl(obj->reg + offset)
++#define mfd_writel(obj, offset, val) writel(val, obj->reg + offset)
++
++struct hsu_dma_buffer {
++ u8 *buf;
++ dma_addr_t dma_addr;
++ u32 dma_size;
++ u32 ofs;
++};
++
++struct hsu_dma_chan {
++ u32 id;
++ u32 dirt; /* to or from device */
++ struct uart_hsu_port *uport;
++ void __iomem *reg;
++};
++
++struct uart_hsu_port {
++ struct uart_port port;
++ unsigned char ier;
++ unsigned char lcr;
++ unsigned char mcr;
++ unsigned int lsr_break_flag;
++ char name[12];
++ int index;
++ struct device *dev;
++
++ struct hsu_dma_chan *txc;
++ struct hsu_dma_chan *rxc;
++ struct hsu_dma_buffer txbuf;
++ struct hsu_dma_buffer rxbuf;
++ int use_dma; /* flag for DMA/PIO */
++ int running;
++ int dma_tx_on;
++};
++
++/* Top level data structure of HSU */
++struct hsu_port {
++ struct pci_device *pdev;
++
++ void __iomem *reg;
++ unsigned long paddr;
++ unsigned long iolen;
++ u32 irq;
++
++ struct uart_hsu_port port[3];
++ struct hsu_dma_chan chans[10];
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *debugfs;
++#endif
++};
++
++static inline void hexdump(char *str, u8 *addr, int cnt)
++{
++ int i;
++
++ for (i = 0; i < cnt; i += 8) {
++ printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
++ addr[i], addr[i+1], addr[i+2], addr[i+3],
++ addr[i+4], addr[i+5], addr[i+6], addr[i+7]);
++ printk("\n");
++ }
++}
++
++static inline unsigned int serial_in(struct uart_hsu_port *up, int offset)
++{
++ unsigned int val;
++
++ if (offset > UART_MSR) {
++ offset <<= 2;
++ val = readl(up->port.membase + offset);
++ } else
++ val = (unsigned int)readb(up->port.membase + offset);
++
++ return val;
++}
++
++static inline void serial_out(struct uart_hsu_port *up, int offset, int value)
++{
++ if (offset > UART_MSR) {
++ offset <<= 2;
++ writel(value, up->port.membase + offset);
++ } else {
++ unsigned char val = value & 0xff;
++ writeb(val, up->port.membase + offset);
++ }
++}
++
++#ifdef CONFIG_DEBUG_FS
++
++#define HSU_REGS_BUFSIZE 1024
++
++static int hsu_show_regs_open(struct inode *inode, struct file *file)
++{
++ file->private_data = inode->i_private;
++ return 0;
++}
++
++static ssize_t port_show_regs(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct uart_hsu_port *up = file->private_data;
++ char *buf;
++ u32 len = 0;
++ ssize_t ret;
++
++ buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
++ if (!buf)
++ return 0;
++
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "MFD HSU port[%d] regs:\n", up->index);
++
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "=================================\n");
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "IER: \t\t0x%08x\n", serial_in(up, UART_IER));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "PS: \t\t0x%08x\n", serial_in(up, UART_PS));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
++ kfree(buf);
++ return ret;
++}
++
++static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct hsu_dma_chan *chan = file->private_data;
++ char *buf;
++ u32 len = 0;
++ ssize_t ret;
++
++ buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
++ if (!buf)
++ return 0;
++
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "MFD HSU DMA channel [%d] regs:\n", chan->id);
++
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "=================================\n");
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR));
++ len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
++ "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
++ kfree(buf);
++ return ret;
++}
++
++static const struct file_operations port_regs_ops = {
++ .owner = THIS_MODULE,
++ .open = hsu_show_regs_open,
++ .read = port_show_regs,
++};
++
++static const struct file_operations dma_regs_ops = {
++ .owner = THIS_MODULE,
++ .open = hsu_show_regs_open,
++ .read = dma_show_regs,
++};
++
++static int hsu_debugfs_init(struct hsu_port *hsu)
++{
++ int i;
++ char name[32];
++
++ hsu->debugfs = debugfs_create_dir("hsu", NULL);
++ if (!hsu->debugfs)
++ return -ENOMEM;
++
++ for (i = 0; i < 3; i++) {
++ snprintf(name, sizeof(name), "port_%d_regs", i);
++ debugfs_create_file(name, S_IFREG | S_IRUGO,
++ hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops);
++ }
++
++ for (i = 0; i < 6; i++) {
++ snprintf(name, sizeof(name), "dma_chan_%d_regs", i);
++ debugfs_create_file(name, S_IFREG | S_IRUGO,
++ hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops);
++ }
++
++ return 0;
++}
++
++static void hsu_debugfs_remove(struct hsu_port *hsu)
++{
++ if (hsu->debugfs)
++ debugfs_remove_recursive(hsu->debugfs);
++}
++
++#else
++static inline int hsu_debugfs_init(struct hsu_port *hsu)
++{
++ return 0;
++}
++
++static inline void hsu_debugfs_remove(struct hsu_port *hsu)
++{
++}
++#endif /* CONFIG_DEBUG_FS */
++
++static void serial_hsu_enable_ms(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++
++ up->ier |= UART_IER_MSI;
++ serial_out(up, UART_IER, up->ier);
++}
++
++void hsu_dma_tx(struct uart_hsu_port *up)
++{
++ struct circ_buf *xmit = &up->port.state->xmit;
++ struct hsu_dma_buffer *dbuf = &up->txbuf;
++ int count;
++
++ /* test_and_set_bit may be better, but anyway it's in lock protected mode */
++ if (up->dma_tx_on)
++ return;
++
++ /* Update the circ buf info */
++ xmit->tail += dbuf->ofs;
++ xmit->tail &= UART_XMIT_SIZE - 1;
++
++ up->port.icount.tx += dbuf->ofs;
++ dbuf->ofs = 0;
++
++ /* Disable the channel */
++ chan_writel(up->txc, HSU_CH_CR, 0x0);
++
++ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) {
++ dma_sync_single_for_device(up->port.dev,
++ dbuf->dma_addr,
++ dbuf->dma_size,
++ DMA_TO_DEVICE);
++
++ count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
++ dbuf->ofs = count;
++
++ /* Reprogram the channel */
++ chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail);
++ chan_writel(up->txc, HSU_CH_D0TSR, count);
++
++ /* Reenable the channel */
++ chan_writel(up->txc, HSU_CH_DCR, 0x1
++ | (0x1 << 8)
++ | (0x1 << 16)
++ | (0x1 << 24));
++
++ WARN(chan_readl(up->txc, HSU_CH_CR) & 0x1,
++ "TX channel has already be started!!\n");
++ up->dma_tx_on = 1;
++ chan_writel(up->txc, HSU_CH_CR, 0x1);
++ }
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&up->port);
++}
++
++/* The buffer is already cache coherent */
++void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf)
++{
++ /* Need start RX dma channel here */
++ dbuf->ofs = 0;
++
++ chan_writel(rxc, HSU_CH_BSR, 32);
++ chan_writel(rxc, HSU_CH_MOTSR, 4);
++
++ chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr);
++ chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size);
++ chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8)
++ | (0x1 << 16)
++ | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
++ );
++ chan_writel(rxc, HSU_CH_CR, 0x3);
++}
++
++/* Protected by spin_lock_irqsave(port->lock) */
++static void serial_hsu_start_tx(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++
++ if (up->use_dma) {
++ hsu_dma_tx(up);
++ } else if (!(up->ier & UART_IER_THRI)) {
++ up->ier |= UART_IER_THRI;
++ serial_out(up, UART_IER, up->ier);
++ }
++}
++
++static void serial_hsu_stop_tx(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ struct hsu_dma_chan *txc = up->txc;
++
++ if (up->use_dma)
++ chan_writel(txc, HSU_CH_CR, 0x0);
++ else if (up->ier & UART_IER_THRI) {
++ up->ier &= ~UART_IER_THRI;
++ serial_out(up, UART_IER, up->ier);
++ }
++}
++
++/* This is always called in spinlock protected mode, so
++ * modify timeout timer is safe here */
++void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
++{
++ struct hsu_dma_buffer *dbuf = &up->rxbuf;
++ struct hsu_dma_chan *chan = up->rxc;
++ struct uart_port *port = &up->port;
++ struct tty_struct *tty = port->state->port.tty;
++ int count;
++
++ if (!tty)
++ return;
++
++ /*
++ * first need to know how many is already transferred,
++ * then check if its a timeout DMA irq, and return
++ * the trail bytes out, push them up and reenable the
++ * channel, better to use 2 descriptors at the same time
++ */
++
++ /* timeout IRQ, need wait some time, see Errata 2 */
++ if (int_sts & 0xf00)
++ udelay(2);
++
++ /* Stop the channel */
++ chan_writel(chan, HSU_CH_CR, 0x0);
++
++ /* We can use 2 ways to calc the actual transfer len */
++ count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
++
++ if (!count)
++ return;
++
++ dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
++ dbuf->dma_size, DMA_FROM_DEVICE);
++
++ /*
++ * head will only wrap around when we recycle
++ * the DMA buffer, and when that happens, we
++ * explicitly set tail to 0. So head will
++ * always be greater than tail.
++ */
++ tty_insert_flip_string(tty, dbuf->buf, count);
++ port->icount.rx += count;
++
++ dma_sync_single_for_device(up->port.dev, dbuf->dma_addr,
++ dbuf->dma_size, DMA_FROM_DEVICE);
++
++ /* Reprogram the channel */
++ chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr);
++ chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size);
++ chan_writel(chan, HSU_CH_DCR, 0x1
++ | (0x1 << 8)
++ | (0x1 << 16)
++ | (0x1 << 24) /* timeout bit, see HSU Errata 1 */
++ );
++ chan_writel(chan, HSU_CH_CR, 0x3);
++
++ tty_flip_buffer_push(tty);
++}
++
++static void serial_hsu_stop_rx(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ struct hsu_dma_chan *chan = up->rxc;
++
++ if (up->use_dma)
++ chan_writel(chan, HSU_CH_CR, 0x2);
++ else {
++ up->ier &= ~UART_IER_RLSI;
++ up->port.read_status_mask &= ~UART_LSR_DR;
++ serial_out(up, UART_IER, up->ier);
++ }
++}
++
++/*
++ * if there is error flag, should we just reset the FIFO or keeps
++ * working on it
++ */
++static inline void receive_chars(struct uart_hsu_port *up, int *status)
++{
++ struct tty_struct *tty = up->port.state->port.tty;
++ unsigned int ch, flag;
++ unsigned int max_count = 256;
++
++ if (!tty)
++ return;
++
++ do {
++ ch = serial_in(up, UART_RX);
++ flag = TTY_NORMAL;
++ up->port.icount.rx++;
++
++ if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
++ UART_LSR_FE | UART_LSR_OE))) {
++
++ dev_warn(up->dev, "We really rush into ERR/BI case"
++ "status = 0x%02x", *status);
++ /* For statistics only */
++ if (*status & UART_LSR_BI) {
++ *status &= ~(UART_LSR_FE | UART_LSR_PE);
++ up->port.icount.brk++;
++ /*
++ * We do the SysRQ and SAK checking
++ * here because otherwise the break
++ * may get masked by ignore_status_mask
++ * or read_status_mask.
++ */
++ if (uart_handle_break(&up->port))
++ goto ignore_char;
++ } else if (*status & UART_LSR_PE)
++ up->port.icount.parity++;
++ else if (*status & UART_LSR_FE)
++ up->port.icount.frame++;
++ if (*status & UART_LSR_OE)
++ up->port.icount.overrun++;
++
++ /* Mask off conditions which should be ignored. */
++ *status &= up->port.read_status_mask;
++
++#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
++ if (up->port.cons &&
++ up->port.cons->index == up->port.line) {
++ /* Recover the break flag from console xmit */
++ *status |= up->lsr_break_flag;
++ up->lsr_break_flag = 0;
++ }
++#endif
++ if (*status & UART_LSR_BI) {
++ flag = TTY_BREAK;
++ } else if (*status & UART_LSR_PE)
++ flag = TTY_PARITY;
++ else if (*status & UART_LSR_FE)
++ flag = TTY_FRAME;
++ }
++
++ if (uart_handle_sysrq_char(&up->port, ch))
++ goto ignore_char;
++
++ uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
++ ignore_char:
++ *status = serial_in(up, UART_LSR);
++ } while ((*status & UART_LSR_DR) && max_count--);
++ tty_flip_buffer_push(tty);
++}
++
++static void transmit_chars(struct uart_hsu_port *up)
++{
++ struct circ_buf *xmit = &up->port.state->xmit;
++ int count;
++ int i = 0; /* for debug use */
++
++ if (up->port.x_char) {
++ serial_out(up, UART_TX, up->port.x_char);
++ up->port.icount.tx++;
++ up->port.x_char = 0;
++ return;
++ }
++ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
++ serial_hsu_stop_tx(&up->port);
++ return;
++ }
++
++#ifndef MFD_HSU_A0_STEPPING
++ count = up->port.fifosize / 2;
++#else
++ /*
++ * A0 only supports fully empty IRQ, and the first char written
++ * into it won't clear the EMPT bit, so we may need be cautious
++ * by useing a shorter buffer
++ */
++ /* count = up->port.fifosize; */
++ count = up->port.fifosize - 4;
++#endif
++ do {
++ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ i++;
++
++ up->port.icount.tx++;
++ if (uart_circ_empty(xmit))
++ break;
++ } while (--count > 0);
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&up->port);
++
++ if (uart_circ_empty(xmit))
++ serial_hsu_stop_tx(&up->port);
++}
++
++static inline void check_modem_status(struct uart_hsu_port *up)
++{
++ int status;
++
++ status = serial_in(up, UART_MSR);
++
++ if ((status & UART_MSR_ANY_DELTA) == 0)
++ return;
++
++ if (status & UART_MSR_TERI)
++ up->port.icount.rng++;
++ if (status & UART_MSR_DDSR)
++ up->port.icount.dsr++;
++ /* We may only get DDCD when HW init and reset */
++ if (status & UART_MSR_DDCD)
++ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
++ /* will start/stop_tx accordingly */
++ if (status & UART_MSR_DCTS)
++ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
++
++ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
++}
++
++/*
++ * This handles the interrupt from one port.
++ */
++static irqreturn_t port_irq(int irq, void *dev_id)
++{
++ struct uart_hsu_port *up = dev_id;
++ unsigned int iir, lsr;
++ unsigned long flags;
++
++ if (unlikely(!up->running))
++ return IRQ_NONE;
++
++ if (up->use_dma) {
++ lsr = serial_in(up, UART_LSR);
++ if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
++ UART_LSR_FE | UART_LSR_OE)))
++ dev_warn(up->dev,
++ "Got lsr irq while using DMA, lsr = 0x%2x\n",
++ lsr);
++ check_modem_status(up);
++ return IRQ_HANDLED;
++ }
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ iir = serial_in(up, UART_IIR);
++ if (iir & UART_IIR_NO_INT) {
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ return IRQ_NONE;
++ }
++
++ lsr = serial_in(up, UART_LSR);
++
++ if (lsr & UART_LSR_DR)
++ receive_chars(up, &lsr);
++
++ /* lsr will be renewed during the receive_chars */
++ if (lsr & UART_LSR_THRE)
++ transmit_chars(up);
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ return IRQ_HANDLED;
++}
++
++static inline void dma_chan_irq(struct hsu_dma_chan *chan)
++{
++ struct uart_hsu_port *up = chan->uport;
++ unsigned long flags;
++ u32 int_sts;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ if (!up->use_dma || !up->running)
++ goto exit;
++
++ /*
++ * No matter what situation, need read clear the IRQ status
++ * There is a bug, see Errata 5, HSD 2900918
++ */
++ int_sts = chan_readl(chan, HSU_CH_SR);
++
++ /* Rx channel */
++ if (chan->dirt == DMA_FROM_DEVICE)
++ hsu_dma_rx(up, int_sts);
++
++ /* Tx channel */
++ if (chan->dirt == DMA_TO_DEVICE) {
++ /* dma for irq should be done */
++ chan_writel(chan, HSU_CH_CR, 0x0);
++ up->dma_tx_on = 0;
++ hsu_dma_tx(up);
++ }
++
++exit:
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ return;
++}
++
++static irqreturn_t dma_irq(int irq, void *dev_id)
++{
++ struct hsu_port *hsu = dev_id;
++ u32 int_sts, i;
++
++ int_sts = mfd_readl(hsu, HSU_GBL_DMAISR);
++
++ /* Currently we only have 6 channels may be used */
++ for (i = 0; i < 6; i++) {
++ if (int_sts & 0x1)
++ dma_chan_irq(&hsu->chans[i]);
++ int_sts >>= 1;
++ }
++
++ return IRQ_HANDLED;
++}
++
++static unsigned int serial_hsu_tx_empty(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ return ret;
++}
++
++static unsigned int serial_hsu_get_mctrl(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ unsigned char status;
++ unsigned int ret;
++
++ status = serial_in(up, UART_MSR);
++
++ ret = 0;
++ if (status & UART_MSR_DCD)
++ ret |= TIOCM_CAR;
++ if (status & UART_MSR_RI)
++ ret |= TIOCM_RNG;
++ if (status & UART_MSR_DSR)
++ ret |= TIOCM_DSR;
++ if (status & UART_MSR_CTS)
++ ret |= TIOCM_CTS;
++ return ret;
++}
++
++static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ unsigned char mcr = 0;
++
++ if (mctrl & TIOCM_RTS)
++ mcr |= UART_MCR_RTS;
++ if (mctrl & TIOCM_DTR)
++ mcr |= UART_MCR_DTR;
++ if (mctrl & TIOCM_OUT1)
++ mcr |= UART_MCR_OUT1;
++ if (mctrl & TIOCM_OUT2)
++ mcr |= UART_MCR_OUT2;
++ if (mctrl & TIOCM_LOOP)
++ mcr |= UART_MCR_LOOP;
++
++ mcr |= up->mcr;
++
++ serial_out(up, UART_MCR, mcr);
++}
++
++static void serial_hsu_break_ctl(struct uart_port *port, int break_state)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ if (break_state == -1)
++ up->lcr |= UART_LCR_SBC;
++ else
++ up->lcr &= ~UART_LCR_SBC;
++ serial_out(up, UART_LCR, up->lcr);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++/*
++ * What special to do:
++ * 1. chose the 64B fifo mode
++ * 2. make sure not to select half empty mode for A0 stepping
++ * 3. start dma or pio depends on configuration
++ * 4. we only allocate dma memory when needed
++ */
++static int serial_hsu_startup(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ unsigned long flags;
++
++ /*
++ * Clear the FIFO buffers and disable them.
++ * (they will be reenabled in set_termios())
++ */
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
++ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
++ serial_out(up, UART_FCR, 0);
++
++ /* Clear the interrupt registers. */
++ (void) serial_in(up, UART_LSR);
++ (void) serial_in(up, UART_RX);
++ (void) serial_in(up, UART_IIR);
++ (void) serial_in(up, UART_MSR);
++
++ /* Now, initialize the UART, default is 8n1 */
++ serial_out(up, UART_LCR, UART_LCR_WLEN8);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ up->port.mctrl |= TIOCM_OUT2;
++ serial_hsu_set_mctrl(&up->port, up->port.mctrl);
++
++ /*
++ * Finally, enable interrupts. Note: Modem status interrupts
++ * are set via set_termios(), which will be occurring imminently
++ * anyway, so we don't enable them here.
++ */
++ if (!up->use_dma)
++ up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE;
++ else
++ up->ier = 0;
++ serial_out(up, UART_IER, up->ier);
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /* DMA init */
++ /* When use DMA, TX/RX's FIFO and IRQ should be disabled */
++ if (up->use_dma) {
++ struct hsu_dma_buffer *dbuf;
++ struct circ_buf *xmit = &port->state->xmit;
++
++ up->dma_tx_on = 0;
++
++ /* First allocate the RX buffer */
++ dbuf = &up->rxbuf;
++ dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL);
++ if (!dbuf->buf) {
++ up->use_dma = 0;
++ goto exit;
++ }
++ dbuf->dma_addr = dma_map_single(port->dev,
++ dbuf->buf,
++ HSU_DMA_BUF_SIZE,
++ DMA_FROM_DEVICE);
++ dbuf->dma_size = HSU_DMA_BUF_SIZE;
++
++ /* Start the RX channel right now */
++ hsu_dma_start_rx_chan(up->rxc, dbuf);
++
++ /* Next init the TX DMA */
++ dbuf = &up->txbuf;
++ dbuf->buf = xmit->buf;
++ dbuf->dma_addr = dma_map_single(port->dev,
++ dbuf->buf,
++ UART_XMIT_SIZE,
++ DMA_TO_DEVICE);
++ dbuf->dma_size = UART_XMIT_SIZE;
++
++ /* This should not be changed all around */
++ chan_writel(up->txc, HSU_CH_BSR, 32);
++ chan_writel(up->txc, HSU_CH_MOTSR, 4);
++ dbuf->ofs = 0;
++ }
++
++exit:
++ /* And clear the interrupt registers again for luck. */
++ (void) serial_in(up, UART_LSR);
++ (void) serial_in(up, UART_RX);
++ (void) serial_in(up, UART_IIR);
++ (void) serial_in(up, UART_MSR);
++
++ up->running = 1;
++ return 0;
++}
++
++static void serial_hsu_shutdown(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ unsigned long flags;
++
++ /* Disable interrupts from this port */
++ up->ier = 0;
++ serial_out(up, UART_IER, 0);
++ up->running = 0;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ up->port.mctrl &= ~TIOCM_OUT2;
++ serial_hsu_set_mctrl(&up->port, up->port.mctrl);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /* Disable break condition and FIFOs */
++ serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
++ UART_FCR_CLEAR_RCVR |
++ UART_FCR_CLEAR_XMIT);
++ serial_out(up, UART_FCR, 0);
++}
++
++static void
++serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
++ struct ktermios *old)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ struct tty_struct *tty = port->state->port.tty;
++ unsigned char cval, fcr = 0;
++ unsigned long flags;
++ unsigned int baud, quot;
++ u32 mul = 0x3600;
++ u32 ps = 0x10;
++
++ switch (termios->c_cflag & CSIZE) {
++ case CS5:
++ cval = UART_LCR_WLEN5;
++ break;
++ case CS6:
++ cval = UART_LCR_WLEN6;
++ break;
++ case CS7:
++ cval = UART_LCR_WLEN7;
++ break;
++ default:
++ case CS8:
++ cval = UART_LCR_WLEN8;
++ break;
++ }
++
++ /* CMSPAR isn't supported by this driver */
++ if (tty)
++ tty->termios->c_cflag &= ~CMSPAR;
++
++ if (termios->c_cflag & CSTOPB)
++ cval |= UART_LCR_STOP;
++ if (termios->c_cflag & PARENB)
++ cval |= UART_LCR_PARITY;
++ if (!(termios->c_cflag & PARODD))
++ cval |= UART_LCR_EPAR;
++
++ /*
++ * For those basic low baud rate we can get the direct
++ * scalar from 2746800, like 115200 = 2746800/24, for those
++ * higher baud rate, we have to handle them case by case,
++ * but DIV reg is never touched as its default value 0x3d09
++ */
++ baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
++ quot = uart_get_divisor(port, baud);
++
++ switch (baud) {
++ case 3500000:
++ mul = 0x3345;
++ ps = 0xC;
++ quot = 1;
++ break;
++ case 2500000:
++ mul = 0x2710;
++ ps = 0x10;
++ quot = 1;
++ break;
++ case 18432000:
++ mul = 0x2400;
++ ps = 0x10;
++ quot = 1;
++ break;
++ case 1500000:
++ mul = 0x1D4C;
++ ps = 0xc;
++ quot = 1;
++ break;
++ default:
++ ;
++ }
++
++ if ((up->port.uartclk / quot) < (2400 * 16))
++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
++ else if ((up->port.uartclk / quot) < (230400 * 16))
++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B;
++ else
++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;
++
++ fcr |= UART_FCR_HSU_64B_FIFO;
++#ifdef MFD_HSU_A0_STEPPING
++ /* A0 doesn't support half empty IRQ */
++ fcr |= UART_FCR_FULL_EMPT_TXI;
++#endif
++
++ /*
++ * Ok, we're now changing the port state. Do it with
++ * interrupts disabled.
++ */
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ /* Update the per-port timeout */
++ uart_update_timeout(port, termios->c_cflag, baud);
++
++ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
++ if (termios->c_iflag & INPCK)
++ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++ if (termios->c_iflag & (BRKINT | PARMRK))
++ up->port.read_status_mask |= UART_LSR_BI;
++
++ /* Characters to ignore */
++ up->port.ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
++ if (termios->c_iflag & IGNBRK) {
++ up->port.ignore_status_mask |= UART_LSR_BI;
++ /*
++ * If we're ignoring parity and break indicators,
++ * ignore overruns too (for real raw support).
++ */
++ if (termios->c_iflag & IGNPAR)
++ up->port.ignore_status_mask |= UART_LSR_OE;
++ }
++
++ /* Ignore all characters if CREAD is not set */
++ if ((termios->c_cflag & CREAD) == 0)
++ up->port.ignore_status_mask |= UART_LSR_DR;
++
++ /*
++ * CTS flow control flag and modem status interrupts, disable
++ * MSI by default
++ */
++ up->ier &= ~UART_IER_MSI;
++ if (UART_ENABLE_MS(&up->port, termios->c_cflag))
++ up->ier |= UART_IER_MSI;
++
++ serial_out(up, UART_IER, up->ier);
++
++ if (termios->c_cflag & CRTSCTS)
++ up->mcr |= UART_MCR_AFE | UART_MCR_RTS;
++ else
++ up->mcr &= ~UART_MCR_AFE;
++
++ serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
++ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
++ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
++ serial_out(up, UART_LCR, cval); /* reset DLAB */
++ serial_out(up, UART_MUL, mul); /* set MUL */
++ serial_out(up, UART_PS, ps); /* set PS */
++ up->lcr = cval; /* Save LCR */
++ serial_hsu_set_mctrl(&up->port, up->port.mctrl);
++ serial_out(up, UART_FCR, fcr);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++static void
++serial_hsu_pm(struct uart_port *port, unsigned int state,
++ unsigned int oldstate)
++{
++}
++
++static void serial_hsu_release_port(struct uart_port *port)
++{
++}
++
++static int serial_hsu_request_port(struct uart_port *port)
++{
++ return 0;
++}
++
++static void serial_hsu_config_port(struct uart_port *port, int flags)
++{
++#if 0
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ up->port.type = PORT_MFD;
++#endif
++}
++
++static int
++serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++ /* We don't want the core code to modify any port params */
++ return -EINVAL;
++}
++
++static const char *
++serial_hsu_type(struct uart_port *port)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++ return up->name;
++}
++
++/* Mainly for uart console use */
++static struct uart_hsu_port *serial_hsu_ports[3];
++static struct uart_driver serial_hsu_reg;
++
++#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
++
++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
++
++/* Wait for transmitter & holding register to empty */
++static inline void wait_for_xmitr(struct uart_hsu_port *up)
++{
++ unsigned int status, tmout = 1000;
++
++ /* Wait up to 1ms for the character to be sent. */
++ do {
++ status = serial_in(up, UART_LSR);
++
++ if (status & UART_LSR_BI)
++ up->lsr_break_flag = UART_LSR_BI;
++
++ if (--tmout == 0)
++ break;
++ udelay(1);
++ } while (!(status & BOTH_EMPTY));
++
++ /* Wait up to 1s for flow control if necessary */
++ if (up->port.flags & UPF_CONS_FLOW) {
++ tmout = 1000000;
++ while (--tmout &&
++ ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
++ udelay(1);
++ }
++}
++
++static void serial_hsu_console_putchar(struct uart_port *port, int ch)
++{
++ struct uart_hsu_port *up =
++ container_of(port, struct uart_hsu_port, port);
++
++ wait_for_xmitr(up);
++ serial_out(up, UART_TX, ch);
++}
++
++/*
++ * Print a string to the serial port trying not to disturb
++ * any possible real use of the port...
++ *
++ * The console_lock must be held when we get here.
++ */
++static void
++serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
++{
++ struct uart_hsu_port *up = serial_hsu_ports[co->index];
++ unsigned long flags;
++ unsigned int ier;
++ int locked = 1;
++
++ local_irq_save(flags);
++ if (up->port.sysrq)
++ locked = 0;
++ else if (oops_in_progress) {
++ locked = spin_trylock(&up->port.lock);
++ } else
++ spin_lock(&up->port.lock);
++
++ /* First save the IER then disable the interrupts */
++ ier = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, 0);
++
++ uart_console_write(&up->port, s, count, serial_hsu_console_putchar);
++
++ /*
++ * Finally, wait for transmitter to become empty
++ * and restore the IER
++ */
++ wait_for_xmitr(up);
++ serial_out(up, UART_IER, ier);
++
++ if (locked)
++ spin_unlock(&up->port.lock);
++ local_irq_restore(flags);
++}
++
++static struct console serial_hsu_console;
++
++static int __init
++serial_hsu_console_setup(struct console *co, char *options)
++{
++ struct uart_hsu_port *up;
++ int baud = 115200;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++ int ret;
++
++ if (co->index == -1 || co->index >= serial_hsu_reg.nr)
++ co->index = 0;
++ up = serial_hsu_ports[co->index];
++ if (!up)
++ return -ENODEV;
++
++ if (options)
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++
++ ret = uart_set_options(&up->port, co, baud, parity, bits, flow);
++
++ return ret;
++}
++
++static struct console serial_hsu_console = {
++ .name = "ttyMFD",
++ .write = serial_hsu_console_write,
++ .device = uart_console_device,
++ .setup = serial_hsu_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = 2,
++ .data = &serial_hsu_reg,
++};
++#endif
++
++struct uart_ops serial_hsu_pops = {
++ .tx_empty = serial_hsu_tx_empty,
++ .set_mctrl = serial_hsu_set_mctrl,
++ .get_mctrl = serial_hsu_get_mctrl,
++ .stop_tx = serial_hsu_stop_tx,
++ .start_tx = serial_hsu_start_tx,
++ .stop_rx = serial_hsu_stop_rx,
++ .enable_ms = serial_hsu_enable_ms,
++ .break_ctl = serial_hsu_break_ctl,
++ .startup = serial_hsu_startup,
++ .shutdown = serial_hsu_shutdown,
++ .set_termios = serial_hsu_set_termios,
++ .pm = serial_hsu_pm,
++ .type = serial_hsu_type,
++ .release_port = serial_hsu_release_port,
++ .request_port = serial_hsu_request_port,
++ .config_port = serial_hsu_config_port,
++ .verify_port = serial_hsu_verify_port,
++};
++
++static struct uart_driver serial_hsu_reg = {
++ .owner = THIS_MODULE,
++ .driver_name = "MFD serial",
++ .dev_name = "ttyMFD",
++ .major = TTY_MAJOR,
++ .minor = 128,
++ .nr = 3,
++};
++
++#ifdef CONFIG_PM
++static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ struct uart_hsu_port *up;
++
++ up = pci_get_drvdata(pdev);
++ if (!up)
++ return 0;
++
++ uart_suspend_port(&serial_hsu_reg, &up->port);
++
++ return 0;
++}
++
++static int serial_hsu_resume(struct pci_dev *pdev)
++{
++ struct uart_hsu_port *up;
++
++ up = pci_get_drvdata(pdev);
++ if (!up)
++ return 0;
++ uart_resume_port(&serial_hsu_reg, &up->port);
++ return 0;
++}
++#else
++#define serial_hsu_suspend NULL
++#define serial_hsu_resume NULL
++#endif
++
++/* temp global pointer before we settle down on using one or four PCI dev */
++static struct hsu_port *phsu;
++
++static int serial_hsu_probe(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++{
++ struct uart_hsu_port *uport;
++ int index, ret;
++
++ printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n",
++ pdev->vendor, pdev->device);
++
++ switch (pdev->device) {
++ case 0x081B:
++ index = 0;
++ break;
++ case 0x081C:
++ index = 1;
++ break;
++ case 0x081D:
++ index = 2;
++ break;
++ case 0x081E:
++ /* internal DMA controller */
++ index = 3;
++ break;
++ default:
++ dev_err(&pdev->dev, "HSU: out of index!");
++ return -ENODEV;
++ }
++
++ ret = pci_enable_device(pdev);
++ if (ret)
++ return ret;
++
++ if (index == 3) {
++ /* DMA controller */
++ ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu);
++ if (ret) {
++ dev_err(&pdev->dev, "can not get IRQ\n");
++ goto err_disable;
++ }
++ pci_set_drvdata(pdev, phsu);
++ } else {
++ /* UART port 0~2 */
++ uport = &phsu->port[index];
++ uport->port.irq = pdev->irq;
++ uport->port.dev = &pdev->dev;
++ uport->dev = &pdev->dev;
++
++ ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport);
++ if (ret) {
++ dev_err(&pdev->dev, "can not get IRQ\n");
++ goto err_disable;
++ }
++ uart_add_one_port(&serial_hsu_reg, &uport->port);
++
++#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
++ if (index == 2) {
++ register_console(&serial_hsu_console);
++ uport->port.cons = &serial_hsu_console;
++ }
++#endif
++ pci_set_drvdata(pdev, uport);
++ }
++
++ return 0;
++
++err_disable:
++ pci_disable_device(pdev);
++ return ret;
++}
++
++static void hsu_global_init(void)
++{
++ struct hsu_port *hsu;
++ struct uart_hsu_port *uport;
++ struct hsu_dma_chan *dchan;
++ int i, ret;
++
++ hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL);
++ if (!hsu)
++ return;
++
++ /* Get basic io resource and map it */
++ hsu->paddr = 0xffa28000;
++ hsu->iolen = 0x1000;
++
++ if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global")))
++ pr_warning("HSU: error in request mem region\n");
++
++ hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen);
++ if (!hsu->reg) {
++ pr_err("HSU: error in ioremap\n");
++ ret = -ENOMEM;
++ goto err_free_region;
++ }
++
++ /* Initialise the 3 UART ports */
++ uport = hsu->port;
++ for (i = 0; i < 3; i++) {
++ uport->port.type = PORT_MFD;
++ uport->port.iotype = UPIO_MEM;
++ uport->port.mapbase = (resource_size_t)hsu->paddr
++ + HSU_PORT_REG_OFFSET
++ + i * HSU_PORT_REG_LENGTH;
++ uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET
++ + i * HSU_PORT_REG_LENGTH;
++
++ sprintf(uport->name, "hsu_port%d", i);
++ uport->port.fifosize = 64;
++ uport->port.ops = &serial_hsu_pops;
++ uport->port.line = i;
++ uport->port.flags = UPF_IOREMAP;
++ /* make the maxim support rate to 2746800 bps */
++ uport->port.uartclk = 115200 * 24 * 16;
++
++ uport->running = 0;
++ uport->txc = &hsu->chans[i * 2];
++ uport->rxc = &hsu->chans[i * 2 + 1];
++
++ serial_hsu_ports[i] = uport;
++ uport->index = i;
++ uport++;
++ }
++
++ /* Initialise 6 dma channels */
++ dchan = hsu->chans;
++ for (i = 0; i < 6; i++) {
++ dchan->id = i;
++ dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
++ dchan->uport = &hsu->port[i/2];
++ dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
++ i * HSU_DMA_CHANS_REG_LENGTH;
++ dchan++;
++ }
++
++ phsu = hsu;
++
++ hsu_debugfs_init(hsu);
++ return;
++
++err_free_region:
++ release_mem_region(hsu->paddr, hsu->iolen);
++ kfree(hsu);
++ return;
++}
++
++static void serial_hsu_remove(struct pci_dev *pdev)
++{
++ struct hsu_port *hsu;
++ int i;
++
++ hsu = pci_get_drvdata(pdev);
++ if (!hsu)
++ return;
++
++ for (i = 0; i < 3; i++)
++ uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port);
++
++ pci_set_drvdata(pdev, NULL);
++ free_irq(hsu->irq, hsu);
++ pci_disable_device(pdev);
++}
++
++/* First 3 are UART ports, and the 4th is the DMA */
++static const struct pci_device_id pci_ids[] __devinitdata = {
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) },
++ {},
++};
++
++static struct pci_driver hsu_pci_driver = {
++ .name = "HSU serial",
++ .id_table = pci_ids,
++ .probe = serial_hsu_probe,
++ .remove = __devexit_p(serial_hsu_remove),
++ .suspend = serial_hsu_suspend,
++ .resume = serial_hsu_resume,
++};
++
++static int __init hsu_pci_init(void)
++{
++ int ret;
++
++ hsu_global_init();
++
++ ret = uart_register_driver(&serial_hsu_reg);
++ if (ret)
++ return ret;
++
++ return pci_register_driver(&hsu_pci_driver);
++}
++
++static void __exit hsu_pci_exit(void)
++{
++ pci_unregister_driver(&hsu_pci_driver);
++ uart_unregister_driver(&serial_hsu_reg);
++
++ hsu_debugfs_remove(phsu);
++
++ kfree(phsu);
++}
++
++module_init(hsu_pci_init);
++module_exit(hsu_pci_exit);
++
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:medfield-hsu");
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -189,6 +189,8 @@
+ /* MAX3107 */
+ #define PORT_MAX3107 94
+
++/* High Speed UART for Medfield */
++#define PORT_MFD 95
+
+ #ifdef __KERNEL__
+
+--- a/include/linux/serial_reg.h
++++ b/include/linux/serial_reg.h
+@@ -221,8 +221,24 @@
+ #define UART_FCR_PXAR16 0x80 /* receive FIFO threshold = 16 */
+ #define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */
+
++/*
++ * Intel MID on-chip HSU (High Speed UART) defined bits
++ */
++#define UART_FCR_HSU_64_1B 0x00 /* receive FIFO treshold = 1 */
++#define UART_FCR_HSU_64_16B 0x40 /* receive FIFO treshold = 16 */
++#define UART_FCR_HSU_64_32B 0x80 /* receive FIFO treshold = 32 */
++#define UART_FCR_HSU_64_56B 0xc0 /* receive FIFO treshold = 56 */
++
++#define UART_FCR_HSU_16_1B 0x00 /* receive FIFO treshold = 1 */
++#define UART_FCR_HSU_16_4B 0x40 /* receive FIFO treshold = 4 */
++#define UART_FCR_HSU_16_8B 0x80 /* receive FIFO treshold = 8 */
++#define UART_FCR_HSU_16_14B 0xc0 /* receive FIFO treshold = 14 */
+
++#define UART_FCR_HSU_64B_FIFO 0x20 /* chose 64 bytes FIFO */
++#define UART_FCR_HSU_16B_FIFO 0x00 /* chose 16 bytes FIFO */
+
++#define UART_FCR_HALF_EMPT_TXI 0x00 /* trigger TX_EMPT IRQ for half empty */
++#define UART_FCR_FULL_EMPT_TXI 0x08 /* trigger TX_EMPT IRQ for full empty */
+
+ /*
+ * These register definitions are for the 16C950
diff --git a/tty/hsu-some-code-cleanup.patch b/tty/hsu-some-code-cleanup.patch
new file mode 100644
index 00000000000000..360a8e9170bead
--- /dev/null
+++ b/tty/hsu-some-code-cleanup.patch
@@ -0,0 +1,282 @@
+From alan@linux.intel.com Mon Jul 26 14:23:31 2010
+From: Alan Cox <alan@linux.intel.com>
+Subject: hsu: some code cleanup
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Date: Mon, 26 Jul 2010 10:18:32 +0100
+Message-ID: <20100726091828.21579.78601.stgit@localhost.localdomain>
+
+From: Feng Tang <feng.tang@intel.com>
+
+Major changes are:
+* refine the comments in the driver
+* remove unused member from structure "hsu_port"
+* extended spin_lock protoction for dma mode in port_irq()
+
+Signed-off-by: Feng Tang <feng.tang@intel.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/mfd.c | 85 +++++++++++----------------------------------------
+ 1 file changed, 19 insertions(+), 66 deletions(-)
+
+--- a/drivers/serial/mfd.c
++++ b/drivers/serial/mfd.c
+@@ -3,7 +3,7 @@
+ *
+ * Refer pxa.c, 8250.c and some other drivers in drivers/serial/
+ *
+- * (C) Copyright 2009 Intel Corporation
++ * (C) Copyright 2010 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+@@ -11,30 +11,16 @@
+ * of the License.
+ */
+
+-
+ /* Notes:
+- * 1. there should be 2 types of register access method, one for
+- * UART ports, the other for the general purpose registers
+- *
+- * 2. It used to have a Irda port, but was defeatured recently
+- *
+- * 3. Based on the info from HSU MAS, 0/1 channel are assigned to
+- * port0, 2/3 chan to port 1, 4/5 chan to port 3. Even number
+- * chan will be read, odd chan for write
+- *
+- * 4. HUS supports both the 64B and 16B FIFO version, but this driver
+- * will only use 64B version
++ * 1. DMA channel allocation: 0/1 channel are assigned to port 0,
++ * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans
++ * are used for RX, odd chans for TX
+ *
+- * 5. In A0 stepping, UART will not support TX half empty flag, thus
+- * need add a #ifdef judgement
++ * 2. In A0 stepping, UART will not support TX half empty flag
+ *
+- * 6. One more bug for A0, the loopback mode won't support AFC
+- * auto-flow control
+- *
+- * 7. HSU has some special FCR control bits, we add it to serial_reg.h
+- *
+- * 8. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always asserted,
+- * only when the HW is reset the DDCD and DDSR will be triggered
++ * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
++ * asserted, only when the HW is reset the DDCD and DDSR will
++ * be triggered
+ */
+
+ #include <linux/module.h>
+@@ -75,7 +61,7 @@ struct hsu_dma_buffer {
+
+ struct hsu_dma_chan {
+ u32 id;
+- u32 dirt; /* to or from device */
++ enum dma_data_direction dirt;
+ struct uart_hsu_port *uport;
+ void __iomem *reg;
+ struct timer_list rx_timer; /* only needed by RX channel */
+@@ -102,8 +88,6 @@ struct uart_hsu_port {
+
+ /* Top level data structure of HSU */
+ struct hsu_port {
+- struct pci_device *pdev;
+-
+ void __iomem *reg;
+ unsigned long paddr;
+ unsigned long iolen;
+@@ -112,23 +96,9 @@ struct hsu_port {
+ struct uart_hsu_port port[3];
+ struct hsu_dma_chan chans[10];
+
+-#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs;
+-#endif
+ };
+
+-static inline void hexdump(char *str, u8 *addr, int cnt)
+-{
+- int i;
+-
+- for (i = 0; i < cnt; i += 8) {
+- printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
+- addr[i], addr[i+1], addr[i+2], addr[i+3],
+- addr[i+4], addr[i+5], addr[i+6], addr[i+7]);
+- printk("\n");
+- }
+-}
+-
+ static inline unsigned int serial_in(struct uart_hsu_port *up, int offset)
+ {
+ unsigned int val;
+@@ -353,9 +323,6 @@ void hsu_dma_tx(struct uart_hsu_port *up
+ | (0x1 << 8)
+ | (0x1 << 16)
+ | (0x1 << 24));
+-
+- WARN(chan_readl(up->txc, HSU_CH_CR) & 0x1,
+- "TX channel has already be started!!\n");
+ up->dma_tx_on = 1;
+ chan_writel(up->txc, HSU_CH_CR, 0x1);
+ }
+@@ -367,7 +334,6 @@ void hsu_dma_tx(struct uart_hsu_port *up
+ /* The buffer is already cache coherent */
+ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf)
+ {
+- /* Need start RX dma channel here */
+ dbuf->ofs = 0;
+
+ chan_writel(rxc, HSU_CH_BSR, 32);
+@@ -426,35 +392,32 @@ void hsu_dma_rx(struct uart_hsu_port *up
+ return;
+
+ /*
+- * first need to know how many is already transferred,
++ * First need to know how many is already transferred,
+ * then check if its a timeout DMA irq, and return
+ * the trail bytes out, push them up and reenable the
+- * channel, better to use 2 descriptors at the same time
++ * channel
+ */
+
+- /* timeout IRQ, need wait some time, see Errata 2 */
++ /* Timeout IRQ, need wait some time, see Errata 2 */
+ if (int_sts & 0xf00)
+ udelay(2);
+
+ /* Stop the channel */
+ chan_writel(chan, HSU_CH_CR, 0x0);
+
+- /* We can use 2 ways to calc the actual transfer len */
+ count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
+-
+ if (!count) {
+- /* restart the channel before we leave */
++ /* Restart the channel before we leave */
+ chan_writel(chan, HSU_CH_CR, 0x3);
+ return;
+ }
+-
+ del_timer(&chan->rx_timer);
+
+ dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
+ dbuf->dma_size, DMA_FROM_DEVICE);
+
+ /*
+- * head will only wrap around when we recycle
++ * Head will only wrap around when we recycle
+ * the DMA buffer, and when that happens, we
+ * explicitly set tail to 0. So head will
+ * always be greater than tail.
+@@ -496,10 +459,6 @@ static void serial_hsu_stop_rx(struct ua
+ }
+ }
+
+-/*
+- * if there is error flag, should we just reset the FIFO or keeps
+- * working on it
+- */
+ static inline void receive_chars(struct uart_hsu_port *up, int *status)
+ {
+ struct tty_struct *tty = up->port.state->port.tty;
+@@ -571,7 +530,6 @@ static void transmit_chars(struct uart_h
+ {
+ struct circ_buf *xmit = &up->port.state->xmit;
+ int count;
+- int i = 0; /* for debug use */
+
+ if (up->port.x_char) {
+ serial_out(up, UART_TX, up->port.x_char);
+@@ -592,13 +550,11 @@ static void transmit_chars(struct uart_h
+ * into it won't clear the EMPT bit, so we may need be cautious
+ * by useing a shorter buffer
+ */
+- /* count = up->port.fifosize; */
+ count = up->port.fifosize - 4;
+ #endif
+ do {
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+- i++;
+
+ up->port.icount.tx++;
+ if (uart_circ_empty(xmit))
+@@ -628,7 +584,7 @@ static inline void check_modem_status(st
+ /* We may only get DDCD when HW init and reset */
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+- /* will start/stop_tx accordingly */
++ /* Will start/stop_tx accordingly */
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+
+@@ -647,6 +603,7 @@ static irqreturn_t port_irq(int irq, voi
+ if (unlikely(!up->running))
+ return IRQ_NONE;
+
++ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->use_dma) {
+ lsr = serial_in(up, UART_LSR);
+ if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
+@@ -655,10 +612,10 @@ static irqreturn_t port_irq(int irq, voi
+ "Got lsr irq while using DMA, lsr = 0x%2x\n",
+ lsr);
+ check_modem_status(up);
++ spin_unlock_irqrestore(&up->port.lock, flags);
+ return IRQ_HANDLED;
+ }
+
+- spin_lock_irqsave(&up->port.lock, flags);
+ iir = serial_in(up, UART_IIR);
+ if (iir & UART_IIR_NO_INT) {
+ spin_unlock_irqrestore(&up->port.lock, flags);
+@@ -666,9 +623,9 @@ static irqreturn_t port_irq(int irq, voi
+ }
+
+ lsr = serial_in(up, UART_LSR);
+-
+ if (lsr & UART_LSR_DR)
+ receive_chars(up, &lsr);
++ check_modem_status(up);
+
+ /* lsr will be renewed during the receive_chars */
+ if (lsr & UART_LSR_THRE)
+@@ -701,7 +658,6 @@ static inline void dma_chan_irq(struct h
+
+ /* Tx channel */
+ if (chan->dirt == DMA_TO_DEVICE) {
+- /* dma for irq should be done */
+ chan_writel(chan, HSU_CH_CR, 0x0);
+ up->dma_tx_on = 0;
+ hsu_dma_tx(up);
+@@ -851,7 +807,6 @@ static int serial_hsu_startup(struct uar
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /* DMA init */
+- /* When use DMA, TX/RX's FIFO and IRQ should be disabled */
+ if (up->use_dma) {
+ struct hsu_dma_buffer *dbuf;
+ struct circ_buf *xmit = &port->state->xmit;
+@@ -1090,11 +1045,9 @@ static int serial_hsu_request_port(struc
+
+ static void serial_hsu_config_port(struct uart_port *port, int flags)
+ {
+-#if 0
+ struct uart_hsu_port *up =
+ container_of(port, struct uart_hsu_port, port);
+ up->port.type = PORT_MFD;
+-#endif
+ }
+
+ static int
+@@ -1426,7 +1379,7 @@ static void hsu_global_init(void)
+ uport->port.ops = &serial_hsu_pops;
+ uport->port.line = i;
+ uport->port.flags = UPF_IOREMAP;
+- /* make the maxim support rate to 2746800 bps */
++ /* set the scalable maxim support rate to 2746800 bps */
+ uport->port.uartclk = 115200 * 24 * 16;
+
+ uport->running = 0;
diff --git a/tty/mxser-remove-unnesesary-null-check.patch b/tty/mxser-remove-unnesesary-null-check.patch
new file mode 100644
index 00000000000000..ac753788456305
--- /dev/null
+++ b/tty/mxser-remove-unnesesary-null-check.patch
@@ -0,0 +1,33 @@
+From segooon@gmail.com Mon Jul 26 14:24:13 2010
+From: Kulikov Vasiliy <segooon@gmail.com>
+To: kernel-janitors@vger.kernel.org
+Cc: Jiri Slaby <jirislaby@gmail.com>,
+ Greg Kroah-Hartman <gregkh@suse.de>, Alan Cox <alan@linux.intel.com>,
+ Andrew Morton <akpm@linux-foundation.org>, Tejun Heo <tj@kernel.org>,
+ linux-kernel@vger.kernel.org
+Subject: mxser: remove unnesesary NULL check
+Date: Fri, 23 Jul 2010 20:34:53 +0400
+Message-Id: <1279902893-27006-1-git-send-email-segooon@gmail.com>
+
+mxser_transmit_chars(tty, port) is called only from mxser_interrupt().
+NULL check is performed in mxser_interrupt() so it is redundant here.
+
+Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
+Acked-by: Jiri Slaby <jirislaby@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/mxser.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/mxser.c
++++ b/drivers/char/mxser.c
+@@ -2193,7 +2193,7 @@ static void mxser_transmit_chars(struct
+ port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
+ port->icount.tx += (cnt - port->xmit_cnt);
+
+- if (port->xmit_cnt < WAKEUP_CHARS && tty)
++ if (port->xmit_cnt < WAKEUP_CHARS)
+ tty_wakeup(tty);
+
+ if (port->xmit_cnt <= 0) {
diff --git a/tty/serial-add-support-for-ox16pci958-card.patch b/tty/serial-add-support-for-ox16pci958-card.patch
new file mode 100644
index 00000000000000..490a2e1fc0f9c5
--- /dev/null
+++ b/tty/serial-add-support-for-ox16pci958-card.patch
@@ -0,0 +1,65 @@
+From a.beregalov@gmail.com Mon Jul 26 14:21:38 2010
+From: Alexander Beregalov <a.beregalov@gmail.com>
+To: gregkh@suse.de
+Cc: linux-kernel@vger.kernel.org,
+ Lytochkin Boris <lytboris@gmail.com>,
+ Alexander Beregalov <a.beregalov@gmail.com>
+Subject: [PATCH] serial: add support for OX16PCI958 card
+Date: Mon, 26 Jul 2010 10:02:26 +0400
+Message-Id: <1280124146-24735-1-git-send-email-a.beregalov@gmail.com>
+
+From: Lytochkin Boris <lytboris@gmail.com>
+
+Signed-off-by: Lytochkin Boris <lytboris@gmail.com>
+Tested-by: Lytochkin Boris <lytboris@gmail.com>
+Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250_pci.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/serial/8250_pci.c
++++ b/drivers/serial/8250_pci.c
+@@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct seria
+ #define PCI_DEVICE_ID_TITAN_800E 0xA014
+ #define PCI_DEVICE_ID_TITAN_200EI 0xA016
+ #define PCI_DEVICE_ID_TITAN_200EISI 0xA017
++#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
+
+ /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
+@@ -1542,6 +1543,8 @@ enum pci_board_num_t {
+ pbn_b2_4_921600,
+ pbn_b2_8_921600,
+
++ pbn_b2_8_1152000,
++
+ pbn_b2_bt_1_115200,
+ pbn_b2_bt_2_115200,
+ pbn_b2_bt_4_115200,
+@@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards
+ .uart_offset = 8,
+ },
+
++ [pbn_b2_8_1152000] = {
++ .flags = FL_BASE2,
++ .num_ports = 8,
++ .base_baud = 1152000,
++ .uart_offset = 8,
++ },
++
+ [pbn_b2_bt_1_115200] = {
+ .flags = FL_BASE2|FL_BASE_BARS,
+ .num_ports = 1,
+@@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_t
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
++ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
++ PCI_ANY_ID , PCI_ANY_ID, 0, 0,
++ pbn_b2_8_1152000 },
+
+ /*
+ * Oxford Semiconductor Inc. Tornado PCI express device range.
diff --git a/usb/usb-gadget-file_storage-serial-parameter-even-if-not-test-mode.patch b/usb/usb-gadget-file_storage-serial-parameter-even-if-not-test-mode.patch
new file mode 100644
index 00000000000000..b28f922b984297
--- /dev/null
+++ b/usb/usb-gadget-file_storage-serial-parameter-even-if-not-test-mode.patch
@@ -0,0 +1,104 @@
+From m.nazarewicz@samsung.com Mon Jul 26 14:26:35 2010
+Date: Thu, 22 Jul 2010 14:16:37 +0200
+From: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Subject: USB: gadget: file_storage: serial parameter even if not test mode
+To: linux-usb@vger.kernel.org
+Cc: Kyungmin Park <kyungmin.park@samsung.com>,
+ Marek Szyprowski <m.szyprowski@samsung.com>,
+ David Brownell <david-b@pacbell.net>, Alan Stern <stern@rowland.harvard.edu>,
+ Greg KH <greg@kroah.com>, linux-kernel@vger.kernel.org,
+ Yann Cantin <yann.cantin@laposte.net>
+Message-id: <709d887b2249e9651060729eb62b29a1d3edc256.1279794290.git.m.nazarewicz@samsung.com>
+
+Moved the serial parameter handling code out of "#ifdef
+CONFIG_USB_FILE_STORAGE_TEST".
+
+This modifies Yann Cantin's commit "USB: Add a serial number
+parameter to g_file_storage" module as per Alan Stern's request.
+
+Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Anand Gadiyar <gadiyar@ti.com>
+Cc: David Brownell <david-b@pacbell.net>
+Cc: Yann Cantin <yann.cantin@laposte.net>
+
+---
+ drivers/usb/gadget/file_storage.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -321,7 +321,7 @@ static struct {
+ unsigned short vendor;
+ unsigned short product;
+ unsigned short release;
+- char *serial_parm;
++ char *serial;
+ unsigned int buflen;
+
+ int transport_type;
+@@ -365,6 +365,8 @@ MODULE_PARM_DESC(stall, "false to preven
+ module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
+ MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
+
++module_param_named(serial, mod_data.serial, charp, S_IRUGO);
++MODULE_PARM_DESC(serial, "USB serial number");
+
+ /* In the non-TEST version, only the module parameters listed above
+ * are available. */
+@@ -386,9 +388,6 @@ MODULE_PARM_DESC(product, "USB Product I
+ module_param_named(release, mod_data.release, ushort, S_IRUGO);
+ MODULE_PARM_DESC(release, "USB release number");
+
+-module_param_named(serial, mod_data.serial_parm, charp, S_IRUGO);
+-MODULE_PARM_DESC(serial, "USB serial number");
+-
+ module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
+ MODULE_PARM_DESC(buflen, "I/O buffer size");
+
+@@ -3291,10 +3290,12 @@ static int __init check_parameters(struc
+ return -ETOOSMALL;
+ }
+
++#endif /* CONFIG_USB_FILE_STORAGE_TEST */
++
+ /* Serial string handling.
+ * On a real device, the serial string would be loaded
+ * from permanent storage. */
+- if (mod_data.serial_parm) {
++ if (mod_data.serial) {
+ const char *ch;
+ unsigned len = 0;
+
+@@ -3303,7 +3304,7 @@ static int __init check_parameters(struc
+ * 12 uppercase hexadecimal characters.
+ * BBB need at least 12 uppercase hexadecimal characters,
+ * with a maximum of 126. */
+- for (ch = mod_data.serial_parm; *ch; ++ch) {
++ for (ch = mod_data.serial; *ch; ++ch) {
+ ++len;
+ if ((*ch < '0' || *ch > '9') &&
+ (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
+@@ -3322,8 +3323,11 @@ static int __init check_parameters(struc
+ "Failing back to default\n");
+ goto fill_serial;
+ }
+- fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial_parm;
++ fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
+ } else {
++ WARNING(fsg,
++ "Userspace failed to provide serial number; "
++ "Failing back to default\n");
+ fill_serial:
+ /* Serial number not specified or invalid, make our own.
+ * We just encode it from the driver version string,
+@@ -3339,8 +3343,6 @@ fill_serial:
+ }
+ }
+
+-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+-
+ return 0;
+ }
+
diff --git a/usb/usb-imx21-hcd-set-task-state-with-schedule_timeout_uninterruptible.patch b/usb/usb-imx21-hcd-set-task-state-with-schedule_timeout_uninterruptible.patch
new file mode 100644
index 00000000000000..3ad0b83b5c8f25
--- /dev/null
+++ b/usb/usb-imx21-hcd-set-task-state-with-schedule_timeout_uninterruptible.patch
@@ -0,0 +1,32 @@
+From linux-usb-owner@vger.kernel.org Mon Jul 26 14:22:01 2010
+From: Kulikov Vasiliy <segooon@gmail.com>
+To: kernel-janitors@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@suse.de>, Tejun Heo <tj@kernel.org>,
+ Martin Fuzzey <mfuzzey@gmail.com>, linux-usb@vger.kernel.org,
+ linux-kernel@vger.kernel.org
+Subject: [PATCH] usb: imx21-hcd: set task state with schedule_timeout_uninterruptible()
+Date: Mon, 26 Jul 2010 12:26:22 +0400
+Message-Id: <1280132783-8182-1-git-send-email-segooon@gmail.com>
+
+imx21_hc_reset() uses schedule_timeout() without setting state to
+STATE_(UN)INTERRUPTIBLE. As it is called in cycle without checking of
+pending signals, use schedule_timeout_uninterruptible().
+
+Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/imx21-hcd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/imx21-hcd.c
++++ b/drivers/usb/host/imx21-hcd.c
+@@ -1521,7 +1521,7 @@ static int imx21_hc_reset(struct usb_hcd
+ return -ETIMEDOUT;
+ }
+ spin_unlock_irq(&imx21->lock);
+- schedule_timeout(1);
++ schedule_timeout_uninterruptible(1);
+ spin_lock_irq(&imx21->lock);
+ }
+ spin_unlock_irqrestore(&imx21->lock, flags);
diff --git a/usb/usb-serial-enabling-support-for-segway-rmp-in-ftdi_sio.patch b/usb/usb-serial-enabling-support-for-segway-rmp-in-ftdi_sio.patch
new file mode 100644
index 00000000000000..727e7155ecca04
--- /dev/null
+++ b/usb/usb-serial-enabling-support-for-segway-rmp-in-ftdi_sio.patch
@@ -0,0 +1,49 @@
+From jgrogers@gatech.edu Mon Jul 26 14:18:48 2010
+From: John Rogers <jgrogers@gatech.edu>
+Subject: USB: serial: enabling support for Segway RMP in ftdi_sio
+Date: Sat, 24 Jul 2010 09:50:52 -0400
+Message-Id: <9CA0AFB3-3DF4-496D-8ECC-1C60C90C861B@mail.gatech.edu>
+Cc: linux-usb@vger.kernel.org
+To: greg@kroah.com
+
+From: John G. Rogers <jgrogers@gmail.com>
+
+I have added the ProductID=0xe729 VendorID=FTDI_VID=0x0403 which will
+enable support for the Segway Robotic Mobility Platform (RMP200) in the
+ftdi_sio kernel module. Currently, users of the Segway RMP200 must use
+a RUN+="/sbin/modprobe -q ftdi-sio product=0xe729 vendor=0x0403 in a
+udev rule to get the ftdi_sio module to handle the usb interface and
+mount it on /dev/ttyXXX. This is not a good solution because some users
+will have multiple USB to Serial converters which will use the ftdi_sio
+module.
+
+Signed-off-by: John Rogers <jgrogers@gmail.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -746,6 +746,7 @@ static struct usb_device_id id_table_com
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
++ { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
+ { }, /* Optional parameter entry */
+ { } /* Terminating entry */
+ };
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -1032,3 +1032,8 @@
+ #define XVERVE_SIGNALYZER_SH2_PID 0xBCA2
+ #define XVERVE_SIGNALYZER_SH4_PID 0xBCA4
+
++/*
++ * Segway Robotic Mobility Platform USB interface (using VID 0x0403)
++ * Submitted by John G. Rogers
++ */
++#define SEGWAY_RMP200_PID 0xe729
diff --git a/usb/usb-uvc-move-constants-and-structures-definitions-to-linux-usb-video.h.patch b/usb/usb-uvc-move-constants-and-structures-definitions-to-linux-usb-video.h.patch
deleted file mode 100644
index 59c6f4834cb351..00000000000000
--- a/usb/usb-uvc-move-constants-and-structures-definitions-to-linux-usb-video.h.patch
+++ /dev/null
@@ -1,1044 +0,0 @@
-From laurent.pinchart@ideasonboard.com Wed Jun 16 13:25:39 2010
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Mon, 7 Jun 2010 13:09:47 +0200
-Subject: USB: uvc: Move constants and structures definitions to linux/usb/video.h
-To: linux-usb@vger.kernel.org
-Message-ID: <1275908987-5774-1-git-send-email-laurent.pinchart@ideasonboard.com>
-
-
-The UVC host and gadget drivers both define constants and structures in
-private header files. Move all those definitions to linux/usb/video.h
-where they can be shared by the two drivers (and be available for
-userspace applications).
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- drivers/media/video/uvc/uvcvideo.h | 19 -
- drivers/usb/gadget/f_uvc.c | 16 -
- drivers/usb/gadget/f_uvc.h | 352 --------------------------------
- drivers/usb/gadget/uvc.h | 36 ---
- drivers/usb/gadget/webcam.c | 24 +-
- include/linux/usb/video.h | 397 +++++++++++++++++++++++++++++++++++++
- 6 files changed, 418 insertions(+), 426 deletions(-)
-
---- a/drivers/media/video/uvc/uvcvideo.h
-+++ b/drivers/media/video/uvc/uvcvideo.h
-@@ -179,25 +179,6 @@ struct uvc_device;
- /* TODO: Put the most frequently accessed fields at the beginning of
- * structures to maximize cache efficiency.
- */
--struct uvc_streaming_control {
-- __u16 bmHint;
-- __u8 bFormatIndex;
-- __u8 bFrameIndex;
-- __u32 dwFrameInterval;
-- __u16 wKeyFrameRate;
-- __u16 wPFrameRate;
-- __u16 wCompQuality;
-- __u16 wCompWindowSize;
-- __u16 wDelay;
-- __u32 dwMaxVideoFrameSize;
-- __u32 dwMaxPayloadTransferSize;
-- __u32 dwClockFrequency;
-- __u8 bmFramingInfo;
-- __u8 bPreferedVersion;
-- __u8 bMinVersion;
-- __u8 bMaxVersion;
--};
--
- struct uvc_menu_info {
- __u32 value;
- __u8 name[32];
---- a/drivers/usb/gadget/f_uvc.c
-+++ b/drivers/usb/gadget/f_uvc.c
-@@ -61,12 +61,12 @@ static struct usb_gadget_strings *uvc_fu
- #define UVC_INTF_VIDEO_STREAMING 1
-
- static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
-- .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
-+ .bLength = sizeof(uvc_iad),
- .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
- .bFirstInterface = 0,
- .bInterfaceCount = 2,
- .bFunctionClass = USB_CLASS_VIDEO,
-- .bFunctionSubClass = 0x03,
-+ .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION,
- .bFunctionProtocol = 0x00,
- .iFunction = 0,
- };
-@@ -78,7 +78,7 @@ static struct usb_interface_descriptor u
- .bAlternateSetting = 0,
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_VIDEO,
-- .bInterfaceSubClass = 0x01,
-+ .bInterfaceSubClass = UVC_SC_VIDEOCONTROL,
- .bInterfaceProtocol = 0x00,
- .iInterface = 0,
- };
-@@ -106,7 +106,7 @@ static struct usb_interface_descriptor u
- .bAlternateSetting = 0,
- .bNumEndpoints = 0,
- .bInterfaceClass = USB_CLASS_VIDEO,
-- .bInterfaceSubClass = 0x02,
-+ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING,
- .bInterfaceProtocol = 0x00,
- .iInterface = 0,
- };
-@@ -118,7 +118,7 @@ static struct usb_interface_descriptor u
- .bAlternateSetting = 1,
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_VIDEO,
-- .bInterfaceSubClass = 0x02,
-+ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING,
- .bInterfaceProtocol = 0x00,
- .iInterface = 0,
- };
-@@ -603,15 +603,15 @@ uvc_bind_config(struct usb_configuration
-
- /* Validate the descriptors. */
- if (control == NULL || control[0] == NULL ||
-- control[0]->bDescriptorSubType != UVC_DT_HEADER)
-+ control[0]->bDescriptorSubType != UVC_VC_HEADER)
- goto error;
-
- if (fs_streaming == NULL || fs_streaming[0] == NULL ||
-- fs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER)
-+ fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
- goto error;
-
- if (hs_streaming == NULL || hs_streaming[0] == NULL ||
-- hs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER)
-+ hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
- goto error;
-
- uvc->desc.control = control;
---- a/drivers/usb/gadget/f_uvc.h
-+++ b/drivers/usb/gadget/f_uvc.h
-@@ -15,357 +15,7 @@
- #define _F_UVC_H_
-
- #include <linux/usb/composite.h>
--
--#define USB_CLASS_VIDEO_CONTROL 1
--#define USB_CLASS_VIDEO_STREAMING 2
--
--struct uvc_descriptor_header {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
--} __attribute__ ((packed));
--
--struct uvc_header_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u16 bcdUVC;
-- __u16 wTotalLength;
-- __u32 dwClockFrequency;
-- __u8 bInCollection;
-- __u8 baInterfaceNr[];
--} __attribute__((__packed__));
--
--#define UVC_HEADER_DESCRIPTOR(n) uvc_header_descriptor_##n
--
--#define DECLARE_UVC_HEADER_DESCRIPTOR(n) \
--struct UVC_HEADER_DESCRIPTOR(n) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u16 bcdUVC; \
-- __u16 wTotalLength; \
-- __u32 dwClockFrequency; \
-- __u8 bInCollection; \
-- __u8 baInterfaceNr[n]; \
--} __attribute__ ((packed))
--
--struct uvc_input_terminal_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bTerminalID;
-- __u16 wTerminalType;
-- __u8 bAssocTerminal;
-- __u8 iTerminal;
--} __attribute__((__packed__));
--
--struct uvc_output_terminal_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bTerminalID;
-- __u16 wTerminalType;
-- __u8 bAssocTerminal;
-- __u8 bSourceID;
-- __u8 iTerminal;
--} __attribute__((__packed__));
--
--struct uvc_camera_terminal_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bTerminalID;
-- __u16 wTerminalType;
-- __u8 bAssocTerminal;
-- __u8 iTerminal;
-- __u16 wObjectiveFocalLengthMin;
-- __u16 wObjectiveFocalLengthMax;
-- __u16 wOcularFocalLength;
-- __u8 bControlSize;
-- __u8 bmControls[3];
--} __attribute__((__packed__));
--
--struct uvc_selector_unit_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bUnitID;
-- __u8 bNrInPins;
-- __u8 baSourceID[0];
-- __u8 iSelector;
--} __attribute__((__packed__));
--
--#define UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
-- uvc_selector_unit_descriptor_##n
--
--#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
--struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u8 bUnitID; \
-- __u8 bNrInPins; \
-- __u8 baSourceID[n]; \
-- __u8 iSelector; \
--} __attribute__ ((packed))
--
--struct uvc_processing_unit_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bUnitID;
-- __u8 bSourceID;
-- __u16 wMaxMultiplier;
-- __u8 bControlSize;
-- __u8 bmControls[2];
-- __u8 iProcessing;
--} __attribute__((__packed__));
--
--struct uvc_extension_unit_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bUnitID;
-- __u8 guidExtensionCode[16];
-- __u8 bNumControls;
-- __u8 bNrInPins;
-- __u8 baSourceID[0];
-- __u8 bControlSize;
-- __u8 bmControls[0];
-- __u8 iExtension;
--} __attribute__((__packed__));
--
--#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
-- uvc_extension_unit_descriptor_##p_##n
--
--#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
--struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u8 bUnitID; \
-- __u8 guidExtensionCode[16]; \
-- __u8 bNumControls; \
-- __u8 bNrInPins; \
-- __u8 baSourceID[p]; \
-- __u8 bControlSize; \
-- __u8 bmControls[n]; \
-- __u8 iExtension; \
--} __attribute__ ((packed))
--
--struct uvc_control_endpoint_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u16 wMaxTransferSize;
--} __attribute__((__packed__));
--
--#define UVC_DT_HEADER 1
--#define UVC_DT_INPUT_TERMINAL 2
--#define UVC_DT_OUTPUT_TERMINAL 3
--#define UVC_DT_SELECTOR_UNIT 4
--#define UVC_DT_PROCESSING_UNIT 5
--#define UVC_DT_EXTENSION_UNIT 6
--
--#define UVC_DT_HEADER_SIZE(n) (12+(n))
--#define UVC_DT_INPUT_TERMINAL_SIZE 8
--#define UVC_DT_OUTPUT_TERMINAL_SIZE 9
--#define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n))
--#define UVC_DT_SELECTOR_UNIT_SIZE(n) (6+(n))
--#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n))
--#define UVC_DT_EXTENSION_UNIT_SIZE(p,n) (24+(p)+(n))
--#define UVC_DT_CONTROL_ENDPOINT_SIZE 5
--
--struct uvc_input_header_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bNumFormats;
-- __u16 wTotalLength;
-- __u8 bEndpointAddress;
-- __u8 bmInfo;
-- __u8 bTerminalLink;
-- __u8 bStillCaptureMethod;
-- __u8 bTriggerSupport;
-- __u8 bTriggerUsage;
-- __u8 bControlSize;
-- __u8 bmaControls[];
--} __attribute__((__packed__));
--
--#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
-- uvc_input_header_descriptor_##n_##p
--
--#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
--struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u8 bNumFormats; \
-- __u16 wTotalLength; \
-- __u8 bEndpointAddress; \
-- __u8 bmInfo; \
-- __u8 bTerminalLink; \
-- __u8 bStillCaptureMethod; \
-- __u8 bTriggerSupport; \
-- __u8 bTriggerUsage; \
-- __u8 bControlSize; \
-- __u8 bmaControls[p][n]; \
--} __attribute__ ((packed))
--
--struct uvc_output_header_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bNumFormats;
-- __u16 wTotalLength;
-- __u8 bEndpointAddress;
-- __u8 bTerminalLink;
-- __u8 bControlSize;
-- __u8 bmaControls[];
--} __attribute__((__packed__));
--
--#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
-- uvc_output_header_descriptor_##n_##p
--
--#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
--struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u8 bNumFormats; \
-- __u16 wTotalLength; \
-- __u8 bEndpointAddress; \
-- __u8 bTerminalLink; \
-- __u8 bControlSize; \
-- __u8 bmaControls[p][n]; \
--} __attribute__ ((packed))
--
--struct uvc_format_uncompressed {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bFormatIndex;
-- __u8 bNumFrameDescriptors;
-- __u8 guidFormat[16];
-- __u8 bBitsPerPixel;
-- __u8 bDefaultFrameIndex;
-- __u8 bAspectRatioX;
-- __u8 bAspectRatioY;
-- __u8 bmInterfaceFlags;
-- __u8 bCopyProtect;
--} __attribute__((__packed__));
--
--struct uvc_frame_uncompressed {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bFrameIndex;
-- __u8 bmCapabilities;
-- __u16 wWidth;
-- __u16 wHeight;
-- __u32 dwMinBitRate;
-- __u32 dwMaxBitRate;
-- __u32 dwMaxVideoFrameBufferSize;
-- __u32 dwDefaultFrameInterval;
-- __u8 bFrameIntervalType;
-- __u32 dwFrameInterval[];
--} __attribute__((__packed__));
--
--#define UVC_FRAME_UNCOMPRESSED(n) \
-- uvc_frame_uncompressed_##n
--
--#define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \
--struct UVC_FRAME_UNCOMPRESSED(n) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u8 bFrameIndex; \
-- __u8 bmCapabilities; \
-- __u16 wWidth; \
-- __u16 wHeight; \
-- __u32 dwMinBitRate; \
-- __u32 dwMaxBitRate; \
-- __u32 dwMaxVideoFrameBufferSize; \
-- __u32 dwDefaultFrameInterval; \
-- __u8 bFrameIntervalType; \
-- __u32 dwFrameInterval[n]; \
--} __attribute__ ((packed))
--
--struct uvc_format_mjpeg {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bFormatIndex;
-- __u8 bNumFrameDescriptors;
-- __u8 bmFlags;
-- __u8 bDefaultFrameIndex;
-- __u8 bAspectRatioX;
-- __u8 bAspectRatioY;
-- __u8 bmInterfaceFlags;
-- __u8 bCopyProtect;
--} __attribute__((__packed__));
--
--struct uvc_frame_mjpeg {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bFrameIndex;
-- __u8 bmCapabilities;
-- __u16 wWidth;
-- __u16 wHeight;
-- __u32 dwMinBitRate;
-- __u32 dwMaxBitRate;
-- __u32 dwMaxVideoFrameBufferSize;
-- __u32 dwDefaultFrameInterval;
-- __u8 bFrameIntervalType;
-- __u32 dwFrameInterval[];
--} __attribute__((__packed__));
--
--#define UVC_FRAME_MJPEG(n) \
-- uvc_frame_mjpeg_##n
--
--#define DECLARE_UVC_FRAME_MJPEG(n) \
--struct UVC_FRAME_MJPEG(n) { \
-- __u8 bLength; \
-- __u8 bDescriptorType; \
-- __u8 bDescriptorSubType; \
-- __u8 bFrameIndex; \
-- __u8 bmCapabilities; \
-- __u16 wWidth; \
-- __u16 wHeight; \
-- __u32 dwMinBitRate; \
-- __u32 dwMaxBitRate; \
-- __u32 dwMaxVideoFrameBufferSize; \
-- __u32 dwDefaultFrameInterval; \
-- __u8 bFrameIntervalType; \
-- __u32 dwFrameInterval[n]; \
--} __attribute__ ((packed))
--
--struct uvc_color_matching_descriptor {
-- __u8 bLength;
-- __u8 bDescriptorType;
-- __u8 bDescriptorSubType;
-- __u8 bColorPrimaries;
-- __u8 bTransferCharacteristics;
-- __u8 bMatrixCoefficients;
--} __attribute__((__packed__));
--
--#define UVC_DT_INPUT_HEADER 1
--#define UVC_DT_OUTPUT_HEADER 2
--#define UVC_DT_FORMAT_UNCOMPRESSED 4
--#define UVC_DT_FRAME_UNCOMPRESSED 5
--#define UVC_DT_FORMAT_MJPEG 6
--#define UVC_DT_FRAME_MJPEG 7
--#define UVC_DT_COLOR_MATCHING 13
--
--#define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p))
--#define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p))
--#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE 27
--#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n))
--#define UVC_DT_FORMAT_MJPEG_SIZE 11
--#define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n))
--#define UVC_DT_COLOR_MATCHING_SIZE 6
-+#include <linux/usb/video.h>
-
- extern int uvc_bind_config(struct usb_configuration *c,
- const struct uvc_descriptor_header * const *control,
---- a/drivers/usb/gadget/uvc.h
-+++ b/drivers/usb/gadget/uvc.h
-@@ -48,39 +48,6 @@ struct uvc_event
- #define UVC_INTF_STREAMING 1
-
- /* ------------------------------------------------------------------------
-- * UVC constants & structures
-- */
--
--/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
--#define UVC_STREAM_EOH (1 << 7)
--#define UVC_STREAM_ERR (1 << 6)
--#define UVC_STREAM_STI (1 << 5)
--#define UVC_STREAM_RES (1 << 4)
--#define UVC_STREAM_SCR (1 << 3)
--#define UVC_STREAM_PTS (1 << 2)
--#define UVC_STREAM_EOF (1 << 1)
--#define UVC_STREAM_FID (1 << 0)
--
--struct uvc_streaming_control {
-- __u16 bmHint;
-- __u8 bFormatIndex;
-- __u8 bFrameIndex;
-- __u32 dwFrameInterval;
-- __u16 wKeyFrameRate;
-- __u16 wPFrameRate;
-- __u16 wCompQuality;
-- __u16 wCompWindowSize;
-- __u16 wDelay;
-- __u32 dwMaxVideoFrameSize;
-- __u32 dwMaxPayloadTransferSize;
-- __u32 dwClockFrequency;
-- __u8 bmFramingInfo;
-- __u8 bPreferedVersion;
-- __u8 bMinVersion;
-- __u8 bMaxVersion;
--} __attribute__((__packed__));
--
--/* ------------------------------------------------------------------------
- * Debugging, printing and logging
- */
-
-@@ -137,9 +104,6 @@ extern unsigned int uvc_trace_param;
- #define UVC_MAX_REQUEST_SIZE 64
- #define UVC_MAX_EVENTS 4
-
--#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8
--#define USB_CLASS_MISC 0xef
--
- /* ------------------------------------------------------------------------
- * Structures
- */
---- a/drivers/usb/gadget/webcam.c
-+++ b/drivers/usb/gadget/webcam.c
-@@ -90,7 +90,7 @@ DECLARE_UVC_HEADER_DESCRIPTOR(1);
- static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
- .bLength = UVC_DT_HEADER_SIZE(1),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_HEADER,
-+ .bDescriptorSubType = UVC_VC_HEADER,
- .bcdUVC = cpu_to_le16(0x0100),
- .wTotalLength = 0, /* dynamic */
- .dwClockFrequency = cpu_to_le32(48000000),
-@@ -101,7 +101,7 @@ static const struct UVC_HEADER_DESCRIPTO
- static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
- .bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_INPUT_TERMINAL,
-+ .bDescriptorSubType = UVC_VC_INPUT_TERMINAL,
- .bTerminalID = 1,
- .wTerminalType = cpu_to_le16(0x0201),
- .bAssocTerminal = 0,
-@@ -118,7 +118,7 @@ static const struct uvc_camera_terminal_
- static const struct uvc_processing_unit_descriptor uvc_processing = {
- .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_PROCESSING_UNIT,
-+ .bDescriptorSubType = UVC_VC_PROCESSING_UNIT,
- .bUnitID = 2,
- .bSourceID = 1,
- .wMaxMultiplier = cpu_to_le16(16*1024),
-@@ -131,7 +131,7 @@ static const struct uvc_processing_unit_
- static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
- .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_OUTPUT_TERMINAL,
-+ .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL,
- .bTerminalID = 3,
- .wTerminalType = cpu_to_le16(0x0101),
- .bAssocTerminal = 0,
-@@ -144,7 +144,7 @@ DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2
- static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
- .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_INPUT_HEADER,
-+ .bDescriptorSubType = UVC_VS_INPUT_HEADER,
- .bNumFormats = 2,
- .wTotalLength = 0, /* dynamic */
- .bEndpointAddress = 0, /* dynamic */
-@@ -161,7 +161,7 @@ static const struct UVC_INPUT_HEADER_DES
- static const struct uvc_format_uncompressed uvc_format_yuv = {
- .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_FORMAT_UNCOMPRESSED,
-+ .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
- .bFormatIndex = 1,
- .bNumFrameDescriptors = 2,
- .guidFormat =
-@@ -181,7 +181,7 @@ DECLARE_UVC_FRAME_UNCOMPRESSED(3);
- static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_FRAME_UNCOMPRESSED,
-+ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
- .bFrameIndex = 1,
- .bmCapabilities = 0,
- .wWidth = cpu_to_le16(640),
-@@ -199,7 +199,7 @@ static const struct UVC_FRAME_UNCOMPRESS
- static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_FRAME_UNCOMPRESSED,
-+ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
- .bFrameIndex = 2,
- .bmCapabilities = 0,
- .wWidth = cpu_to_le16(1280),
-@@ -215,7 +215,7 @@ static const struct UVC_FRAME_UNCOMPRESS
- static const struct uvc_format_mjpeg uvc_format_mjpg = {
- .bLength = UVC_DT_FORMAT_MJPEG_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_FORMAT_MJPEG,
-+ .bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
- .bFormatIndex = 2,
- .bNumFrameDescriptors = 2,
- .bmFlags = 0,
-@@ -232,7 +232,7 @@ DECLARE_UVC_FRAME_MJPEG(3);
- static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
- .bLength = UVC_DT_FRAME_MJPEG_SIZE(3),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_FRAME_MJPEG,
-+ .bDescriptorSubType = UVC_VS_FRAME_MJPEG,
- .bFrameIndex = 1,
- .bmCapabilities = 0,
- .wWidth = cpu_to_le16(640),
-@@ -250,7 +250,7 @@ static const struct UVC_FRAME_MJPEG(3) u
- static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
- .bLength = UVC_DT_FRAME_MJPEG_SIZE(1),
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_FRAME_MJPEG,
-+ .bDescriptorSubType = UVC_VS_FRAME_MJPEG,
- .bFrameIndex = 2,
- .bmCapabilities = 0,
- .wWidth = cpu_to_le16(1280),
-@@ -266,7 +266,7 @@ static const struct UVC_FRAME_MJPEG(1) u
- static const struct uvc_color_matching_descriptor uvc_color_matching = {
- .bLength = UVC_DT_COLOR_MATCHING_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
-- .bDescriptorSubType = UVC_DT_COLOR_MATCHING,
-+ .bDescriptorSubType = UVC_VS_COLORFORMAT,
- .bColorPrimaries = 1,
- .bTransferCharacteristics = 1,
- .bMatrixCoefficients = 4,
---- a/include/linux/usb/video.h
-+++ b/include/linux/usb/video.h
-@@ -160,5 +160,402 @@
- #define UVC_STATUS_TYPE_CONTROL 1
- #define UVC_STATUS_TYPE_STREAMING 2
-
-+/* 2.4.3.3. Payload Header Information */
-+#define UVC_STREAM_EOH (1 << 7)
-+#define UVC_STREAM_ERR (1 << 6)
-+#define UVC_STREAM_STI (1 << 5)
-+#define UVC_STREAM_RES (1 << 4)
-+#define UVC_STREAM_SCR (1 << 3)
-+#define UVC_STREAM_PTS (1 << 2)
-+#define UVC_STREAM_EOF (1 << 1)
-+#define UVC_STREAM_FID (1 << 0)
-+
-+/* ------------------------------------------------------------------------
-+ * UVC structures
-+ */
-+
-+/* All UVC descriptors have these 3 fields at the beginning */
-+struct uvc_descriptor_header {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+} __attribute__((packed));
-+
-+/* 3.7.2. Video Control Interface Header Descriptor */
-+struct uvc_header_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u16 bcdUVC;
-+ __u16 wTotalLength;
-+ __u32 dwClockFrequency;
-+ __u8 bInCollection;
-+ __u8 baInterfaceNr[];
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_HEADER_SIZE(n) (12+(n))
-+
-+#define UVC_HEADER_DESCRIPTOR(n) \
-+ uvc_header_descriptor_##n
-+
-+#define DECLARE_UVC_HEADER_DESCRIPTOR(n) \
-+struct UVC_HEADER_DESCRIPTOR(n) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u16 bcdUVC; \
-+ __u16 wTotalLength; \
-+ __u32 dwClockFrequency; \
-+ __u8 bInCollection; \
-+ __u8 baInterfaceNr[n]; \
-+} __attribute__ ((packed))
-+
-+/* 3.7.2.1. Input Terminal Descriptor */
-+struct uvc_input_terminal_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bTerminalID;
-+ __u16 wTerminalType;
-+ __u8 bAssocTerminal;
-+ __u8 iTerminal;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_INPUT_TERMINAL_SIZE 8
-+
-+/* 3.7.2.2. Output Terminal Descriptor */
-+struct uvc_output_terminal_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bTerminalID;
-+ __u16 wTerminalType;
-+ __u8 bAssocTerminal;
-+ __u8 bSourceID;
-+ __u8 iTerminal;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_OUTPUT_TERMINAL_SIZE 9
-+
-+/* 3.7.2.3. Camera Terminal Descriptor */
-+struct uvc_camera_terminal_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bTerminalID;
-+ __u16 wTerminalType;
-+ __u8 bAssocTerminal;
-+ __u8 iTerminal;
-+ __u16 wObjectiveFocalLengthMin;
-+ __u16 wObjectiveFocalLengthMax;
-+ __u16 wOcularFocalLength;
-+ __u8 bControlSize;
-+ __u8 bmControls[3];
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n))
-+
-+/* 3.7.2.4. Selector Unit Descriptor */
-+struct uvc_selector_unit_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bUnitID;
-+ __u8 bNrInPins;
-+ __u8 baSourceID[0];
-+ __u8 iSelector;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_SELECTOR_UNIT_SIZE(n) (6+(n))
-+
-+#define UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
-+ uvc_selector_unit_descriptor_##n
-+
-+#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
-+struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u8 bUnitID; \
-+ __u8 bNrInPins; \
-+ __u8 baSourceID[n]; \
-+ __u8 iSelector; \
-+} __attribute__ ((packed))
-+
-+/* 3.7.2.5. Processing Unit Descriptor */
-+struct uvc_processing_unit_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bUnitID;
-+ __u8 bSourceID;
-+ __u16 wMaxMultiplier;
-+ __u8 bControlSize;
-+ __u8 bmControls[2];
-+ __u8 iProcessing;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n))
-+
-+/* 3.7.2.6. Extension Unit Descriptor */
-+struct uvc_extension_unit_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bUnitID;
-+ __u8 guidExtensionCode[16];
-+ __u8 bNumControls;
-+ __u8 bNrInPins;
-+ __u8 baSourceID[0];
-+ __u8 bControlSize;
-+ __u8 bmControls[0];
-+ __u8 iExtension;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_EXTENSION_UNIT_SIZE(p, n) (24+(p)+(n))
-+
-+#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
-+ uvc_extension_unit_descriptor_##p_##n
-+
-+#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
-+struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u8 bUnitID; \
-+ __u8 guidExtensionCode[16]; \
-+ __u8 bNumControls; \
-+ __u8 bNrInPins; \
-+ __u8 baSourceID[p]; \
-+ __u8 bControlSize; \
-+ __u8 bmControls[n]; \
-+ __u8 iExtension; \
-+} __attribute__ ((packed))
-+
-+/* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */
-+struct uvc_control_endpoint_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u16 wMaxTransferSize;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_CONTROL_ENDPOINT_SIZE 5
-+
-+/* 3.9.2.1. Input Header Descriptor */
-+struct uvc_input_header_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bNumFormats;
-+ __u16 wTotalLength;
-+ __u8 bEndpointAddress;
-+ __u8 bmInfo;
-+ __u8 bTerminalLink;
-+ __u8 bStillCaptureMethod;
-+ __u8 bTriggerSupport;
-+ __u8 bTriggerUsage;
-+ __u8 bControlSize;
-+ __u8 bmaControls[];
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p))
-+
-+#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
-+ uvc_input_header_descriptor_##n_##p
-+
-+#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
-+struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u8 bNumFormats; \
-+ __u16 wTotalLength; \
-+ __u8 bEndpointAddress; \
-+ __u8 bmInfo; \
-+ __u8 bTerminalLink; \
-+ __u8 bStillCaptureMethod; \
-+ __u8 bTriggerSupport; \
-+ __u8 bTriggerUsage; \
-+ __u8 bControlSize; \
-+ __u8 bmaControls[p][n]; \
-+} __attribute__ ((packed))
-+
-+/* 3.9.2.2. Output Header Descriptor */
-+struct uvc_output_header_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bNumFormats;
-+ __u16 wTotalLength;
-+ __u8 bEndpointAddress;
-+ __u8 bTerminalLink;
-+ __u8 bControlSize;
-+ __u8 bmaControls[];
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p))
-+
-+#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
-+ uvc_output_header_descriptor_##n_##p
-+
-+#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
-+struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u8 bNumFormats; \
-+ __u16 wTotalLength; \
-+ __u8 bEndpointAddress; \
-+ __u8 bTerminalLink; \
-+ __u8 bControlSize; \
-+ __u8 bmaControls[p][n]; \
-+} __attribute__ ((packed))
-+
-+/* 3.9.2.6. Color matching descriptor */
-+struct uvc_color_matching_descriptor {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bColorPrimaries;
-+ __u8 bTransferCharacteristics;
-+ __u8 bMatrixCoefficients;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_COLOR_MATCHING_SIZE 6
-+
-+/* 4.3.1.1. Video Probe and Commit Controls */
-+struct uvc_streaming_control {
-+ __u16 bmHint;
-+ __u8 bFormatIndex;
-+ __u8 bFrameIndex;
-+ __u32 dwFrameInterval;
-+ __u16 wKeyFrameRate;
-+ __u16 wPFrameRate;
-+ __u16 wCompQuality;
-+ __u16 wCompWindowSize;
-+ __u16 wDelay;
-+ __u32 dwMaxVideoFrameSize;
-+ __u32 dwMaxPayloadTransferSize;
-+ __u32 dwClockFrequency;
-+ __u8 bmFramingInfo;
-+ __u8 bPreferedVersion;
-+ __u8 bMinVersion;
-+ __u8 bMaxVersion;
-+} __attribute__((__packed__));
-+
-+/* Uncompressed Payload - 3.1.1. Uncompressed Video Format Descriptor */
-+struct uvc_format_uncompressed {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bFormatIndex;
-+ __u8 bNumFrameDescriptors;
-+ __u8 guidFormat[16];
-+ __u8 bBitsPerPixel;
-+ __u8 bDefaultFrameIndex;
-+ __u8 bAspectRatioX;
-+ __u8 bAspectRatioY;
-+ __u8 bmInterfaceFlags;
-+ __u8 bCopyProtect;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE 27
-+
-+/* Uncompressed Payload - 3.1.2. Uncompressed Video Frame Descriptor */
-+struct uvc_frame_uncompressed {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bFrameIndex;
-+ __u8 bmCapabilities;
-+ __u16 wWidth;
-+ __u16 wHeight;
-+ __u32 dwMinBitRate;
-+ __u32 dwMaxBitRate;
-+ __u32 dwMaxVideoFrameBufferSize;
-+ __u32 dwDefaultFrameInterval;
-+ __u8 bFrameIntervalType;
-+ __u32 dwFrameInterval[];
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n))
-+
-+#define UVC_FRAME_UNCOMPRESSED(n) \
-+ uvc_frame_uncompressed_##n
-+
-+#define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \
-+struct UVC_FRAME_UNCOMPRESSED(n) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u8 bFrameIndex; \
-+ __u8 bmCapabilities; \
-+ __u16 wWidth; \
-+ __u16 wHeight; \
-+ __u32 dwMinBitRate; \
-+ __u32 dwMaxBitRate; \
-+ __u32 dwMaxVideoFrameBufferSize; \
-+ __u32 dwDefaultFrameInterval; \
-+ __u8 bFrameIntervalType; \
-+ __u32 dwFrameInterval[n]; \
-+} __attribute__ ((packed))
-+
-+/* MJPEG Payload - 3.1.1. MJPEG Video Format Descriptor */
-+struct uvc_format_mjpeg {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bFormatIndex;
-+ __u8 bNumFrameDescriptors;
-+ __u8 bmFlags;
-+ __u8 bDefaultFrameIndex;
-+ __u8 bAspectRatioX;
-+ __u8 bAspectRatioY;
-+ __u8 bmInterfaceFlags;
-+ __u8 bCopyProtect;
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_FORMAT_MJPEG_SIZE 11
-+
-+/* MJPEG Payload - 3.1.2. MJPEG Video Frame Descriptor */
-+struct uvc_frame_mjpeg {
-+ __u8 bLength;
-+ __u8 bDescriptorType;
-+ __u8 bDescriptorSubType;
-+ __u8 bFrameIndex;
-+ __u8 bmCapabilities;
-+ __u16 wWidth;
-+ __u16 wHeight;
-+ __u32 dwMinBitRate;
-+ __u32 dwMaxBitRate;
-+ __u32 dwMaxVideoFrameBufferSize;
-+ __u32 dwDefaultFrameInterval;
-+ __u8 bFrameIntervalType;
-+ __u32 dwFrameInterval[];
-+} __attribute__((__packed__));
-+
-+#define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n))
-+
-+#define UVC_FRAME_MJPEG(n) \
-+ uvc_frame_mjpeg_##n
-+
-+#define DECLARE_UVC_FRAME_MJPEG(n) \
-+struct UVC_FRAME_MJPEG(n) { \
-+ __u8 bLength; \
-+ __u8 bDescriptorType; \
-+ __u8 bDescriptorSubType; \
-+ __u8 bFrameIndex; \
-+ __u8 bmCapabilities; \
-+ __u16 wWidth; \
-+ __u16 wHeight; \
-+ __u32 dwMinBitRate; \
-+ __u32 dwMaxBitRate; \
-+ __u32 dwMaxVideoFrameBufferSize; \
-+ __u32 dwDefaultFrameInterval; \
-+ __u8 bFrameIntervalType; \
-+ __u32 dwFrameInterval[n]; \
-+} __attribute__ ((packed))
-+
- #endif /* __LINUX_USB_VIDEO_H */
-