aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 09:46:57 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 09:46:57 -0700
commit55e32a4d9095c0fa0e22e730151a4255c86bee71 (patch)
treec2f286b98d6e904aec54f9633530873a9b4cee1e
parenteac3d97d10da4d8904524cee5e8dcd63067583d8 (diff)
downloadltsi-kernel-55e32a4d9095c0fa0e22e730151a4255c86bee71.tar.gz
more kzm9g patches added
-rw-r--r--patches.kzm9g/0001-tty-serial-allow-ports-to-override-the-irq-handler.patch36
-rw-r--r--patches.kzm9g/0002-serial-introduce-generic-port-in-out-helpers.patch53
-rw-r--r--patches.kzm9g/0003-serial-8250-increase-PASS_LIMIT.patch39
-rw-r--r--patches.kzm9g/0004-serial-Fix-wakeup-init-logic-to-speed-up-startup.patch60
-rw-r--r--patches.kzm9g/0005-tty-serial8250-allow-platforms-to-override-irq-handl.patch140
-rw-r--r--patches.kzm9g/0006-tty-serial8250-remove-UPIO_DWAPB-32.patch167
-rw-r--r--patches.kzm9g/0007-tty-8250-export-serial8250_handle_irq.patch32
-rw-r--r--patches.kzm9g/0008-serial-8250-Move-UPIO_TSI-to-powerpc.patch129
-rw-r--r--patches.kzm9g/0009-serial-Support-the-EFR-register-of-XR1715x-uarts.patch159
-rw-r--r--patches.kzm9g/0010-8250-ratelimit-LSR-safety-check-engaged-warning.patch44
-rw-r--r--patches.kzm9g/0011-serial-8250-replace-hardcoded-0xbf-with-define.patch33
-rw-r--r--patches.kzm9g/0012-serial-move-struct-uart_8250_port-from-8250.c-to-825.patch98
-rw-r--r--patches.kzm9g/0013-serial-clean-up-parameter-passing-for-8250-Rx-IRQ-ha.patch79
-rw-r--r--patches.kzm9g/0014-serial-export-the-key-functions-for-an-8250-IRQ-hand.patch161
-rw-r--r--patches.kzm9g/0015-serial-make-8250-timeout-use-the-specified-IRQ-handl.patch51
-rw-r--r--patches.kzm9g/0016-serial-manually-inline-serial8250_handle_port.patch77
-rw-r--r--patches.kzm9g/0017-serial-group-all-the-8250-related-code-together.patch746
-rw-r--r--patches.kzm9g/0018-serial-Kill-off-NO_IRQ.patch361
-rw-r--r--patches.kzm9g/0019-tty-fix-a-build-failure-on-sparc.patch42
-rw-r--r--patches.kzm9g/0020-tty-sparc-rename-drivers-tty-serial-suncore.h-includ.patch199
-rw-r--r--patches.kzm9g/0021-serial-delete-last-unused-traces-of-pausing-I-O-in-8.patch732
-rw-r--r--patches.kzm9g/0022-serial-make-8250-s-serial_in-shareable-to-other-driv.patch73
-rw-r--r--patches.kzm9g/0023-serial-delete-useless-void-casts-in-8250.c.patch84
-rw-r--r--patches.kzm9g/0024-serial-reduce-number-of-indirections-in-8250-code.patch958
-rw-r--r--patches.kzm9g/0025-serial-use-serial_port_in-out-vs-serial_in-out-in-82.patch455
-rw-r--r--patches.kzm9g/0026-serial-remove-back-and-forth-conversions-in-serial_o.patch56
-rw-r--r--patches.kzm9g/0027-serial-8250_pci-add-a-force-background-timer-flag-an.patch118
-rw-r--r--patches.kzm9g/0028-8250.c-less-than-2400-baud-fix.patch51
-rw-r--r--patches.kzm9g/0029-serial8250-Add-dl_read-dl_write-callbacks.patch203
-rw-r--r--patches.kzm9g/0030-serial8250-Use-dl_read-dl_write-on-Alchemy.patch138
-rw-r--r--patches.kzm9g/0031-serial8250-Use-dl_read-dl_write-on-RM9K.patch139
-rw-r--r--patches.kzm9g/0032-serial8250-Clean-up-default-map-and-dl-code.patch134
-rw-r--r--patches.kzm9g/0033-serial8250-Introduce-serial8250_register_8250_port.patch169
-rw-r--r--patches.kzm9g/0034-serial8250-em-Emma-Mobile-UART-driver-V2.patch254
-rw-r--r--patches.kzm9g/0035-serial8250-em-clk_get-IS_ERR-error-handling-fix.patch38
-rw-r--r--patches.kzm9g/0036-cpuidle-create-bootparam-cpuidle.off-1.patch116
-rw-r--r--patches.kzm9g/0037-cpuidle-replace-xen-access-to-x86-pm_idle-and-defaul.patch85
-rw-r--r--patches.kzm9g/0038-cpuidle-stop-depending-on-pm_idle.patch254
-rw-r--r--patches.kzm9g/0039-cpuidle-Consistent-spelling-of-cpuidle_idle_call.patch53
-rw-r--r--patches.kzm9g/0040-sh-Fix-up-fallout-from-cpuidle-changes.patch32
-rw-r--r--patches.kzm9g/0041-cpuidle-Add-module.h-to-drivers-cpuidle-files-as-req.patch41
-rw-r--r--patches.kzm9g/0042-cpuidle-Move-dev-last_residency-update-to-driver-ent.patch868
-rw-r--r--patches.kzm9g/0043-cpuidle-Remove-CPUIDLE_FLAG_IGNORE-and-dev-prepare.patch89
-rw-r--r--patches.kzm9g/0044-cpuidle-Split-cpuidle_state-structure-and-move-per-c.patch531
-rw-r--r--patches.kzm9g/0045-cpuidle-Single-Global-registration-of-idle-states.patch1520
-rw-r--r--patches.kzm9g/0046-cpuidle-Add-common-time-keeping-and-irq-enabling.patch285
-rw-r--r--patches.kzm9g/0047-mm-add-vm_area_add_early.patch92
-rw-r--r--patches.kzm9g/0048-clockevents-Make-clockevents_config-a-global-symbol.patch46
-rw-r--r--patches.kzm9g/0049-clocksource-em_sti-Emma-Mobile-STI-driver-V2.patch484
-rw-r--r--patches.kzm9g/0050-ARM-move-initialization-of-the-high_memory-variable-.patch63
-rw-r--r--patches.kzm9g/0051-ARM-move-iotable-mappings-within-the-vmalloc-region.patch207
-rw-r--r--patches.kzm9g/0052-ARM-simplify-__iounmap-when-dealing-with-section-bas.patch66
-rw-r--r--patches.kzm9g/0053-ARM-add-generic-ioremap-optimization-by-reusing-stat.patch177
-rw-r--r--patches.kzm9g/0054-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch72
-rw-r--r--patches.kzm9g/0055-ARM-mach-shmobile-Allow-SoC-specific-CPU-kill-code.patch67
-rw-r--r--patches.kzm9g/0056-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch46
-rw-r--r--patches.kzm9g/0057-ARM-Undelete-KZM9D-mach-type.patch32
-rw-r--r--patches.kzm9g/0058-gpio-Emma-Mobile-GPIO-driver.patch481
-rw-r--r--patches.kzm9g/0059-mach-shmobile-Emma-Mobile-EV2-SoC-base-support-V3.patch493
-rw-r--r--patches.kzm9g/0060-mach-shmobile-KZM9D-board-support-V3.patch110
-rw-r--r--patches.kzm9g/0061-mach-shmobile-Emma-Mobile-EV2-SMP-support-V3.patch329
-rw-r--r--patches.kzm9g/0062-mach-shmobile-Emma-Mobile-EV2-GPIO-support-V3.patch280
-rw-r--r--patches.kzm9g/0063-mach-shmobile-KZM9D-board-Ethernet-support-V3.patch82
-rw-r--r--series66
64 files changed, 13375 insertions, 0 deletions
diff --git a/patches.kzm9g/0001-tty-serial-allow-ports-to-override-the-irq-handler.patch b/patches.kzm9g/0001-tty-serial-allow-ports-to-override-the-irq-handler.patch
new file mode 100644
index 00000000000000..3d7f126e8a3640
--- /dev/null
+++ b/patches.kzm9g/0001-tty-serial-allow-ports-to-override-the-irq-handler.patch
@@ -0,0 +1,36 @@
+From bc8d01eecbc317f8f39268b1e5e4fcb9ac1d89af Mon Sep 17 00:00:00 2001
+From: Jamie Iles <jamie@jamieiles.com>
+Date: Mon, 15 Aug 2011 10:17:51 +0100
+Subject: tty: serial: allow ports to override the irq handler
+
+Some serial ports may have unusal requirements for interrupt handling
+(e.g. the Synopsys DesignWare 8250-alike port and it's busy detect
+interrupt). Add a .handle_irq callback that can be used for platforms
+to override the interrupt behaviour in a similar fashion to the
+.serial_out and .serial_in callbacks.
+
+Signed-off-by: Jamie Iles <jamie@jamieiles.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit a74036f51272975e9538e80cd1bb64dce164b208)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/serial_core.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index a5c3114..b6fa317 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -300,6 +300,7 @@ struct uart_port {
+ void (*set_termios)(struct uart_port *,
+ struct ktermios *new,
+ struct ktermios *old);
++ int (*handle_irq)(struct uart_port *);
+ void (*pm)(struct uart_port *, unsigned int state,
+ unsigned int old);
+ unsigned int irq; /* irq number */
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0002-serial-introduce-generic-port-in-out-helpers.patch b/patches.kzm9g/0002-serial-introduce-generic-port-in-out-helpers.patch
new file mode 100644
index 00000000000000..377a496df1eb0e
--- /dev/null
+++ b/patches.kzm9g/0002-serial-introduce-generic-port-in-out-helpers.patch
@@ -0,0 +1,53 @@
+From 790111bbb9291b79c960d33b406ccc7ab9833a76 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:12 -0500
+Subject: serial: introduce generic port in/out helpers
+
+Looking at the existing serial drivers (esp. the 8250 derived
+variants) we see a common trend. They create a hardware specific
+port struct, which in turn contains a generic serial_port struct.
+
+The other trend, is that they all create some sort of shortcut
+to go through the hardware specific struct, to the serial_port
+struct, which has the basic in/out operations within. Looking
+for the serial_in and serial_out in several drivers shows this.
+
+Rather than let this continue, lets create a generic set of
+similar helper wrappers that can be used on a struct port, so
+we can eliminate bouncing out through hardware specific struct
+pointers just to come back into struct port where possible.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 927353a75602dd97144352f53177e18093fdd198)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/serial_core.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index b6fa317..1cb6309 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -376,6 +376,16 @@ struct uart_port {
+ void *private_data; /* generic platform data pointer */
+ };
+
++static inline int serial_port_in(struct uart_port *up, int offset)
++{
++ return up->serial_in(up, offset);
++}
++
++static inline void serial_port_out(struct uart_port *up, int offset, int value)
++{
++ up->serial_out(up, offset, value);
++}
++
+ /*
+ * This is the state information which is persistent across opens.
+ */
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0003-serial-8250-increase-PASS_LIMIT.patch b/patches.kzm9g/0003-serial-8250-increase-PASS_LIMIT.patch
new file mode 100644
index 00000000000000..f2433d9055fa8a
--- /dev/null
+++ b/patches.kzm9g/0003-serial-8250-increase-PASS_LIMIT.patch
@@ -0,0 +1,39 @@
+From 0028c21552eb37ad26e53e0d6d0a977d886b0abf Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jirislaby@gmail.com>
+Date: Sun, 5 Jun 2011 22:51:49 +0200
+Subject: serial: 8250, increase PASS_LIMIT
+
+With virtual machines like qemu, it's pretty common to see "too much
+work for irq4" messages nowadays. This happens when a bunch of output
+is printed on the emulated serial console. This is caused by too low
+PASS_LIMIT. When ISR loops more than the limit, it spits the message.
+
+I've been using a kernel with doubled the limit and I couldn't see no
+problems. Maybe it's time to get rid of the message now?
+
+Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
+Cc: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit e7328ae1848966181a7ac47e8ae6cddbd2cf55f3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index 762ce72..7f50999 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -81,7 +81,7 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
+ #define DEBUG_INTR(fmt...) do { } while (0)
+ #endif
+
+-#define PASS_LIMIT 256
++#define PASS_LIMIT 512
+
+ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0004-serial-Fix-wakeup-init-logic-to-speed-up-startup.patch b/patches.kzm9g/0004-serial-Fix-wakeup-init-logic-to-speed-up-startup.patch
new file mode 100644
index 00000000000000..6a58103c6edb37
--- /dev/null
+++ b/patches.kzm9g/0004-serial-Fix-wakeup-init-logic-to-speed-up-startup.patch
@@ -0,0 +1,60 @@
+From da29566854e9ffb6770255fbd915184073d2d0b1 Mon Sep 17 00:00:00 2001
+From: Simon Glass <sjg@chromium.org>
+Date: Thu, 19 Jan 2012 11:28:56 -0800
+Subject: serial: Fix wakeup init logic to speed up startup
+
+The synchronize_rcu() call resulting from making every serial driver
+wake-up capable (commit b3b708fa) slows boot down on my Tegra2x system
+(with CONFIG_PREEMPT disabled).
+
+But this is avoidable since it is the device_set_wakeup_enable() and then
+subsequence disable which causes the delay. We might as well just make
+the device wakeup capable but not actually enable it for wakeup until
+needed.
+
+Effectively the current code does this:
+
+ device_set_wakeup_capable(dev, 1);
+ device_set_wakeup_enable(dev, 1);
+ device_set_wakeup_enable(dev, 0);
+
+We can just drop the last two lines.
+
+Before this change my boot log says:
+[ 0.227062] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
+[ 0.702928] serial8250.0: ttyS0 at MMIO 0x70006040 (irq = 69) is a Tegra
+
+after:
+[ 0.227264] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
+[ 0.227983] serial8250.0: ttyS0 at MMIO 0x70006040 (irq = 69) is a Tegra
+
+for saving of 450ms.
+
+Suggested-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
+Signed-off-by: Simon Glass <sjg@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 773598357c0baf03081cf87f2b444f97744faf1e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/serial_core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -2391,11 +2391,11 @@ int uart_add_one_port(struct uart_driver
+ */
+ tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
+ if (likely(!IS_ERR(tty_dev))) {
+- device_init_wakeup(tty_dev, 1);
+- device_set_wakeup_enable(tty_dev, 0);
+- } else
++ device_set_wakeup_capable(tty_dev, 1);
++ } else {
+ printk(KERN_ERR "Cannot register tty device on line %d\n",
+ uport->line);
++ }
+
+ /*
+ * Ensure UPF_DEAD is not set.
diff --git a/patches.kzm9g/0005-tty-serial8250-allow-platforms-to-override-irq-handl.patch b/patches.kzm9g/0005-tty-serial8250-allow-platforms-to-override-irq-handl.patch
new file mode 100644
index 00000000000000..a12baef1285a9a
--- /dev/null
+++ b/patches.kzm9g/0005-tty-serial8250-allow-platforms-to-override-irq-handl.patch
@@ -0,0 +1,140 @@
+From 5d815ba3618efabed3571204df30a309d2471aee Mon Sep 17 00:00:00 2001
+From: Jamie Iles <jamie@jamieiles.com>
+Date: Mon, 15 Aug 2011 10:17:52 +0100
+Subject: tty: serial8250: allow platforms to override irq handler
+
+Some ports (e.g. Synopsys DesignWare 8250) have special requirements for
+handling the interrupts. Allow these platforms to specify their own
+interrupt handler that will override the default.
+serial8250_handle_irq() is provided so that platforms can extend the IRQ
+handler rather than completely replacing it.
+
+Signed-off-by: Jamie Iles <jamie@jamieiles.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 583d28e92f667eb6cc81ea87daaa7e321c23fe14)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 39 +++++++++++++++++++++++++++++++++++----
+ include/linux/serial_8250.h | 2 ++
+ 2 files changed, 37 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index 7f50999..97007e5 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -509,6 +509,8 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
+ outb(value, p->iobase + offset);
+ }
+
++static int serial8250_default_handle_irq(struct uart_port *port);
++
+ static void set_io_from_upio(struct uart_port *p)
+ {
+ struct uart_8250_port *up =
+@@ -557,6 +559,7 @@ static void set_io_from_upio(struct uart_port *p)
+ }
+ /* Remember loaded iotype */
+ up->cur_iotype = p->iotype;
++ p->handle_irq = serial8250_default_handle_irq;
+ }
+
+ static void
+@@ -1621,6 +1624,28 @@ static void serial8250_handle_port(struct uart_8250_port *up)
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ }
+
++int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
++{
++ struct uart_8250_port *up =
++ container_of(port, struct uart_8250_port, port);
++
++ if (!(iir & UART_IIR_NO_INT)) {
++ serial8250_handle_port(up);
++ return 1;
++ }
++
++ return 0;
++}
++
++static int serial8250_default_handle_irq(struct uart_port *port)
++{
++ struct uart_8250_port *up =
++ container_of(port, struct uart_8250_port, port);
++ unsigned int iir = serial_in(up, UART_IIR);
++
++ return serial8250_handle_irq(port, iir);
++}
++
+ /*
+ * This is the serial driver's interrupt routine.
+ *
+@@ -1648,13 +1673,12 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
+ l = i->head;
+ do {
+ struct uart_8250_port *up;
+- unsigned int iir;
++ struct uart_port *port;
+
+ up = list_entry(l, struct uart_8250_port, list);
++ port = &up->port;
+
+- iir = serial_in(up, UART_IIR);
+- if (!(iir & UART_IIR_NO_INT)) {
+- serial8250_handle_port(up);
++ if (port->handle_irq(port)) {
+
+ handled = 1;
+
+@@ -3050,6 +3074,10 @@ int __init early_serial_setup(struct uart_port *port)
+ p->serial_in = port->serial_in;
+ if (port->serial_out)
+ p->serial_out = port->serial_out;
++ if (port->handle_irq)
++ p->handle_irq = port->handle_irq;
++ else
++ p->handle_irq = serial8250_default_handle_irq;
+
+ return 0;
+ }
+@@ -3118,6 +3146,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
+ port.type = p->type;
+ port.serial_in = p->serial_in;
+ port.serial_out = p->serial_out;
++ port.handle_irq = p->handle_irq;
+ port.set_termios = p->set_termios;
+ port.pm = p->pm;
+ port.dev = &dev->dev;
+@@ -3283,6 +3312,8 @@ int serial8250_register_port(struct uart_port *port)
+ uart->port.serial_in = port->serial_in;
+ if (port->serial_out)
+ uart->port.serial_out = port->serial_out;
++ if (port->handle_irq)
++ uart->port.handle_irq = port->handle_irq;
+ /* Possibly override set_termios call */
+ if (port->set_termios)
+ uart->port.set_termios = port->set_termios;
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index 97f5b45..1f05bbe 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -35,6 +35,7 @@ struct plat_serial8250_port {
+ void (*set_termios)(struct uart_port *,
+ struct ktermios *new,
+ struct ktermios *old);
++ int (*handle_irq)(struct uart_port *);
+ void (*pm)(struct uart_port *, unsigned int state,
+ unsigned old);
+ };
+@@ -80,6 +81,7 @@ extern void serial8250_do_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old);
+ extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate);
++int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
+
+ extern void serial8250_set_isa_configurator(void (*v)
+ (int port, struct uart_port *up,
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0006-tty-serial8250-remove-UPIO_DWAPB-32.patch b/patches.kzm9g/0006-tty-serial8250-remove-UPIO_DWAPB-32.patch
new file mode 100644
index 00000000000000..098799ff62900b
--- /dev/null
+++ b/patches.kzm9g/0006-tty-serial8250-remove-UPIO_DWAPB-32.patch
@@ -0,0 +1,167 @@
+From ea7db772ed2f7cf3ce5d40ea3da4f4ead0505fb2 Mon Sep 17 00:00:00 2001
+From: Jamie Iles <jamie@jamieiles.com>
+Date: Mon, 15 Aug 2011 10:17:55 +0100
+Subject: tty: serial8250: remove UPIO_DWAPB{,32}
+
+Now that platforms can override the port IRQ handler and the only user
+of these UPIO modes has been converted over, kill off UPIO_DWAPB and
+UPIO_DWAPB32.
+
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Jamie Iles <jamie@jamieiles.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 4834d028978583dfe8e1fc19f1180ceb03d8dfb7)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 68 ---------------------------------------
+ drivers/tty/serial/serial_core.c | 4 --
+ include/linux/serial_core.h | 4 --
+ 3 files changed, 1 insertion(+), 75 deletions(-)
+
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -461,42 +461,6 @@ static void tsi_serial_out(struct uart_p
+ writeb(value, p->membase + offset);
+ }
+
+-/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */
+-static inline void dwapb_save_out_value(struct uart_port *p, int offset,
+- int value)
+-{
+- struct uart_8250_port *up =
+- container_of(p, struct uart_8250_port, port);
+-
+- if (offset == UART_LCR)
+- up->lcr = value;
+-}
+-
+-/* Read the IER to ensure any interrupt is cleared before returning from ISR. */
+-static inline void dwapb_check_clear_ier(struct uart_port *p, int offset)
+-{
+- if (offset == UART_TX || offset == UART_IER)
+- p->serial_in(p, UART_IER);
+-}
+-
+-static void dwapb_serial_out(struct uart_port *p, int offset, int value)
+-{
+- int save_offset = offset;
+- offset = map_8250_out_reg(p, offset) << p->regshift;
+- dwapb_save_out_value(p, save_offset, value);
+- writeb(value, p->membase + offset);
+- dwapb_check_clear_ier(p, save_offset);
+-}
+-
+-static void dwapb32_serial_out(struct uart_port *p, int offset, int value)
+-{
+- int save_offset = offset;
+- offset = map_8250_out_reg(p, offset) << p->regshift;
+- dwapb_save_out_value(p, save_offset, value);
+- writel(value, p->membase + offset);
+- dwapb_check_clear_ier(p, save_offset);
+-}
+-
+ static unsigned int io_serial_in(struct uart_port *p, int offset)
+ {
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+@@ -542,16 +506,6 @@ static void set_io_from_upio(struct uart
+ p->serial_out = tsi_serial_out;
+ break;
+
+- case UPIO_DWAPB:
+- p->serial_in = mem_serial_in;
+- p->serial_out = dwapb_serial_out;
+- break;
+-
+- case UPIO_DWAPB32:
+- p->serial_in = mem32_serial_in;
+- p->serial_out = dwapb32_serial_out;
+- break;
+-
+ default:
+ p->serial_in = io_serial_in;
+ p->serial_out = io_serial_out;
+@@ -570,8 +524,6 @@ serial_out_sync(struct uart_8250_port *u
+ case UPIO_MEM:
+ case UPIO_MEM32:
+ case UPIO_AU:
+- case UPIO_DWAPB:
+- case UPIO_DWAPB32:
+ p->serial_out(p, offset, value);
+ p->serial_in(p, UART_LCR); /* safe, no side-effects */
+ break;
+@@ -1679,23 +1631,7 @@ static irqreturn_t serial8250_interrupt(
+ port = &up->port;
+
+ if (port->handle_irq(port)) {
+-
+ handled = 1;
+-
+- end = NULL;
+- } else if ((up->port.iotype == UPIO_DWAPB ||
+- up->port.iotype == UPIO_DWAPB32) &&
+- (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+- /* The DesignWare APB UART has an Busy Detect (0x07)
+- * interrupt meaning an LCR write attempt occurred while the
+- * UART was busy. The interrupt must be cleared by reading
+- * the UART status register (USR) and the LCR re-written. */
+- unsigned int status;
+- status = *(volatile u32 *)up->port.private_data;
+- serial_out(up, UART_LCR, up->lcr);
+-
+- handled = 1;
+-
+ end = NULL;
+ } else if (end == NULL)
+ end = l;
+@@ -2594,8 +2530,6 @@ static int serial8250_request_std_resour
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM:
+- case UPIO_DWAPB:
+- case UPIO_DWAPB32:
+ if (!up->port.mapbase)
+ break;
+
+@@ -2632,8 +2566,6 @@ static void serial8250_release_std_resou
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM:
+- case UPIO_DWAPB:
+- case UPIO_DWAPB32:
+ if (!up->port.mapbase)
+ break;
+
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -2065,8 +2065,6 @@ uart_report_port(struct uart_driver *drv
+ case UPIO_MEM32:
+ case UPIO_AU:
+ case UPIO_TSI:
+- case UPIO_DWAPB:
+- case UPIO_DWAPB32:
+ snprintf(address, sizeof(address),
+ "MMIO 0x%llx", (unsigned long long)port->mapbase);
+ break;
+@@ -2487,8 +2485,6 @@ int uart_match_port(struct uart_port *po
+ case UPIO_MEM32:
+ case UPIO_AU:
+ case UPIO_TSI:
+- case UPIO_DWAPB:
+- case UPIO_DWAPB32:
+ return (port1->mapbase == port2->mapbase);
+ }
+ return 0;
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -318,9 +318,7 @@ struct uart_port {
+ #define UPIO_MEM32 (3)
+ #define UPIO_AU (4) /* Au1x00 type IO */
+ #define UPIO_TSI (5) /* Tsi108/109 type IO */
+-#define UPIO_DWAPB (6) /* DesignWare APB UART */
+-#define UPIO_RM9000 (7) /* RM9000 type IO */
+-#define UPIO_DWAPB32 (8) /* DesignWare APB UART (32 bit accesses) */
++#define UPIO_RM9000 (6) /* RM9000 type IO */
+
+ unsigned int read_status_mask; /* driver specific */
+ unsigned int ignore_status_mask; /* driver specific */
diff --git a/patches.kzm9g/0007-tty-8250-export-serial8250_handle_irq.patch b/patches.kzm9g/0007-tty-8250-export-serial8250_handle_irq.patch
new file mode 100644
index 00000000000000..3d88d9e48044bb
--- /dev/null
+++ b/patches.kzm9g/0007-tty-8250-export-serial8250_handle_irq.patch
@@ -0,0 +1,32 @@
+From e54750f312943c2135375552a80f417f969ec95f Mon Sep 17 00:00:00 2001
+From: Jamie Iles <jamie@jamieiles.com>
+Date: Fri, 26 Aug 2011 19:04:49 +0100
+Subject: tty: 8250: export serial8250_handle_irq
+
+Allow modules to use the normal 8250 irq handler inside their own.
+
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jamie Iles <jamie@jamieiles.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit c7a1bdc5c951aae15021d13e3f5c0b2fe9d56112)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index 5d92b93..454fc92 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -1588,6 +1588,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+ static int serial8250_default_handle_irq(struct uart_port *port)
+ {
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0008-serial-8250-Move-UPIO_TSI-to-powerpc.patch b/patches.kzm9g/0008-serial-8250-Move-UPIO_TSI-to-powerpc.patch
new file mode 100644
index 00000000000000..c6b2a860b26229
--- /dev/null
+++ b/patches.kzm9g/0008-serial-8250-Move-UPIO_TSI-to-powerpc.patch
@@ -0,0 +1,129 @@
+From 173bc58b2e469e0f92a58de4b3644e171895300f Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Mon, 27 Jun 2011 11:45:16 +0000
+Subject: serial/8250: Move UPIO_TSI to powerpc
+
+This iotype is only used by the legacy_serial code in powerpc, so the
+code should live there, rather than be compiled in for every 8250
+driver.
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: linuxppc-dev@lists.ozlabs.org
+Cc: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-serial@vger.kernel.org
+Acked-by: David Daney <david.daney@cavium.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+(cherry picked from commit 7df5659eefad9b6d457ccdee016bd78bd064cfc0)
+
+Conflicts:
+
+ drivers/tty/serial/8250.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/powerpc/kernel/legacy_serial.c | 25 +++++++++++++++++++++++++
+ drivers/tty/serial/8250.c | 23 -----------------------
+ 2 files changed, 25 insertions(+), 23 deletions(-)
+
+diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
+index 2b97b80..c7b5afe 100644
+--- a/arch/powerpc/kernel/legacy_serial.c
++++ b/arch/powerpc/kernel/legacy_serial.c
+@@ -6,6 +6,7 @@
+ #include <linux/pci.h>
+ #include <linux/of_address.h>
+ #include <linux/of_device.h>
++#include <linux/serial_reg.h>
+ #include <asm/io.h>
+ #include <asm/mmu.h>
+ #include <asm/prom.h>
+@@ -47,6 +48,24 @@ static struct __initdata of_device_id legacy_serial_parents[] = {
+ static unsigned int legacy_serial_count;
+ static int legacy_serial_console = -1;
+
++static unsigned int tsi_serial_in(struct uart_port *p, int offset)
++{
++ unsigned int tmp;
++ offset = offset << p->regshift;
++ if (offset == UART_IIR) {
++ tmp = readl(p->membase + (UART_IIR & ~3));
++ return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
++ } else
++ return readb(p->membase + offset);
++}
++
++static void tsi_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = offset << p->regshift;
++ if (!((offset == UART_IER) && (value & UART_IER_UUE)))
++ writeb(value, p->membase + offset);
++}
++
+ static int __init add_legacy_port(struct device_node *np, int want_index,
+ int iotype, phys_addr_t base,
+ phys_addr_t taddr, unsigned long irq,
+@@ -102,6 +121,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
+ legacy_serial_ports[index].iobase = base;
+ else
+ legacy_serial_ports[index].mapbase = base;
++
+ legacy_serial_ports[index].iotype = iotype;
+ legacy_serial_ports[index].uartclk = clock;
+ legacy_serial_ports[index].irq = irq;
+@@ -112,6 +132,11 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
+ legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
+ legacy_serial_infos[index].irq_check_parent = irq_check_parent;
+
++ if (iotype == UPIO_TSI) {
++ legacy_serial_ports[index].serial_in = tsi_serial_in;
++ legacy_serial_ports[index].serial_out = tsi_serial_out;
++ }
++
+ printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
+ index, np->full_name);
+ printk(KERN_DEBUG " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index 454fc92..a0e502b 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -443,24 +443,6 @@ static void au_serial_out(struct uart_port *p, int offset, int value)
+ __raw_writel(value, p->membase + offset);
+ }
+
+-static unsigned int tsi_serial_in(struct uart_port *p, int offset)
+-{
+- unsigned int tmp;
+- offset = map_8250_in_reg(p, offset) << p->regshift;
+- if (offset == UART_IIR) {
+- tmp = readl(p->membase + (UART_IIR & ~3));
+- return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+- } else
+- return readb(p->membase + offset);
+-}
+-
+-static void tsi_serial_out(struct uart_port *p, int offset, int value)
+-{
+- offset = map_8250_out_reg(p, offset) << p->regshift;
+- if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+- writeb(value, p->membase + offset);
+-}
+-
+ static unsigned int io_serial_in(struct uart_port *p, int offset)
+ {
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+@@ -501,11 +483,6 @@ static void set_io_from_upio(struct uart_port *p)
+ p->serial_out = au_serial_out;
+ break;
+
+- case UPIO_TSI:
+- p->serial_in = tsi_serial_in;
+- p->serial_out = tsi_serial_out;
+- break;
+-
+ default:
+ p->serial_in = io_serial_in;
+ p->serial_out = io_serial_out;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0009-serial-Support-the-EFR-register-of-XR1715x-uarts.patch b/patches.kzm9g/0009-serial-Support-the-EFR-register-of-XR1715x-uarts.patch
new file mode 100644
index 00000000000000..43c28f5c3a3329
--- /dev/null
+++ b/patches.kzm9g/0009-serial-Support-the-EFR-register-of-XR1715x-uarts.patch
@@ -0,0 +1,159 @@
+From 5df029e7baab27a7b6f848739659865a006820f9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?S=C3=B8ren=20Holm?= <sgh@sgh.dk>
+Date: Fri, 2 Sep 2011 22:55:37 +0200
+Subject: serial: Support the EFR-register of XR1715x uarts.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The EFR (Enhenced-Features-Register) is located at a different offset
+than the other devices supporting UART_CAP_EFR. This change add a special
+setup quick to set UPF_EXAR_EFR on the port. UPF_EXAR_EFR is then used to
+the port type to PORT_XR17D15X since it is for sure a XR17D15X uart.
+
+Signed-off-by: Søren Holm <sgh@sgh.dk>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 06315348b16178e4c006e7892ef8e5e65f49c66a)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 20 +++++++++++++++++++-
+ drivers/tty/serial/8250_pci.c | 33 +++++++++++++++++++++++++++++++++
+ include/linux/serial_core.h | 4 +++-
+ include/linux/serial_reg.h | 1 +
+ 4 files changed, 56 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index a0e502b..69802bd 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -309,6 +309,13 @@ static const struct serial8250_config uart_config[] = {
+ UART_FCR_T_TRIG_01,
+ .flags = UART_CAP_FIFO | UART_CAP_RTOIE,
+ },
++ [PORT_XR17D15X] = {
++ .name = "XR17D15X",
++ .fifo_size = 64,
++ .tx_loadsz = 64,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
++ },
+ };
+
+ #if defined(CONFIG_MIPS_ALCHEMY)
+@@ -1052,6 +1059,14 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ serial_outp(up, UART_IER, iersave);
+
+ /*
++ * Exar uarts have EFR in a weird location
++ */
++ if (up->port.flags & UPF_EXAR_EFR) {
++ up->port.type = PORT_XR17D15X;
++ up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
++ }
++
++ /*
+ * We distinguish between 16550A and U6 16550A by counting
+ * how many bytes are in the FIFO.
+ */
+@@ -2396,7 +2411,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ efr |= UART_EFR_CTS;
+
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_outp(up, UART_EFR, efr);
++ if (up->port.flags & UPF_EXAR_EFR)
++ serial_outp(up, UART_XR_EFR, efr);
++ else
++ serial_outp(up, UART_EFR, efr);
+ }
+
+ #ifdef CONFIG_ARCH_OMAP
+diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
+index ff48fdb..a213f38 100644
+--- a/drivers/tty/serial/8250_pci.c
++++ b/drivers/tty/serial/8250_pci.c
+@@ -1003,6 +1003,15 @@ static int pci_eg20t_init(struct pci_dev *dev)
+ #endif
+ }
+
++static int
++pci_xr17c154_setup(struct serial_private *priv,
++ const struct pciserial_board *board,
++ struct uart_port *port, int idx)
++{
++ port->flags |= UPF_EXAR_EFR;
++ return pci_default_setup(priv, board, port, idx);
++}
++
+ /* This should be in linux/pci_ids.h */
+ #define PCI_VENDOR_ID_SBSMODULARIO 0x124B
+ #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
+@@ -1407,6 +1416,30 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ .setup = pci_timedia_setup,
+ },
+ /*
++ * Exar cards
++ */
++ {
++ .vendor = PCI_VENDOR_ID_EXAR,
++ .device = PCI_DEVICE_ID_EXAR_XR17C152,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = pci_xr17c154_setup,
++ },
++ {
++ .vendor = PCI_VENDOR_ID_EXAR,
++ .device = PCI_DEVICE_ID_EXAR_XR17C154,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = pci_xr17c154_setup,
++ },
++ {
++ .vendor = PCI_VENDOR_ID_EXAR,
++ .device = PCI_DEVICE_ID_EXAR_XR17C158,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = pci_xr17c154_setup,
++ },
++ /*
+ * Xircom cards
+ */
+ {
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index 4880024..d611ca0 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -46,7 +46,8 @@
+ #define PORT_AR7 18 /* Texas Instruments AR7 internal UART */
+ #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */
+ #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */
+-#define PORT_MAX_8250 20 /* max port ID */
++#define PORT_XR17D15X 21 /* Exar XR17D15x UART */
++#define PORT_MAX_8250 21 /* max port ID */
+
+ /*
+ * ARM specific type numbers. These are not currently guaranteed
+@@ -349,6 +350,7 @@ struct uart_port {
+ #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16))
+ #define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
+ #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
++#define UPF_EXAR_EFR ((__force upf_t) (1 << 25))
+ /* The exact UART type is known and should not be probed. */
+ #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
+ #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
+diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
+index c75bda3..8ce70d7 100644
+--- a/include/linux/serial_reg.h
++++ b/include/linux/serial_reg.h
+@@ -152,6 +152,7 @@
+ * LCR=0xBF (or DLAB=1 for 16C660)
+ */
+ #define UART_EFR 2 /* I/O: Extended Features Register */
++#define UART_XR_EFR 9 /* I/O: Extended Features Register (XR17D15x) */
+ #define UART_EFR_CTS 0x80 /* CTS flow control */
+ #define UART_EFR_RTS 0x40 /* RTS flow control */
+ #define UART_EFR_SCD 0x20 /* Special character detect */
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0010-8250-ratelimit-LSR-safety-check-engaged-warning.patch b/patches.kzm9g/0010-8250-ratelimit-LSR-safety-check-engaged-warning.patch
new file mode 100644
index 00000000000000..14fcdd5e5e0251
--- /dev/null
+++ b/patches.kzm9g/0010-8250-ratelimit-LSR-safety-check-engaged-warning.patch
@@ -0,0 +1,44 @@
+From 72ad6d3c5d84c98203676d587b25898690591ab7 Mon Sep 17 00:00:00 2001
+From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Date: Mon, 26 Sep 2011 09:14:34 -0400
+Subject: 8250: ratelimit LSR safety check engaged warning.
+
+On my BIOSTAR TA890FXE the ttyS0 ends up spewing:
+
+[904682.485933] ttyS0: LSR safety check engaged!
+[904692.505895] ttyS0: LSR safety check engaged!
+[904702.525972] ttyS0: LSR safety check engaged!
+[904712.545967] ttyS0: LSR safety check engaged!
+[904722.566125] ttyS0: LSR safety check engaged!
+..
+lets limit it so it won't be the only thing visible
+in the ring buffer.
+
+CC: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 7808a4c4853fa0203085cf2217e01823d9f0c70c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index 69802bd..eeadf1b 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -2034,8 +2034,8 @@ static int serial8250_startup(struct uart_port *port)
+ */
+ if (!(up->port.flags & UPF_BUGGY_UART) &&
+ (serial_inp(up, UART_LSR) == 0xff)) {
+- printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+- serial_index(&up->port));
++ printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
++ serial_index(&up->port));
+ return -ENODEV;
+ }
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0011-serial-8250-replace-hardcoded-0xbf-with-define.patch b/patches.kzm9g/0011-serial-8250-replace-hardcoded-0xbf-with-define.patch
new file mode 100644
index 00000000000000..97c8003f6ac0d1
--- /dev/null
+++ b/patches.kzm9g/0011-serial-8250-replace-hardcoded-0xbf-with-define.patch
@@ -0,0 +1,33 @@
+From 698dcc00ab4b72502d3b69bf1167b7c3977f5e5a Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <w.sang@pengutronix.de>
+Date: Fri, 9 Dec 2011 18:07:13 +0100
+Subject: serial: 8250: replace hardcoded 0xbf with #define
+
+Makes it easier to find all occurences requesting CONF_MODE_B.
+
+Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 7d73aaf1d45d9bd95638680361db4d019ebb75bb)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index eeadf1b..f8f2320 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -2000,7 +2000,7 @@ static int serial8250_startup(struct uart_port *port)
+ serial_outp(up, UART_IER, 0);
+ serial_outp(up, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+- serial_outp(up, UART_LCR, 0xBF);
++ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_outp(up, UART_EFR, UART_EFR_ECB);
+ serial_outp(up, UART_LCR, 0);
+ }
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0012-serial-move-struct-uart_8250_port-from-8250.c-to-825.patch b/patches.kzm9g/0012-serial-move-struct-uart_8250_port-from-8250.c-to-825.patch
new file mode 100644
index 00000000000000..1c8f17df539bfc
--- /dev/null
+++ b/patches.kzm9g/0012-serial-move-struct-uart_8250_port-from-8250.c-to-825.patch
@@ -0,0 +1,98 @@
+From 028e3de52cdfd054b54d0ff7c2b576aaf299a1df Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Sun, 4 Dec 2011 18:42:18 -0500
+Subject: serial: move struct uart_8250_port from 8250.c to 8250.h
+
+Since we want to promote sharing and move away from one single
+uart driver with a bunch of platform specific bugfixes all
+munged into one, relocate some header like material from
+the C file to the header.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 850624c15da4651f4c6b821723419d8777659577)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 26 --------------------------
+ drivers/tty/serial/8250.h | 26 ++++++++++++++++++++++++++
+ 2 files changed, 26 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index f8f2320..4a60d74 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -129,32 +129,6 @@ static unsigned long probe_rsa[PORT_RSA_MAX];
+ static unsigned int probe_rsa_count;
+ #endif /* CONFIG_SERIAL_8250_RSA */
+
+-struct uart_8250_port {
+- struct uart_port port;
+- struct timer_list timer; /* "no irq" timer */
+- struct list_head list; /* ports on this IRQ */
+- unsigned short capabilities; /* port capabilities */
+- unsigned short bugs; /* port bugs */
+- unsigned int tx_loadsz; /* transmit fifo load size */
+- unsigned char acr;
+- unsigned char ier;
+- unsigned char lcr;
+- unsigned char mcr;
+- unsigned char mcr_mask; /* mask of user bits */
+- unsigned char mcr_force; /* mask of forced bits */
+- unsigned char cur_iotype; /* Running I/O type */
+-
+- /*
+- * Some bits in registers are cleared on a read, so they must
+- * be saved whenever the register is read but the bits will not
+- * be immediately processed.
+- */
+-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
+- unsigned char lsr_saved_flags;
+-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+- unsigned char msr_saved_flags;
+-};
+-
+ struct irq_info {
+ struct hlist_node node;
+ int irq;
+diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h
+index 6edf4a6..ae027be 100644
+--- a/drivers/tty/serial/8250.h
++++ b/drivers/tty/serial/8250.h
+@@ -13,6 +13,32 @@
+
+ #include <linux/serial_8250.h>
+
++struct uart_8250_port {
++ struct uart_port port;
++ struct timer_list timer; /* "no irq" timer */
++ struct list_head list; /* ports on this IRQ */
++ unsigned short capabilities; /* port capabilities */
++ unsigned short bugs; /* port bugs */
++ unsigned int tx_loadsz; /* transmit fifo load size */
++ unsigned char acr;
++ unsigned char ier;
++ unsigned char lcr;
++ unsigned char mcr;
++ unsigned char mcr_mask; /* mask of user bits */
++ unsigned char mcr_force; /* mask of forced bits */
++ unsigned char cur_iotype; /* Running I/O type */
++
++ /*
++ * Some bits in registers are cleared on a read, so they must
++ * be saved whenever the register is read but the bits will not
++ * be immediately processed.
++ */
++#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
++ unsigned char lsr_saved_flags;
++#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
++ unsigned char msr_saved_flags;
++};
++
+ struct old_serial_port {
+ unsigned int uart;
+ unsigned int baud_base;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0013-serial-clean-up-parameter-passing-for-8250-Rx-IRQ-ha.patch b/patches.kzm9g/0013-serial-clean-up-parameter-passing-for-8250-Rx-IRQ-ha.patch
new file mode 100644
index 00000000000000..918651f8c8b27b
--- /dev/null
+++ b/patches.kzm9g/0013-serial-clean-up-parameter-passing-for-8250-Rx-IRQ-ha.patch
@@ -0,0 +1,79 @@
+From 955d6b2ede1041858602dacb15c624bf8aa325f8 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Sun, 4 Dec 2011 18:42:19 -0500
+Subject: serial: clean up parameter passing for 8250 Rx IRQ handling
+
+The receive_chars() was taking a pointer to a passed in LSR value
+in status and knocking off bits as it processed them. But since
+receive_chars isn't returning a value, we can instead pass in
+a normal non-pointer value for LSR, and simply return the
+residual (unprocessed) LSR once it is done.
+
+The value in this cleanup, is that it clarifies the API of the
+receive_chars prior to exporting it to other 8250-like drivers
+for shared usage.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 0690f41fddd285c3473e4af2a42d15bce7ff3e68)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index 4a60d74..fbcd8a5 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -1375,11 +1375,16 @@ static void clear_rx_fifo(struct uart_8250_port *up)
+ } while (1);
+ }
+
+-static void
+-receive_chars(struct uart_8250_port *up, unsigned int *status)
++/*
++ * receive_chars: processes according to the passed in LSR
++ * value, and returns the remaining LSR bits not handled
++ * by this Rx routine.
++ */
++static unsigned char
++receive_chars(struct uart_8250_port *up, unsigned char lsr)
+ {
+ struct tty_struct *tty = up->port.state->port.tty;
+- unsigned char ch, lsr = *status;
++ unsigned char ch;
+ int max_count = 256;
+ char flag;
+
+@@ -1455,7 +1460,7 @@ ignore_char:
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+- *status = lsr;
++ return lsr;
+ }
+
+ static void transmit_chars(struct uart_8250_port *up)
+@@ -1524,7 +1529,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
+ */
+ static void serial8250_handle_port(struct uart_8250_port *up)
+ {
+- unsigned int status;
++ unsigned char status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+@@ -1534,7 +1539,7 @@ static void serial8250_handle_port(struct uart_8250_port *up)
+ DEBUG_INTR("status = %x...", status);
+
+ if (status & (UART_LSR_DR | UART_LSR_BI))
+- receive_chars(up, &status);
++ status = receive_chars(up, status);
+ check_modem_status(up);
+ if (status & UART_LSR_THRE)
+ transmit_chars(up);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0014-serial-export-the-key-functions-for-an-8250-IRQ-hand.patch b/patches.kzm9g/0014-serial-export-the-key-functions-for-an-8250-IRQ-hand.patch
new file mode 100644
index 00000000000000..04b2ab12162ff9
--- /dev/null
+++ b/patches.kzm9g/0014-serial-export-the-key-functions-for-an-8250-IRQ-hand.patch
@@ -0,0 +1,161 @@
+From d55f600016446155f3d9a86467566353071c7205 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Sun, 4 Dec 2011 18:42:20 -0500
+Subject: serial: export the key functions for an 8250 IRQ handler
+
+For drivers that need to construct their own IRQ handler, the
+three components are seen in the current handle_port -- i.e.
+Rx, Tx and modem_status.
+
+Make these exported symbols so that "almost" 8250 UARTs can
+construct their own IRQ handler with these shared components,
+while working around their own unique errata issues.
+
+The function names are given a serial8250 prefix, since they
+are now entering the global namespace.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 3986fb2ba67bb30cac18b0cff48c88d69ad37681)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 29 +++++++++++++++--------------
+ include/linux/serial_8250.h | 4 ++++
+ 2 files changed, 19 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index fbcd8a5..d759fcc 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -1300,8 +1300,6 @@ static void serial8250_stop_tx(struct uart_port *port)
+ }
+ }
+
+-static void transmit_chars(struct uart_8250_port *up);
+-
+ static void serial8250_start_tx(struct uart_port *port)
+ {
+ struct uart_8250_port *up =
+@@ -1318,7 +1316,7 @@ static void serial8250_start_tx(struct uart_port *port)
+ if ((up->port.type == PORT_RM9000) ?
+ (lsr & UART_LSR_THRE) :
+ (lsr & UART_LSR_TEMT))
+- transmit_chars(up);
++ serial8250_tx_chars(up);
+ }
+ }
+
+@@ -1376,12 +1374,12 @@ static void clear_rx_fifo(struct uart_8250_port *up)
+ }
+
+ /*
+- * receive_chars: processes according to the passed in LSR
++ * serial8250_rx_chars: processes according to the passed in LSR
+ * value, and returns the remaining LSR bits not handled
+ * by this Rx routine.
+ */
+-static unsigned char
+-receive_chars(struct uart_8250_port *up, unsigned char lsr)
++unsigned char
++serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ {
+ struct tty_struct *tty = up->port.state->port.tty;
+ unsigned char ch;
+@@ -1462,8 +1460,9 @@ ignore_char:
+ spin_lock(&up->port.lock);
+ return lsr;
+ }
++EXPORT_SYMBOL_GPL(serial8250_rx_chars);
+
+-static void transmit_chars(struct uart_8250_port *up)
++void serial8250_tx_chars(struct uart_8250_port *up)
+ {
+ struct circ_buf *xmit = &up->port.state->xmit;
+ int count;
+@@ -1500,8 +1499,9 @@ static void transmit_chars(struct uart_8250_port *up)
+ if (uart_circ_empty(xmit))
+ __stop_tx(up);
+ }
++EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+
+-static unsigned int check_modem_status(struct uart_8250_port *up)
++unsigned int serial8250_modem_status(struct uart_8250_port *up)
+ {
+ unsigned int status = serial_in(up, UART_MSR);
+
+@@ -1523,6 +1523,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
+
+ return status;
+ }
++EXPORT_SYMBOL_GPL(serial8250_modem_status);
+
+ /*
+ * This handles the interrupt from one port.
+@@ -1539,10 +1540,10 @@ static void serial8250_handle_port(struct uart_8250_port *up)
+ DEBUG_INTR("status = %x...", status);
+
+ if (status & (UART_LSR_DR | UART_LSR_BI))
+- status = receive_chars(up, status);
+- check_modem_status(up);
++ status = serial8250_rx_chars(up, status);
++ serial8250_modem_status(up);
+ if (status & UART_LSR_THRE)
+- transmit_chars(up);
++ serial8250_tx_chars(up);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ }
+@@ -1780,7 +1781,7 @@ static void serial8250_backup_timeout(unsigned long data)
+ }
+
+ if (!(iir & UART_IIR_NO_INT))
+- transmit_chars(up);
++ serial8250_tx_chars(up);
+
+ if (is_real_interrupt(up->port.irq))
+ serial_out(up, UART_IER, ier);
+@@ -1814,7 +1815,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
+ unsigned int status;
+ unsigned int ret;
+
+- status = check_modem_status(up);
++ status = serial8250_modem_status(up);
+
+ ret = 0;
+ if (status & UART_MSR_DCD)
+@@ -2861,7 +2862,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ * while processing with interrupts off.
+ */
+ if (up->msr_saved_flags)
+- check_modem_status(up);
++ serial8250_modem_status(up);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index 1f05bbe..b44034e 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -66,6 +66,7 @@ enum {
+ * dependent on the 8250 driver.
+ */
+ struct uart_port;
++struct uart_8250_port;
+
+ int serial8250_register_port(struct uart_port *);
+ void serial8250_unregister_port(int line);
+@@ -82,6 +83,9 @@ extern void serial8250_do_set_termios(struct uart_port *port,
+ extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate);
+ int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
++unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
++void serial8250_tx_chars(struct uart_8250_port *up);
++unsigned int serial8250_modem_status(struct uart_8250_port *up);
+
+ extern void serial8250_set_isa_configurator(void (*v)
+ (int port, struct uart_port *up,
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0015-serial-make-8250-timeout-use-the-specified-IRQ-handl.patch b/patches.kzm9g/0015-serial-make-8250-timeout-use-the-specified-IRQ-handl.patch
new file mode 100644
index 00000000000000..7205efee649dcb
--- /dev/null
+++ b/patches.kzm9g/0015-serial-make-8250-timeout-use-the-specified-IRQ-handl.patch
@@ -0,0 +1,51 @@
+From 6f7a0cbda97ea6ac36b334a2639275f60f830390 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Sun, 4 Dec 2011 18:42:21 -0500
+Subject: serial: make 8250 timeout use the specified IRQ handler
+
+The current 8250 timeout code duplicates the code path in
+serial8250_default_handle_irq and then serial8250_handle_irq
+i.e. reading iir, check for IIR_NO_INT, and then calling
+serial8250_handle_port.
+
+So the immediate thought is to replace the duplicated code
+with a call to serial8250_default_handle_irq.
+
+But this highlights a problem. We let 8250 driver variants
+use their own IRQ handler via specifying their own custom
+->handle_irq, but in the event of a timeout, we ignore their
+handler and implicitly run serial8250_default_handle_irq instead.
+
+So, go through the struct to get ->handle_irq and call that,
+which for most will still be serial8250_default_handle_irq.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit a0431476e95d18bb65349e7bcf98eb10b5ad00b9)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index d759fcc..a5c6c7d 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -1738,11 +1738,8 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
+ static void serial8250_timeout(unsigned long data)
+ {
+ struct uart_8250_port *up = (struct uart_8250_port *)data;
+- unsigned int iir;
+
+- iir = serial_in(up, UART_IIR);
+- if (!(iir & UART_IIR_NO_INT))
+- serial8250_handle_port(up);
++ up->port.handle_irq(&up->port);
+ mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
+ }
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0016-serial-manually-inline-serial8250_handle_port.patch b/patches.kzm9g/0016-serial-manually-inline-serial8250_handle_port.patch
new file mode 100644
index 00000000000000..e14803ceb1e44e
--- /dev/null
+++ b/patches.kzm9g/0016-serial-manually-inline-serial8250_handle_port.patch
@@ -0,0 +1,77 @@
+From f1e4b73758b9bead03589febddcb3dba5132ddf7 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Sun, 4 Dec 2011 18:42:22 -0500
+Subject: serial: manually inline serial8250_handle_port
+
+Currently serial8250_handle_irq is a trivial wrapper around
+serial8250_handle_port, which actually does all the work.
+
+Since there are no other callers of serial8250_handle_port, we
+can just move it inline into serial8250_handle_irq. This also
+makes it more clear what functionality any custom IRQ handlers
+need to provide if not using serial8250_default_handle_irq.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 86b21199fc45e0052e181fefc07c747e9dc903b3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250.c | 23 ++++++++---------------
+ 1 file changed, 8 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
+index a5c6c7d..047221d 100644
+--- a/drivers/tty/serial/8250.c
++++ b/drivers/tty/serial/8250.c
+@@ -1528,10 +1528,15 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
+ /*
+ * This handles the interrupt from one port.
+ */
+-static void serial8250_handle_port(struct uart_8250_port *up)
++int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+ {
+ unsigned char status;
+ unsigned long flags;
++ struct uart_8250_port *up =
++ container_of(port, struct uart_8250_port, port);
++
++ if (iir & UART_IIR_NO_INT)
++ return 0;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+@@ -1546,19 +1551,7 @@ static void serial8250_handle_port(struct uart_8250_port *up)
+ serial8250_tx_chars(up);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+-}
+-
+-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+-{
+- struct uart_8250_port *up =
+- container_of(port, struct uart_8250_port, port);
+-
+- if (!(iir & UART_IIR_NO_INT)) {
+- serial8250_handle_port(up);
+- return 1;
+- }
+-
+- return 0;
++ return 1;
+ }
+ EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+@@ -2825,7 +2818,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+- /* serial8250_handle_port() already took the lock */
++ /* serial8250_handle_irq() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0017-serial-group-all-the-8250-related-code-together.patch b/patches.kzm9g/0017-serial-group-all-the-8250-related-code-together.patch
new file mode 100644
index 00000000000000..d045b50b493364
--- /dev/null
+++ b/patches.kzm9g/0017-serial-group-all-the-8250-related-code-together.patch
@@ -0,0 +1,746 @@
+From 1ab1670cb4d8cba1870f9dc3fd7806262f72a904 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 5 Jan 2012 18:21:43 -0500
+Subject: serial: group all the 8250 related code together
+
+The drivers/tty/serial dir is already getting rather busy.
+Relocate the 8250 related drivers to their own subdir to
+reduce the clutter.
+
+Note that sunsu.c is not included in this move -- it is
+8250-like hardware, but it does not use any of the existing
+infrastructure -- and does not depend on SERIAL_8250.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit 9bef3d4197379a995fa80f81950bbbf8d32e9e8b)
+
+Conflicts:
+
+ drivers/tty/serial/8250/Kconfig
+ drivers/tty/serial/8250/Makefile
+ drivers/tty/serial/8250/8250_dw.c
+ drivers/tty/serial/8250/8250_fsl.c
+ drivers/tty/serial/Kconfig
+ drivers/tty/serial/Makefile
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/{ => 8250}/8250.c | 0
+ drivers/tty/serial/{ => 8250}/8250.h | 0
+ drivers/tty/serial/{ => 8250}/8250_accent.c | 0
+ drivers/tty/serial/{ => 8250}/8250_acorn.c | 0
+ drivers/tty/serial/{ => 8250}/8250_boca.c | 0
+ drivers/tty/serial/{ => 8250}/8250_early.c | 0
+ drivers/tty/serial/{ => 8250}/8250_exar_st16c554.c | 0
+ drivers/tty/serial/{ => 8250}/8250_fourport.c | 0
+ drivers/tty/serial/{ => 8250}/8250_gsc.c | 0
+ drivers/tty/serial/{ => 8250}/8250_hp300.c | 0
+ drivers/tty/serial/{ => 8250}/8250_hub6.c | 0
+ drivers/tty/serial/{ => 8250}/8250_mca.c | 0
+ drivers/tty/serial/{ => 8250}/8250_pci.c | 0
+ drivers/tty/serial/{ => 8250}/8250_pnp.c | 0
+ drivers/tty/serial/8250/Kconfig | 268 ++++++++++++++++++++
+ drivers/tty/serial/8250/Makefile | 18 ++
+ drivers/tty/serial/{ => 8250}/m32r_sio.c | 0
+ drivers/tty/serial/{ => 8250}/m32r_sio.h | 0
+ drivers/tty/serial/{ => 8250}/m32r_sio_reg.h | 0
+ drivers/tty/serial/{ => 8250}/serial_cs.c | 0
+ drivers/tty/serial/Kconfig | 262 +------------------
+ drivers/tty/serial/Makefile | 17 +-
+ 22 files changed, 290 insertions(+), 275 deletions(-)
+ rename drivers/tty/serial/{ => 8250}/8250.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250.h (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_accent.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_acorn.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_boca.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_early.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_exar_st16c554.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_fourport.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_gsc.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_hp300.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_hub6.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_mca.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_pci.c (100%)
+ rename drivers/tty/serial/{ => 8250}/8250_pnp.c (100%)
+ create mode 100644 drivers/tty/serial/8250/Kconfig
+ create mode 100644 drivers/tty/serial/8250/Makefile
+ rename drivers/tty/serial/{ => 8250}/m32r_sio.c (100%)
+ rename drivers/tty/serial/{ => 8250}/m32r_sio.h (100%)
+ rename drivers/tty/serial/{ => 8250}/m32r_sio_reg.h (100%)
+ rename drivers/tty/serial/{ => 8250}/serial_cs.c (100%)
+
+diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250/8250.c
+similarity index 100%
+rename from drivers/tty/serial/8250.c
+rename to drivers/tty/serial/8250/8250.c
+diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250/8250.h
+similarity index 100%
+rename from drivers/tty/serial/8250.h
+rename to drivers/tty/serial/8250/8250.h
+diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c
+similarity index 100%
+rename from drivers/tty/serial/8250_accent.c
+rename to drivers/tty/serial/8250/8250_accent.c
+diff --git a/drivers/tty/serial/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
+similarity index 100%
+rename from drivers/tty/serial/8250_acorn.c
+rename to drivers/tty/serial/8250/8250_acorn.c
+diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c
+similarity index 100%
+rename from drivers/tty/serial/8250_boca.c
+rename to drivers/tty/serial/8250/8250_boca.c
+diff --git a/drivers/tty/serial/8250_early.c b/drivers/tty/serial/8250/8250_early.c
+similarity index 100%
+rename from drivers/tty/serial/8250_early.c
+rename to drivers/tty/serial/8250/8250_early.c
+diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c
+similarity index 100%
+rename from drivers/tty/serial/8250_exar_st16c554.c
+rename to drivers/tty/serial/8250/8250_exar_st16c554.c
+diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c
+similarity index 100%
+rename from drivers/tty/serial/8250_fourport.c
+rename to drivers/tty/serial/8250/8250_fourport.c
+diff --git a/drivers/tty/serial/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
+similarity index 100%
+rename from drivers/tty/serial/8250_gsc.c
+rename to drivers/tty/serial/8250/8250_gsc.c
+diff --git a/drivers/tty/serial/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
+similarity index 100%
+rename from drivers/tty/serial/8250_hp300.c
+rename to drivers/tty/serial/8250/8250_hp300.c
+diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
+similarity index 100%
+rename from drivers/tty/serial/8250_hub6.c
+rename to drivers/tty/serial/8250/8250_hub6.c
+diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250/8250_mca.c
+similarity index 100%
+rename from drivers/tty/serial/8250_mca.c
+rename to drivers/tty/serial/8250/8250_mca.c
+diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+similarity index 100%
+rename from drivers/tty/serial/8250_pci.c
+rename to drivers/tty/serial/8250/8250_pci.c
+diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
+similarity index 100%
+rename from drivers/tty/serial/8250_pnp.c
+rename to drivers/tty/serial/8250/8250_pnp.c
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+new file mode 100644
+index 0000000..b1bb251
+--- /dev/null
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -0,0 +1,268 @@
++#
++# The 8250/16550 serial drivers. You shouldn't be in this list unless
++# you somehow have an implicit or explicit dependency on SERIAL_8250.
++#
++
++config SERIAL_8250
++ tristate "8250/16550 and compatible serial support"
++ select SERIAL_CORE
++ ---help---
++ This selects whether you want to include the driver for the standard
++ serial ports. The standard answer is Y. People who might say N
++ here are those that are setting up dedicated Ethernet WWW/FTP
++ servers, or users that have one of the various bus mice instead of a
++ serial mouse and don't intend to use their machine's standard serial
++ port for anything. (Note that the Cyclades and Stallion multi
++ serial port drivers do not need this driver built in for them to
++ work.)
++
++ To compile this driver as a module, choose M here: the
++ module will be called 8250.
++ [WARNING: Do not compile this driver as a module if you are using
++ non-standard serial ports, since the configuration information will
++ be lost when the driver is unloaded. This limitation may be lifted
++ in the future.]
++
++ BTW1: If you have a mouseman serial mouse which is not recognized by
++ the X window system, try running gpm first.
++
++ BTW2: If you intend to use a software modem (also called Winmodem)
++ under Linux, forget it. These modems are crippled and require
++ proprietary drivers which are only available under Windows.
++
++ Most people will say Y or M here, so that they can use serial mice,
++ modems and similar devices connecting to the standard serial ports.
++
++config SERIAL_8250_CONSOLE
++ bool "Console on 8250/16550 and compatible serial port"
++ depends on SERIAL_8250=y
++ select SERIAL_CORE_CONSOLE
++ ---help---
++ If you say Y here, it will be possible to use a serial port as the
++ system console (the system console is the device which receives all
++ kernel messages and warnings and which allows logins in single user
++ mode). This could be useful if some terminal or printer is connected
++ to that serial port.
++
++ Even if you say Y here, the currently visible virtual console
++ (/dev/tty0) will still be used as the system console by default, but
++ you can alter that using a kernel command line option such as
++ "console=ttyS1". (Try "man bootparam" or see the documentation of
++ your boot loader (grub or lilo or loadlin) about how to pass options
++ to the kernel at boot time.)
++
++ If you don't have a VGA card installed and you say Y here, the
++ kernel will automatically use the first serial line, /dev/ttyS0, as
++ system console.
++
++ You can set that using a kernel command line option such as
++ "console=uart8250,io,0x3f8,9600n8"
++ "console=uart8250,mmio,0xff5e0000,115200n8".
++ and it will switch to normal serial console when the corresponding
++ port is ready.
++ "earlycon=uart8250,io,0x3f8,9600n8"
++ "earlycon=uart8250,mmio,0xff5e0000,115200n8".
++ it will not only setup early console.
++
++ If unsure, say N.
++
++config FIX_EARLYCON_MEM
++ bool
++ depends on X86
++ default y
++
++config SERIAL_8250_GSC
++ tristate
++ depends on SERIAL_8250 && GSC
++ default SERIAL_8250
++
++config SERIAL_8250_PCI
++ tristate "8250/16550 PCI device support" if EXPERT
++ depends on SERIAL_8250 && PCI
++ default SERIAL_8250
++ help
++ This builds standard PCI serial support. You may be able to
++ disable this feature if you only need legacy serial support.
++ Saves about 9K.
++
++config SERIAL_8250_PNP
++ tristate "8250/16550 PNP device support" if EXPERT
++ depends on SERIAL_8250 && PNP
++ default SERIAL_8250
++ help
++ This builds standard PNP serial support. You may be able to
++ disable this feature if you only need legacy serial support.
++
++config SERIAL_8250_HP300
++ tristate
++ depends on SERIAL_8250 && HP300
++ default SERIAL_8250
++
++config SERIAL_8250_CS
++ tristate "8250/16550 PCMCIA device support"
++ depends on PCMCIA && SERIAL_8250
++ ---help---
++ Say Y here to enable support for 16-bit PCMCIA serial devices,
++ including serial port cards, modems, and the modem functions of
++ multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
++ credit-card size devices often used with laptops.)
++
++ To compile this driver as a module, choose M here: the
++ module will be called serial_cs.
++
++ If unsure, say N.
++
++config SERIAL_8250_NR_UARTS
++ int "Maximum number of 8250/16550 serial ports"
++ depends on SERIAL_8250
++ default "4"
++ help
++ Set this to the number of serial ports you want the driver
++ to support. This includes any ports discovered via ACPI or
++ PCI enumeration and any ports that may be added at run-time
++ via hot-plug, or any ISA multi-port serial cards.
++
++config SERIAL_8250_RUNTIME_UARTS
++ int "Number of 8250/16550 serial ports to register at runtime"
++ depends on SERIAL_8250
++ range 0 SERIAL_8250_NR_UARTS
++ default "4"
++ help
++ Set this to the maximum number of serial ports you want
++ the kernel to register at boot time. This can be overridden
++ with the module parameter "nr_uarts", or boot-time parameter
++ 8250.nr_uarts
++
++config SERIAL_8250_EXTENDED
++ bool "Extended 8250/16550 serial driver options"
++ depends on SERIAL_8250
++ help
++ If you wish to use any non-standard features of the standard "dumb"
++ driver, say Y here. This includes HUB6 support, shared serial
++ interrupts, special multiport support, support for more than the
++ four COM 1/2/3/4 boards, etc.
++
++ Note that the answer to this question won't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about serial driver options. If unsure, say N.
++
++config SERIAL_8250_MANY_PORTS
++ bool "Support more than 4 legacy serial ports"
++ depends on SERIAL_8250_EXTENDED && !IA64
++ help
++ Say Y here if you have dumb serial boards other than the four
++ standard COM 1/2/3/4 ports. This may happen if you have an AST
++ FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
++ from <http://www.tldp.org/docs.html#howto>), or other custom
++ serial port hardware which acts similar to standard serial port
++ hardware. If you only use the standard COM 1/2/3/4 ports, you can
++ say N here to save some memory. You can also say Y if you have an
++ "intelligent" multiport card such as Cyclades, Digiboards, etc.
++
++#
++# Multi-port serial cards
++#
++
++config SERIAL_8250_FOURPORT
++ tristate "Support Fourport cards"
++ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
++ help
++ Say Y here if you have an AST FourPort serial board.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_fourport.
++
++config SERIAL_8250_ACCENT
++ tristate "Support Accent cards"
++ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
++ help
++ Say Y here if you have an Accent Async serial board.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_accent.
++
++config SERIAL_8250_BOCA
++ tristate "Support Boca cards"
++ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
++ help
++ Say Y here if you have a Boca serial board. Please read the Boca
++ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_boca.
++
++config SERIAL_8250_EXAR_ST16C554
++ tristate "Support Exar ST16C554/554D Quad UART"
++ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
++ help
++ The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
++ tinkering with your Envoy TU301, or have a machine with this UART,
++ say Y here.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_exar_st16c554.
++
++config SERIAL_8250_HUB6
++ tristate "Support Hub6 cards"
++ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
++ help
++ Say Y here if you have a HUB6 serial board.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_hub6.
++
++#
++# Misc. options/drivers.
++#
++
++config SERIAL_8250_SHARE_IRQ
++ bool "Support for sharing serial interrupts"
++ depends on SERIAL_8250_EXTENDED
++ help
++ Some serial boards have hardware support which allows multiple dumb
++ serial ports on the same board to share a single IRQ. To enable
++ support for this in the serial driver, say Y here.
++
++config SERIAL_8250_DETECT_IRQ
++ bool "Autodetect IRQ on standard ports (unsafe)"
++ depends on SERIAL_8250_EXTENDED
++ help
++ Say Y here if you want the kernel to try to guess which IRQ
++ to use for your serial port.
++
++ This is considered unsafe; it is far better to configure the IRQ in
++ a boot script using the setserial command.
++
++ If unsure, say N.
++
++config SERIAL_8250_RSA
++ bool "Support RSA serial ports"
++ depends on SERIAL_8250_EXTENDED
++ help
++ ::: To be written :::
++
++config SERIAL_8250_MCA
++ tristate "Support 8250-type ports on MCA buses"
++ depends on SERIAL_8250 != n && MCA
++ help
++ Say Y here if you have a MCA serial ports.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_mca.
++
++config SERIAL_8250_ACORN
++ tristate "Acorn expansion card serial port support"
++ depends on ARCH_ACORN && SERIAL_8250
++ help
++ If you have an Atomwide Serial card or Serial Port card for an Acorn
++ system, say Y to this option. The driver can handle 1, 2, or 3 port
++ cards. If unsure, say N.
++
++config SERIAL_8250_RM9K
++ bool "Support for MIPS RM9xxx integrated serial port"
++ depends on SERIAL_8250 != n && SERIAL_RM9000
++ select SERIAL_8250_SHARE_IRQ
++ help
++ Selecting this option will add support for the integrated serial
++ port hardware found on MIPS RM9122 and similar processors.
++ If unsure, say N.
+diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
+new file mode 100644
+index 0000000..c0d0c29
+--- /dev/null
++++ b/drivers/tty/serial/8250/Makefile
+@@ -0,0 +1,18 @@
++#
++# Makefile for the 8250 serial device drivers.
++#
++
++obj-$(CONFIG_SERIAL_8250) += 8250.o
++obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
++obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
++obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
++obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
++obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
++obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
++obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
++obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
++obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
++obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
++obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
++obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
++obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
+diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/8250/m32r_sio.c
+similarity index 100%
+rename from drivers/tty/serial/m32r_sio.c
+rename to drivers/tty/serial/8250/m32r_sio.c
+diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/8250/m32r_sio.h
+similarity index 100%
+rename from drivers/tty/serial/m32r_sio.h
+rename to drivers/tty/serial/8250/m32r_sio.h
+diff --git a/drivers/tty/serial/m32r_sio_reg.h b/drivers/tty/serial/8250/m32r_sio_reg.h
+similarity index 100%
+rename from drivers/tty/serial/m32r_sio_reg.h
+rename to drivers/tty/serial/8250/m32r_sio_reg.h
+diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
+similarity index 100%
+rename from drivers/tty/serial/serial_cs.c
+rename to drivers/tty/serial/8250/serial_cs.c
+diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
+index 9789293..69349bf 100644
+--- a/drivers/tty/serial/Kconfig
++++ b/drivers/tty/serial/Kconfig
+@@ -5,267 +5,7 @@
+ menu "Serial drivers"
+ depends on HAS_IOMEM
+
+-#
+-# The new 8250/16550 serial drivers
+-config SERIAL_8250
+- tristate "8250/16550 and compatible serial support"
+- select SERIAL_CORE
+- ---help---
+- This selects whether you want to include the driver for the standard
+- serial ports. The standard answer is Y. People who might say N
+- here are those that are setting up dedicated Ethernet WWW/FTP
+- servers, or users that have one of the various bus mice instead of a
+- serial mouse and don't intend to use their machine's standard serial
+- port for anything. (Note that the Cyclades and Stallion multi
+- serial port drivers do not need this driver built in for them to
+- work.)
+-
+- To compile this driver as a module, choose M here: the
+- module will be called 8250.
+- [WARNING: Do not compile this driver as a module if you are using
+- non-standard serial ports, since the configuration information will
+- be lost when the driver is unloaded. This limitation may be lifted
+- in the future.]
+-
+- BTW1: If you have a mouseman serial mouse which is not recognized by
+- the X window system, try running gpm first.
+-
+- BTW2: If you intend to use a software modem (also called Winmodem)
+- under Linux, forget it. These modems are crippled and require
+- proprietary drivers which are only available under Windows.
+-
+- Most people will say Y or M here, so that they can use serial mice,
+- modems and similar devices connecting to the standard serial ports.
+-
+-config SERIAL_8250_CONSOLE
+- bool "Console on 8250/16550 and compatible serial port"
+- depends on SERIAL_8250=y
+- select SERIAL_CORE_CONSOLE
+- ---help---
+- If you say Y here, it will be possible to use a serial port as the
+- system console (the system console is the device which receives all
+- kernel messages and warnings and which allows logins in single user
+- mode). This could be useful if some terminal or printer is connected
+- to that serial port.
+-
+- Even if you say Y here, the currently visible virtual console
+- (/dev/tty0) will still be used as the system console by default, but
+- you can alter that using a kernel command line option such as
+- "console=ttyS1". (Try "man bootparam" or see the documentation of
+- your boot loader (grub or lilo or loadlin) about how to pass options
+- to the kernel at boot time.)
+-
+- If you don't have a VGA card installed and you say Y here, the
+- kernel will automatically use the first serial line, /dev/ttyS0, as
+- system console.
+-
+- You can set that using a kernel command line option such as
+- "console=uart8250,io,0x3f8,9600n8"
+- "console=uart8250,mmio,0xff5e0000,115200n8".
+- and it will switch to normal serial console when the corresponding
+- port is ready.
+- "earlycon=uart8250,io,0x3f8,9600n8"
+- "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+- it will not only setup early console.
+-
+- If unsure, say N.
+-
+-config FIX_EARLYCON_MEM
+- bool
+- depends on X86
+- default y
+-
+-config SERIAL_8250_GSC
+- tristate
+- depends on SERIAL_8250 && GSC
+- default SERIAL_8250
+-
+-config SERIAL_8250_PCI
+- tristate "8250/16550 PCI device support" if EXPERT
+- depends on SERIAL_8250 && PCI
+- default SERIAL_8250
+- help
+- This builds standard PCI serial support. You may be able to
+- disable this feature if you only need legacy serial support.
+- Saves about 9K.
+-
+-config SERIAL_8250_PNP
+- tristate "8250/16550 PNP device support" if EXPERT
+- depends on SERIAL_8250 && PNP
+- default SERIAL_8250
+- help
+- This builds standard PNP serial support. You may be able to
+- disable this feature if you only need legacy serial support.
+-
+-config SERIAL_8250_HP300
+- tristate
+- depends on SERIAL_8250 && HP300
+- default SERIAL_8250
+-
+-config SERIAL_8250_CS
+- tristate "8250/16550 PCMCIA device support"
+- depends on PCMCIA && SERIAL_8250
+- ---help---
+- Say Y here to enable support for 16-bit PCMCIA serial devices,
+- including serial port cards, modems, and the modem functions of
+- multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
+- credit-card size devices often used with laptops.)
+-
+- To compile this driver as a module, choose M here: the
+- module will be called serial_cs.
+-
+- If unsure, say N.
+-
+-config SERIAL_8250_NR_UARTS
+- int "Maximum number of 8250/16550 serial ports"
+- depends on SERIAL_8250
+- default "4"
+- help
+- Set this to the number of serial ports you want the driver
+- to support. This includes any ports discovered via ACPI or
+- PCI enumeration and any ports that may be added at run-time
+- via hot-plug, or any ISA multi-port serial cards.
+-
+-config SERIAL_8250_RUNTIME_UARTS
+- int "Number of 8250/16550 serial ports to register at runtime"
+- depends on SERIAL_8250
+- range 0 SERIAL_8250_NR_UARTS
+- default "4"
+- help
+- Set this to the maximum number of serial ports you want
+- the kernel to register at boot time. This can be overridden
+- with the module parameter "nr_uarts", or boot-time parameter
+- 8250.nr_uarts
+-
+-config SERIAL_8250_EXTENDED
+- bool "Extended 8250/16550 serial driver options"
+- depends on SERIAL_8250
+- help
+- If you wish to use any non-standard features of the standard "dumb"
+- driver, say Y here. This includes HUB6 support, shared serial
+- interrupts, special multiport support, support for more than the
+- four COM 1/2/3/4 boards, etc.
+-
+- Note that the answer to this question won't directly affect the
+- kernel: saying N will just cause the configurator to skip all
+- the questions about serial driver options. If unsure, say N.
+-
+-config SERIAL_8250_MANY_PORTS
+- bool "Support more than 4 legacy serial ports"
+- depends on SERIAL_8250_EXTENDED && !IA64
+- help
+- Say Y here if you have dumb serial boards other than the four
+- standard COM 1/2/3/4 ports. This may happen if you have an AST
+- FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
+- from <http://www.tldp.org/docs.html#howto>), or other custom
+- serial port hardware which acts similar to standard serial port
+- hardware. If you only use the standard COM 1/2/3/4 ports, you can
+- say N here to save some memory. You can also say Y if you have an
+- "intelligent" multiport card such as Cyclades, Digiboards, etc.
+-
+-#
+-# Multi-port serial cards
+-#
+-
+-config SERIAL_8250_FOURPORT
+- tristate "Support Fourport cards"
+- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+- help
+- Say Y here if you have an AST FourPort serial board.
+-
+- To compile this driver as a module, choose M here: the module
+- will be called 8250_fourport.
+-
+-config SERIAL_8250_ACCENT
+- tristate "Support Accent cards"
+- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+- help
+- Say Y here if you have an Accent Async serial board.
+-
+- To compile this driver as a module, choose M here: the module
+- will be called 8250_accent.
+-
+-config SERIAL_8250_BOCA
+- tristate "Support Boca cards"
+- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+- help
+- Say Y here if you have a Boca serial board. Please read the Boca
+- mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
+-
+- To compile this driver as a module, choose M here: the module
+- will be called 8250_boca.
+-
+-config SERIAL_8250_EXAR_ST16C554
+- tristate "Support Exar ST16C554/554D Quad UART"
+- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+- help
+- The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
+- tinkering with your Envoy TU301, or have a machine with this UART,
+- say Y here.
+-
+- To compile this driver as a module, choose M here: the module
+- will be called 8250_exar_st16c554.
+-
+-config SERIAL_8250_HUB6
+- tristate "Support Hub6 cards"
+- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+- help
+- Say Y here if you have a HUB6 serial board.
+-
+- To compile this driver as a module, choose M here: the module
+- will be called 8250_hub6.
+-
+-config SERIAL_8250_SHARE_IRQ
+- bool "Support for sharing serial interrupts"
+- depends on SERIAL_8250_EXTENDED
+- help
+- Some serial boards have hardware support which allows multiple dumb
+- serial ports on the same board to share a single IRQ. To enable
+- support for this in the serial driver, say Y here.
+-
+-config SERIAL_8250_DETECT_IRQ
+- bool "Autodetect IRQ on standard ports (unsafe)"
+- depends on SERIAL_8250_EXTENDED
+- help
+- Say Y here if you want the kernel to try to guess which IRQ
+- to use for your serial port.
+-
+- This is considered unsafe; it is far better to configure the IRQ in
+- a boot script using the setserial command.
+-
+- If unsure, say N.
+-
+-config SERIAL_8250_RSA
+- bool "Support RSA serial ports"
+- depends on SERIAL_8250_EXTENDED
+- help
+- ::: To be written :::
+-
+-config SERIAL_8250_MCA
+- tristate "Support 8250-type ports on MCA buses"
+- depends on SERIAL_8250 != n && MCA
+- help
+- Say Y here if you have a MCA serial ports.
+-
+- To compile this driver as a module, choose M here: the module
+- will be called 8250_mca.
+-
+-config SERIAL_8250_ACORN
+- tristate "Acorn expansion card serial port support"
+- depends on ARCH_ACORN && SERIAL_8250
+- help
+- If you have an Atomwide Serial card or Serial Port card for an Acorn
+- system, say Y to this option. The driver can handle 1, 2, or 3 port
+- cards. If unsure, say N.
+-
+-config SERIAL_8250_RM9K
+- bool "Support for MIPS RM9xxx integrated serial port"
+- depends on SERIAL_8250 != n && SERIAL_RM9000
+- select SERIAL_8250_SHARE_IRQ
+- help
+- Selecting this option will add support for the integrated serial
+- port hardware found on MIPS RM9122 and similar processors.
+- If unsure, say N.
++source "drivers/tty/serial/8250/Kconfig"
+
+ comment "Non-8250 serial port support"
+
+diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
+index cb2628f..b74267d 100644
+--- a/drivers/tty/serial/Makefile
++++ b/drivers/tty/serial/Makefile
+@@ -14,20 +14,9 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
+ obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
+ obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
+
+-obj-$(CONFIG_SERIAL_8250) += 8250.o
+-obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
+-obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
+-obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
+-obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
+-obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
+-obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
+-obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
+-obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
+-obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
+-obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+-obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+-obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+-obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
++# Now bring in any enabled 8250/16450/16550 type drivers.
++obj-$(CONFIG_SERIAL_8250) += 8250/
++
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0018-serial-Kill-off-NO_IRQ.patch b/patches.kzm9g/0018-serial-Kill-off-NO_IRQ.patch
new file mode 100644
index 00000000000000..20a2b724db0863
--- /dev/null
+++ b/patches.kzm9g/0018-serial-Kill-off-NO_IRQ.patch
@@ -0,0 +1,361 @@
+From f2a0fc4b05410441cf28a4894bb7f1e1983a77bb Mon Sep 17 00:00:00 2001
+From: Alan Cox <alan@linux.intel.com>
+Date: Thu, 26 Jan 2012 17:44:09 +0000
+Subject: serial: Kill off NO_IRQ
+
+We transform the offenders into a test of irq <= 0 which will be ok while
+the ARM people get their platform sorted. Once that is done (or in a while
+if they don't do it anyway) then we will change them all to !irq checks.
+
+For arch specific drivers that are already using NO_IRQ = 0 we just test
+against zero so we don't need to re-review them later.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+(cherry picked from commit d4e33fac2408d37f7b52e80ca2a89f9fb482914f)
+
+Conflicts:
+
+ drivers/tty/serial/m32r_sio.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/hvc/hvc_beat.c | 2 +-
+ drivers/tty/hvc/hvc_rtas.c | 2 +-
+ drivers/tty/hvc/hvc_udbg.c | 2 +-
+ drivers/tty/hvc/hvc_xen.c | 2 +-
+ drivers/tty/hvc/hvcs.c | 4 ++--
+ drivers/tty/hvc/hvsi.c | 2 +-
+ drivers/tty/serial/21285.c | 4 ++--
+ drivers/tty/serial/8250/8250.c | 21 +++++++--------------
+ drivers/tty/serial/mpc52xx_uart.c | 4 ++--
+ drivers/tty/serial/mux.c | 2 +-
+ drivers/tty/serial/pmac_zilog.c | 2 +-
+ drivers/tty/serial/sunzilog.c | 10 +++++-----
+ drivers/tty/serial/ucc_uart.c | 2 +-
+ drivers/tty/serial/vr41xx_siu.c | 4 ++--
+ 14 files changed, 28 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/tty/hvc/hvc_beat.c b/drivers/tty/hvc/hvc_beat.c
+index 5fe4631..1560d23 100644
+--- a/drivers/tty/hvc/hvc_beat.c
++++ b/drivers/tty/hvc/hvc_beat.c
+@@ -113,7 +113,7 @@ static int __init hvc_beat_init(void)
+ if (!firmware_has_feature(FW_FEATURE_BEAT))
+ return -ENODEV;
+
+- hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16);
++ hp = hvc_alloc(0, 0, &hvc_beat_get_put_ops, 16);
+ if (IS_ERR(hp))
+ return PTR_ERR(hp);
+ hvc_beat_dev = hp;
+diff --git a/drivers/tty/hvc/hvc_rtas.c b/drivers/tty/hvc/hvc_rtas.c
+index 61c4a61..0069bb8 100644
+--- a/drivers/tty/hvc/hvc_rtas.c
++++ b/drivers/tty/hvc/hvc_rtas.c
+@@ -94,7 +94,7 @@ static int __init hvc_rtas_init(void)
+
+ /* Allocate an hvc_struct for the console device we instantiated
+ * earlier. Save off hp so that we can return it on exit */
+- hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16);
++ hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16);
+ if (IS_ERR(hp))
+ return PTR_ERR(hp);
+
+diff --git a/drivers/tty/hvc/hvc_udbg.c b/drivers/tty/hvc/hvc_udbg.c
+index b0957e6..4c9b13e 100644
+--- a/drivers/tty/hvc/hvc_udbg.c
++++ b/drivers/tty/hvc/hvc_udbg.c
+@@ -69,7 +69,7 @@ static int __init hvc_udbg_init(void)
+
+ BUG_ON(hvc_udbg_dev);
+
+- hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16);
++ hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16);
+ if (IS_ERR(hp))
+ return PTR_ERR(hp);
+
+diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
+index 52fdf60..a1b0a75 100644
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -176,7 +176,7 @@ static int __init xen_hvc_init(void)
+ xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
+ }
+ if (xencons_irq < 0)
+- xencons_irq = 0; /* NO_IRQ */
++ xencons_irq = 0;
+ else
+ irq_set_noprobe(xencons_irq);
+
+diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
+index 4c8b665..cb0bf44 100644
+--- a/drivers/tty/hvc/hvcs.c
++++ b/drivers/tty/hvc/hvcs.c
+@@ -1203,7 +1203,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
+ {
+ struct hvcs_struct *hvcsd;
+ unsigned long flags;
+- int irq = NO_IRQ;
++ int irq;
+
+ /*
+ * Is someone trying to close the file associated with this device after
+@@ -1264,7 +1264,7 @@ static void hvcs_hangup(struct tty_struct * tty)
+ struct hvcs_struct *hvcsd = tty->driver_data;
+ unsigned long flags;
+ int temp_open_count;
+- int irq = NO_IRQ;
++ int irq;
+
+ spin_lock_irqsave(&hvcsd->lock, flags);
+ /* Preserve this so that we know how many kref refs to put */
+diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
+index 8a8d637..8e1fbd3 100644
+--- a/drivers/tty/hvc/hvsi.c
++++ b/drivers/tty/hvc/hvsi.c
+@@ -1298,7 +1298,7 @@ static int __init hvsi_console_init(void)
+ hp->state = HVSI_CLOSED;
+ hp->vtermno = *vtermno;
+ hp->virq = irq_create_mapping(NULL, irq[0]);
+- if (hp->virq == NO_IRQ) {
++ if (hp->virq == 0) {
+ printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
+ __func__, irq[0]);
+ continue;
+diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c
+index 1b37626..f899996 100644
+--- a/drivers/tty/serial/21285.c
++++ b/drivers/tty/serial/21285.c
+@@ -331,7 +331,7 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct
+ int ret = 0;
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
+ ret = -EINVAL;
+- if (ser->irq != NO_IRQ)
++ if (ser->irq <= 0)
+ ret = -EINVAL;
+ if (ser->baud_base != port->uartclk / 16)
+ ret = -EINVAL;
+@@ -360,7 +360,7 @@ static struct uart_ops serial21285_ops = {
+ static struct uart_port serial21285_port = {
+ .mapbase = 0x42000160,
+ .iotype = UPIO_MEM,
+- .irq = NO_IRQ,
++ .irq = 0,
+ .fifosize = 16,
+ .ops = &serial21285_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 047221d..e7c1304 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -86,13 +86,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
+ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+
+-/*
+- * We default to IRQ0 for the "no irq" hack. Some
+- * machine types want others as well - they're free
+- * to redefine this in their header file.
+- */
+-#define is_real_interrupt(irq) ((irq) != 0)
+-
+ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ
+ #define CONFIG_SERIAL_DETECT_IRQ 1
+ #endif
+@@ -1748,7 +1741,7 @@ static void serial8250_backup_timeout(unsigned long data)
+ * Must disable interrupts or else we risk racing with the interrupt
+ * based handler.
+ */
+- if (is_real_interrupt(up->port.irq)) {
++ if (up->port.irq) {
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
+ }
+@@ -1773,7 +1766,7 @@ static void serial8250_backup_timeout(unsigned long data)
+ if (!(iir & UART_IIR_NO_INT))
+ serial8250_tx_chars(up);
+
+- if (is_real_interrupt(up->port.irq))
++ if (up->port.irq)
+ serial_out(up, UART_IER, ier);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+@@ -2026,7 +2019,7 @@ static int serial8250_startup(struct uart_port *port)
+ serial_outp(up, UART_LCR, 0);
+ }
+
+- if (is_real_interrupt(up->port.irq)) {
++ if (up->port.irq) {
+ unsigned char iir1;
+ /*
+ * Test for UARTs that do not reassert THRE when the
+@@ -2081,7 +2074,7 @@ static int serial8250_startup(struct uart_port *port)
+ * hardware interrupt, we use a timer-based system. The original
+ * driver used to do this with IRQ0.
+ */
+- if (!is_real_interrupt(up->port.irq)) {
++ if (!up->port.irq) {
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+ } else {
+@@ -2097,13 +2090,13 @@ static int serial8250_startup(struct uart_port *port)
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+- if (!is_real_interrupt(up->port.irq))
++ if (!up->port.irq)
+ up->port.mctrl |= TIOCM_OUT1;
+ } else
+ /*
+ * Most PC uarts need OUT2 raised to enable interrupts.
+ */
+- if (is_real_interrupt(up->port.irq))
++ if (up->port.irq)
+ up->port.mctrl |= TIOCM_OUT2;
+
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+@@ -2221,7 +2214,7 @@ static void serial8250_shutdown(struct uart_port *port)
+
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+- if (is_real_interrupt(up->port.irq))
++ if (up->port.irq)
+ serial_unlink_irq_chain(up);
+ }
+
+diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
+index a0bcd8a..0d0d859 100644
+--- a/drivers/tty/serial/mpc52xx_uart.c
++++ b/drivers/tty/serial/mpc52xx_uart.c
+@@ -506,7 +506,7 @@ static int __init mpc512x_psc_fifoc_init(void)
+
+ psc_fifoc_irq = irq_of_parse_and_map(np, 0);
+ of_node_put(np);
+- if (psc_fifoc_irq == NO_IRQ) {
++ if (psc_fifoc_irq == 0) {
+ pr_err("%s: Can't get FIFOC irq\n", __func__);
+ iounmap(psc_fifoc);
+ return -ENODEV;
+@@ -1353,7 +1353,7 @@ static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
+ }
+
+ psc_ops->get_irq(port, op->dev.of_node);
+- if (port->irq == NO_IRQ) {
++ if (port->irq == 0) {
+ dev_dbg(&op->dev, "Could not get irq\n");
+ return -EINVAL;
+ }
+diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
+index 9711e06..3605c79 100644
+--- a/drivers/tty/serial/mux.c
++++ b/drivers/tty/serial/mux.c
+@@ -497,7 +497,7 @@ static int __init mux_probe(struct parisc_device *dev)
+ port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);
+ port->iotype = UPIO_MEM;
+ port->type = PORT_MUX;
+- port->irq = NO_IRQ;
++ port->irq = 0;
+ port->uartclk = 0;
+ port->fifosize = MUX_FIFO_SIZE;
+ port->ops = &mux_pops;
+diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
+index 5acd24a..22ef6b2 100644
+--- a/drivers/tty/serial/pmac_zilog.c
++++ b/drivers/tty/serial/pmac_zilog.c
+@@ -1565,7 +1565,7 @@ no_dma:
+ * fixed up interrupt info, but we use the device-tree directly
+ * here due to early probing so we need the fixup too.
+ */
+- if (uap->port.irq == NO_IRQ &&
++ if (uap->port.irq == 0 &&
+ np->parent && np->parent->parent &&
+ of_device_is_compatible(np->parent->parent, "gatwick")) {
+ /* IRQs on gatwick are offset by 64 */
+diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
+index 8e916e7..5a47d1b 100644
+--- a/drivers/tty/serial/sunzilog.c
++++ b/drivers/tty/serial/sunzilog.c
+@@ -1397,7 +1397,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
+ #endif
+ }
+
+-static int zilog_irq = -1;
++static int zilog_irq;
+
+ static int __devinit zs_probe(struct platform_device *op)
+ {
+@@ -1425,7 +1425,7 @@ static int __devinit zs_probe(struct platform_device *op)
+
+ rp = sunzilog_chip_regs[inst];
+
+- if (zilog_irq == -1)
++ if (!zilog_irq)
+ zilog_irq = op->archdata.irqs[0];
+
+ up = &sunzilog_port_table[inst * 2];
+@@ -1580,7 +1580,7 @@ static int __init sunzilog_init(void)
+ if (err)
+ goto out_unregister_uart;
+
+- if (zilog_irq != -1) {
++ if (!zilog_irq) {
+ struct uart_sunzilog_port *up = sunzilog_irq_chain;
+ err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
+ "zs", sunzilog_irq_chain);
+@@ -1621,7 +1621,7 @@ static void __exit sunzilog_exit(void)
+ {
+ platform_driver_unregister(&zs_driver);
+
+- if (zilog_irq != -1) {
++ if (!zilog_irq) {
+ struct uart_sunzilog_port *up = sunzilog_irq_chain;
+
+ /* Disable Interrupts */
+@@ -1637,7 +1637,7 @@ static void __exit sunzilog_exit(void)
+ }
+
+ free_irq(zilog_irq, sunzilog_irq_chain);
+- zilog_irq = -1;
++ zilog_irq = 0;
+ }
+
+ if (sunzilog_reg.nr) {
+diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
+index c327218..d5b8e7e 100644
+--- a/drivers/tty/serial/ucc_uart.c
++++ b/drivers/tty/serial/ucc_uart.c
+@@ -1355,7 +1355,7 @@ static int ucc_uart_probe(struct platform_device *ofdev)
+ }
+
+ qe_port->port.irq = irq_of_parse_and_map(np, 0);
+- if (qe_port->port.irq == NO_IRQ) {
++ if (qe_port->port.irq == 0) {
+ dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n",
+ qe_port->ucc_num + 1);
+ ret = -EINVAL;
+diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
+index 3beb6ab..15be73d 100644
+--- a/drivers/tty/serial/vr41xx_siu.c
++++ b/drivers/tty/serial/vr41xx_siu.c
+@@ -61,7 +61,7 @@
+ static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
+ [0 ... SIU_PORTS_MAX-1] = {
+ .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
+- .irq = -1,
++ .irq = 0,
+ },
+ };
+
+@@ -171,7 +171,7 @@ static inline unsigned int siu_check_type(struct uart_port *port)
+ {
+ if (port->line == 0)
+ return PORT_VR41XX_SIU;
+- if (port->line == 1 && port->irq != -1)
++ if (port->line == 1 && port->irq)
+ return PORT_VR41XX_DSIU;
+
+ return PORT_UNKNOWN;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0019-tty-fix-a-build-failure-on-sparc.patch b/patches.kzm9g/0019-tty-fix-a-build-failure-on-sparc.patch
new file mode 100644
index 00000000000000..35a49625e5f4f7
--- /dev/null
+++ b/patches.kzm9g/0019-tty-fix-a-build-failure-on-sparc.patch
@@ -0,0 +1,42 @@
+From 571708bcbfb19bb1d4916d2bbc4c5cc23b4a701a Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Fri, 3 Feb 2012 13:22:10 +0800
+Subject: tty: fix a build failure on sparc
+
+On sparc, there is a build failure:
+
+drivers/tty/serial/8250/8250.c:48:21: error: suncore.h: No such file or directory
+drivers/tty/serial/8250/8250.c:3275: error: implicit declaration of function 'sunserial_register_minors'
+drivers/tty/serial/8250/8250.c:3305: error: implicit declaration of function 'sunserial_unregister_minors'
+
+this is due to commit 9bef3d4197379a995fa80f81950bbbf8d32e9e8b
+(serial: group all the 8250 related code together) moved these files
+into 8250/ subdirectory, but forgot to change the reference
+to drivers/tty/serial/suncore.h.
+
+Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: WANG Cong <xiyou.wangcong@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit e7c9bba7999a8e55efb96d4279c025ca587c5ecd)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index e7c1304..a154ba2 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -45,7 +45,7 @@
+ #include "8250.h"
+
+ #ifdef CONFIG_SPARC
+-#include "suncore.h"
++#include "../suncore.h"
+ #endif
+
+ /*
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0020-tty-sparc-rename-drivers-tty-serial-suncore.h-includ.patch b/patches.kzm9g/0020-tty-sparc-rename-drivers-tty-serial-suncore.h-includ.patch
new file mode 100644
index 00000000000000..073454477bb0df
--- /dev/null
+++ b/patches.kzm9g/0020-tty-sparc-rename-drivers-tty-serial-suncore.h-includ.patch
@@ -0,0 +1,199 @@
+From 7242a5c3b6dae31b7d9fc687ece21d96aa27bead Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 9 Feb 2012 18:48:19 -0500
+Subject: tty: sparc: rename drivers/tty/serial/suncore.h ->
+ include/linux/sunserialcore.h
+
+There are multiple users of this file from different source
+paths now, and rather than have ../ paths in include statements,
+just move the file to the linux header dir.
+
+Suggested-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 6816383a09b5be8d35f14f4c25dedb64498e4959)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ MAINTAINERS | 2 +-
+ drivers/tty/serial/8250/8250.c | 7 +++----
+ drivers/tty/serial/suncore.c | 2 +-
+ drivers/tty/serial/suncore.h | 33 ---------------------------------
+ drivers/tty/serial/sunhv.c | 3 +--
+ drivers/tty/serial/sunsab.c | 2 +-
+ drivers/tty/serial/sunsu.c | 3 +--
+ drivers/tty/serial/sunzilog.c | 2 +-
+ include/linux/sunserialcore.h | 33 +++++++++++++++++++++++++++++++++
+ 9 files changed, 42 insertions(+), 45 deletions(-)
+ rename drivers/tty/serial/suncore.h => include/linux/sunserialcore.h (98%)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -5958,8 +5958,8 @@ L: sparclinux@vger.kernel.org
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
+ S: Maintained
++F: include/linux/sunserialcore.h
+ F: drivers/tty/serial/suncore.c
+-F: drivers/tty/serial/suncore.h
+ F: drivers/tty/serial/sunhv.c
+ F: drivers/tty/serial/sunsab.c
+ F: drivers/tty/serial/sunsab.h
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -38,16 +38,15 @@
+ #include <linux/nmi.h>
+ #include <linux/mutex.h>
+ #include <linux/slab.h>
++#ifdef CONFIG_SPARC
++#include <linux/sunserialcore.h>
++#endif
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+
+ #include "8250.h"
+
+-#ifdef CONFIG_SPARC
+-#include "../suncore.h"
+-#endif
+-
+ /*
+ * Configuration:
+ * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
+--- a/drivers/tty/serial/suncore.c
++++ b/drivers/tty/serial/suncore.c
+@@ -17,11 +17,11 @@
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/serial_core.h>
++#include <linux/sunserialcore.h>
+ #include <linux/init.h>
+
+ #include <asm/prom.h>
+
+-#include "suncore.h"
+
+ static int sunserial_current_minor = 64;
+
+--- a/drivers/tty/serial/suncore.h
++++ /dev/null
+@@ -1,33 +0,0 @@
+-/* suncore.h
+- *
+- * Generic SUN serial/kbd/ms layer. Based entirely
+- * upon drivers/sbus/char/sunserial.h which is:
+- *
+- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+- *
+- * Port to new UART layer is:
+- *
+- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+- */
+-
+-#ifndef _SERIAL_SUN_H
+-#define _SERIAL_SUN_H
+-
+-/* Serial keyboard defines for L1-A processing... */
+-#define SUNKBD_RESET 0xff
+-#define SUNKBD_L1 0x01
+-#define SUNKBD_UP 0x80
+-#define SUNKBD_A 0x4d
+-
+-extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
+-extern int suncore_mouse_baud_detection(unsigned char, int);
+-
+-extern int sunserial_register_minors(struct uart_driver *, int);
+-extern void sunserial_unregister_minors(struct uart_driver *, int);
+-
+-extern int sunserial_console_match(struct console *, struct device_node *,
+- struct uart_driver *, int, bool);
+-extern void sunserial_console_termios(struct console *,
+- struct device_node *);
+-
+-#endif /* !(_SERIAL_SUN_H) */
+--- a/drivers/tty/serial/sunhv.c
++++ b/drivers/tty/serial/sunhv.c
+@@ -29,8 +29,7 @@
+ #endif
+
+ #include <linux/serial_core.h>
+-
+-#include "suncore.h"
++#include <linux/sunserialcore.h>
+
+ #define CON_BREAK ((long)-1)
+ #define CON_HUP ((long)-2)
+--- a/drivers/tty/serial/sunsab.c
++++ b/drivers/tty/serial/sunsab.c
+@@ -43,8 +43,8 @@
+ #endif
+
+ #include <linux/serial_core.h>
++#include <linux/sunserialcore.h>
+
+-#include "suncore.h"
+ #include "sunsab.h"
+
+ struct uart_sunsab_port {
+--- a/drivers/tty/serial/sunsu.c
++++ b/drivers/tty/serial/sunsu.c
+@@ -47,8 +47,7 @@
+ #endif
+
+ #include <linux/serial_core.h>
+-
+-#include "suncore.h"
++#include <linux/sunserialcore.h>
+
+ /* We are on a NS PC87303 clocked with 24.0 MHz, which results
+ * in a UART clock of 1.8462 MHz.
+--- a/drivers/tty/serial/sunzilog.c
++++ b/drivers/tty/serial/sunzilog.c
+@@ -43,8 +43,8 @@
+ #endif
+
+ #include <linux/serial_core.h>
++#include <linux/sunserialcore.h>
+
+-#include "suncore.h"
+ #include "sunzilog.h"
+
+ /* On 32-bit sparcs we need to delay after register accesses
+--- /dev/null
++++ b/include/linux/sunserialcore.h
+@@ -0,0 +1,33 @@
++/* sunserialcore.h
++ *
++ * Generic SUN serial/kbd/ms layer. Based entirely
++ * upon drivers/sbus/char/sunserial.h which is:
++ *
++ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
++ *
++ * Port to new UART layer is:
++ *
++ * Copyright (C) 2002 David S. Miller (davem@redhat.com)
++ */
++
++#ifndef _SERIAL_SUN_H
++#define _SERIAL_SUN_H
++
++/* Serial keyboard defines for L1-A processing... */
++#define SUNKBD_RESET 0xff
++#define SUNKBD_L1 0x01
++#define SUNKBD_UP 0x80
++#define SUNKBD_A 0x4d
++
++extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
++extern int suncore_mouse_baud_detection(unsigned char, int);
++
++extern int sunserial_register_minors(struct uart_driver *, int);
++extern void sunserial_unregister_minors(struct uart_driver *, int);
++
++extern int sunserial_console_match(struct console *, struct device_node *,
++ struct uart_driver *, int, bool);
++extern void sunserial_console_termios(struct console *,
++ struct device_node *);
++
++#endif /* !(_SERIAL_SUN_H) */
diff --git a/patches.kzm9g/0021-serial-delete-last-unused-traces-of-pausing-I-O-in-8.patch b/patches.kzm9g/0021-serial-delete-last-unused-traces-of-pausing-I-O-in-8.patch
new file mode 100644
index 00000000000000..5356b24616bf68
--- /dev/null
+++ b/patches.kzm9g/0021-serial-delete-last-unused-traces-of-pausing-I-O-in-8.patch
@@ -0,0 +1,732 @@
+From 6312e447e5cfbc4a17af35d1c1bb0b12df671ad2 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:08 -0500
+Subject: serial: delete last unused traces of pausing I/O in 8250
+
+This is the last traces of pausing I/O that we had back some
+twenty years ago. Probably was only required for 8MHz ISA
+cards running "on the edge" at 12MHz. Anyway it hasn't been
+in use for years, so lets just bury it for good.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 0acf519f3f22450ae8f90cdb0f77b046fc731624)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 308 +++++++++++++++++++---------------------
+ 1 file changed, 150 insertions(+), 158 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 9e2e282..fe75134 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -486,26 +486,18 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value)
+ (up->port.serial_in(&(up)->port, (offset)))
+ #define serial_out(up, offset, value) \
+ (up->port.serial_out(&(up)->port, (offset), (value)))
+-/*
+- * We used to support using pause I/O for certain machines. We
+- * haven't supported this for a while, but just in case it's badly
+- * needed for certain old 386 machines, I've left these #define's
+- * in....
+- */
+-#define serial_inp(up, offset) serial_in(up, offset)
+-#define serial_outp(up, offset, value) serial_out(up, offset, value)
+
+ /* Uart divisor latch read */
+ static inline int _serial_dl_read(struct uart_8250_port *up)
+ {
+- return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
++ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+ }
+
+ /* Uart divisor latch write */
+ static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+ {
+- serial_outp(up, UART_DLL, value & 0xff);
+- serial_outp(up, UART_DLM, value >> 8 & 0xff);
++ serial_out(up, UART_DLL, value & 0xff);
++ serial_out(up, UART_DLM, value >> 8 & 0xff);
+ }
+
+ #if defined(CONFIG_MIPS_ALCHEMY)
+@@ -575,10 +567,10 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+ static void serial8250_clear_fifos(struct uart_8250_port *p)
+ {
+ if (p->capabilities & UART_CAP_FIFO) {
+- serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+- serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
++ serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+- serial_outp(p, UART_FCR, 0);
++ serial_out(p, UART_FCR, 0);
+ }
+ }
+
+@@ -591,15 +583,15 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+ {
+ if (p->capabilities & UART_CAP_SLEEP) {
+ if (p->capabilities & UART_CAP_EFR) {
+- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_outp(p, UART_EFR, UART_EFR_ECB);
+- serial_outp(p, UART_LCR, 0);
++ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(p, UART_EFR, UART_EFR_ECB);
++ serial_out(p, UART_LCR, 0);
+ }
+- serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
++ serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+ if (p->capabilities & UART_CAP_EFR) {
+- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_outp(p, UART_EFR, 0);
+- serial_outp(p, UART_LCR, 0);
++ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(p, UART_EFR, 0);
++ serial_out(p, UART_LCR, 0);
+ }
+ }
+ }
+@@ -614,12 +606,12 @@ static int __enable_rsa(struct uart_8250_port *up)
+ unsigned char mode;
+ int result;
+
+- mode = serial_inp(up, UART_RSA_MSR);
++ mode = serial_in(up, UART_RSA_MSR);
+ result = mode & UART_RSA_MSR_FIFO;
+
+ if (!result) {
+- serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
+- mode = serial_inp(up, UART_RSA_MSR);
++ serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
++ mode = serial_in(up, UART_RSA_MSR);
+ result = mode & UART_RSA_MSR_FIFO;
+ }
+
+@@ -638,7 +630,7 @@ static void enable_rsa(struct uart_8250_port *up)
+ spin_unlock_irq(&up->port.lock);
+ }
+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+- serial_outp(up, UART_RSA_FRR, 0);
++ serial_out(up, UART_RSA_FRR, 0);
+ }
+ }
+
+@@ -657,12 +649,12 @@ static void disable_rsa(struct uart_8250_port *up)
+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+ spin_lock_irq(&up->port.lock);
+
+- mode = serial_inp(up, UART_RSA_MSR);
++ mode = serial_in(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+
+ if (!result) {
+- serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
+- mode = serial_inp(up, UART_RSA_MSR);
++ serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
++ mode = serial_in(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+ }
+
+@@ -683,28 +675,28 @@ static int size_fifo(struct uart_8250_port *up)
+ unsigned short old_dl;
+ int count;
+
+- old_lcr = serial_inp(up, UART_LCR);
+- serial_outp(up, UART_LCR, 0);
+- old_fcr = serial_inp(up, UART_FCR);
+- old_mcr = serial_inp(up, UART_MCR);
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
++ old_lcr = serial_in(up, UART_LCR);
++ serial_out(up, UART_LCR, 0);
++ old_fcr = serial_in(up, UART_FCR);
++ old_mcr = serial_in(up, UART_MCR);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+- serial_outp(up, UART_MCR, UART_MCR_LOOP);
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
++ serial_out(up, UART_MCR, UART_MCR_LOOP);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ old_dl = serial_dl_read(up);
+ serial_dl_write(up, 0x0001);
+- serial_outp(up, UART_LCR, 0x03);
++ serial_out(up, UART_LCR, 0x03);
+ for (count = 0; count < 256; count++)
+- serial_outp(up, UART_TX, count);
++ serial_out(up, UART_TX, count);
+ mdelay(20);/* FIXME - schedule_timeout */
+- for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
++ for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
+ (count < 256); count++)
+- serial_inp(up, UART_RX);
+- serial_outp(up, UART_FCR, old_fcr);
+- serial_outp(up, UART_MCR, old_mcr);
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
++ serial_in(up, UART_RX);
++ serial_out(up, UART_FCR, old_fcr);
++ serial_out(up, UART_MCR, old_mcr);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_dl_write(up, old_dl);
+- serial_outp(up, UART_LCR, old_lcr);
++ serial_out(up, UART_LCR, old_lcr);
+
+ return count;
+ }
+@@ -719,20 +711,20 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+ unsigned char old_dll, old_dlm, old_lcr;
+ unsigned int id;
+
+- old_lcr = serial_inp(p, UART_LCR);
+- serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
++ old_lcr = serial_in(p, UART_LCR);
++ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
+
+- old_dll = serial_inp(p, UART_DLL);
+- old_dlm = serial_inp(p, UART_DLM);
++ old_dll = serial_in(p, UART_DLL);
++ old_dlm = serial_in(p, UART_DLM);
+
+- serial_outp(p, UART_DLL, 0);
+- serial_outp(p, UART_DLM, 0);
++ serial_out(p, UART_DLL, 0);
++ serial_out(p, UART_DLM, 0);
+
+- id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
++ id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
+
+- serial_outp(p, UART_DLL, old_dll);
+- serial_outp(p, UART_DLM, old_dlm);
+- serial_outp(p, UART_LCR, old_lcr);
++ serial_out(p, UART_DLL, old_dll);
++ serial_out(p, UART_DLM, old_dlm);
++ serial_out(p, UART_LCR, old_lcr);
+
+ return id;
+ }
+@@ -842,11 +834,11 @@ static void autoconfig_8250(struct uart_8250_port *up)
+ up->port.type = PORT_8250;
+
+ scratch = serial_in(up, UART_SCR);
+- serial_outp(up, UART_SCR, 0xa5);
++ serial_out(up, UART_SCR, 0xa5);
+ status1 = serial_in(up, UART_SCR);
+- serial_outp(up, UART_SCR, 0x5a);
++ serial_out(up, UART_SCR, 0x5a);
+ status2 = serial_in(up, UART_SCR);
+- serial_outp(up, UART_SCR, scratch);
++ serial_out(up, UART_SCR, scratch);
+
+ if (status1 == 0xa5 && status2 == 0x5a)
+ up->port.type = PORT_16450;
+@@ -877,7 +869,7 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+ } else {
+ status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+ status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
+- serial_outp(up, 0x04, status);
++ serial_out(up, 0x04, status);
+ }
+ return 1;
+ }
+@@ -900,9 +892,9 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ * Check for presence of the EFR when DLAB is set.
+ * Only ST16C650V1 UARTs pass this test.
+ */
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ if (serial_in(up, UART_EFR) == 0) {
+- serial_outp(up, UART_EFR, 0xA8);
++ serial_out(up, UART_EFR, 0xA8);
+ if (serial_in(up, UART_EFR) != 0) {
+ DEBUG_AUTOCONF("EFRv1 ");
+ up->port.type = PORT_16650;
+@@ -910,7 +902,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ } else {
+ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+ }
+- serial_outp(up, UART_EFR, 0);
++ serial_out(up, UART_EFR, 0);
+ return;
+ }
+
+@@ -918,7 +910,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ * Maybe it requires 0xbf to be written to the LCR.
+ * (other ST16C650V2 UARTs, TI16C752A, etc)
+ */
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
+ DEBUG_AUTOCONF("EFRv2 ");
+ autoconfig_has_efr(up);
+@@ -932,23 +924,23 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ * switch back to bank 2, read it from EXCR1 again and check
+ * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
+ */
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, 0);
+ status1 = serial_in(up, UART_MCR);
+- serial_outp(up, UART_LCR, 0xE0);
++ serial_out(up, UART_LCR, 0xE0);
+ status2 = serial_in(up, 0x02); /* EXCR1 */
+
+ if (!((status2 ^ status1) & UART_MCR_LOOP)) {
+- serial_outp(up, UART_LCR, 0);
+- serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
+- serial_outp(up, UART_LCR, 0xE0);
++ serial_out(up, UART_LCR, 0);
++ serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
++ serial_out(up, UART_LCR, 0xE0);
+ status2 = serial_in(up, 0x02); /* EXCR1 */
+- serial_outp(up, UART_LCR, 0);
+- serial_outp(up, UART_MCR, status1);
++ serial_out(up, UART_LCR, 0);
++ serial_out(up, UART_MCR, status1);
+
+ if ((status2 ^ status1) & UART_MCR_LOOP) {
+ unsigned short quot;
+
+- serial_outp(up, UART_LCR, 0xE0);
++ serial_out(up, UART_LCR, 0xE0);
+
+ quot = serial_dl_read(up);
+ quot <<= 3;
+@@ -956,7 +948,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ if (ns16550a_goto_highspeed(up))
+ serial_dl_write(up, quot);
+
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, 0);
+
+ up->port.uartclk = 921600*16;
+ up->port.type = PORT_NS16550A;
+@@ -971,15 +963,15 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ * Try setting it with and without DLAB set. Cheap clones
+ * set bit 5 without DLAB set.
+ */
+- serial_outp(up, UART_LCR, 0);
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
++ serial_out(up, UART_LCR, 0);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+ status1 = serial_in(up, UART_IIR) >> 5;
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+ status2 = serial_in(up, UART_IIR) >> 5;
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_out(up, UART_LCR, 0);
+
+ DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
+
+@@ -998,13 +990,13 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ * already a 1 and maybe locked there before we even start start.
+ */
+ iersave = serial_in(up, UART_IER);
+- serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
++ serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
+ if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+ /*
+ * OK it's in a known zero state, try writing and reading
+ * without disturbing the current state of the other bits.
+ */
+- serial_outp(up, UART_IER, iersave | UART_IER_UUE);
++ serial_out(up, UART_IER, iersave | UART_IER_UUE);
+ if (serial_in(up, UART_IER) & UART_IER_UUE) {
+ /*
+ * It's an Xscale.
+@@ -1022,7 +1014,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ */
+ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+ }
+- serial_outp(up, UART_IER, iersave);
++ serial_out(up, UART_IER, iersave);
+
+ /*
+ * Exar uarts have EFR in a weird location
+@@ -1084,8 +1076,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ * Note: this is safe as long as MCR bit 4 is clear
+ * and the device is in "PC" mode.
+ */
+- scratch = serial_inp(up, UART_IER);
+- serial_outp(up, UART_IER, 0);
++ scratch = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, 0);
+ #ifdef __i386__
+ outb(0xff, 0x080);
+ #endif
+@@ -1093,13 +1085,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+ * 16C754B) allow only to modify them if an EFR bit is set.
+ */
+- scratch2 = serial_inp(up, UART_IER) & 0x0f;
+- serial_outp(up, UART_IER, 0x0F);
++ scratch2 = serial_in(up, UART_IER) & 0x0f;
++ serial_out(up, UART_IER, 0x0F);
+ #ifdef __i386__
+ outb(0, 0x080);
+ #endif
+- scratch3 = serial_inp(up, UART_IER) & 0x0f;
+- serial_outp(up, UART_IER, scratch);
++ scratch3 = serial_in(up, UART_IER) & 0x0f;
++ serial_out(up, UART_IER, scratch);
+ if (scratch2 != 0 || scratch3 != 0x0F) {
+ /*
+ * We failed; there's nothing here
+@@ -1123,9 +1115,9 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ * that conflicts with COM 1-4 --- we hope!
+ */
+ if (!(up->port.flags & UPF_SKIP_TEST)) {
+- serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
+- status1 = serial_inp(up, UART_MSR) & 0xF0;
+- serial_outp(up, UART_MCR, save_mcr);
++ serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
++ status1 = serial_in(up, UART_MSR) & 0xF0;
++ serial_out(up, UART_MCR, save_mcr);
+ if (status1 != 0x90) {
+ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+ status1);
+@@ -1142,11 +1134,11 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ * We also initialise the EFR (if any) to zero for later. The
+ * EFR occupies the same register location as the FCR and IIR.
+ */
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_outp(up, UART_EFR, 0);
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(up, UART_EFR, 0);
++ serial_out(up, UART_LCR, 0);
+
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ scratch = serial_in(up, UART_IIR) >> 6;
+
+ DEBUG_AUTOCONF("iir=%d ", scratch);
+@@ -1183,7 +1175,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ }
+ #endif
+
+- serial_outp(up, UART_LCR, save_lcr);
++ serial_out(up, UART_LCR, save_lcr);
+
+ if (up->capabilities != uart_config[up->port.type].flags) {
+ printk(KERN_WARNING
+@@ -1204,15 +1196,15 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ */
+ #ifdef CONFIG_SERIAL_8250_RSA
+ if (up->port.type == PORT_RSA)
+- serial_outp(up, UART_RSA_FRR, 0);
++ serial_out(up, UART_RSA_FRR, 0);
+ #endif
+- serial_outp(up, UART_MCR, save_mcr);
++ serial_out(up, UART_MCR, save_mcr);
+ serial8250_clear_fifos(up);
+ serial_in(up, UART_RX);
+ if (up->capabilities & UART_CAP_UUE)
+- serial_outp(up, UART_IER, UART_IER_UUE);
++ serial_out(up, UART_IER, UART_IER_UUE);
+ else
+- serial_outp(up, UART_IER, 0);
++ serial_out(up, UART_IER, 0);
+
+ out:
+ spin_unlock_irqrestore(&up->port.lock, flags);
+@@ -1236,31 +1228,31 @@ static void autoconfig_irq(struct uart_8250_port *up)
+
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+- save_mcr = serial_inp(up, UART_MCR);
+- save_ier = serial_inp(up, UART_IER);
+- serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
++ save_mcr = serial_in(up, UART_MCR);
++ save_ier = serial_in(up, UART_IER);
++ serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+ irqs = probe_irq_on();
+- serial_outp(up, UART_MCR, 0);
++ serial_out(up, UART_MCR, 0);
+ udelay(10);
+ if (up->port.flags & UPF_FOURPORT) {
+- serial_outp(up, UART_MCR,
++ serial_out(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS);
+ } else {
+- serial_outp(up, UART_MCR,
++ serial_out(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+ }
+- serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
+- (void)serial_inp(up, UART_LSR);
+- (void)serial_inp(up, UART_RX);
+- (void)serial_inp(up, UART_IIR);
+- (void)serial_inp(up, UART_MSR);
+- serial_outp(up, UART_TX, 0xFF);
++ serial_out(up, UART_IER, 0x0f); /* enable all intrs */
++ (void)serial_in(up, UART_LSR);
++ (void)serial_in(up, UART_RX);
++ (void)serial_in(up, UART_IIR);
++ (void)serial_in(up, UART_MSR);
++ serial_out(up, UART_TX, 0xFF);
+ udelay(20);
+ irq = probe_irq_off(irqs);
+
+- serial_outp(up, UART_MCR, save_mcr);
+- serial_outp(up, UART_IER, save_ier);
++ serial_out(up, UART_MCR, save_mcr);
++ serial_out(up, UART_IER, save_ier);
+
+ if (up->port.flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+@@ -1380,7 +1372,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+
+ do {
+ if (likely(lsr & UART_LSR_DR))
+- ch = serial_inp(up, UART_RX);
++ ch = serial_in(up, UART_RX);
+ else
+ /*
+ * Intel 82571 has a Serial Over Lan device that will
+@@ -1445,7 +1437,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+
+ ignore_char:
+- lsr = serial_inp(up, UART_LSR);
++ lsr = serial_in(up, UART_LSR);
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(tty);
+@@ -1460,7 +1452,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
+ int count;
+
+ if (up->port.x_char) {
+- serial_outp(up, UART_TX, up->port.x_char);
++ serial_out(up, UART_TX, up->port.x_char);
+ up->port.icount.tx++;
+ up->port.x_char = 0;
+ return;
+@@ -1532,7 +1524,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+- status = serial_inp(up, UART_LSR);
++ status = serial_in(up, UART_LSR);
+
+ DEBUG_INTR("status = %x...", status);
+
+@@ -1892,12 +1884,12 @@ static int serial8250_get_poll_char(struct uart_port *port)
+ {
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+- unsigned char lsr = serial_inp(up, UART_LSR);
++ unsigned char lsr = serial_in(up, UART_LSR);
+
+ if (!(lsr & UART_LSR_DR))
+ return NO_POLL_CHAR;
+
+- return serial_inp(up, UART_RX);
++ return serial_in(up, UART_RX);
+ }
+
+
+@@ -1957,14 +1949,14 @@ static int serial8250_startup(struct uart_port *port)
+ if (up->port.type == PORT_16C950) {
+ /* Wake up and initialize UART */
+ up->acr = 0;
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_outp(up, UART_EFR, UART_EFR_ECB);
+- serial_outp(up, UART_IER, 0);
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(up, UART_EFR, UART_EFR_ECB);
++ serial_out(up, UART_IER, 0);
++ serial_out(up, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_outp(up, UART_EFR, UART_EFR_ECB);
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(up, UART_EFR, UART_EFR_ECB);
++ serial_out(up, UART_LCR, 0);
+ }
+
+ #ifdef CONFIG_SERIAL_8250_RSA
+@@ -1984,10 +1976,10 @@ static int serial8250_startup(struct uart_port *port)
+ /*
+ * Clear the interrupt registers.
+ */
+- (void) serial_inp(up, UART_LSR);
+- (void) serial_inp(up, UART_RX);
+- (void) serial_inp(up, UART_IIR);
+- (void) serial_inp(up, UART_MSR);
++ (void) serial_in(up, UART_LSR);
++ (void) serial_in(up, UART_RX);
++ (void) serial_in(up, UART_IIR);
++ (void) serial_in(up, UART_MSR);
+
+ /*
+ * At this point, there's no way the LSR could still be 0xff;
+@@ -1995,7 +1987,7 @@ static int serial8250_startup(struct uart_port *port)
+ * here.
+ */
+ if (!(up->port.flags & UPF_BUGGY_UART) &&
+- (serial_inp(up, UART_LSR) == 0xff)) {
++ (serial_in(up, UART_LSR) == 0xff)) {
+ printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+ serial_index(&up->port));
+ return -ENODEV;
+@@ -2007,15 +1999,15 @@ static int serial8250_startup(struct uart_port *port)
+ if (up->port.type == PORT_16850) {
+ unsigned char fctr;
+
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+- fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+- serial_outp(up, UART_TRG, UART_TRG_96);
+- serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+- serial_outp(up, UART_TRG, UART_TRG_96);
++ fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
++ serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
++ serial_out(up, UART_TRG, UART_TRG_96);
++ serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
++ serial_out(up, UART_TRG, UART_TRG_96);
+
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, 0);
+ }
+
+ if (up->port.irq) {
+@@ -2085,7 +2077,7 @@ static int serial8250_startup(struct uart_port *port)
+ /*
+ * Now, initialize the UART
+ */
+- serial_outp(up, UART_LCR, UART_LCR_WLEN8);
++ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+@@ -2118,10 +2110,10 @@ static int serial8250_startup(struct uart_port *port)
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+ */
+- serial_outp(up, UART_IER, UART_IER_THRI);
++ serial_out(up, UART_IER, UART_IER_THRI);
+ lsr = serial_in(up, UART_LSR);
+ iir = serial_in(up, UART_IIR);
+- serial_outp(up, UART_IER, 0);
++ serial_out(up, UART_IER, 0);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+@@ -2141,10 +2133,10 @@ dont_test_tx_en:
+ * saved flags to avoid getting false values from polling
+ * routines or the previous session.
+ */
+- serial_inp(up, UART_LSR);
+- serial_inp(up, UART_RX);
+- serial_inp(up, UART_IIR);
+- serial_inp(up, UART_MSR);
++ serial_in(up, UART_LSR);
++ serial_in(up, UART_RX);
++ serial_in(up, UART_IIR);
++ serial_in(up, UART_MSR);
+ up->lsr_saved_flags = 0;
+ up->msr_saved_flags = 0;
+
+@@ -2154,7 +2146,7 @@ dont_test_tx_en:
+ * anyway, so we don't enable them here.
+ */
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+- serial_outp(up, UART_IER, up->ier);
++ serial_out(up, UART_IER, up->ier);
+
+ if (up->port.flags & UPF_FOURPORT) {
+ unsigned int icp;
+@@ -2179,7 +2171,7 @@ static void serial8250_shutdown(struct uart_port *port)
+ * Disable interrupts from this port
+ */
+ up->ier = 0;
+- serial_outp(up, UART_IER, 0);
++ serial_out(up, UART_IER, 0);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+@@ -2195,7 +2187,7 @@ static void serial8250_shutdown(struct uart_port *port)
+ /*
+ * Disable break condition and FIFOs
+ */
+- serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
++ serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+ serial8250_clear_fifos(up);
+
+ #ifdef CONFIG_SERIAL_8250_RSA
+@@ -2372,11 +2364,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ if (termios->c_cflag & CRTSCTS)
+ efr |= UART_EFR_CTS;
+
+- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (up->port.flags & UPF_EXAR_EFR)
+- serial_outp(up, UART_XR_EFR, efr);
++ serial_out(up, UART_XR_EFR, efr);
+ else
+- serial_outp(up, UART_EFR, efr);
++ serial_out(up, UART_EFR, efr);
+ }
+
+ #ifdef CONFIG_ARCH_OMAP
+@@ -2392,9 +2384,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+
+ if (up->capabilities & UART_NATSEMI) {
+ /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
+- serial_outp(up, UART_LCR, 0xe0);
++ serial_out(up, UART_LCR, 0xe0);
+ } else {
+- serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
++ serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+ }
+
+ serial_dl_write(up, quot);
+@@ -2404,16 +2396,16 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ * is written without DLAB set, this mode will be disabled.
+ */
+ if (up->port.type == PORT_16750)
+- serial_outp(up, UART_FCR, fcr);
++ serial_out(up, UART_FCR, fcr);
+
+- serial_outp(up, UART_LCR, cval); /* reset DLAB */
++ serial_out(up, UART_LCR, cval); /* reset DLAB */
+ up->lcr = cval; /* Save LCR */
+ if (up->port.type != PORT_16750) {
+ if (fcr & UART_FCR_ENABLE_FIFO) {
+ /* emulated UARTs (Lucent Venus 167x) need two steps */
+- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ }
+- serial_outp(up, UART_FCR, fcr); /* set fcr */
++ serial_out(up, UART_FCR, fcr); /* set fcr */
+ }
+ serial8250_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+@@ -2995,11 +2987,11 @@ void serial8250_resume_port(int line)
+
+ if (up->capabilities & UART_NATSEMI) {
+ /* Ensure it's still in high speed mode */
+- serial_outp(up, UART_LCR, 0xE0);
++ serial_out(up, UART_LCR, 0xE0);
+
+ ns16550a_goto_highspeed(up);
+
+- serial_outp(up, UART_LCR, 0);
++ serial_out(up, UART_LCR, 0);
+ up->port.uartclk = 921600*16;
+ }
+ uart_resume_port(&serial8250_reg, &up->port);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0022-serial-make-8250-s-serial_in-shareable-to-other-driv.patch b/patches.kzm9g/0022-serial-make-8250-s-serial_in-shareable-to-other-driv.patch
new file mode 100644
index 00000000000000..5492bd40e93e39
--- /dev/null
+++ b/patches.kzm9g/0022-serial-make-8250-s-serial_in-shareable-to-other-driv.patch
@@ -0,0 +1,73 @@
+From aa16319bc84ef2b1c48898c340accb81575be000 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:09 -0500
+Subject: serial: make 8250's serial_in shareable to other drivers.
+
+Currently 8250.c has serial_in and serial_out as shortcuts
+to doing the port I/O. They are implemented as macros a
+ways down in the file. This isn't by accident, but is
+implicitly required, so cpp doesn't mangle other instances
+of the common string "serial_in", as it exists as a field
+in the port struct itself.
+
+The above mangling avoidance violates the principle of least
+surprise, and it also prevents the shortcuts from being
+relocated up to the top of file, or into 8250.h -- either
+being a better location than the current one.
+
+Move them to 8250.h so other 8250-like drivers can also use
+the shortcuts, and in the process, make the conflicting
+names go away by using static inlines instead of macros.
+The object file size remains unchanged with this modification.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 3f0ab32753b49ae7afc5b69e3f23152d92aa1f85)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 5 -----
+ drivers/tty/serial/8250/8250.h | 10 ++++++++++
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index fe75134..06e17d5 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -482,11 +482,6 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value)
+ }
+ }
+
+-#define serial_in(up, offset) \
+- (up->port.serial_in(&(up)->port, (offset)))
+-#define serial_out(up, offset, value) \
+- (up->port.serial_out(&(up)->port, (offset), (value)))
+-
+ /* Uart divisor latch read */
+ static inline int _serial_dl_read(struct uart_8250_port *up)
+ {
+diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
+index ae027be..2868a1d 100644
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -86,6 +86,16 @@ struct serial8250_config {
+ #define SERIAL8250_SHARE_IRQS 0
+ #endif
+
++static inline int serial_in(struct uart_8250_port *up, int offset)
++{
++ return up->port.serial_in(&up->port, offset);
++}
++
++static inline void serial_out(struct uart_8250_port *up, int offset, int value)
++{
++ up->port.serial_out(&up->port, offset, value);
++}
++
+ #if defined(__alpha__) && !defined(CONFIG_PCI)
+ /*
+ * Digital did something really horribly wrong with the OUT1 and OUT2
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0023-serial-delete-useless-void-casts-in-8250.c.patch b/patches.kzm9g/0023-serial-delete-useless-void-casts-in-8250.c.patch
new file mode 100644
index 00000000000000..ee3eaff5a34de7
--- /dev/null
+++ b/patches.kzm9g/0023-serial-delete-useless-void-casts-in-8250.c.patch
@@ -0,0 +1,84 @@
+From e5d5cfab51ec956d809d5951e2ec3b7d7fe7819c Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:10 -0500
+Subject: serial: delete useless void casts in 8250.c
+
+These might have worked some magic with an ancient gcc back in
+1992, but "objdump --disassemble" on gcc 4.6 on x86-64 shows
+identical output before and after this commit. Send the casts
+and their hysterical rasins to the bitbucket.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 0d263a264c4b8376ccf33248f6fac873310e5e05)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 06e17d5..5da9f99 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -1218,7 +1218,7 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ ICP = (up->port.iobase & 0xfe0) | 0x1f;
+ save_ICP = inb_p(ICP);
+ outb_p(0x80, ICP);
+- (void) inb_p(ICP);
++ inb_p(ICP);
+ }
+
+ /* forget possible initially masked and pending IRQ */
+@@ -1238,10 +1238,10 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+ }
+ serial_out(up, UART_IER, 0x0f); /* enable all intrs */
+- (void)serial_in(up, UART_LSR);
+- (void)serial_in(up, UART_RX);
+- (void)serial_in(up, UART_IIR);
+- (void)serial_in(up, UART_MSR);
++ serial_in(up, UART_LSR);
++ serial_in(up, UART_RX);
++ serial_in(up, UART_IIR);
++ serial_in(up, UART_MSR);
+ serial_out(up, UART_TX, 0xFF);
+ udelay(20);
+ irq = probe_irq_off(irqs);
+@@ -1971,10 +1971,10 @@ static int serial8250_startup(struct uart_port *port)
+ /*
+ * 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);
++ serial_in(up, UART_LSR);
++ serial_in(up, UART_RX);
++ serial_in(up, UART_IIR);
++ serial_in(up, UART_MSR);
+
+ /*
+ * At this point, there's no way the LSR could still be 0xff;
+@@ -2150,7 +2150,7 @@ dont_test_tx_en:
+ */
+ icp = (up->port.iobase & 0xfe0) | 0x01f;
+ outb_p(0x80, icp);
+- (void) inb_p(icp);
++ inb_p(icp);
+ }
+
+ return 0;
+@@ -2196,7 +2196,7 @@ static void serial8250_shutdown(struct uart_port *port)
+ * Read data port to reset things, and then unlink from
+ * the IRQ chain.
+ */
+- (void) serial_in(up, UART_RX);
++ serial_in(up, UART_RX);
+
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0024-serial-reduce-number-of-indirections-in-8250-code.patch b/patches.kzm9g/0024-serial-reduce-number-of-indirections-in-8250-code.patch
new file mode 100644
index 00000000000000..f729a5591f1fc3
--- /dev/null
+++ b/patches.kzm9g/0024-serial-reduce-number-of-indirections-in-8250-code.patch
@@ -0,0 +1,958 @@
+From 83c841cec4163679900da8fa7845ef51fd8d9486 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:11 -0500
+Subject: serial: reduce number of indirections in 8250 code
+
+The serial_8250_port struct contains within a serial_port struct
+and many times one or the other, or both are in scope within
+functions via a passed in arg, or via container_of.
+
+However there are a lot of cases where we have access directly
+to the port pointer, but yet go through the parent 8250_port
+structure instead to get it. These should just use the port
+struct directly.
+
+Similarly there are cases where it makes sense (from a code
+cleanliness point of view) to declare a local for the port
+struct, so we aren't going through the parent 8250_port struct
+repeatedly to get to it.
+
+We get a small reduction in text size, but it appears that
+gcc was smart enough to internally be doing most of this
+already, so the readability improvement is the larger gain.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit dfe42443ea1d30c98db59b7b1f914bc147d31336)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 322 +++++++++++++++++++++-------------------
+ 1 file changed, 167 insertions(+), 155 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 5da9f99..9ffb3cf 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -1040,24 +1040,25 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ {
+ unsigned char status1, scratch, scratch2, scratch3;
+ unsigned char save_lcr, save_mcr;
++ struct uart_port *port = &up->port;
+ unsigned long flags;
+
+- if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
++ if (!port->iobase && !port->mapbase && !port->membase)
+ return;
+
+ DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
+- serial_index(&up->port), up->port.iobase, up->port.membase);
++ serial_index(port), port->iobase, port->membase);
+
+ /*
+ * We really do need global IRQs disabled here - we're going to
+ * be frobbing the chips IRQ enable register to see if it exists.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&port->lock, flags);
+
+ up->capabilities = 0;
+ up->bugs = 0;
+
+- if (!(up->port.flags & UPF_BUGGY_UART)) {
++ if (!(port->flags & UPF_BUGGY_UART)) {
+ /*
+ * Do a simple existence test first; if we fail this,
+ * there's no point trying anything else.
+@@ -1109,7 +1110,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ * manufacturer would be stupid enough to design a board
+ * that conflicts with COM 1-4 --- we hope!
+ */
+- if (!(up->port.flags & UPF_SKIP_TEST)) {
++ if (!(port->flags & UPF_SKIP_TEST)) {
+ serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
+ status1 = serial_in(up, UART_MSR) & 0xF0;
+ serial_out(up, UART_MCR, save_mcr);
+@@ -1143,10 +1144,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ autoconfig_8250(up);
+ break;
+ case 1:
+- up->port.type = PORT_UNKNOWN;
++ port->type = PORT_UNKNOWN;
+ break;
+ case 2:
+- up->port.type = PORT_16550;
++ port->type = PORT_16550;
+ break;
+ case 3:
+ autoconfig_16550a(up);
+@@ -1157,13 +1158,12 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ /*
+ * Only probe for RSA ports if we got the region.
+ */
+- if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
++ if (port->type == PORT_16550A && probeflags & PROBE_RSA) {
+ int i;
+
+ for (i = 0 ; i < probe_rsa_count; ++i) {
+- if (probe_rsa[i] == up->port.iobase &&
+- __enable_rsa(up)) {
+- up->port.type = PORT_RSA;
++ if (probe_rsa[i] == port->iobase && __enable_rsa(up)) {
++ port->type = PORT_RSA;
+ break;
+ }
+ }
+@@ -1172,25 +1172,25 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+
+ serial_out(up, UART_LCR, save_lcr);
+
+- if (up->capabilities != uart_config[up->port.type].flags) {
++ if (up->capabilities != uart_config[port->type].flags) {
+ printk(KERN_WARNING
+ "ttyS%d: detected caps %08x should be %08x\n",
+- serial_index(&up->port), up->capabilities,
+- uart_config[up->port.type].flags);
++ serial_index(port), up->capabilities,
++ uart_config[port->type].flags);
+ }
+
+- up->port.fifosize = uart_config[up->port.type].fifo_size;
+- up->capabilities = uart_config[up->port.type].flags;
+- up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
++ port->fifosize = uart_config[up->port.type].fifo_size;
++ up->capabilities = uart_config[port->type].flags;
++ up->tx_loadsz = uart_config[port->type].tx_loadsz;
+
+- if (up->port.type == PORT_UNKNOWN)
++ if (port->type == PORT_UNKNOWN)
+ goto out;
+
+ /*
+ * Reset the UART.
+ */
+ #ifdef CONFIG_SERIAL_8250_RSA
+- if (up->port.type == PORT_RSA)
++ if (port->type == PORT_RSA)
+ serial_out(up, UART_RSA_FRR, 0);
+ #endif
+ serial_out(up, UART_MCR, save_mcr);
+@@ -1202,20 +1202,21 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+ serial_out(up, UART_IER, 0);
+
+ out:
+- spin_unlock_irqrestore(&up->port.lock, flags);
+- DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
++ spin_unlock_irqrestore(&port->lock, flags);
++ DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
+ }
+
+ static void autoconfig_irq(struct uart_8250_port *up)
+ {
++ struct uart_port *port = &up->port;
+ unsigned char save_mcr, save_ier;
+ unsigned char save_ICP = 0;
+ unsigned int ICP = 0;
+ unsigned long irqs;
+ int irq;
+
+- if (up->port.flags & UPF_FOURPORT) {
+- ICP = (up->port.iobase & 0xfe0) | 0x1f;
++ if (port->flags & UPF_FOURPORT) {
++ ICP = (port->iobase & 0xfe0) | 0x1f;
+ save_ICP = inb_p(ICP);
+ outb_p(0x80, ICP);
+ inb_p(ICP);
+@@ -1230,7 +1231,7 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ irqs = probe_irq_on();
+ serial_out(up, UART_MCR, 0);
+ udelay(10);
+- if (up->port.flags & UPF_FOURPORT) {
++ if (port->flags & UPF_FOURPORT) {
+ serial_out(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS);
+ } else {
+@@ -1249,10 +1250,10 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ serial_out(up, UART_MCR, save_mcr);
+ serial_out(up, UART_IER, save_ier);
+
+- if (up->port.flags & UPF_FOURPORT)
++ if (port->flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+
+- up->port.irq = (irq > 0) ? irq : 0;
++ port->irq = (irq > 0) ? irq : 0;
+ }
+
+ static inline void __stop_tx(struct uart_8250_port *p)
+@@ -1273,7 +1274,7 @@ static void serial8250_stop_tx(struct uart_port *port)
+ /*
+ * We really want to stop the transmitter from sending.
+ */
+- if (up->port.type == PORT_16C950) {
++ if (port->type == PORT_16C950) {
+ up->acr |= UART_ACR_TXDIS;
+ serial_icr_write(up, UART_ACR, up->acr);
+ }
+@@ -1292,7 +1293,7 @@ static void serial8250_start_tx(struct uart_port *port)
+ unsigned char lsr;
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+- if ((up->port.type == PORT_RM9000) ?
++ if ((port->type == PORT_RM9000) ?
+ (lsr & UART_LSR_THRE) :
+ (lsr & UART_LSR_TEMT))
+ serial8250_tx_chars(up);
+@@ -1302,7 +1303,7 @@ static void serial8250_start_tx(struct uart_port *port)
+ /*
+ * Re-enable the transmitter if we disabled it.
+ */
+- if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
++ if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
+ up->acr &= ~UART_ACR_TXDIS;
+ serial_icr_write(up, UART_ACR, up->acr);
+ }
+@@ -1360,7 +1361,8 @@ static void clear_rx_fifo(struct uart_8250_port *up)
+ unsigned char
+ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ {
+- struct tty_struct *tty = up->port.state->port.tty;
++ struct uart_port *port = &up->port;
++ struct tty_struct *tty = port->state->port.tty;
+ unsigned char ch;
+ int max_count = 256;
+ char flag;
+@@ -1379,7 +1381,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ ch = 0;
+
+ flag = TTY_NORMAL;
+- up->port.icount.rx++;
++ port->icount.rx++;
+
+ lsr |= up->lsr_saved_flags;
+ up->lsr_saved_flags = 0;
+@@ -1390,12 +1392,12 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ */
+ if (lsr & UART_LSR_BI) {
+ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+- up->port.icount.brk++;
++ port->icount.brk++;
+ /*
+ * If tegra port then clear the rx fifo to
+ * accept another break/character.
+ */
+- if (up->port.type == PORT_TEGRA)
++ if (port->type == PORT_TEGRA)
+ clear_rx_fifo(up);
+
+ /*
+@@ -1404,19 +1406,19 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+- if (uart_handle_break(&up->port))
++ if (uart_handle_break(port))
+ goto ignore_char;
+ } else if (lsr & UART_LSR_PE)
+- up->port.icount.parity++;
++ port->icount.parity++;
+ else if (lsr & UART_LSR_FE)
+- up->port.icount.frame++;
++ port->icount.frame++;
+ if (lsr & UART_LSR_OE)
+- up->port.icount.overrun++;
++ port->icount.overrun++;
+
+ /*
+ * Mask off conditions which should be ignored.
+ */
+- lsr &= up->port.read_status_mask;
++ lsr &= port->read_status_mask;
+
+ if (lsr & UART_LSR_BI) {
+ DEBUG_INTR("handling break....");
+@@ -1426,34 +1428,35 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ else if (lsr & UART_LSR_FE)
+ flag = TTY_FRAME;
+ }
+- if (uart_handle_sysrq_char(&up->port, ch))
++ if (uart_handle_sysrq_char(port, ch))
+ goto ignore_char;
+
+- uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
++ uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
+
+ ignore_char:
+ lsr = serial_in(up, UART_LSR);
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+- spin_unlock(&up->port.lock);
++ spin_unlock(&port->lock);
+ tty_flip_buffer_push(tty);
+- spin_lock(&up->port.lock);
++ spin_lock(&port->lock);
+ return lsr;
+ }
+ EXPORT_SYMBOL_GPL(serial8250_rx_chars);
+
+ void serial8250_tx_chars(struct uart_8250_port *up)
+ {
+- struct circ_buf *xmit = &up->port.state->xmit;
++ struct uart_port *port = &up->port;
++ struct circ_buf *xmit = &port->state->xmit;
+ int count;
+
+- if (up->port.x_char) {
+- serial_out(up, UART_TX, up->port.x_char);
+- up->port.icount.tx++;
+- up->port.x_char = 0;
++ if (port->x_char) {
++ serial_out(up, UART_TX, port->x_char);
++ port->icount.tx++;
++ port->x_char = 0;
+ return;
+ }
+- if (uart_tx_stopped(&up->port)) {
+- serial8250_stop_tx(&up->port);
++ if (uart_tx_stopped(port)) {
++ serial8250_stop_tx(port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
+@@ -1465,13 +1468,13 @@ void serial8250_tx_chars(struct uart_8250_port *up)
+ do {
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+- up->port.icount.tx++;
++ 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);
++ uart_write_wakeup(port);
+
+ DEBUG_INTR("THRE...");
+
+@@ -1482,22 +1485,23 @@ EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+
+ unsigned int serial8250_modem_status(struct uart_8250_port *up)
+ {
++ struct uart_port *port = &up->port;
+ unsigned int status = serial_in(up, UART_MSR);
+
+ status |= up->msr_saved_flags;
+ up->msr_saved_flags = 0;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+- up->port.state != NULL) {
++ port->state != NULL) {
+ if (status & UART_MSR_TERI)
+- up->port.icount.rng++;
++ port->icount.rng++;
+ if (status & UART_MSR_DDSR)
+- up->port.icount.dsr++;
++ port->icount.dsr++;
+ if (status & UART_MSR_DDCD)
+- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
++ uart_handle_dcd_change(port, status & UART_MSR_DCD);
+ if (status & UART_MSR_DCTS)
+- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
++ uart_handle_cts_change(port, status & UART_MSR_CTS);
+
+- wake_up_interruptible(&up->port.state->port.delta_msr_wait);
++ wake_up_interruptible(&port->state->port.delta_msr_wait);
+ }
+
+ return status;
+@@ -1517,7 +1521,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+ if (iir & UART_IIR_NO_INT)
+ return 0;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&port->lock, flags);
+
+ status = serial_in(up, UART_LSR);
+
+@@ -1529,7 +1533,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+ if (status & UART_LSR_THRE)
+ serial8250_tx_chars(up);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ spin_unlock_irqrestore(&port->lock, flags);
+ return 1;
+ }
+ EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+@@ -1769,10 +1773,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
+ unsigned long flags;
+ unsigned int lsr;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&port->lock, flags);
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ spin_unlock_irqrestore(&port->lock, flags);
+
+ return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+ }
+@@ -1826,13 +1830,13 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
+ container_of(port, struct uart_8250_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&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);
++ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ /*
+@@ -1933,15 +1937,15 @@ static int serial8250_startup(struct uart_port *port)
+ unsigned char lsr, iir;
+ int retval;
+
+- up->port.fifosize = uart_config[up->port.type].fifo_size;
++ port->fifosize = uart_config[up->port.type].fifo_size;
+ up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+ up->capabilities = uart_config[up->port.type].flags;
+ up->mcr = 0;
+
+- if (up->port.iotype != up->cur_iotype)
++ if (port->iotype != up->cur_iotype)
+ set_io_from_upio(port);
+
+- if (up->port.type == PORT_16C950) {
++ if (port->type == PORT_16C950) {
+ /* Wake up and initialize UART */
+ up->acr = 0;
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+@@ -1981,17 +1985,17 @@ static int serial8250_startup(struct uart_port *port)
+ * if it is, then bail out, because there's likely no UART
+ * here.
+ */
+- if (!(up->port.flags & UPF_BUGGY_UART) &&
++ if (!(port->flags & UPF_BUGGY_UART) &&
+ (serial_in(up, UART_LSR) == 0xff)) {
+ printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+- serial_index(&up->port));
++ serial_index(port));
+ return -ENODEV;
+ }
+
+ /*
+ * For a XR16C850, we need to set the trigger levels
+ */
+- if (up->port.type == PORT_16850) {
++ if (port->type == PORT_16850) {
+ unsigned char fctr;
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+@@ -2005,7 +2009,7 @@ static int serial8250_startup(struct uart_port *port)
+ serial_out(up, UART_LCR, 0);
+ }
+
+- if (up->port.irq) {
++ if (port->irq) {
+ unsigned char iir1;
+ /*
+ * Test for UARTs that do not reassert THRE when the
+@@ -2015,9 +2019,9 @@ static int serial8250_startup(struct uart_port *port)
+ * the interrupt is enabled. Delays are necessary to
+ * allow register changes to become visible.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&port->lock, flags);
+ if (up->port.irqflags & IRQF_SHARED)
+- disable_irq_nosync(up->port.irq);
++ disable_irq_nosync(port->irq);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+@@ -2029,9 +2033,9 @@ static int serial8250_startup(struct uart_port *port)
+ iir = serial_in(up, UART_IIR);
+ serial_out(up, UART_IER, 0);
+
+- if (up->port.irqflags & IRQF_SHARED)
+- enable_irq(up->port.irq);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ if (port->irqflags & IRQF_SHARED)
++ enable_irq(port->irq);
++ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * If the interrupt is not reasserted, setup a timer to
+@@ -2060,7 +2064,7 @@ static int serial8250_startup(struct uart_port *port)
+ * hardware interrupt, we use a timer-based system. The original
+ * driver used to do this with IRQ0.
+ */
+- if (!up->port.irq) {
++ if (!port->irq) {
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+ } else {
+@@ -2074,7 +2078,7 @@ static int serial8250_startup(struct uart_port *port)
+ */
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&port->lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ if (!up->port.irq)
+ up->port.mctrl |= TIOCM_OUT1;
+@@ -2082,10 +2086,10 @@ static int serial8250_startup(struct uart_port *port)
+ /*
+ * Most PC uarts need OUT2 raised to enable interrupts.
+ */
+- if (up->port.irq)
++ if (port->irq)
+ up->port.mctrl |= TIOCM_OUT2;
+
+- serial8250_set_mctrl(&up->port, up->port.mctrl);
++ serial8250_set_mctrl(port, port->mctrl);
+
+ /* Serial over Lan (SoL) hack:
+ Intel 8257x Gigabit ethernet chips have a
+@@ -2121,7 +2125,7 @@ static int serial8250_startup(struct uart_port *port)
+ }
+
+ dont_test_tx_en:
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * Clear the interrupt registers again for luck, and clear the
+@@ -2143,12 +2147,12 @@ dont_test_tx_en:
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+
+- if (up->port.flags & UPF_FOURPORT) {
++ if (port->flags & UPF_FOURPORT) {
+ unsigned int icp;
+ /*
+ * Enable interrupts on the AST Fourport board
+ */
+- icp = (up->port.iobase & 0xfe0) | 0x01f;
++ icp = (port->iobase & 0xfe0) | 0x01f;
+ outb_p(0x80, icp);
+ inb_p(icp);
+ }
+@@ -2168,16 +2172,16 @@ static void serial8250_shutdown(struct uart_port *port)
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
+- spin_lock_irqsave(&up->port.lock, flags);
+- if (up->port.flags & UPF_FOURPORT) {
++ spin_lock_irqsave(&port->lock, flags);
++ if (port->flags & UPF_FOURPORT) {
+ /* reset interrupts on the AST Fourport board */
+- inb((up->port.iobase & 0xfe0) | 0x1f);
+- up->port.mctrl |= TIOCM_OUT1;
++ inb((port->iobase & 0xfe0) | 0x1f);
++ port->mctrl |= TIOCM_OUT1;
+ } else
+- up->port.mctrl &= ~TIOCM_OUT2;
++ port->mctrl &= ~TIOCM_OUT2;
+
+- serial8250_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ serial8250_set_mctrl(port, port->mctrl);
++ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * Disable break condition and FIFOs
+@@ -2200,7 +2204,7 @@ static void serial8250_shutdown(struct uart_port *port)
+
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+- if (up->port.irq)
++ if (port->irq)
+ serial_unlink_irq_chain(up);
+ }
+
+@@ -2275,11 +2279,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
+ quot++;
+
+- if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
++ if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
+ if (baud < 2400)
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+ else
+- fcr = uart_config[up->port.type].fcr;
++ fcr = uart_config[port->type].fcr;
+ }
+
+ /*
+@@ -2290,7 +2294,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ * have sufficient FIFO entries for the latency of the remote
+ * UART to respond. IOW, at least 32 bytes of FIFO.
+ */
+- if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
++ if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
+ up->mcr &= ~UART_MCR_AFE;
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE;
+@@ -2300,40 +2304,40 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ spin_lock_irqsave(&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;
++ 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;
++ port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+- up->port.read_status_mask |= UART_LSR_BI;
++ port->read_status_mask |= UART_LSR_BI;
+
+ /*
+ * Characteres to ignore
+ */
+- up->port.ignore_status_mask = 0;
++ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
++ port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+- up->port.ignore_status_mask |= UART_LSR_BI;
++ 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;
++ 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;
++ port->ignore_status_mask |= UART_LSR_DR;
+
+ /*
+ * CTS flow control flag and modem status interrupts
+@@ -2360,7 +2364,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ efr |= UART_EFR_CTS;
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- if (up->port.flags & UPF_EXAR_EFR)
++ if (port->flags & UPF_EXAR_EFR)
+ serial_out(up, UART_XR_EFR, efr);
+ else
+ serial_out(up, UART_EFR, efr);
+@@ -2390,20 +2394,20 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+ * is written without DLAB set, this mode will be disabled.
+ */
+- if (up->port.type == PORT_16750)
++ if (port->type == PORT_16750)
+ serial_out(up, UART_FCR, fcr);
+
+ serial_out(up, UART_LCR, cval); /* reset DLAB */
+ up->lcr = cval; /* Save LCR */
+- if (up->port.type != PORT_16750) {
++ if (port->type != PORT_16750) {
+ if (fcr & UART_FCR_ENABLE_FIFO) {
+ /* emulated UARTs (Lucent Venus 167x) need two steps */
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ }
+ serial_out(up, UART_FCR, fcr); /* set fcr */
+ }
+- serial8250_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ serial8250_set_mctrl(port, port->mctrl);
++ spin_unlock_irqrestore(&port->lock, flags);
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+@@ -2468,26 +2472,26 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+ static int serial8250_request_std_resource(struct uart_8250_port *up)
+ {
+ unsigned int size = serial8250_port_size(up);
++ struct uart_port *port = &up->port;
+ int ret = 0;
+
+- switch (up->port.iotype) {
++ switch (port->iotype) {
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM:
+- if (!up->port.mapbase)
++ if (!port->mapbase)
+ break;
+
+- if (!request_mem_region(up->port.mapbase, size, "serial")) {
++ if (!request_mem_region(port->mapbase, size, "serial")) {
+ ret = -EBUSY;
+ break;
+ }
+
+- if (up->port.flags & UPF_IOREMAP) {
+- up->port.membase = ioremap_nocache(up->port.mapbase,
+- size);
+- if (!up->port.membase) {
+- release_mem_region(up->port.mapbase, size);
++ if (port->flags & UPF_IOREMAP) {
++ port->membase = ioremap_nocache(port->mapbase, size);
++ if (!port->membase) {
++ release_mem_region(port->mapbase, size);
+ ret = -ENOMEM;
+ }
+ }
+@@ -2495,7 +2499,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
+
+ case UPIO_HUB6:
+ case UPIO_PORT:
+- if (!request_region(up->port.iobase, size, "serial"))
++ if (!request_region(port->iobase, size, "serial"))
+ ret = -EBUSY;
+ break;
+ }
+@@ -2505,26 +2509,27 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
+ static void serial8250_release_std_resource(struct uart_8250_port *up)
+ {
+ unsigned int size = serial8250_port_size(up);
++ struct uart_port *port = &up->port;
+
+- switch (up->port.iotype) {
++ switch (port->iotype) {
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM:
+- if (!up->port.mapbase)
++ if (!port->mapbase)
+ break;
+
+- if (up->port.flags & UPF_IOREMAP) {
+- iounmap(up->port.membase);
+- up->port.membase = NULL;
++ if (port->flags & UPF_IOREMAP) {
++ iounmap(port->membase);
++ port->membase = NULL;
+ }
+
+- release_mem_region(up->port.mapbase, size);
++ release_mem_region(port->mapbase, size);
+ break;
+
+ case UPIO_HUB6:
+ case UPIO_PORT:
+- release_region(up->port.iobase, size);
++ release_region(port->iobase, size);
+ break;
+ }
+ }
+@@ -2533,12 +2538,13 @@ static int serial8250_request_rsa_resource(struct uart_8250_port *up)
+ {
+ unsigned long start = UART_RSA_BASE << up->port.regshift;
+ unsigned int size = 8 << up->port.regshift;
++ struct uart_port *port = &up->port;
+ int ret = -EINVAL;
+
+- switch (up->port.iotype) {
++ switch (port->iotype) {
+ case UPIO_HUB6:
+ case UPIO_PORT:
+- start += up->port.iobase;
++ start += port->iobase;
+ if (request_region(start, size, "serial-rsa"))
+ ret = 0;
+ else
+@@ -2553,11 +2559,12 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
+ {
+ unsigned long offset = UART_RSA_BASE << up->port.regshift;
+ unsigned int size = 8 << up->port.regshift;
++ struct uart_port *port = &up->port;
+
+- switch (up->port.iotype) {
++ switch (port->iotype) {
+ case UPIO_HUB6:
+ case UPIO_PORT:
+- release_region(up->port.iobase + offset, size);
++ release_region(port->iobase + offset, size);
+ break;
+ }
+ }
+@@ -2568,7 +2575,7 @@ static void serial8250_release_port(struct uart_port *port)
+ container_of(port, struct uart_8250_port, port);
+
+ serial8250_release_std_resource(up);
+- if (up->port.type == PORT_RSA)
++ if (port->type == PORT_RSA)
+ serial8250_release_rsa_resource(up);
+ }
+
+@@ -2579,7 +2586,7 @@ static int serial8250_request_port(struct uart_port *port)
+ int ret = 0;
+
+ ret = serial8250_request_std_resource(up);
+- if (ret == 0 && up->port.type == PORT_RSA) {
++ if (ret == 0 && port->type == PORT_RSA) {
+ ret = serial8250_request_rsa_resource(up);
+ if (ret < 0)
+ serial8250_release_std_resource(up);
+@@ -2607,22 +2614,22 @@ static void serial8250_config_port(struct uart_port *port, int flags)
+ if (ret < 0)
+ probeflags &= ~PROBE_RSA;
+
+- if (up->port.iotype != up->cur_iotype)
++ if (port->iotype != up->cur_iotype)
+ set_io_from_upio(port);
+
+ if (flags & UART_CONFIG_TYPE)
+ autoconfig(up, probeflags);
+
+ /* if access method is AU, it is a 16550 with a quirk */
+- if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
++ if (port->type == PORT_16550A && port->iotype == UPIO_AU)
+ up->bugs |= UART_BUG_NOMSR;
+
+- if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
++ if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
+ autoconfig_irq(up);
+
+- if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
++ if (port->type != PORT_RSA && probeflags & PROBE_RSA)
+ serial8250_release_rsa_resource(up);
+- if (up->port.type == PORT_UNKNOWN)
++ if (port->type == PORT_UNKNOWN)
+ serial8250_release_std_resource(up);
+ }
+
+@@ -2696,9 +2703,10 @@ static void __init serial8250_isa_init_ports(void)
+
+ for (i = 0; i < nr_uarts; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
++ struct uart_port *port = &up->port;
+
+- up->port.line = i;
+- spin_lock_init(&up->port.lock);
++ port->line = i;
++ spin_lock_init(&port->lock);
+
+ init_timer(&up->timer);
+ up->timer.function = serial8250_timeout;
+@@ -2709,7 +2717,7 @@ static void __init serial8250_isa_init_ports(void)
+ up->mcr_mask = ~ALPHA_KLUDGE_MCR;
+ up->mcr_force = ALPHA_KLUDGE_MCR;
+
+- up->port.ops = &serial8250_pops;
++ port->ops = &serial8250_pops;
+ }
+
+ if (share_irqs)
+@@ -2718,17 +2726,19 @@ static void __init serial8250_isa_init_ports(void)
+ for (i = 0, up = serial8250_ports;
+ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
+ i++, up++) {
+- up->port.iobase = old_serial_port[i].port;
+- up->port.irq = irq_canonicalize(old_serial_port[i].irq);
+- up->port.irqflags = old_serial_port[i].irqflags;
+- up->port.uartclk = old_serial_port[i].baud_base * 16;
+- up->port.flags = old_serial_port[i].flags;
+- up->port.hub6 = old_serial_port[i].hub6;
+- up->port.membase = old_serial_port[i].iomem_base;
+- up->port.iotype = old_serial_port[i].io_type;
+- up->port.regshift = old_serial_port[i].iomem_reg_shift;
+- set_io_from_upio(&up->port);
+- up->port.irqflags |= irqflag;
++ struct uart_port *port = &up->port;
++
++ port->iobase = old_serial_port[i].port;
++ port->irq = irq_canonicalize(old_serial_port[i].irq);
++ port->irqflags = old_serial_port[i].irqflags;
++ port->uartclk = old_serial_port[i].baud_base * 16;
++ port->flags = old_serial_port[i].flags;
++ port->hub6 = old_serial_port[i].hub6;
++ port->membase = old_serial_port[i].iomem_base;
++ port->iotype = old_serial_port[i].io_type;
++ port->regshift = old_serial_port[i].iomem_reg_shift;
++ set_io_from_upio(port);
++ port->irqflags |= irqflag;
+ if (serial8250_isa_config != NULL)
+ serial8250_isa_config(i, &up->port, &up->capabilities);
+
+@@ -2789,6 +2799,7 @@ static void
+ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ {
+ struct uart_8250_port *up = &serial8250_ports[co->index];
++ struct uart_port *port = &up->port;
+ unsigned long flags;
+ unsigned int ier;
+ int locked = 1;
+@@ -2796,13 +2807,13 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ touch_nmi_watchdog();
+
+ local_irq_save(flags);
+- if (up->port.sysrq) {
++ if (port->sysrq) {
+ /* serial8250_handle_irq() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+- locked = spin_trylock(&up->port.lock);
++ locked = spin_trylock(&port->lock);
+ } else
+- spin_lock(&up->port.lock);
++ spin_lock(&port->lock);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -2814,7 +2825,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ else
+ serial_out(up, UART_IER, 0);
+
+- uart_console_write(&up->port, s, count, serial8250_console_putchar);
++ uart_console_write(port, s, count, serial8250_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+@@ -2834,7 +2845,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ serial8250_modem_status(up);
+
+ if (locked)
+- spin_unlock(&up->port.lock);
++ spin_unlock(&port->lock);
+ local_irq_restore(flags);
+ }
+
+@@ -2979,6 +2990,7 @@ void serial8250_suspend_port(int line)
+ void serial8250_resume_port(int line)
+ {
+ struct uart_8250_port *up = &serial8250_ports[line];
++ struct uart_port *port = &up->port;
+
+ if (up->capabilities & UART_NATSEMI) {
+ /* Ensure it's still in high speed mode */
+@@ -2987,9 +2999,9 @@ void serial8250_resume_port(int line)
+ ns16550a_goto_highspeed(up);
+
+ serial_out(up, UART_LCR, 0);
+- up->port.uartclk = 921600*16;
++ port->uartclk = 921600*16;
+ }
+- uart_resume_port(&serial8250_reg, &up->port);
++ uart_resume_port(&serial8250_reg, port);
+ }
+
+ /*
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0025-serial-use-serial_port_in-out-vs-serial_in-out-in-82.patch b/patches.kzm9g/0025-serial-use-serial_port_in-out-vs-serial_in-out-in-82.patch
new file mode 100644
index 00000000000000..249a4282220bec
--- /dev/null
+++ b/patches.kzm9g/0025-serial-use-serial_port_in-out-vs-serial_in-out-in-82.patch
@@ -0,0 +1,455 @@
+From 291546c8ba381a8579bdcfc2a1dee3971c3ac9b9 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:13 -0500
+Subject: serial: use serial_port_in/out vs serial_in/out in 8250
+
+The serial_in and serial_out helpers are expecting to operate
+on an 8250_port struct. These in turn go after the contained
+normal port struct which actually has the actual in/out accessors.
+
+But what is happening in some cases, is that a function is passed
+in a port struct, and it runs container_of to get the 8250_port
+struct, and then it uses serial_in/out helpers on that. But when
+you do, it goes full circle, since it jumps back inside the 8250_port
+to find the contained port struct (which we already knew!).
+
+So, if we are operating in a scope where we know the struct port,
+then use the serial_port_in/out helpers and avoid the bouncing
+around. If we don't have the struct port handy, and it isn't
+worth making a local for it, then just leave things as-is which
+uses the serial_in/out helpers that will resolve the 8250_port
+onto the struct port.
+
+Mostly, gcc figures this out on its own -- so this doesn't bring to
+the table any revolutionary runtime delta. However, it is somewhat
+misleading to always hammer away on 8250 structs, when the actual
+underlying property isn't at all 8250 specific -- and this change
+makes that clear.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 4fd996a14660f56a6fd92ce7c8fb167d262c994f)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 160 ++++++++++++++++++++--------------------
+ 1 file changed, 80 insertions(+), 80 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 9ffb3cf..cb45a29 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -1287,7 +1287,7 @@ static void serial8250_start_tx(struct uart_port *port)
+
+ if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+- serial_out(up, UART_IER, up->ier);
++ serial_port_out(port, UART_IER, up->ier);
+
+ if (up->bugs & UART_BUG_TXEN) {
+ unsigned char lsr;
+@@ -1316,7 +1316,7 @@ static void serial8250_stop_rx(struct uart_port *port)
+
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+- serial_out(up, UART_IER, up->ier);
++ serial_port_out(port, UART_IER, up->ier);
+ }
+
+ static void serial8250_enable_ms(struct uart_port *port)
+@@ -1329,7 +1329,7 @@ static void serial8250_enable_ms(struct uart_port *port)
+ return;
+
+ up->ier |= UART_IER_MSI;
+- serial_out(up, UART_IER, up->ier);
++ serial_port_out(port, UART_IER, up->ier);
+ }
+
+ /*
+@@ -1523,7 +1523,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+
+ spin_lock_irqsave(&port->lock, flags);
+
+- status = serial_in(up, UART_LSR);
++ status = serial_port_in(port, UART_LSR);
+
+ DEBUG_INTR("status = %x...", status);
+
+@@ -1540,9 +1540,7 @@ EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+ static int serial8250_default_handle_irq(struct uart_port *port)
+ {
+- struct uart_8250_port *up =
+- container_of(port, struct uart_8250_port, port);
+- unsigned int iir = serial_in(up, UART_IIR);
++ unsigned int iir = serial_port_in(port, UART_IIR);
+
+ return serial8250_handle_irq(port, iir);
+ }
+@@ -1774,7 +1772,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
+ unsigned int lsr;
+
+ spin_lock_irqsave(&port->lock, flags);
+- lsr = serial_in(up, UART_LSR);
++ lsr = serial_port_in(port, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+@@ -1821,7 +1819,7 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+
+ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
+
+- serial_out(up, UART_MCR, mcr);
++ serial_port_out(port, UART_MCR, mcr);
+ }
+
+ static void serial8250_break_ctl(struct uart_port *port, int break_state)
+@@ -1835,7 +1833,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+- serial_out(up, UART_LCR, up->lcr);
++ serial_port_out(port, UART_LCR, up->lcr);
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+@@ -1881,14 +1879,12 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+
+ static int serial8250_get_poll_char(struct uart_port *port)
+ {
+- struct uart_8250_port *up =
+- container_of(port, struct uart_8250_port, port);
+- unsigned char lsr = serial_in(up, UART_LSR);
++ unsigned char lsr = serial_port_in(port, UART_LSR);
+
+ if (!(lsr & UART_LSR_DR))
+ return NO_POLL_CHAR;
+
+- return serial_in(up, UART_RX);
++ return serial_port_in(port, UART_RX);
+ }
+
+
+@@ -1902,21 +1898,21 @@ static void serial8250_put_poll_char(struct uart_port *port,
+ /*
+ * First save the IER then disable the interrupts
+ */
+- ier = serial_in(up, UART_IER);
++ ier = serial_port_in(port, UART_IER);
+ if (up->capabilities & UART_CAP_UUE)
+- serial_out(up, UART_IER, UART_IER_UUE);
++ serial_port_out(port, UART_IER, UART_IER_UUE);
+ else
+- serial_out(up, UART_IER, 0);
++ serial_port_out(port, UART_IER, 0);
+
+ wait_for_xmitr(up, BOTH_EMPTY);
+ /*
+ * Send the character out.
+ * If a LF, also do CR...
+ */
+- serial_out(up, UART_TX, c);
++ serial_port_out(port, UART_TX, c);
+ if (c == 10) {
+ wait_for_xmitr(up, BOTH_EMPTY);
+- serial_out(up, UART_TX, 13);
++ serial_port_out(port, UART_TX, 13);
+ }
+
+ /*
+@@ -1924,7 +1920,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+- serial_out(up, UART_IER, ier);
++ serial_port_out(port, UART_IER, ier);
+ }
+
+ #endif /* CONFIG_CONSOLE_POLL */
+@@ -1948,14 +1944,14 @@ static int serial8250_startup(struct uart_port *port)
+ if (port->type == PORT_16C950) {
+ /* Wake up and initialize UART */
+ up->acr = 0;
+- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_out(up, UART_EFR, UART_EFR_ECB);
+- serial_out(up, UART_IER, 0);
+- serial_out(up, UART_LCR, 0);
++ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_port_out(port, UART_EFR, UART_EFR_ECB);
++ serial_port_out(port, UART_IER, 0);
++ serial_port_out(port, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+- serial_out(up, UART_EFR, UART_EFR_ECB);
+- serial_out(up, UART_LCR, 0);
++ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_port_out(port, UART_EFR, UART_EFR_ECB);
++ serial_port_out(port, UART_LCR, 0);
+ }
+
+ #ifdef CONFIG_SERIAL_8250_RSA
+@@ -1975,10 +1971,10 @@ static int serial8250_startup(struct uart_port *port)
+ /*
+ * Clear the interrupt registers.
+ */
+- serial_in(up, UART_LSR);
+- serial_in(up, UART_RX);
+- serial_in(up, UART_IIR);
+- serial_in(up, UART_MSR);
++ serial_port_in(port, UART_LSR);
++ serial_port_in(port, UART_RX);
++ serial_port_in(port, UART_IIR);
++ serial_port_in(port, UART_MSR);
+
+ /*
+ * At this point, there's no way the LSR could still be 0xff;
+@@ -1986,7 +1982,7 @@ static int serial8250_startup(struct uart_port *port)
+ * here.
+ */
+ if (!(port->flags & UPF_BUGGY_UART) &&
+- (serial_in(up, UART_LSR) == 0xff)) {
++ (serial_port_in(port, UART_LSR) == 0xff)) {
+ printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+ serial_index(port));
+ return -ENODEV;
+@@ -2001,12 +1997,14 @@ static int serial8250_startup(struct uart_port *port)
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+ fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+- serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+- serial_out(up, UART_TRG, UART_TRG_96);
+- serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+- serial_out(up, UART_TRG, UART_TRG_96);
++ serial_port_out(port, UART_FCTR,
++ fctr | UART_FCTR_TRGD | UART_FCTR_RX);
++ serial_port_out(port, UART_TRG, UART_TRG_96);
++ serial_port_out(port, UART_FCTR,
++ fctr | UART_FCTR_TRGD | UART_FCTR_TX);
++ serial_port_out(port, UART_TRG, UART_TRG_96);
+
+- serial_out(up, UART_LCR, 0);
++ serial_port_out(port, UART_LCR, 0);
+ }
+
+ if (port->irq) {
+@@ -2026,12 +2024,12 @@ static int serial8250_startup(struct uart_port *port)
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+- iir1 = serial_in(up, UART_IIR);
+- serial_out(up, UART_IER, 0);
++ iir1 = serial_port_in(port, UART_IIR);
++ serial_port_out(port, UART_IER, 0);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow a working UART time to re-assert THRE */
+- iir = serial_in(up, UART_IIR);
+- serial_out(up, UART_IER, 0);
++ iir = serial_port_in(port, UART_IIR);
++ serial_port_out(port, UART_IER, 0);
+
+ if (port->irqflags & IRQF_SHARED)
+ enable_irq(port->irq);
+@@ -2076,7 +2074,7 @@ static int serial8250_startup(struct uart_port *port)
+ /*
+ * Now, initialize the UART
+ */
+- serial_out(up, UART_LCR, UART_LCR_WLEN8);
++ serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+@@ -2109,10 +2107,10 @@ static int serial8250_startup(struct uart_port *port)
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+ */
+- serial_out(up, UART_IER, UART_IER_THRI);
+- lsr = serial_in(up, UART_LSR);
+- iir = serial_in(up, UART_IIR);
+- serial_out(up, UART_IER, 0);
++ serial_port_out(port, UART_IER, UART_IER_THRI);
++ lsr = serial_port_in(port, UART_LSR);
++ iir = serial_port_in(port, UART_IIR);
++ serial_port_out(port, UART_IER, 0);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+@@ -2132,10 +2130,10 @@ dont_test_tx_en:
+ * saved flags to avoid getting false values from polling
+ * routines or the previous session.
+ */
+- serial_in(up, UART_LSR);
+- serial_in(up, UART_RX);
+- serial_in(up, UART_IIR);
+- serial_in(up, UART_MSR);
++ serial_port_in(port, UART_LSR);
++ serial_port_in(port, UART_RX);
++ serial_port_in(port, UART_IIR);
++ serial_port_in(port, UART_MSR);
+ up->lsr_saved_flags = 0;
+ up->msr_saved_flags = 0;
+
+@@ -2145,7 +2143,7 @@ dont_test_tx_en:
+ * anyway, so we don't enable them here.
+ */
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+- serial_out(up, UART_IER, up->ier);
++ serial_port_out(port, UART_IER, up->ier);
+
+ if (port->flags & UPF_FOURPORT) {
+ unsigned int icp;
+@@ -2170,7 +2168,7 @@ static void serial8250_shutdown(struct uart_port *port)
+ * Disable interrupts from this port
+ */
+ up->ier = 0;
+- serial_out(up, UART_IER, 0);
++ serial_port_out(port, UART_IER, 0);
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (port->flags & UPF_FOURPORT) {
+@@ -2186,7 +2184,8 @@ static void serial8250_shutdown(struct uart_port *port)
+ /*
+ * Disable break condition and FIFOs
+ */
+- serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
++ serial_port_out(port, UART_LCR,
++ serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
+ serial8250_clear_fifos(up);
+
+ #ifdef CONFIG_SERIAL_8250_RSA
+@@ -2200,7 +2199,7 @@ static void serial8250_shutdown(struct uart_port *port)
+ * Read data port to reset things, and then unlink from
+ * the IRQ chain.
+ */
+- serial_in(up, UART_RX);
++ serial_port_in(port, UART_RX);
+
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+@@ -2351,7 +2350,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ if (up->capabilities & UART_CAP_RTOIE)
+ up->ier |= UART_IER_RTOIE;
+
+- serial_out(up, UART_IER, up->ier);
++ serial_port_out(port, UART_IER, up->ier);
+
+ if (up->capabilities & UART_CAP_EFR) {
+ unsigned char efr = 0;
+@@ -2363,11 +2362,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ if (termios->c_cflag & CRTSCTS)
+ efr |= UART_EFR_CTS;
+
+- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
++ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (port->flags & UPF_EXAR_EFR)
+- serial_out(up, UART_XR_EFR, efr);
++ serial_port_out(port, UART_XR_EFR, efr);
+ else
+- serial_out(up, UART_EFR, efr);
++ serial_port_out(port, UART_EFR, efr);
+ }
+
+ #ifdef CONFIG_ARCH_OMAP
+@@ -2375,18 +2374,20 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ if (cpu_is_omap1510() && is_omap_port(up)) {
+ if (baud == 115200) {
+ quot = 1;
+- serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
++ serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
+ } else
+- serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
++ serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
+ }
+ #endif
+
+- if (up->capabilities & UART_NATSEMI) {
+- /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
+- serial_out(up, UART_LCR, 0xe0);
+- } else {
+- serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+- }
++ /*
++ * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
++ * otherwise just set DLAB
++ */
++ if (up->capabilities & UART_NATSEMI)
++ serial_port_out(port, UART_LCR, 0xe0);
++ else
++ serial_port_out(port, UART_LCR, cval | UART_LCR_DLAB);
+
+ serial_dl_write(up, quot);
+
+@@ -2395,16 +2396,15 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ * is written without DLAB set, this mode will be disabled.
+ */
+ if (port->type == PORT_16750)
+- serial_out(up, UART_FCR, fcr);
++ serial_port_out(port, UART_FCR, fcr);
+
+- serial_out(up, UART_LCR, cval); /* reset DLAB */
++ serial_port_out(port, UART_LCR, cval); /* reset DLAB */
+ up->lcr = cval; /* Save LCR */
+ if (port->type != PORT_16750) {
+- if (fcr & UART_FCR_ENABLE_FIFO) {
+- /* emulated UARTs (Lucent Venus 167x) need two steps */
+- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+- }
+- serial_out(up, UART_FCR, fcr); /* set fcr */
++ /* emulated UARTs (Lucent Venus 167x) need two steps */
++ if (fcr & UART_FCR_ENABLE_FIFO)
++ serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_port_out(port, UART_FCR, fcr); /* set fcr */
+ }
+ serial8250_set_mctrl(port, port->mctrl);
+ spin_unlock_irqrestore(&port->lock, flags);
+@@ -2786,7 +2786,7 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
+ container_of(port, struct uart_8250_port, port);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+- serial_out(up, UART_TX, ch);
++ serial_port_out(port, UART_TX, ch);
+ }
+
+ /*
+@@ -2818,12 +2818,12 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ /*
+ * First save the IER then disable the interrupts
+ */
+- ier = serial_in(up, UART_IER);
++ ier = serial_port_in(port, UART_IER);
+
+ if (up->capabilities & UART_CAP_UUE)
+- serial_out(up, UART_IER, UART_IER_UUE);
++ serial_port_out(port, UART_IER, UART_IER_UUE);
+ else
+- serial_out(up, UART_IER, 0);
++ serial_port_out(port, UART_IER, 0);
+
+ uart_console_write(port, s, count, serial8250_console_putchar);
+
+@@ -2832,7 +2832,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+- serial_out(up, UART_IER, ier);
++ serial_port_out(port, UART_IER, ier);
+
+ /*
+ * The receive handling will happen properly because the
+@@ -2994,11 +2994,11 @@ void serial8250_resume_port(int line)
+
+ if (up->capabilities & UART_NATSEMI) {
+ /* Ensure it's still in high speed mode */
+- serial_out(up, UART_LCR, 0xE0);
++ serial_port_out(port, UART_LCR, 0xE0);
+
+ ns16550a_goto_highspeed(up);
+
+- serial_out(up, UART_LCR, 0);
++ serial_port_out(port, UART_LCR, 0);
+ port->uartclk = 921600*16;
+ }
+ uart_resume_port(&serial8250_reg, port);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0026-serial-remove-back-and-forth-conversions-in-serial_o.patch b/patches.kzm9g/0026-serial-remove-back-and-forth-conversions-in-serial_o.patch
new file mode 100644
index 00000000000000..efe8300234a695
--- /dev/null
+++ b/patches.kzm9g/0026-serial-remove-back-and-forth-conversions-in-serial_o.patch
@@ -0,0 +1,56 @@
+From 51a2897e38814dc21408888a8d3ddd364e7686e2 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 8 Mar 2012 19:12:14 -0500
+Subject: serial: remove back and forth conversions in serial_out_sync
+
+The two callers to serial_out_sync() have a struct port right
+there in scope, but then pass in a struct 8250_port which then
+is locally resolved back to a struct port.
+
+Delete the needless back and forth and just pass in the struct
+port directly. Rename the function to have "_port" in its
+name, so the name <--> args relationship is consistent with the
+other serial_in/out vs serial_port_in/out function classes.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 55e4016dd055e262e4b078b81c80b55386ead0f4)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index cb45a29..56492d2 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -467,9 +467,8 @@ static void set_io_from_upio(struct uart_port *p)
+ }
+
+ static void
+-serial_out_sync(struct uart_8250_port *up, int offset, int value)
++serial_port_out_sync(struct uart_port *p, int offset, int value)
+ {
+- struct uart_port *p = &up->port;
+ switch (p->iotype) {
+ case UPIO_MEM:
+ case UPIO_MEM32:
+@@ -2022,11 +2021,11 @@ static int serial8250_startup(struct uart_port *port)
+ disable_irq_nosync(port->irq);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+- serial_out_sync(up, UART_IER, UART_IER_THRI);
++ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+ iir1 = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+- serial_out_sync(up, UART_IER, UART_IER_THRI);
++ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow a working UART time to re-assert THRE */
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0027-serial-8250_pci-add-a-force-background-timer-flag-an.patch b/patches.kzm9g/0027-serial-8250_pci-add-a-force-background-timer-flag-an.patch
new file mode 100644
index 00000000000000..95b07cdfa19be1
--- /dev/null
+++ b/patches.kzm9g/0027-serial-8250_pci-add-a-force-background-timer-flag-an.patch
@@ -0,0 +1,118 @@
+From b503e9756dc79ffaf2b3160b79c1bf2aed842547 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 6 Apr 2012 11:49:50 -0700
+Subject: serial/8250_pci: add a "force background timer" flag and use it for
+ the "kt" serial port
+
+Workaround dropped notifications in the iir register. Register reads
+coincident with new interrupt notifications sometimes result in this
+device clearing the interrupt event without reporting it in the read
+data.
+
+The serial core already has a heuristic for determining when a device
+has an untrustworthy iir register. In this case when we apriori know
+that the iir is faulty use a flag (UPF_BUG_THRE) to bypass the test and
+force usage of the background timer.
+
+[stable: 3.3.x]
+Acked-by: Alan Cox <alan@linux.intel.com>
+Cc: stable <stable@vger.kernel.org>
+Reported-by: Nhan H Mai <nhan.h.mai@intel.com>
+Reported-by: Sudhakar Mamillapalli <sudhakar@fb.com>
+Tested-by: Nhan H Mai <nhan.h.mai@intel.com>
+Tested-by: Sudhakar Mamillapalli <sudhakar@fb.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit bc02d15a3452fdf9276e8fb89c5e504a88df888a)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 8 +++++---
+ drivers/tty/serial/8250/8250_pci.c | 17 ++++++++++++++++-
+ include/linux/serial_core.h | 1 +
+ 3 files changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 56492d2..5c27f7e 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -2035,10 +2035,12 @@ static int serial8250_startup(struct uart_port *port)
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+- * If the interrupt is not reasserted, setup a timer to
+- * kick the UART on a regular basis.
++ * If the interrupt is not reasserted, or we otherwise
++ * don't trust the iir, setup a timer to kick the UART
++ * on a regular basis.
+ */
+- if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
++ if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
++ up->port.flags & UPF_BUG_THRE) {
+ up->bugs |= UART_BUG_THRE;
+ pr_debug("ttyS%d - using backup timer\n",
+ serial_index(port));
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index a213f38..107eff0 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -994,6 +994,14 @@ static int skip_tx_en_setup(struct serial_private *priv,
+ return pci_default_setup(priv, board, port, idx);
+ }
+
++static int kt_serial_setup(struct serial_private *priv,
++ const struct pciserial_board *board,
++ struct uart_port *port, int idx)
++{
++ port->flags |= UPF_BUG_THRE;
++ return skip_tx_en_setup(priv, board, port, idx);
++}
++
+ static int pci_eg20t_init(struct pci_dev *dev)
+ {
+ #if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE)
+@@ -1012,7 +1020,6 @@ pci_xr17c154_setup(struct serial_private *priv,
+ return pci_default_setup(priv, board, port, idx);
+ }
+
+-/* This should be in linux/pci_ids.h */
+ #define PCI_VENDOR_ID_SBSMODULARIO 0x124B
+ #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
+ #define PCI_DEVICE_ID_OCTPRO 0x0001
+@@ -1038,6 +1045,7 @@ pci_xr17c154_setup(struct serial_private *priv,
+ #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
+ #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
+ #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
++#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+
+ /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
+@@ -1122,6 +1130,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ .subdevice = PCI_ANY_ID,
+ .setup = ce4100_serial_setup,
+ },
++ {
++ .vendor = PCI_VENDOR_ID_INTEL,
++ .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = kt_serial_setup,
++ },
+ /*
+ * ITE
+ */
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index d611ca0..724fde0 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -351,6 +351,7 @@ struct uart_port {
+ #define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
+ #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
+ #define UPF_EXAR_EFR ((__force upf_t) (1 << 25))
++#define UPF_BUG_THRE ((__force upf_t) (1 << 26))
+ /* The exact UART type is known and should not be probed. */
+ #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
+ #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0028-8250.c-less-than-2400-baud-fix.patch b/patches.kzm9g/0028-8250.c-less-than-2400-baud-fix.patch
new file mode 100644
index 00000000000000..44791ce2d1d895
--- /dev/null
+++ b/patches.kzm9g/0028-8250.c-less-than-2400-baud-fix.patch
@@ -0,0 +1,51 @@
+From 5fbfa3c9a23c95bb26065fb7a6ee3d6256d2a410 Mon Sep 17 00:00:00 2001
+From: Christian Melki <christian.melki@ericsson.se>
+Date: Mon, 30 Apr 2012 11:21:26 +0200
+Subject: 8250.c: less than 2400 baud fix.
+
+We noticed that we were loosing data at speed less than 2400 baud.
+It turned out our (TI16750 compatible) uart with 64 byte outgoing fifo
+was truncated to 16 byte (bit 5 sets fifo len) when modifying the fcr
+reg.
+The input code still fills the buffer with 64 bytes if I remember
+correctly and thus data is lost.
+Our fix was to remove whiping of the fcr content and just add the
+TRIGGER_1 which we want for latency.
+I can't see why this would not work on less than 2400 always, for all
+uarts ...
+Otherwise one would have to make sure the filling of the fifo re-checks
+the current state of available fifo size (urrk).
+
+Signed-off-by: Christian Melki <christian.melki@ericsson.se>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit f9a9111b540fd67db5dab332f4b83d86c90e27b1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 5c27f7e..d537431 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -2280,10 +2280,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ quot++;
+
+ if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
+- if (baud < 2400)
+- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+- else
+- fcr = uart_config[port->type].fcr;
++ fcr = uart_config[port->type].fcr;
++ if (baud < 2400) {
++ fcr &= ~UART_FCR_TRIGGER_MASK;
++ fcr |= UART_FCR_TRIGGER_1;
++ }
+ }
+
+ /*
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0029-serial8250-Add-dl_read-dl_write-callbacks.patch b/patches.kzm9g/0029-serial8250-Add-dl_read-dl_write-callbacks.patch
new file mode 100644
index 00000000000000..b1eb8440605ba8
--- /dev/null
+++ b/patches.kzm9g/0029-serial8250-Add-dl_read-dl_write-callbacks.patch
@@ -0,0 +1,203 @@
+From c7fbe0d5b21bad7ee177f745bfd423f0ed57243d Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 2 May 2012 21:46:51 +0900
+Subject: serial8250: Add dl_read()/dl_write() callbacks
+
+Convert serial_dl_read() and serial_dl_write() from macro
+to 8250 specific callbacks. This change makes it easier to
+support 8250 hardware with non-standard DLL and DLM register
+configurations such as Alchemy, RM9K and upcoming Emma Mobile
+UART hardware.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit cc419fa0d38c425e4ea7bffeed931b07b0a3e461)
+
+Conflicts:
+ drivers/tty/serial/8250/8250.h
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 117 ++++++++++++++++++++++------------------
+ drivers/tty/serial/8250/8250.h | 14 +++++
+ 2 files changed, 78 insertions(+), 53 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index d537431..7a31149 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -284,6 +284,66 @@ static const struct serial8250_config uart_config[] = {
+ },
+ };
+
++/* Uart divisor latch read */
++static int default_dl_read(struct uart_8250_port *up)
++{
++ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
++}
++
++/* Uart divisor latch write */
++static void default_dl_write(struct uart_8250_port *up, int value)
++{
++ serial_out(up, UART_DLL, value & 0xff);
++ serial_out(up, UART_DLM, value >> 8 & 0xff);
++}
++
++#if defined(CONFIG_MIPS_ALCHEMY)
++/* Au1x00 haven't got a standard divisor latch */
++static int _serial_dl_read(struct uart_8250_port *up)
++{
++ if (up->port.iotype == UPIO_AU)
++ return __raw_readl(up->port.membase + 0x28);
++ else
++ return default_dl_read(up);
++}
++
++static void _serial_dl_write(struct uart_8250_port *up, int value)
++{
++ if (up->port.iotype == UPIO_AU)
++ __raw_writel(value, up->port.membase + 0x28);
++ else
++ default_dl_write(up, value);
++}
++#elif defined(CONFIG_SERIAL_8250_RM9K)
++static int _serial_dl_read(struct uart_8250_port *up)
++{
++ return (up->port.iotype == UPIO_RM9000) ?
++ (((__raw_readl(up->port.membase + 0x10) << 8) |
++ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
++ default_dl_read(up);
++}
++
++static void _serial_dl_write(struct uart_8250_port *up, int value)
++{
++ if (up->port.iotype == UPIO_RM9000) {
++ __raw_writel(value, up->port.membase + 0x08);
++ __raw_writel(value >> 8, up->port.membase + 0x10);
++ } else {
++ default_dl_write(up, value);
++ }
++}
++#else
++static int _serial_dl_read(struct uart_8250_port *up)
++{
++ return default_dl_read(up);
++}
++
++static void _serial_dl_write(struct uart_8250_port *up, int value)
++{
++ default_dl_write(up, value);
++}
++#endif
++
+ #if defined(CONFIG_MIPS_ALCHEMY)
+
+ /* Au1x00 UART hardware has a weird register layout */
+@@ -434,6 +494,10 @@ static void set_io_from_upio(struct uart_port *p)
+ {
+ struct uart_8250_port *up =
+ container_of(p, struct uart_8250_port, port);
++
++ up->dl_read = _serial_dl_read;
++ up->dl_write = _serial_dl_write;
++
+ switch (p->iotype) {
+ case UPIO_HUB6:
+ p->serial_in = hub6_serial_in;
+@@ -481,59 +545,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
+ }
+ }
+
+-/* Uart divisor latch read */
+-static inline int _serial_dl_read(struct uart_8250_port *up)
+-{
+- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+-}
+-
+-/* Uart divisor latch write */
+-static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+-{
+- serial_out(up, UART_DLL, value & 0xff);
+- serial_out(up, UART_DLM, value >> 8 & 0xff);
+-}
+-
+-#if defined(CONFIG_MIPS_ALCHEMY)
+-/* Au1x00 haven't got a standard divisor latch */
+-static int serial_dl_read(struct uart_8250_port *up)
+-{
+- if (up->port.iotype == UPIO_AU)
+- return __raw_readl(up->port.membase + 0x28);
+- else
+- return _serial_dl_read(up);
+-}
+-
+-static void serial_dl_write(struct uart_8250_port *up, int value)
+-{
+- if (up->port.iotype == UPIO_AU)
+- __raw_writel(value, up->port.membase + 0x28);
+- else
+- _serial_dl_write(up, value);
+-}
+-#elif defined(CONFIG_SERIAL_8250_RM9K)
+-static int serial_dl_read(struct uart_8250_port *up)
+-{
+- return (up->port.iotype == UPIO_RM9000) ?
+- (((__raw_readl(up->port.membase + 0x10) << 8) |
+- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+- _serial_dl_read(up);
+-}
+-
+-static void serial_dl_write(struct uart_8250_port *up, int value)
+-{
+- if (up->port.iotype == UPIO_RM9000) {
+- __raw_writel(value, up->port.membase + 0x08);
+- __raw_writel(value >> 8, up->port.membase + 0x10);
+- } else {
+- _serial_dl_write(up, value);
+- }
+-}
+-#else
+-#define serial_dl_read(up) _serial_dl_read(up)
+-#define serial_dl_write(up, value) _serial_dl_write(up, value)
+-#endif
+-
+ /*
+ * For the 16C950
+ */
+diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
+index 2868a1d..bafe034 100644
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -37,6 +37,10 @@ struct uart_8250_port {
+ unsigned char lsr_saved_flags;
+ #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
++
++ /* 8250 specific callbacks */
++ int (*dl_read)(struct uart_8250_port *);
++ void (*dl_write)(struct uart_8250_port *, int);
+ };
+
+ struct old_serial_port {
+@@ -96,6 +100,16 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
+ up->port.serial_out(&up->port, offset, value);
+ }
+
++static inline int serial_dl_read(struct uart_8250_port *up)
++{
++ return up->dl_read(up);
++}
++
++static inline void serial_dl_write(struct uart_8250_port *up, int value)
++{
++ up->dl_write(up, value);
++}
++
+ #if defined(__alpha__) && !defined(CONFIG_PCI)
+ /*
+ * Digital did something really horribly wrong with the OUT1 and OUT2
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0030-serial8250-Use-dl_read-dl_write-on-Alchemy.patch b/patches.kzm9g/0030-serial8250-Use-dl_read-dl_write-on-Alchemy.patch
new file mode 100644
index 00000000000000..d543de7ec41cc8
--- /dev/null
+++ b/patches.kzm9g/0030-serial8250-Use-dl_read-dl_write-on-Alchemy.patch
@@ -0,0 +1,138 @@
+From c5c260031fff81671154c36017619be60bd9db4d Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 2 May 2012 21:47:00 +0900
+Subject: serial8250: Use dl_read()/dl_write() on Alchemy
+
+Convert the 8250 Alchemy support code to make
+use of the new dl_read()/dl_write() callbacks.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 6b4160313c239d61c3907b2aaaeeec156911c9d1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 67 ++++++++++++++++------------------------
+ 1 file changed, 26 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 7a31149..ce7717c 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -297,24 +297,7 @@ static void default_dl_write(struct uart_8250_port *up, int value)
+ serial_out(up, UART_DLM, value >> 8 & 0xff);
+ }
+
+-#if defined(CONFIG_MIPS_ALCHEMY)
+-/* Au1x00 haven't got a standard divisor latch */
+-static int _serial_dl_read(struct uart_8250_port *up)
+-{
+- if (up->port.iotype == UPIO_AU)
+- return __raw_readl(up->port.membase + 0x28);
+- else
+- return default_dl_read(up);
+-}
+-
+-static void _serial_dl_write(struct uart_8250_port *up, int value)
+-{
+- if (up->port.iotype == UPIO_AU)
+- __raw_writel(value, up->port.membase + 0x28);
+- else
+- default_dl_write(up, value);
+-}
+-#elif defined(CONFIG_SERIAL_8250_RM9K)
++#if defined(CONFIG_SERIAL_8250_RM9K)
+ static int _serial_dl_read(struct uart_8250_port *up)
+ {
+ return (up->port.iotype == UPIO_RM9000) ?
+@@ -344,7 +327,7 @@ static void _serial_dl_write(struct uart_8250_port *up, int value)
+ }
+ #endif
+
+-#if defined(CONFIG_MIPS_ALCHEMY)
++#ifdef CONFIG_MIPS_ALCHEMY
+
+ /* Au1x00 UART hardware has a weird register layout */
+ static const u8 au_io_in_map[] = {
+@@ -365,22 +348,32 @@ static const u8 au_io_out_map[] = {
+ [UART_MCR] = 6,
+ };
+
+-/* sane hardware needs no mapping */
+-static inline int map_8250_in_reg(struct uart_port *p, int offset)
++static unsigned int au_serial_in(struct uart_port *p, int offset)
+ {
+- if (p->iotype != UPIO_AU)
+- return offset;
+- return au_io_in_map[offset];
++ offset = au_io_in_map[offset] << p->regshift;
++ return __raw_readl(p->membase + offset);
+ }
+
+-static inline int map_8250_out_reg(struct uart_port *p, int offset)
++static void au_serial_out(struct uart_port *p, int offset, int value)
+ {
+- if (p->iotype != UPIO_AU)
+- return offset;
+- return au_io_out_map[offset];
++ offset = au_io_out_map[offset] << p->regshift;
++ __raw_writel(value, p->membase + offset);
++}
++
++/* Au1x00 haven't got a standard divisor latch */
++static int au_serial_dl_read(struct uart_8250_port *up)
++{
++ return __raw_readl(up->port.membase + 0x28);
+ }
+
+-#elif defined(CONFIG_SERIAL_8250_RM9K)
++static void au_serial_dl_write(struct uart_8250_port *up, int value)
++{
++ __raw_writel(value, up->port.membase + 0x28);
++}
++
++#endif
++
++#if defined(CONFIG_SERIAL_8250_RM9K)
+
+ static const u8
+ regmap_in[8] = {
+@@ -464,18 +457,6 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+ return readl(p->membase + offset);
+ }
+
+-static unsigned int au_serial_in(struct uart_port *p, int offset)
+-{
+- offset = map_8250_in_reg(p, offset) << p->regshift;
+- return __raw_readl(p->membase + offset);
+-}
+-
+-static void au_serial_out(struct uart_port *p, int offset, int value)
+-{
+- offset = map_8250_out_reg(p, offset) << p->regshift;
+- __raw_writel(value, p->membase + offset);
+-}
+-
+ static unsigned int io_serial_in(struct uart_port *p, int offset)
+ {
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+@@ -515,10 +496,14 @@ static void set_io_from_upio(struct uart_port *p)
+ p->serial_out = mem32_serial_out;
+ break;
+
++#ifdef CONFIG_MIPS_ALCHEMY
+ case UPIO_AU:
+ p->serial_in = au_serial_in;
+ p->serial_out = au_serial_out;
++ up->dl_read = au_serial_dl_read;
++ up->dl_write = au_serial_dl_write;
+ break;
++#endif
+
+ default:
+ p->serial_in = io_serial_in;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0031-serial8250-Use-dl_read-dl_write-on-RM9K.patch b/patches.kzm9g/0031-serial8250-Use-dl_read-dl_write-on-RM9K.patch
new file mode 100644
index 00000000000000..11c12350a223cd
--- /dev/null
+++ b/patches.kzm9g/0031-serial8250-Use-dl_read-dl_write-on-RM9K.patch
@@ -0,0 +1,139 @@
+From b2a0b1532958cbf0ef8e7078c78558b2e78bb524 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 2 May 2012 21:47:09 +0900
+Subject: serial8250: Use dl_read()/dl_write() on RM9K
+
+Convert the 8250 RM9K support code to make
+use of the new dl_read()/dl_write() callbacks.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 28bf4cf22dcd936f93dd6063696b1accdc1d5207)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 62 +++++++++++++++++++---------------------
+ 1 file changed, 29 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index ce7717c..36ce1e2 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -297,25 +297,6 @@ static void default_dl_write(struct uart_8250_port *up, int value)
+ serial_out(up, UART_DLM, value >> 8 & 0xff);
+ }
+
+-#if defined(CONFIG_SERIAL_8250_RM9K)
+-static int _serial_dl_read(struct uart_8250_port *up)
+-{
+- return (up->port.iotype == UPIO_RM9000) ?
+- (((__raw_readl(up->port.membase + 0x10) << 8) |
+- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+- default_dl_read(up);
+-}
+-
+-static void _serial_dl_write(struct uart_8250_port *up, int value)
+-{
+- if (up->port.iotype == UPIO_RM9000) {
+- __raw_writel(value, up->port.membase + 0x08);
+- __raw_writel(value >> 8, up->port.membase + 0x10);
+- } else {
+- default_dl_write(up, value);
+- }
+-}
+-#else
+ static int _serial_dl_read(struct uart_8250_port *up)
+ {
+ return default_dl_read(up);
+@@ -325,7 +306,6 @@ static void _serial_dl_write(struct uart_8250_port *up, int value)
+ {
+ default_dl_write(up, value);
+ }
+-#endif
+
+ #ifdef CONFIG_MIPS_ALCHEMY
+
+@@ -373,7 +353,7 @@ static void au_serial_dl_write(struct uart_8250_port *up, int value)
+
+ #endif
+
+-#if defined(CONFIG_SERIAL_8250_RM9K)
++#ifdef CONFIG_SERIAL_8250_RM9K
+
+ static const u8
+ regmap_in[8] = {
+@@ -397,28 +377,36 @@ static const u8
+ [UART_SCR] = 0x2c
+ };
+
+-static inline int map_8250_in_reg(struct uart_port *p, int offset)
++static unsigned int rm9k_serial_in(struct uart_port *p, int offset)
+ {
+- if (p->iotype != UPIO_RM9000)
+- return offset;
+- return regmap_in[offset];
++ offset = regmap_in[offset] << p->regshift;
++ return readl(p->membase + offset);
+ }
+
+-static inline int map_8250_out_reg(struct uart_port *p, int offset)
++static void rm9k_serial_out(struct uart_port *p, int offset, int value)
+ {
+- if (p->iotype != UPIO_RM9000)
+- return offset;
+- return regmap_out[offset];
++ offset = regmap_out[offset] << p->regshift;
++ writel(value, p->membase + offset);
+ }
+
+-#else
++static int rm9k_serial_dl_read(struct uart_8250_port *up)
++{
++ return ((__raw_readl(up->port.membase + 0x10) << 8) |
++ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff;
++}
++
++static void rm9k_serial_dl_write(struct uart_8250_port *up, int value)
++{
++ __raw_writel(value, up->port.membase + 0x08);
++ __raw_writel(value >> 8, up->port.membase + 0x10);
++}
++
++#endif
+
+ /* sane hardware needs no mapping */
+ #define map_8250_in_reg(up, offset) (offset)
+ #define map_8250_out_reg(up, offset) (offset)
+
+-#endif
+-
+ static unsigned int hub6_serial_in(struct uart_port *p, int offset)
+ {
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+@@ -490,12 +478,20 @@ static void set_io_from_upio(struct uart_port *p)
+ p->serial_out = mem_serial_out;
+ break;
+
+- case UPIO_RM9000:
+ case UPIO_MEM32:
+ p->serial_in = mem32_serial_in;
+ p->serial_out = mem32_serial_out;
+ break;
+
++#ifdef CONFIG_SERIAL_8250_RM9K
++ case UPIO_RM9000:
++ p->serial_in = rm9k_serial_in;
++ p->serial_out = rm9k_serial_out;
++ up->dl_read = rm9k_serial_dl_read;
++ up->dl_write = rm9k_serial_dl_write;
++ break;
++#endif
++
+ #ifdef CONFIG_MIPS_ALCHEMY
+ case UPIO_AU:
+ p->serial_in = au_serial_in;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0032-serial8250-Clean-up-default-map-and-dl-code.patch b/patches.kzm9g/0032-serial8250-Clean-up-default-map-and-dl-code.patch
new file mode 100644
index 00000000000000..5ebaebd7ba7583
--- /dev/null
+++ b/patches.kzm9g/0032-serial8250-Clean-up-default-map-and-dl-code.patch
@@ -0,0 +1,134 @@
+From 2c6855bab06ff3e78cdcafd00a9ab5b6fd4c3ef3 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 2 May 2012 21:47:18 +0900
+Subject: serial8250: Clean up default map and dl code
+
+Get rid of unused functions and macros now when
+Alchemy and RM9K are converted over to callbacks.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit e8155629ff19e05722ba057d1521baec270d780e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 38 ++++++++++++--------------------------
+ 1 file changed, 12 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 36ce1e2..3445a27 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -285,28 +285,18 @@ static const struct serial8250_config uart_config[] = {
+ };
+
+ /* Uart divisor latch read */
+-static int default_dl_read(struct uart_8250_port *up)
++static int default_serial_dl_read(struct uart_8250_port *up)
+ {
+ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+ }
+
+ /* Uart divisor latch write */
+-static void default_dl_write(struct uart_8250_port *up, int value)
++static void default_serial_dl_write(struct uart_8250_port *up, int value)
+ {
+ serial_out(up, UART_DLL, value & 0xff);
+ serial_out(up, UART_DLM, value >> 8 & 0xff);
+ }
+
+-static int _serial_dl_read(struct uart_8250_port *up)
+-{
+- return default_dl_read(up);
+-}
+-
+-static void _serial_dl_write(struct uart_8250_port *up, int value)
+-{
+- default_dl_write(up, value);
+-}
+-
+ #ifdef CONFIG_MIPS_ALCHEMY
+
+ /* Au1x00 UART hardware has a weird register layout */
+@@ -403,57 +393,53 @@ static void rm9k_serial_dl_write(struct uart_8250_port *up, int value)
+
+ #endif
+
+-/* sane hardware needs no mapping */
+-#define map_8250_in_reg(up, offset) (offset)
+-#define map_8250_out_reg(up, offset) (offset)
+-
+ static unsigned int hub6_serial_in(struct uart_port *p, int offset)
+ {
+- offset = map_8250_in_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ return inb(p->iobase + 1);
+ }
+
+ static void hub6_serial_out(struct uart_port *p, int offset, int value)
+ {
+- offset = map_8250_out_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ outb(value, p->iobase + 1);
+ }
+
+ static unsigned int mem_serial_in(struct uart_port *p, int offset)
+ {
+- offset = map_8250_in_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ return readb(p->membase + offset);
+ }
+
+ static void mem_serial_out(struct uart_port *p, int offset, int value)
+ {
+- offset = map_8250_out_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ writeb(value, p->membase + offset);
+ }
+
+ static void mem32_serial_out(struct uart_port *p, int offset, int value)
+ {
+- offset = map_8250_out_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ writel(value, p->membase + offset);
+ }
+
+ static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+ {
+- offset = map_8250_in_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ return readl(p->membase + offset);
+ }
+
+ static unsigned int io_serial_in(struct uart_port *p, int offset)
+ {
+- offset = map_8250_in_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ return inb(p->iobase + offset);
+ }
+
+ static void io_serial_out(struct uart_port *p, int offset, int value)
+ {
+- offset = map_8250_out_reg(p, offset) << p->regshift;
++ offset = offset << p->regshift;
+ outb(value, p->iobase + offset);
+ }
+
+@@ -464,8 +450,8 @@ static void set_io_from_upio(struct uart_port *p)
+ struct uart_8250_port *up =
+ container_of(p, struct uart_8250_port, port);
+
+- up->dl_read = _serial_dl_read;
+- up->dl_write = _serial_dl_write;
++ up->dl_read = default_serial_dl_read;
++ up->dl_write = default_serial_dl_write;
+
+ switch (p->iotype) {
+ case UPIO_HUB6:
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0033-serial8250-Introduce-serial8250_register_8250_port.patch b/patches.kzm9g/0033-serial8250-Introduce-serial8250_register_8250_port.patch
new file mode 100644
index 00000000000000..f01d7ee280adfa
--- /dev/null
+++ b/patches.kzm9g/0033-serial8250-Introduce-serial8250_register_8250_port.patch
@@ -0,0 +1,169 @@
+From 4d5e00ec9374ddf1ec0995e10380e2e044eb8154 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 2 May 2012 21:47:27 +0900
+Subject: serial8250: Introduce serial8250_register_8250_port()
+
+Introduce yet another 8250 registration function.
+This time it is serial8250_register_8250_port() and it
+allows us to register 8250 hardware instances using struct
+uart_8250_port. The new function makes it possible to
+register 8250 hardware that makes use of 8250 specific
+callbacks such as ->dl_read() and ->dl_write().
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit f73fa05b90eb8c0dd3230c364cf1107f4f8f3848)
+
+Conflicts:
+ drivers/tty/serial/8250/8250.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250.c | 87 ++++++++++++++++++++++++++--------------
+ include/linux/serial_8250.h | 1 +
+ 2 files changed, 58 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 3445a27..8de9a39 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -3132,7 +3132,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
+ }
+
+ /**
+- * serial8250_register_port - register a serial port
++ * serial8250_register_8250_port - register a serial port
+ * @port: serial port template
+ *
+ * Configure the serial port specified by the request. If the
+@@ -3144,50 +3144,54 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
+ *
+ * On success the port is ready to use and the line number is returned.
+ */
+-int serial8250_register_port(struct uart_port *port)
++int serial8250_register_8250_port(struct uart_8250_port *up)
+ {
+ struct uart_8250_port *uart;
+ int ret = -ENOSPC;
+
+- if (port->uartclk == 0)
++ if (up->port.uartclk == 0)
+ return -EINVAL;
+
+ mutex_lock(&serial_mutex);
+
+- uart = serial8250_find_match_or_unused(port);
++ uart = serial8250_find_match_or_unused(&up->port);
+ if (uart) {
+ uart_remove_one_port(&serial8250_reg, &uart->port);
+
+- uart->port.iobase = port->iobase;
+- uart->port.membase = port->membase;
+- uart->port.irq = port->irq;
+- uart->port.irqflags = port->irqflags;
+- uart->port.uartclk = port->uartclk;
+- uart->port.fifosize = port->fifosize;
+- uart->port.regshift = port->regshift;
+- uart->port.iotype = port->iotype;
+- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
+- uart->port.mapbase = port->mapbase;
+- uart->port.private_data = port->private_data;
+- if (port->dev)
+- uart->port.dev = port->dev;
+-
+- if (port->flags & UPF_FIXED_TYPE)
+- serial8250_init_fixed_type_port(uart, port->type);
++ uart->port.iobase = up->port.iobase;
++ uart->port.membase = up->port.membase;
++ uart->port.irq = up->port.irq;
++ uart->port.irqflags = up->port.irqflags;
++ uart->port.uartclk = up->port.uartclk;
++ uart->port.fifosize = up->port.fifosize;
++ uart->port.regshift = up->port.regshift;
++ uart->port.iotype = up->port.iotype;
++ uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
++ uart->port.mapbase = up->port.mapbase;
++ uart->port.private_data = up->port.private_data;
++ if (up->port.dev)
++ uart->port.dev = up->port.dev;
++
++ if (up->port.flags & UPF_FIXED_TYPE)
++ serial8250_init_fixed_type_port(uart, up->port.type);
+
+ set_io_from_upio(&uart->port);
+ /* Possibly override default I/O functions. */
+- if (port->serial_in)
+- uart->port.serial_in = port->serial_in;
+- if (port->serial_out)
+- uart->port.serial_out = port->serial_out;
+- if (port->handle_irq)
+- uart->port.handle_irq = port->handle_irq;
++ if (up->port.serial_in)
++ uart->port.serial_in = up->port.serial_in;
++ if (up->port.serial_out)
++ uart->port.serial_out = up->port.serial_out;
++ if (up->port.handle_irq)
++ uart->port.handle_irq = up->port.handle_irq;
+ /* Possibly override set_termios call */
+- if (port->set_termios)
+- uart->port.set_termios = port->set_termios;
+- if (port->pm)
+- uart->port.pm = port->pm;
++ if (up->port.set_termios)
++ uart->port.set_termios = up->port.set_termios;
++ if (up->port.pm)
++ uart->port.pm = up->port.pm;
++ if (up->dl_read)
++ uart->dl_read = up->dl_read;
++ if (up->dl_write)
++ uart->dl_write = up->dl_write;
+
+ if (serial8250_isa_config != NULL)
+ serial8250_isa_config(0, &uart->port,
+@@ -3201,6 +3205,29 @@ int serial8250_register_port(struct uart_port *port)
+
+ return ret;
+ }
++EXPORT_SYMBOL(serial8250_register_8250_port);
++
++/**
++ * serial8250_register_port - register a serial port
++ * @port: serial port template
++ *
++ * Configure the serial port specified by the request. If the
++ * port exists and is in use, it is hung up and unregistered
++ * first.
++ *
++ * The port is then probed and if necessary the IRQ is autodetected
++ * If this fails an error is returned.
++ *
++ * On success the port is ready to use and the line number is returned.
++ */
++int serial8250_register_port(struct uart_port *port)
++{
++ struct uart_8250_port up;
++
++ memset(&up, 0, sizeof(up));
++ memcpy(&up.port, port, sizeof(*port));
++ return serial8250_register_8250_port(&up);
++}
+ EXPORT_SYMBOL(serial8250_register_port);
+
+ /**
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index b44034e..d7f286e 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -68,6 +68,7 @@ enum {
+ struct uart_port;
+ struct uart_8250_port;
+
++int serial8250_register_8250_port(struct uart_8250_port *);
+ int serial8250_register_port(struct uart_port *);
+ void serial8250_unregister_port(int line);
+ void serial8250_suspend_port(int line);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0034-serial8250-em-Emma-Mobile-UART-driver-V2.patch b/patches.kzm9g/0034-serial8250-em-Emma-Mobile-UART-driver-V2.patch
new file mode 100644
index 00000000000000..d20eea6d874744
--- /dev/null
+++ b/patches.kzm9g/0034-serial8250-em-Emma-Mobile-UART-driver-V2.patch
@@ -0,0 +1,254 @@
+From 851dd6ac01a254a7c6e14a75c0cd0c8aec2d542b Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Thu, 3 May 2012 21:13:09 +0900
+Subject: serial8250-em: Emma Mobile UART driver V2
+
+This is V2 of the Emma Mobile 8250 platform driver.
+
+The hardware itself has according to the data sheet
+up to 64 byte FIFOs but at this point we only make
+use of the 16550 compatible mode.
+
+To support this piece of hardware the common UART
+registers need to be remapped, and the access size
+differences need to be handled.
+
+The DLL and DLM registers can due to offset collision
+not be remapped easily, and because of that this
+driver makes use of ->dl_read() and ->dl_write()
+callbacks. This in turn requires a registration
+function that takes 8250-specific paramenters.
+
+Future potential enhancements include DT support,
+early platform driver console and fine grained PM.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 22886ee96895b7a9f9d06da4dc9420b61b4ef1f7)
+
+Conflicts:
+ drivers/tty/serial/8250/Kconfig
+ drivers/tty/serial/8250/Makefile
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250_em.c | 178 +++++++++++++++++++++++++++++++++++++
+ drivers/tty/serial/8250/Kconfig | 8 ++
+ drivers/tty/serial/8250/Makefile | 1 +
+ 3 files changed, 187 insertions(+)
+ create mode 100644 drivers/tty/serial/8250/8250_em.c
+
+diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
+new file mode 100644
+index 0000000..ff42542
+--- /dev/null
++++ b/drivers/tty/serial/8250/8250_em.c
+@@ -0,0 +1,178 @@
++/*
++ * Renesas Emma Mobile 8250 driver
++ *
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/serial_8250.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/slab.h>
++
++#include "8250.h"
++
++#define UART_DLL_EM 9
++#define UART_DLM_EM 10
++
++struct serial8250_em_priv {
++ struct clk *sclk;
++ int line;
++};
++
++static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
++{
++ switch (offset) {
++ case UART_TX: /* TX @ 0x00 */
++ writeb(value, p->membase);
++ break;
++ case UART_FCR: /* FCR @ 0x0c (+1) */
++ case UART_LCR: /* LCR @ 0x10 (+1) */
++ case UART_MCR: /* MCR @ 0x14 (+1) */
++ case UART_SCR: /* SCR @ 0x20 (+1) */
++ writel(value, p->membase + ((offset + 1) << 2));
++ break;
++ case UART_IER: /* IER @ 0x04 */
++ value &= 0x0f; /* only 4 valid bits - not Xscale */
++ /* fall-through */
++ case UART_DLL_EM: /* DLL @ 0x24 (+9) */
++ case UART_DLM_EM: /* DLM @ 0x28 (+9) */
++ writel(value, p->membase + (offset << 2));
++ }
++}
++
++static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
++{
++ switch (offset) {
++ case UART_RX: /* RX @ 0x00 */
++ return readb(p->membase);
++ case UART_MCR: /* MCR @ 0x14 (+1) */
++ case UART_LSR: /* LSR @ 0x18 (+1) */
++ case UART_MSR: /* MSR @ 0x1c (+1) */
++ case UART_SCR: /* SCR @ 0x20 (+1) */
++ return readl(p->membase + ((offset + 1) << 2));
++ case UART_IER: /* IER @ 0x04 */
++ case UART_IIR: /* IIR @ 0x08 */
++ case UART_DLL_EM: /* DLL @ 0x24 (+9) */
++ case UART_DLM_EM: /* DLM @ 0x28 (+9) */
++ return readl(p->membase + (offset << 2));
++ }
++ return 0;
++}
++
++static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
++{
++ return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
++}
++
++static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
++{
++ serial_out(up, UART_DLL_EM, value & 0xff);
++ serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
++}
++
++static int __devinit serial8250_em_probe(struct platform_device *pdev)
++{
++ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ struct serial8250_em_priv *priv;
++ struct uart_8250_port up;
++ int ret = -EINVAL;
++
++ if (!regs || !irq) {
++ dev_err(&pdev->dev, "missing registers or irq\n");
++ goto err0;
++ }
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv) {
++ dev_err(&pdev->dev, "unable to allocate private data\n");
++ ret = -ENOMEM;
++ goto err0;
++ }
++
++ priv->sclk = clk_get(&pdev->dev, "sclk");
++ if (!priv->sclk) {
++ dev_err(&pdev->dev, "unable to get clock\n");
++ goto err1;
++ }
++
++ memset(&up, 0, sizeof(up));
++ up.port.mapbase = regs->start;
++ up.port.irq = irq->start;
++ up.port.type = PORT_UNKNOWN;
++ up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
++ up.port.dev = &pdev->dev;
++ up.port.private_data = priv;
++
++ clk_enable(priv->sclk);
++ up.port.uartclk = clk_get_rate(priv->sclk);
++
++ up.port.iotype = UPIO_MEM32;
++ up.port.serial_in = serial8250_em_serial_in;
++ up.port.serial_out = serial8250_em_serial_out;
++ up.dl_read = serial8250_em_serial_dl_read;
++ up.dl_write = serial8250_em_serial_dl_write;
++
++ ret = serial8250_register_8250_port(&up);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "unable to register 8250 port\n");
++ goto err2;
++ }
++
++ priv->line = ret;
++ platform_set_drvdata(pdev, priv);
++ return 0;
++
++ err2:
++ clk_disable(priv->sclk);
++ clk_put(priv->sclk);
++ err1:
++ kfree(priv);
++ err0:
++ return ret;
++}
++
++static int __devexit serial8250_em_remove(struct platform_device *pdev)
++{
++ struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
++
++ serial8250_unregister_port(priv->line);
++ clk_disable(priv->sclk);
++ clk_put(priv->sclk);
++ kfree(priv);
++ return 0;
++}
++
++static struct platform_driver serial8250_em_platform_driver = {
++ .driver = {
++ .name = "serial8250-em",
++ .owner = THIS_MODULE,
++ },
++ .probe = serial8250_em_probe,
++ .remove = __devexit_p(serial8250_em_remove),
++};
++
++module_platform_driver(serial8250_em_platform_driver);
++
++MODULE_AUTHOR("Magnus Damm");
++MODULE_DESCRIPTION("Renesas Emma Mobile 8250 Driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+index b1bb251..7aa3b6c 100644
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -266,3 +266,11 @@ config SERIAL_8250_RM9K
+ Selecting this option will add support for the integrated serial
+ port hardware found on MIPS RM9122 and similar processors.
+ If unsure, say N.
++
++config SERIAL_8250_EM
++ tristate "Support for Emma Mobile intergrated serial port"
++ depends on SERIAL_8250 && ARM && HAVE_CLK
++ help
++ Selecting this option will add support for the integrated serial
++ port hardware found on the Emma Mobile line of processors.
++ If unsure, say N.
+diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
+index c0d0c29..6a70704 100644
+--- a/drivers/tty/serial/8250/Makefile
++++ b/drivers/tty/serial/8250/Makefile
+@@ -16,3 +16,4 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+ obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+ obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
++obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0035-serial8250-em-clk_get-IS_ERR-error-handling-fix.patch b/patches.kzm9g/0035-serial8250-em-clk_get-IS_ERR-error-handling-fix.patch
new file mode 100644
index 00000000000000..f0dbf2bf2bd6ed
--- /dev/null
+++ b/patches.kzm9g/0035-serial8250-em-clk_get-IS_ERR-error-handling-fix.patch
@@ -0,0 +1,38 @@
+From 7ff1614653a079059c1d017d4d95376a616649ab Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 9 May 2012 15:49:57 +0900
+Subject: serial8250-em: clk_get() IS_ERR() error handling fix
+
+Update the 8250_em driver to correctly handle the case
+where no clock is associated with the device.
+
+The return value of clk_get() needs to be checked with
+IS_ERR() to avoid NULL pointer referencing.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 94e792ab66d696aad2e52c91bae4cfbeefe4c9f6)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/8250/8250_em.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
+index ff42542..be6c289 100644
+--- a/drivers/tty/serial/8250/8250_em.c
++++ b/drivers/tty/serial/8250/8250_em.c
+@@ -110,8 +110,9 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev)
+ }
+
+ priv->sclk = clk_get(&pdev->dev, "sclk");
+- if (!priv->sclk) {
++ if (IS_ERR(priv->sclk)) {
+ dev_err(&pdev->dev, "unable to get clock\n");
++ ret = PTR_ERR(priv->sclk);
+ goto err1;
+ }
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0036-cpuidle-create-bootparam-cpuidle.off-1.patch b/patches.kzm9g/0036-cpuidle-create-bootparam-cpuidle.off-1.patch
new file mode 100644
index 00000000000000..d0cef7b7014acd
--- /dev/null
+++ b/patches.kzm9g/0036-cpuidle-create-bootparam-cpuidle.off-1.patch
@@ -0,0 +1,116 @@
+From 9c84f8943b8bb242d3eab46ab23bc6daeaa7a02f Mon Sep 17 00:00:00 2001
+From: Len Brown <len.brown@intel.com>
+Date: Fri, 1 Apr 2011 18:13:10 -0400
+Subject: cpuidle: create bootparam "cpuidle.off=1"
+
+useful for disabling cpuidle to fall back
+to architecture-default idle loop
+
+cpuidle drivers and governors will fail to register.
+on x86 they'll say so:
+
+intel_idle: intel_idle yielding to (null)
+ACPI: acpi_idle yielding to (null)
+
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit 62027aea23fcd14478abdddd3b74a4e0f5fb2984)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ Documentation/kernel-parameters.txt | 3 +++
+ drivers/cpuidle/cpuidle.c | 10 ++++++++++
+ drivers/cpuidle/cpuidle.h | 1 +
+ drivers/cpuidle/driver.c | 3 +++
+ drivers/cpuidle/governor.c | 3 +++
+ 5 files changed, 20 insertions(+)
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 400b7be..79cef3c 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -546,6 +546,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ /proc/<pid>/coredump_filter.
+ See also Documentation/filesystems/proc.txt.
+
++ cpuidle.off=1 [CPU_IDLE]
++ disable the cpuidle sub-system
++
+ cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
+ Format:
+ <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index eed4c47..4487396 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -28,6 +28,12 @@ LIST_HEAD(cpuidle_detected_devices);
+ static void (*pm_idle_old)(void);
+
+ static int enabled_devices;
++static int off __read_mostly;
++
++int cpuidle_disabled(void)
++{
++ return off;
++}
+
+ #if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
+ static void cpuidle_kick_cpus(void)
+@@ -427,6 +433,9 @@ static int __init cpuidle_init(void)
+ {
+ int ret;
+
++ if (cpuidle_disabled())
++ return -ENODEV;
++
+ pm_idle_old = pm_idle;
+
+ ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
+@@ -438,4 +447,5 @@ static int __init cpuidle_init(void)
+ return 0;
+ }
+
++module_param(off, int, 0444);
+ core_initcall(cpuidle_init);
+diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h
+index 33e50d5..38c3fd8 100644
+--- a/drivers/cpuidle/cpuidle.h
++++ b/drivers/cpuidle/cpuidle.h
+@@ -13,6 +13,7 @@ extern struct list_head cpuidle_governors;
+ extern struct list_head cpuidle_detected_devices;
+ extern struct mutex cpuidle_lock;
+ extern spinlock_t cpuidle_driver_lock;
++extern int cpuidle_disabled(void);
+
+ /* idle loop */
+ extern void cpuidle_install_idle_handler(void);
+diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
+index fd1601e..3f7e3ce 100644
+--- a/drivers/cpuidle/driver.c
++++ b/drivers/cpuidle/driver.c
+@@ -26,6 +26,9 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
+ if (!drv)
+ return -EINVAL;
+
++ if (cpuidle_disabled())
++ return -ENODEV;
++
+ spin_lock(&cpuidle_driver_lock);
+ if (cpuidle_curr_driver) {
+ spin_unlock(&cpuidle_driver_lock);
+diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c
+index 724c164..ea2f8e7 100644
+--- a/drivers/cpuidle/governor.c
++++ b/drivers/cpuidle/governor.c
+@@ -81,6 +81,9 @@ int cpuidle_register_governor(struct cpuidle_governor *gov)
+ if (!gov || !gov->select)
+ return -EINVAL;
+
++ if (cpuidle_disabled())
++ return -ENODEV;
++
+ mutex_lock(&cpuidle_lock);
+ if (__cpuidle_find_governor(gov->name) == NULL) {
+ ret = 0;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0037-cpuidle-replace-xen-access-to-x86-pm_idle-and-defaul.patch b/patches.kzm9g/0037-cpuidle-replace-xen-access-to-x86-pm_idle-and-defaul.patch
new file mode 100644
index 00000000000000..3ae71b0e25c0c6
--- /dev/null
+++ b/patches.kzm9g/0037-cpuidle-replace-xen-access-to-x86-pm_idle-and-defaul.patch
@@ -0,0 +1,85 @@
+From 761a5d96c87fccab8a53f8c8c3240d8dcdb1bb19 Mon Sep 17 00:00:00 2001
+From: Len Brown <len.brown@intel.com>
+Date: Fri, 1 Apr 2011 18:28:35 -0400
+Subject: cpuidle: replace xen access to x86 pm_idle and default_idle
+
+When a Xen Dom0 kernel boots on a hypervisor, it gets access
+to the raw-hardware ACPI tables. While it parses the idle tables
+for the hypervisor's beneift, it uses HLT for its own idle.
+
+Rather than have xen scribble on pm_idle and access default_idle,
+have it simply disable_cpuidle() so acpi_idle will not load and
+architecture default HLT will be used.
+
+cc: xen-devel@lists.xensource.com
+Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Acked-by: H. Peter Anvin <hpa@linux.intel.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit d91ee5863b71e8c90eaf6035bff3078a85e2e7b5)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/x86/xen/setup.c | 3 ++-
+ drivers/cpuidle/cpuidle.c | 4 ++++
+ include/linux/cpuidle.h | 2 ++
+ 3 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
+index f8dcda4..e16a4ca 100644
+--- a/arch/x86/xen/setup.c
++++ b/arch/x86/xen/setup.c
+@@ -9,6 +9,7 @@
+ #include <linux/mm.h>
+ #include <linux/pm.h>
+ #include <linux/memblock.h>
++#include <linux/cpuidle.h>
+
+ #include <asm/elf.h>
+ #include <asm/vdso.h>
+@@ -459,7 +460,7 @@ void __init xen_arch_setup(void)
+ #ifdef CONFIG_X86_32
+ boot_cpu_data.hlt_works_ok = 1;
+ #endif
+- pm_idle = default_idle;
++ disable_cpuidle();
+ boot_option_idle_override = IDLE_HALT;
+
+ fiddle_vdso();
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index 4487396..cd1c19c 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -34,6 +34,10 @@ int cpuidle_disabled(void)
+ {
+ return off;
+ }
++void disable_cpuidle(void)
++{
++ off = 1;
++}
+
+ #if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
+ static void cpuidle_kick_cpus(void)
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index 36719ea..b89f67d 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -122,6 +122,7 @@ struct cpuidle_driver {
+ };
+
+ #ifdef CONFIG_CPU_IDLE
++extern void disable_cpuidle(void);
+
+ extern int cpuidle_register_driver(struct cpuidle_driver *drv);
+ struct cpuidle_driver *cpuidle_get_driver(void);
+@@ -135,6 +136,7 @@ extern int cpuidle_enable_device(struct cpuidle_device *dev);
+ extern void cpuidle_disable_device(struct cpuidle_device *dev);
+
+ #else
++static inline void disable_cpuidle(void) { }
+
+ static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
+ {return -ENODEV; }
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0038-cpuidle-stop-depending-on-pm_idle.patch b/patches.kzm9g/0038-cpuidle-stop-depending-on-pm_idle.patch
new file mode 100644
index 00000000000000..276df0975f753b
--- /dev/null
+++ b/patches.kzm9g/0038-cpuidle-stop-depending-on-pm_idle.patch
@@ -0,0 +1,254 @@
+From be5500b643f8d3d104e64d9096a5c8d86afadd92 Mon Sep 17 00:00:00 2001
+From: Len Brown <len.brown@intel.com>
+Date: Fri, 1 Apr 2011 19:34:59 -0400
+Subject: cpuidle: stop depending on pm_idle
+
+cpuidle users should call cpuidle_call_idle() directly
+rather than via (pm_idle)() function pointer.
+
+Architecture may choose to continue using (pm_idle)(),
+but cpuidle need not depend on it:
+
+ my_arch_cpu_idle()
+ ...
+ if(cpuidle_call_idle())
+ pm_idle();
+
+cc: Kevin Hilman <khilman@deeprootsystems.com>
+cc: Paul Mundt <lethal@linux-sh.org>
+cc: x86@kernel.org
+Acked-by: H. Peter Anvin <hpa@linux.intel.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit a0bfa1373859e9d11dc92561a8667588803e42d8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/kernel/process.c | 4 +++-
+ arch/sh/kernel/idle.c | 6 ++++--
+ arch/x86/kernel/process_32.c | 4 +++-
+ arch/x86/kernel/process_64.c | 4 +++-
+ drivers/cpuidle/cpuidle.c | 38 ++++++++++++++++++--------------------
+ include/linux/cpuidle.h | 2 ++
+ 6 files changed, 33 insertions(+), 25 deletions(-)
+
+diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
+index 74ae833..5affc61 100644
+--- a/arch/arm/kernel/process.c
++++ b/arch/arm/kernel/process.c
+@@ -30,6 +30,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/random.h>
+ #include <linux/hw_breakpoint.h>
++#include <linux/cpuidle.h>
+
+ #include <asm/cacheflush.h>
+ #include <asm/leds.h>
+@@ -199,7 +200,8 @@ void cpu_idle(void)
+ cpu_relax();
+ } else {
+ stop_critical_timings();
+- pm_idle();
++ if (cpuidle_call_idle())
++ pm_idle();
+ start_critical_timings();
+ /*
+ * This will eventually be removed - pm_idle
+diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
+index 425d604..9c7099e 100644
+--- a/arch/sh/kernel/idle.c
++++ b/arch/sh/kernel/idle.c
+@@ -16,12 +16,13 @@
+ #include <linux/thread_info.h>
+ #include <linux/irqflags.h>
+ #include <linux/smp.h>
++#include <linux/cpuidle.h>
+ #include <asm/pgalloc.h>
+ #include <asm/system.h>
+ #include <asm/atomic.h>
+ #include <asm/smp.h>
+
+-void (*pm_idle)(void) = NULL;
++static void (*pm_idle)(void);
+
+ static int hlt_counter;
+
+@@ -100,7 +101,8 @@ void cpu_idle(void)
+ local_irq_disable();
+ /* Don't trace irqs off for idle */
+ stop_critical_timings();
+- pm_idle();
++ if (cpuidle_call_idle())
++ pm_idle();
+ /*
+ * Sanity check to ensure that pm_idle() returns
+ * with IRQs enabled
+diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
+index fcdb1b3..ca71e9a 100644
+--- a/arch/x86/kernel/process_32.c
++++ b/arch/x86/kernel/process_32.c
+@@ -38,6 +38,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/io.h>
+ #include <linux/kdebug.h>
++#include <linux/cpuidle.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -109,7 +110,8 @@ void cpu_idle(void)
+ local_irq_disable();
+ /* Don't trace irqs off for idle */
+ stop_critical_timings();
+- pm_idle();
++ if (cpuidle_idle_call())
++ pm_idle();
+ start_critical_timings();
+ }
+ tick_nohz_restart_sched_tick();
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index b01898d..ca8df6a 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -37,6 +37,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/io.h>
+ #include <linux/ftrace.h>
++#include <linux/cpuidle.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -136,7 +137,8 @@ void cpu_idle(void)
+ enter_idle();
+ /* Don't trace irqs off for idle */
+ stop_critical_timings();
+- pm_idle();
++ if (cpuidle_idle_call())
++ pm_idle();
+ start_critical_timings();
+
+ /* In many cases the interrupt that ended idle
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index cd1c19c..0df0141 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -25,10 +25,10 @@ DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+
+ DEFINE_MUTEX(cpuidle_lock);
+ LIST_HEAD(cpuidle_detected_devices);
+-static void (*pm_idle_old)(void);
+
+ static int enabled_devices;
+ static int off __read_mostly;
++static int initialized __read_mostly;
+
+ int cpuidle_disabled(void)
+ {
+@@ -56,25 +56,23 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
+ * cpuidle_idle_call - the main idle loop
+ *
+ * NOTE: no locks or semaphores should be used here
++ * return non-zero on failure
+ */
+-static void cpuidle_idle_call(void)
++int cpuidle_idle_call(void)
+ {
+ struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+ struct cpuidle_state *target_state;
+ int next_state;
+
++ if (off)
++ return -ENODEV;
++
++ if (!initialized)
++ return -ENODEV;
++
+ /* check if the device is ready */
+- if (!dev || !dev->enabled) {
+- if (pm_idle_old)
+- pm_idle_old();
+- else
+-#if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE)
+- default_idle();
+-#else
+- local_irq_enable();
+-#endif
+- return;
+- }
++ if (!dev || !dev->enabled)
++ return -EBUSY;
+
+ #if 0
+ /* shows regressions, re-enable for 2.6.29 */
+@@ -99,7 +97,7 @@ static void cpuidle_idle_call(void)
+ next_state = cpuidle_curr_governor->select(dev);
+ if (need_resched()) {
+ local_irq_enable();
+- return;
++ return 0;
+ }
+
+ target_state = &dev->states[next_state];
+@@ -124,6 +122,8 @@ static void cpuidle_idle_call(void)
+ /* give the governor an opportunity to reflect on the outcome */
+ if (cpuidle_curr_governor->reflect)
+ cpuidle_curr_governor->reflect(dev);
++
++ return 0;
+ }
+
+ /**
+@@ -131,10 +131,10 @@ static void cpuidle_idle_call(void)
+ */
+ void cpuidle_install_idle_handler(void)
+ {
+- if (enabled_devices && (pm_idle != cpuidle_idle_call)) {
++ if (enabled_devices) {
+ /* Make sure all changes finished before we switch to new idle */
+ smp_wmb();
+- pm_idle = cpuidle_idle_call;
++ initialized = 1;
+ }
+ }
+
+@@ -143,8 +143,8 @@ void cpuidle_install_idle_handler(void)
+ */
+ void cpuidle_uninstall_idle_handler(void)
+ {
+- if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
+- pm_idle = pm_idle_old;
++ if (enabled_devices) {
++ initialized = 0;
+ cpuidle_kick_cpus();
+ }
+ }
+@@ -440,8 +440,6 @@ static int __init cpuidle_init(void)
+ if (cpuidle_disabled())
+ return -ENODEV;
+
+- pm_idle_old = pm_idle;
+-
+ ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
+ if (ret)
+ return ret;
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index b89f67d..b51629e 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -123,6 +123,7 @@ struct cpuidle_driver {
+
+ #ifdef CONFIG_CPU_IDLE
+ extern void disable_cpuidle(void);
++extern int cpuidle_idle_call(void);
+
+ extern int cpuidle_register_driver(struct cpuidle_driver *drv);
+ struct cpuidle_driver *cpuidle_get_driver(void);
+@@ -137,6 +138,7 @@ extern void cpuidle_disable_device(struct cpuidle_device *dev);
+
+ #else
+ static inline void disable_cpuidle(void) { }
++static inline int cpuidle_idle_call(void) { return -ENODEV; }
+
+ static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
+ {return -ENODEV; }
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0039-cpuidle-Consistent-spelling-of-cpuidle_idle_call.patch b/patches.kzm9g/0039-cpuidle-Consistent-spelling-of-cpuidle_idle_call.patch
new file mode 100644
index 00000000000000..495c66f5cd66dc
--- /dev/null
+++ b/patches.kzm9g/0039-cpuidle-Consistent-spelling-of-cpuidle_idle_call.patch
@@ -0,0 +1,53 @@
+From 8fb27384a7f934ae0f01e86b41a8cdc22bf57ca7 Mon Sep 17 00:00:00 2001
+From: David Brown <davidb@codeaurora.org>
+Date: Thu, 4 Aug 2011 09:24:31 -0700
+Subject: cpuidle: Consistent spelling of cpuidle_idle_call()
+
+Commit a0bfa1373859e9d11dc92561a8667588803e42d8 mispells
+cpuidle_idle_call() on ARM and SH code. Fix this to be consistent.
+
+Cc: Kevin Hilman <khilman@deeprootsystems.com>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: x86@kernel.org
+Cc: Len Brown <len.brown@intel.com>
+Signed-off-by: David Brown <davidb@codeaurora.org>
+[ Also done by Mark Brown - th ebug has been around forever, and was
+ noticed in -next, but the idle tree never picked it up. Bad bad bad ]
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+(cherry picked from commit cbc158d6bfa1990f7869717bb5270867c66068d1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/kernel/process.c | 2 +-
+ arch/sh/kernel/idle.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
+index 5affc61..c9d11ea 100644
+--- a/arch/arm/kernel/process.c
++++ b/arch/arm/kernel/process.c
+@@ -200,7 +200,7 @@ void cpu_idle(void)
+ cpu_relax();
+ } else {
+ stop_critical_timings();
+- if (cpuidle_call_idle())
++ if (cpuidle_idle_call())
+ pm_idle();
+ start_critical_timings();
+ /*
+diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
+index 9c7099e..1db1968 100644
+--- a/arch/sh/kernel/idle.c
++++ b/arch/sh/kernel/idle.c
+@@ -101,7 +101,7 @@ void cpu_idle(void)
+ local_irq_disable();
+ /* Don't trace irqs off for idle */
+ stop_critical_timings();
+- if (cpuidle_call_idle())
++ if (cpuidle_idle_call())
+ pm_idle();
+ /*
+ * Sanity check to ensure that pm_idle() returns
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0040-sh-Fix-up-fallout-from-cpuidle-changes.patch b/patches.kzm9g/0040-sh-Fix-up-fallout-from-cpuidle-changes.patch
new file mode 100644
index 00000000000000..e39f543f6d5345
--- /dev/null
+++ b/patches.kzm9g/0040-sh-Fix-up-fallout-from-cpuidle-changes.patch
@@ -0,0 +1,32 @@
+From ff5ca09e2aa7d364357133e228c8f47ceccaa8a0 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Mon, 8 Aug 2011 16:30:11 +0900
+Subject: sh: Fix up fallout from cpuidle changes.
+
+Fixes up the pm_idle redefinition that was introduced with the earlier
+cpuidle changes.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit c66d3fcbf306af3c0c4b6f4e0d81467f89c67702)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/sh/kernel/idle.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
+index 1db1968..169767f 100644
+--- a/arch/sh/kernel/idle.c
++++ b/arch/sh/kernel/idle.c
+@@ -22,7 +22,7 @@
+ #include <asm/atomic.h>
+ #include <asm/smp.h>
+
+-static void (*pm_idle)(void);
++void (*pm_idle)(void);
+
+ static int hlt_counter;
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0041-cpuidle-Add-module.h-to-drivers-cpuidle-files-as-req.patch b/patches.kzm9g/0041-cpuidle-Add-module.h-to-drivers-cpuidle-files-as-req.patch
new file mode 100644
index 00000000000000..4a4ecdd8a534a1
--- /dev/null
+++ b/patches.kzm9g/0041-cpuidle-Add-module.h-to-drivers-cpuidle-files-as-req.patch
@@ -0,0 +1,41 @@
+From e642a0935f0ebf4599766c1005b6995f79a0cfcd Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Mon, 29 Aug 2011 17:52:39 -0400
+Subject: cpuidle: Add module.h to drivers/cpuidle files as required.
+
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+(cherry picked from commit 884b17e109d61e95ee4c652cf6873341bf1dca63)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/cpuidle/cpuidle.c | 1 +
+ drivers/cpuidle/governors/menu.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index 0df0141..becd6d9 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -17,6 +17,7 @@
+ #include <linux/cpuidle.h>
+ #include <linux/ktime.h>
+ #include <linux/hrtimer.h>
++#include <linux/module.h>
+ #include <trace/events/power.h>
+
+ #include "cpuidle.h"
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index 3600f19..0027524 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -19,6 +19,7 @@
+ #include <linux/tick.h>
+ #include <linux/sched.h>
+ #include <linux/math64.h>
++#include <linux/module.h>
+
+ #define BUCKETS 12
+ #define INTERVALS 8
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0042-cpuidle-Move-dev-last_residency-update-to-driver-ent.patch b/patches.kzm9g/0042-cpuidle-Move-dev-last_residency-update-to-driver-ent.patch
new file mode 100644
index 00000000000000..fb997a6fcea315
--- /dev/null
+++ b/patches.kzm9g/0042-cpuidle-Move-dev-last_residency-update-to-driver-ent.patch
@@ -0,0 +1,868 @@
+From a2bea6713199f518d94d1bcc5acbe8b7523d4b7e Mon Sep 17 00:00:00 2001
+From: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Date: Fri, 28 Oct 2011 16:20:09 +0530
+Subject: cpuidle: Move dev->last_residency update to driver enter routine;
+ remove dev->last_state
+
+Cpuidle governor only suggests the state to enter using the
+governor->select() interface, but allows the low level driver to
+override the recommended state. The actual entered state
+may be different because of software or hardware demotion. Software
+demotion is done by the back-end cpuidle driver and can be accounted
+correctly. Current cpuidle code uses last_state field to capture the
+actual state entered and based on that updates the statistics for the
+state entered.
+
+Ideally the driver enter routine should update the counters,
+and it should return the state actually entered rather than the time
+spent there. The generic cpuidle code should simply handle where
+the counters live in the sysfs namespace, not updating the counters.
+
+Reference:
+https://lkml.org/lkml/2011/3/25/52
+
+Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com>
+Tested-by: Jean Pihet <j-pihet@ti.com>
+Reviewed-by: Kevin Hilman <khilman@ti.com>
+Acked-by: Arjan van de Ven <arjan@linux.intel.com>
+Acked-by: Kevin Hilman <khilman@ti.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit e978aa7d7d57d04eb5f88a7507c4fb98577def77)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-at91/cpuidle.c | 10 +++--
+ arch/arm/mach-davinci/cpuidle.c | 9 ++--
+ arch/arm/mach-exynos4/cpuidle.c | 7 +--
+ arch/arm/mach-kirkwood/cpuidle.c | 12 ++++--
+ arch/arm/mach-omap2/cpuidle34xx.c | 67 +++++++++++++++++------------
+ arch/sh/kernel/cpu/shmobile/cpuidle.c | 12 +++---
+ drivers/acpi/processor_idle.c | 75 +++++++++++++++++++++------------
+ drivers/cpuidle/cpuidle.c | 32 +++++++-------
+ drivers/cpuidle/governors/ladder.c | 13 ++++++
+ drivers/cpuidle/governors/menu.c | 7 ++-
+ drivers/idle/intel_idle.c | 12 ++++--
+ include/linux/cpuidle.h | 7 ++-
+ 12 files changed, 164 insertions(+), 99 deletions(-)
+
+diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
+index f474272..d76a600 100644
+--- a/arch/arm/mach-at91/cpuidle.c
++++ b/arch/arm/mach-at91/cpuidle.c
+@@ -34,7 +34,7 @@ static struct cpuidle_driver at91_idle_driver = {
+
+ /* Actual code that puts the SoC in different idle states */
+ static int at91_enter_idle(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ struct timeval before, after;
+ int idle_time;
+@@ -42,10 +42,10 @@ static int at91_enter_idle(struct cpuidle_device *dev,
+
+ local_irq_disable();
+ do_gettimeofday(&before);
+- if (state == &dev->states[0])
++ if (index == 0)
+ /* Wait for interrupt state */
+ cpu_do_idle();
+- else if (state == &dev->states[1]) {
++ else if (index == 1) {
+ asm("b 1f; .align 5; 1:");
+ asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
+ saved_lpr = sdram_selfrefresh_enable();
+@@ -56,7 +56,9 @@ static int at91_enter_idle(struct cpuidle_device *dev,
+ local_irq_enable();
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+- return idle_time;
++
++ dev->last_residency = idle_time;
++ return index;
+ }
+
+ /* Initialize CPU idle by registering the idle states */
+diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
+index 85cc399..ab9a9e4 100644
+--- a/arch/arm/mach-davinci/cpuidle.c
++++ b/arch/arm/mach-davinci/cpuidle.c
+@@ -79,9 +79,9 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
+
+ /* Actual code that puts the SoC in different idle states */
+ static int davinci_enter_idle(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+- struct davinci_ops *ops = cpuidle_get_statedata(state);
++ struct davinci_ops *ops = cpuidle_get_statedata(&dev->states[index]);
+ struct timeval before, after;
+ int idle_time;
+
+@@ -99,7 +99,10 @@ static int davinci_enter_idle(struct cpuidle_device *dev,
+ local_irq_enable();
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+- return idle_time;
++
++ dev->last_residency = idle_time;
++
++ return index;
+ }
+
+ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
+diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c
+index bf7e96f..ea026e7 100644
+--- a/arch/arm/mach-exynos4/cpuidle.c
++++ b/arch/arm/mach-exynos4/cpuidle.c
+@@ -16,7 +16,7 @@
+ #include <asm/proc-fns.h>
+
+ static int exynos4_enter_idle(struct cpuidle_device *dev,
+- struct cpuidle_state *state);
++ int index);
+
+ static struct cpuidle_state exynos4_cpuidle_set[] = {
+ [0] = {
+@@ -37,7 +37,7 @@ static struct cpuidle_driver exynos4_idle_driver = {
+ };
+
+ static int exynos4_enter_idle(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ struct timeval before, after;
+ int idle_time;
+@@ -52,7 +52,8 @@ static int exynos4_enter_idle(struct cpuidle_device *dev,
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+
+- return idle_time;
++ dev->last_residency = idle_time;
++ return index;
+ }
+
+ static int __init exynos4_init_cpuidle(void)
+diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c
+index 864e569..53d6049 100644
+--- a/arch/arm/mach-kirkwood/cpuidle.c
++++ b/arch/arm/mach-kirkwood/cpuidle.c
+@@ -33,17 +33,17 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
+
+ /* Actual code that puts the SoC in different idle states */
+ static int kirkwood_enter_idle(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ struct timeval before, after;
+ int idle_time;
+
+ local_irq_disable();
+ do_gettimeofday(&before);
+- if (state == &dev->states[0])
++ if (index == 0)
+ /* Wait for interrupt state */
+ cpu_do_idle();
+- else if (state == &dev->states[1]) {
++ else if (index == 1) {
+ /*
+ * Following write will put DDR in self refresh.
+ * Note that we have 256 cycles before DDR puts it
+@@ -58,7 +58,11 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
+ local_irq_enable();
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+- return idle_time;
++
++ /* Update last residency */
++ dev->last_residency = idle_time;
++
++ return index;
+ }
+
+ /* Initialize CPU idle by registering the idle states */
+diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
+index 4bf6e6e..58425c7 100644
+--- a/arch/arm/mach-omap2/cpuidle34xx.c
++++ b/arch/arm/mach-omap2/cpuidle34xx.c
+@@ -88,17 +88,19 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
+ /**
+ * omap3_enter_idle - Programs OMAP3 to enter the specified state
+ * @dev: cpuidle device
+- * @state: The target state to be programmed
++ * @index: the index of state to be entered
+ *
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ */
+ static int omap3_enter_idle(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+- struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
++ struct omap3_idle_statedata *cx =
++ cpuidle_get_statedata(&dev->states[index]);
+ struct timespec ts_preidle, ts_postidle, ts_idle;
+ u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
++ int idle_time;
+
+ /* Used to keep track of the total time in idle */
+ getnstimeofday(&ts_preidle);
+@@ -113,7 +115,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
+ goto return_sleep_time;
+
+ /* Deny idle for C1 */
+- if (state == &dev->states[0]) {
++ if (index == 0) {
+ pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
+ pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
+ }
+@@ -122,7 +124,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
+ omap_sram_idle();
+
+ /* Re-allow idle for C1 */
+- if (state == &dev->states[0]) {
++ if (index == 0) {
+ pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
+ pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
+ }
+@@ -134,28 +136,35 @@ return_sleep_time:
+ local_irq_enable();
+ local_fiq_enable();
+
+- return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
++ idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
++ USEC_PER_SEC;
++
++ /* Update cpuidle counters */
++ dev->last_residency = idle_time;
++
++ return index;
+ }
+
+ /**
+ * next_valid_state - Find next valid C-state
+ * @dev: cpuidle device
+- * @state: Currently selected C-state
++ * @index: Index of currently selected c-state
+ *
+- * If the current state is valid, it is returned back to the caller.
+- * Else, this function searches for a lower c-state which is still
+- * valid.
++ * If the state corresponding to index is valid, index is returned back
++ * to the caller. Else, this function searches for a lower c-state which is
++ * still valid (as defined in omap3_power_states[]) and returns its index.
+ *
+ * A state is valid if the 'valid' field is enabled and
+ * if it satisfies the enable_off_mode condition.
+ */
+-static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
+- struct cpuidle_state *curr)
++static int next_valid_state(struct cpuidle_device *dev,
++ int index)
+ {
+- struct cpuidle_state *next = NULL;
++ struct cpuidle_state *curr = &dev->states[index];
+ struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
+ u32 mpu_deepest_state = PWRDM_POWER_RET;
+ u32 core_deepest_state = PWRDM_POWER_RET;
++ int next_index = -1;
+
+ if (enable_off_mode) {
+ mpu_deepest_state = PWRDM_POWER_OFF;
+@@ -172,20 +181,20 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
+ if ((cx->valid) &&
+ (cx->mpu_state >= mpu_deepest_state) &&
+ (cx->core_state >= core_deepest_state)) {
+- return curr;
++ return index;
+ } else {
+ int idx = OMAP3_NUM_STATES - 1;
+
+ /* Reach the current state starting at highest C-state */
+ for (; idx >= 0; idx--) {
+ if (&dev->states[idx] == curr) {
+- next = &dev->states[idx];
++ next_index = idx;
+ break;
+ }
+ }
+
+ /* Should never hit this condition */
+- WARN_ON(next == NULL);
++ WARN_ON(next_index == -1);
+
+ /*
+ * Drop to next valid state.
+@@ -197,37 +206,39 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
+ if ((cx->valid) &&
+ (cx->mpu_state >= mpu_deepest_state) &&
+ (cx->core_state >= core_deepest_state)) {
+- next = &dev->states[idx];
++ next_index = idx;
+ break;
+ }
+ }
+ /*
+ * C1 is always valid.
+- * So, no need to check for 'next==NULL' outside this loop.
++ * So, no need to check for 'next_index == -1' outside
++ * this loop.
+ */
+ }
+
+- return next;
++ return next_index;
+ }
+
+ /**
+ * omap3_enter_idle_bm - Checks for any bus activity
+ * @dev: cpuidle device
+- * @state: The target state to be programmed
++ * @index: array index of target state to be programmed
+ *
+ * This function checks for any pending activity and then programs
+ * the device to the specified or a safer state.
+ */
+ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+- struct cpuidle_state *new_state;
++ struct cpuidle_state *state = &dev->states[index];
++ int new_state_idx;
+ u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+ struct omap3_idle_statedata *cx;
+ int ret;
+
+ if (!omap3_can_sleep()) {
+- new_state = dev->safe_state;
++ new_state_idx = dev->safe_state_index;
+ goto select_state;
+ }
+
+@@ -237,7 +248,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ */
+ cam_state = pwrdm_read_pwrst(cam_pd);
+ if (cam_state == PWRDM_POWER_ON) {
+- new_state = dev->safe_state;
++ new_state_idx = dev->safe_state_index;
+ goto select_state;
+ }
+
+@@ -264,11 +275,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ if (per_next_state != per_saved_state)
+ pwrdm_set_next_pwrst(per_pd, per_next_state);
+
+- new_state = next_valid_state(dev, state);
++ new_state_idx = next_valid_state(dev, index);
+
+ select_state:
+- dev->last_state = new_state;
+- ret = omap3_enter_idle(dev, new_state);
++ ret = omap3_enter_idle(dev, new_state_idx);
+
+ /* Restore original PER state if it was modified */
+ if (per_next_state != per_saved_state)
+@@ -339,11 +349,12 @@ int __init omap3_idle_init(void)
+
+ cpuidle_register_driver(&omap3_idle_driver);
+ dev = &per_cpu(omap3_idle_dev, smp_processor_id());
++ dev->safe_state_index = -1;
+
+ /* C1 . MPU WFI + Core active */
+ cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
+ (&dev->states[0])->enter = omap3_enter_idle;
+- dev->safe_state = &dev->states[0];
++ dev->safe_state_index = 0;
+ cx->valid = 1; /* C1 is always valid */
+ cx->mpu_state = PWRDM_POWER_ON;
+ cx->core_state = PWRDM_POWER_ON;
+diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
+index e4469e72..7be50d4c 100644
+--- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
++++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
+@@ -25,11 +25,11 @@ static unsigned long cpuidle_mode[] = {
+ };
+
+ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ unsigned long allowed_mode = arch_hwblk_sleep_mode();
+ ktime_t before, after;
+- int requested_state = state - &dev->states[0];
++ int requested_state = index;
+ int allowed_state;
+ int k;
+
+@@ -46,11 +46,13 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
+ */
+ k = min_t(int, allowed_state, requested_state);
+
+- dev->last_state = &dev->states[k];
+ before = ktime_get();
+ sh_mobile_call_standby(cpuidle_mode[k]);
+ after = ktime_get();
+- return ktime_to_ns(ktime_sub(after, before)) >> 10;
++
++ dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10;
++
++ return k;
+ }
+
+ static struct cpuidle_device cpuidle_dev;
+@@ -84,7 +86,7 @@ void sh_mobile_setup_cpuidle(void)
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = cpuidle_sleep_enter;
+
+- dev->safe_state = state;
++ dev->safe_state_index = i-1;
+
+ if (sh_mobile_sleep_supported & SUSP_SH_SF) {
+ state = &dev->states[i++];
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 2e69e09..6be70bf 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -741,22 +741,24 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
+ /**
+ * acpi_idle_enter_c1 - enters an ACPI C1 state-type
+ * @dev: the target CPU
+- * @state: the state data
++ * @index: index of target state
+ *
+ * This is equivalent to the HALT instruction.
+ */
+ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ ktime_t kt1, kt2;
+ s64 idle_time;
+ struct acpi_processor *pr;
++ struct cpuidle_state *state = &dev->states[index];
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+
+ pr = __this_cpu_read(processors);
++ dev->last_residency = 0;
+
+ if (unlikely(!pr))
+- return 0;
++ return -EINVAL;
+
+ local_irq_disable();
+
+@@ -764,7 +766,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+ if (acpi_idle_suspend) {
+ local_irq_enable();
+ cpu_relax();
+- return 0;
++ return -EINVAL;
+ }
+
+ lapic_timer_state_broadcast(pr, cx, 1);
+@@ -773,37 +775,46 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+ kt2 = ktime_get_real();
+ idle_time = ktime_to_us(ktime_sub(kt2, kt1));
+
++ /* Update device last_residency*/
++ dev->last_residency = (int)idle_time;
++
+ local_irq_enable();
+ cx->usage++;
+ lapic_timer_state_broadcast(pr, cx, 0);
+
+- return idle_time;
++ return index;
+ }
+
+ /**
+ * acpi_idle_enter_simple - enters an ACPI state without BM handling
+ * @dev: the target CPU
+- * @state: the state data
++ * @index: the index of suggested state
+ */
+ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ struct acpi_processor *pr;
++ struct cpuidle_state *state = &dev->states[index];
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+ ktime_t kt1, kt2;
+ s64 idle_time_ns;
+ s64 idle_time;
+
+ pr = __this_cpu_read(processors);
++ dev->last_residency = 0;
+
+ if (unlikely(!pr))
+- return 0;
+-
+- if (acpi_idle_suspend)
+- return(acpi_idle_enter_c1(dev, state));
++ return -EINVAL;
+
+ local_irq_disable();
+
++ if (acpi_idle_suspend) {
++ local_irq_enable();
++ cpu_relax();
++ return -EINVAL;
++ }
++
++
+ if (cx->entry_method != ACPI_CSTATE_FFH) {
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+@@ -815,7 +826,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+ if (unlikely(need_resched())) {
+ current_thread_info()->status |= TS_POLLING;
+ local_irq_enable();
+- return 0;
++ return -EINVAL;
+ }
+ }
+
+@@ -837,6 +848,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+ idle_time = idle_time_ns;
+ do_div(idle_time, NSEC_PER_USEC);
+
++ /* Update device last_residency*/
++ dev->last_residency = (int)idle_time;
++
+ /* Tell the scheduler how much we idled: */
+ sched_clock_idle_wakeup_event(idle_time_ns);
+
+@@ -848,7 +862,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+
+ lapic_timer_state_broadcast(pr, cx, 0);
+ cx->time += idle_time;
+- return idle_time;
++ return index;
+ }
+
+ static int c3_cpu_count;
+@@ -857,14 +871,15 @@ static DEFINE_SPINLOCK(c3_lock);
+ /**
+ * acpi_idle_enter_bm - enters C3 with proper BM handling
+ * @dev: the target CPU
+- * @state: the state data
++ * @index: the index of suggested state
+ *
+ * If BM is detected, the deepest non-C3 idle state is entered instead.
+ */
+ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+- struct cpuidle_state *state)
++ int index)
+ {
+ struct acpi_processor *pr;
++ struct cpuidle_state *state = &dev->states[index];
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+ ktime_t kt1, kt2;
+ s64 idle_time_ns;
+@@ -872,22 +887,26 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+
+
+ pr = __this_cpu_read(processors);
++ dev->last_residency = 0;
+
+ if (unlikely(!pr))
+- return 0;
++ return -EINVAL;
+
+- if (acpi_idle_suspend)
+- return(acpi_idle_enter_c1(dev, state));
++
++ if (acpi_idle_suspend) {
++ cpu_relax();
++ return -EINVAL;
++ }
+
+ if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
+- if (dev->safe_state) {
+- dev->last_state = dev->safe_state;
+- return dev->safe_state->enter(dev, dev->safe_state);
++ if (dev->safe_state_index >= 0) {
++ return dev->states[dev->safe_state_index].enter(dev,
++ dev->safe_state_index);
+ } else {
+ local_irq_disable();
+ acpi_safe_halt();
+ local_irq_enable();
+- return 0;
++ return -EINVAL;
+ }
+ }
+
+@@ -904,7 +923,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+ if (unlikely(need_resched())) {
+ current_thread_info()->status |= TS_POLLING;
+ local_irq_enable();
+- return 0;
++ return -EINVAL;
+ }
+ }
+
+@@ -954,6 +973,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+ idle_time = idle_time_ns;
+ do_div(idle_time, NSEC_PER_USEC);
+
++ /* Update device last_residency*/
++ dev->last_residency = (int)idle_time;
++
+ /* Tell the scheduler how much we idled: */
+ sched_clock_idle_wakeup_event(idle_time_ns);
+
+@@ -965,7 +987,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+
+ lapic_timer_state_broadcast(pr, cx, 0);
+ cx->time += idle_time;
+- return idle_time;
++ return index;
+ }
+
+ struct cpuidle_driver acpi_idle_driver = {
+@@ -992,6 +1014,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ }
+
+ dev->cpu = pr->id;
++ dev->safe_state_index = -1;
+ for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+ dev->states[i].name[0] = '\0';
+ dev->states[i].desc[0] = '\0';
+@@ -1027,13 +1050,13 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+
+ state->enter = acpi_idle_enter_c1;
+- dev->safe_state = state;
++ dev->safe_state_index = count;
+ break;
+
+ case ACPI_STATE_C2:
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = acpi_idle_enter_simple;
+- dev->safe_state = state;
++ dev->safe_state_index = count;
+ break;
+
+ case ACPI_STATE_C3:
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index becd6d9..c0f1a3a 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -63,7 +63,7 @@ int cpuidle_idle_call(void)
+ {
+ struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+ struct cpuidle_state *target_state;
+- int next_state;
++ int next_state, entered_state;
+
+ if (off)
+ return -ENODEV;
+@@ -103,26 +103,27 @@ int cpuidle_idle_call(void)
+
+ target_state = &dev->states[next_state];
+
+- /* enter the state and update stats */
+- dev->last_state = target_state;
+-
+ trace_power_start(POWER_CSTATE, next_state, dev->cpu);
+ trace_cpu_idle(next_state, dev->cpu);
+
+- dev->last_residency = target_state->enter(dev, target_state);
++ entered_state = target_state->enter(dev, next_state);
+
+ trace_power_end(dev->cpu);
+ trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
+
+- if (dev->last_state)
+- target_state = dev->last_state;
+-
+- target_state->time += (unsigned long long)dev->last_residency;
+- target_state->usage++;
++ if (entered_state >= 0) {
++ /* Update cpuidle counters */
++ /* This can be moved to within driver enter routine
++ * but that results in multiple copies of same code.
++ */
++ dev->states[entered_state].time +=
++ (unsigned long long)dev->last_residency;
++ dev->states[entered_state].usage++;
++ }
+
+ /* give the governor an opportunity to reflect on the outcome */
+ if (cpuidle_curr_governor->reflect)
+- cpuidle_curr_governor->reflect(dev);
++ cpuidle_curr_governor->reflect(dev, entered_state);
+
+ return 0;
+ }
+@@ -173,11 +174,10 @@ void cpuidle_resume_and_unlock(void)
+ EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
+
+ #ifdef CONFIG_ARCH_HAS_CPU_RELAX
+-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
++static int poll_idle(struct cpuidle_device *dev, int index)
+ {
+ ktime_t t1, t2;
+ s64 diff;
+- int ret;
+
+ t1 = ktime_get();
+ local_irq_enable();
+@@ -189,8 +189,9 @@ static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+
+- ret = (int) diff;
+- return ret;
++ dev->last_residency = (int) diff;
++
++ return index;
+ }
+
+ static void poll_idle_init(struct cpuidle_device *dev)
+@@ -249,7 +250,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
+ dev->states[i].time = 0;
+ }
+ dev->last_residency = 0;
+- dev->last_state = NULL;
+
+ smp_wmb();
+
+diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
+index f62fde2..78b06d2 100644
+--- a/drivers/cpuidle/governors/ladder.c
++++ b/drivers/cpuidle/governors/ladder.c
+@@ -153,11 +153,24 @@ static int ladder_enable_device(struct cpuidle_device *dev)
+ return 0;
+ }
+
++/**
++ * ladder_reflect - update the correct last_state_idx
++ * @dev: the CPU
++ * @index: the index of actual state entered
++ */
++static void ladder_reflect(struct cpuidle_device *dev, int index)
++{
++ struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
++ if (index > 0)
++ ldev->last_state_idx = index;
++}
++
+ static struct cpuidle_governor ladder_governor = {
+ .name = "ladder",
+ .rating = 10,
+ .enable = ladder_enable_device,
+ .select = ladder_select_state,
++ .reflect = ladder_reflect,
+ .owner = THIS_MODULE,
+ };
+
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index 0027524..e27a2af 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -311,14 +311,17 @@ static int menu_select(struct cpuidle_device *dev)
+ /**
+ * menu_reflect - records that data structures need update
+ * @dev: the CPU
++ * @index: the index of actual entered state
+ *
+ * NOTE: it's important to be fast here because this operation will add to
+ * the overall exit latency.
+ */
+-static void menu_reflect(struct cpuidle_device *dev)
++static void menu_reflect(struct cpuidle_device *dev, int index)
+ {
+ struct menu_device *data = &__get_cpu_var(menu_devices);
+- data->needs_update = 1;
++ data->last_state_idx = index;
++ if (index >= 0)
++ data->needs_update = 1;
+ }
+
+ /**
+diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
+index 026f9aa..8f056e1 100644
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -81,7 +81,7 @@ static unsigned int mwait_substates;
+ static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
+
+ static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
+-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
++static int intel_idle(struct cpuidle_device *dev, int index);
+
+ static struct cpuidle_state *cpuidle_state_table;
+
+@@ -209,12 +209,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ /**
+ * intel_idle
+ * @dev: cpuidle_device
+- * @state: cpuidle state
++ * @index: index of cpuidle state
+ *
+ */
+-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
++static int intel_idle(struct cpuidle_device *dev, int index)
+ {
+ unsigned long ecx = 1; /* break on interrupt flag */
++ struct cpuidle_state *state = &dev->states[index];
+ unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
+ unsigned int cstate;
+ ktime_t kt_before, kt_after;
+@@ -256,7 +257,10 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
+ if (!(lapic_timer_reliable_states & (1 << (cstate))))
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+
+- return usec_delta;
++ /* Update cpuidle counters */
++ dev->last_residency = (int)usec_delta;
++
++ return index;
+ }
+
+ static void __setup_broadcast_timer(void *arg)
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index b51629e..8da811b 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -42,7 +42,7 @@ struct cpuidle_state {
+ unsigned long long time; /* in US */
+
+ int (*enter) (struct cpuidle_device *dev,
+- struct cpuidle_state *state);
++ int index);
+ };
+
+ /* Idle State Flags */
+@@ -87,13 +87,12 @@ struct cpuidle_device {
+ int state_count;
+ struct cpuidle_state states[CPUIDLE_STATE_MAX];
+ struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
+- struct cpuidle_state *last_state;
+
+ struct list_head device_list;
+ struct kobject kobj;
+ struct completion kobj_unregister;
+ void *governor_data;
+- struct cpuidle_state *safe_state;
++ int safe_state_index;
+
+ int (*prepare) (struct cpuidle_device *dev);
+ };
+@@ -169,7 +168,7 @@ struct cpuidle_governor {
+ void (*disable) (struct cpuidle_device *dev);
+
+ int (*select) (struct cpuidle_device *dev);
+- void (*reflect) (struct cpuidle_device *dev);
++ void (*reflect) (struct cpuidle_device *dev, int index);
+
+ struct module *owner;
+ };
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0043-cpuidle-Remove-CPUIDLE_FLAG_IGNORE-and-dev-prepare.patch b/patches.kzm9g/0043-cpuidle-Remove-CPUIDLE_FLAG_IGNORE-and-dev-prepare.patch
new file mode 100644
index 00000000000000..549d142a86ca94
--- /dev/null
+++ b/patches.kzm9g/0043-cpuidle-Remove-CPUIDLE_FLAG_IGNORE-and-dev-prepare.patch
@@ -0,0 +1,89 @@
+From bdf8107f9e58c5563946d7cb46e1bed307ce2653 Mon Sep 17 00:00:00 2001
+From: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Date: Fri, 28 Oct 2011 16:20:24 +0530
+Subject: cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev->prepare()
+
+The cpuidle_device->prepare() mechanism causes updates to the
+cpuidle_state[].flags, setting and clearing CPUIDLE_FLAG_IGNORE
+to tell the governor not to chose a state on a per-cpu basis at
+run-time. State demotion is now handled by the driver and it returns
+the actual state entered. Hence, this mechanism is not required.
+Also this removes per-cpu flags from cpuidle_state enabling
+it to be made global.
+
+Reference:
+https://lkml.org/lkml/2011/3/25/52
+
+Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm>
+Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com>
+Tested-by: Jean Pihet <j-pihet@ti.com>
+Acked-by: Arjan van de Ven <arjan@linux.intel.com>
+Reviewed-by: Kevin Hilman <khilman@ti.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit b25edc42bfb9602f0503474b2c94701d5536ce60)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/cpuidle/cpuidle.c | 10 ----------
+ drivers/cpuidle/governors/menu.c | 2 --
+ include/linux/cpuidle.h | 3 ---
+ 3 files changed, 15 deletions(-)
+
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index c0f1a3a..70350d2 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -84,16 +84,6 @@ int cpuidle_idle_call(void)
+ hrtimer_peek_ahead_timers();
+ #endif
+
+- /*
+- * Call the device's prepare function before calling the
+- * governor's select function. ->prepare gives the device's
+- * cpuidle driver a chance to update any dynamic information
+- * of its cpuidle states for the current idle period, e.g.
+- * state availability, latencies, residencies, etc.
+- */
+- if (dev->prepare)
+- dev->prepare(dev);
+-
+ /* ask the governor for the next state */
+ next_state = cpuidle_curr_governor->select(dev);
+ if (need_resched()) {
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index e27a2af..2072aeb 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -289,8 +289,6 @@ static int menu_select(struct cpuidle_device *dev)
+ for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
+ struct cpuidle_state *s = &dev->states[i];
+
+- if (s->flags & CPUIDLE_FLAG_IGNORE)
+- continue;
+ if (s->target_residency > data->predicted_us)
+ continue;
+ if (s->exit_latency > latency_req)
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index 8da811b..c6d85cf 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -47,7 +47,6 @@ struct cpuidle_state {
+
+ /* Idle State Flags */
+ #define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */
+-#define CPUIDLE_FLAG_IGNORE (0x100) /* ignore during this idle period */
+
+ #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
+
+@@ -93,8 +92,6 @@ struct cpuidle_device {
+ struct completion kobj_unregister;
+ void *governor_data;
+ int safe_state_index;
+-
+- int (*prepare) (struct cpuidle_device *dev);
+ };
+
+ DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0044-cpuidle-Split-cpuidle_state-structure-and-move-per-c.patch b/patches.kzm9g/0044-cpuidle-Split-cpuidle_state-structure-and-move-per-c.patch
new file mode 100644
index 00000000000000..d41a55c17819b7
--- /dev/null
+++ b/patches.kzm9g/0044-cpuidle-Split-cpuidle_state-structure-and-move-per-c.patch
@@ -0,0 +1,531 @@
+From f3127a05382f54ff79a80cddcabc22ffdfb510e0 Mon Sep 17 00:00:00 2001
+From: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Date: Fri, 28 Oct 2011 16:20:33 +0530
+Subject: cpuidle: Split cpuidle_state structure and move per-cpu statistics
+ fields
+
+This is the first step towards global registration of cpuidle
+states. The statistics used primarily by the governor are per-cpu
+and have to be split from rest of the fields inside cpuidle_state,
+which would be made global i.e. single copy. The driver_data field
+is also per-cpu and moved.
+
+Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com>
+Tested-by: Jean Pihet <j-pihet@ti.com>
+Reviewed-by: Kevin Hilman <khilman@ti.com>
+Acked-by: Arjan van de Ven <arjan@linux.intel.com>
+Acked-by: Kevin Hilman <khilman@ti.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit 4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-davinci/cpuidle.c | 5 ++--
+ arch/arm/mach-omap2/cpuidle34xx.c | 13 ++++++-----
+ drivers/acpi/processor_idle.c | 25 ++++++++++----------
+ drivers/cpuidle/cpuidle.c | 11 +++++----
+ drivers/cpuidle/sysfs.c | 19 ++++++++++-----
+ drivers/idle/intel_idle.c | 46 +++++++++++++++++++++++++++----------
+ include/linux/cpuidle.h | 25 ++++++++++++--------
+ 7 files changed, 90 insertions(+), 54 deletions(-)
+
+diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
+index ab9a9e4..dda6d2f 100644
+--- a/arch/arm/mach-davinci/cpuidle.c
++++ b/arch/arm/mach-davinci/cpuidle.c
+@@ -81,7 +81,8 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
+ static int davinci_enter_idle(struct cpuidle_device *dev,
+ int index)
+ {
+- struct davinci_ops *ops = cpuidle_get_statedata(&dev->states[index]);
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
++ struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
+ struct timeval before, after;
+ int idle_time;
+
+@@ -143,7 +144,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
+ strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+ if (pdata->ddr2_pdown)
+ davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
+- cpuidle_set_statedata(&device->states[1], &davinci_states[1]);
++ cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
+
+ device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+
+diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
+index 58425c7..d3fce7b 100644
+--- a/arch/arm/mach-omap2/cpuidle34xx.c
++++ b/arch/arm/mach-omap2/cpuidle34xx.c
+@@ -97,7 +97,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
+ int index)
+ {
+ struct omap3_idle_statedata *cx =
+- cpuidle_get_statedata(&dev->states[index]);
++ cpuidle_get_statedata(&dev->states_usage[index]);
+ struct timespec ts_preidle, ts_postidle, ts_idle;
+ u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
+ int idle_time;
+@@ -160,8 +160,9 @@ return_sleep_time:
+ static int next_valid_state(struct cpuidle_device *dev,
+ int index)
+ {
++ struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
+ struct cpuidle_state *curr = &dev->states[index];
+- struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
++ struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
+ u32 mpu_deepest_state = PWRDM_POWER_RET;
+ u32 core_deepest_state = PWRDM_POWER_RET;
+ int next_index = -1;
+@@ -202,7 +203,7 @@ static int next_valid_state(struct cpuidle_device *dev,
+ */
+ idx--;
+ for (; idx >= 0; idx--) {
+- cx = cpuidle_get_statedata(&dev->states[idx]);
++ cx = cpuidle_get_statedata(&dev->states_usage[idx]);
+ if ((cx->valid) &&
+ (cx->mpu_state >= mpu_deepest_state) &&
+ (cx->core_state >= core_deepest_state)) {
+@@ -231,7 +232,6 @@ static int next_valid_state(struct cpuidle_device *dev,
+ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ int index)
+ {
+- struct cpuidle_state *state = &dev->states[index];
+ int new_state_idx;
+ u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+ struct omap3_idle_statedata *cx;
+@@ -264,7 +264,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ * Prevent PER off if CORE is not in retention or off as this
+ * would disable PER wakeups completely.
+ */
+- cx = cpuidle_get_statedata(state);
++ cx = cpuidle_get_statedata(&dev->states_usage[index]);
+ core_next_state = cx->core_state;
+ per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
+ if ((per_next_state == PWRDM_POWER_OFF) &&
+@@ -318,6 +318,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
+ {
+ struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
+ struct cpuidle_state *state = &dev->states[idx];
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
+
+ state->exit_latency = cpuidle_params_table[idx].exit_latency;
+ state->target_residency = cpuidle_params_table[idx].target_residency;
+@@ -326,7 +327,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
+ cx->valid = cpuidle_params_table[idx].valid;
+ sprintf(state->name, "C%d", idx + 1);
+ strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
+- cpuidle_set_statedata(state, cx);
++ cpuidle_set_statedata(state_usage, cx);
+
+ return cx;
+ }
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 6be70bf..c7b89f0 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -745,14 +745,13 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
+ *
+ * This is equivalent to the HALT instruction.
+ */
+-static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+- int index)
++static int acpi_idle_enter_c1(struct cpuidle_device *dev, int index)
+ {
+ ktime_t kt1, kt2;
+ s64 idle_time;
+ struct acpi_processor *pr;
+- struct cpuidle_state *state = &dev->states[index];
+- struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
++ struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
+
+ pr = __this_cpu_read(processors);
+ dev->last_residency = 0;
+@@ -790,12 +789,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+ * @dev: the target CPU
+ * @index: the index of suggested state
+ */
+-static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+- int index)
++static int acpi_idle_enter_simple(struct cpuidle_device *dev, int index)
+ {
+ struct acpi_processor *pr;
+- struct cpuidle_state *state = &dev->states[index];
+- struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
++ struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
+ ktime_t kt1, kt2;
+ s64 idle_time_ns;
+ s64 idle_time;
+@@ -875,12 +873,11 @@ static DEFINE_SPINLOCK(c3_lock);
+ *
+ * If BM is detected, the deepest non-C3 idle state is entered instead.
+ */
+-static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+- int index)
++static int acpi_idle_enter_bm(struct cpuidle_device *dev, int index)
+ {
+ struct acpi_processor *pr;
+- struct cpuidle_state *state = &dev->states[index];
+- struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
++ struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
+ ktime_t kt1, kt2;
+ s64 idle_time_ns;
+ s64 idle_time;
+@@ -1004,6 +1001,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ int i, count = CPUIDLE_DRIVER_STATE_START;
+ struct acpi_processor_cx *cx;
+ struct cpuidle_state *state;
++ struct cpuidle_state_usage *state_usage;
+ struct cpuidle_device *dev = &pr->power.dev;
+
+ if (!pr->flags.power_setup_done)
+@@ -1026,6 +1024,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+ cx = &pr->power.states[i];
+ state = &dev->states[count];
++ state_usage = &dev->states_usage[count];
+
+ if (!cx->valid)
+ continue;
+@@ -1036,7 +1035,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+ continue;
+ #endif
+- cpuidle_set_statedata(state, cx);
++ cpuidle_set_statedata(state_usage, cx);
+
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
+ strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index 70350d2..219a757 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -106,9 +106,9 @@ int cpuidle_idle_call(void)
+ /* This can be moved to within driver enter routine
+ * but that results in multiple copies of same code.
+ */
+- dev->states[entered_state].time +=
++ dev->states_usage[entered_state].time +=
+ (unsigned long long)dev->last_residency;
+- dev->states[entered_state].usage++;
++ dev->states_usage[entered_state].usage++;
+ }
+
+ /* give the governor an opportunity to reflect on the outcome */
+@@ -187,8 +187,9 @@ static int poll_idle(struct cpuidle_device *dev, int index)
+ static void poll_idle_init(struct cpuidle_device *dev)
+ {
+ struct cpuidle_state *state = &dev->states[0];
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[0];
+
+- cpuidle_set_statedata(state, NULL);
++ cpuidle_set_statedata(state_usage, NULL);
+
+ snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
+ snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
+@@ -236,8 +237,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
+ goto fail_sysfs;
+
+ for (i = 0; i < dev->state_count; i++) {
+- dev->states[i].usage = 0;
+- dev->states[i].time = 0;
++ dev->states_usage[i].usage = 0;
++ dev->states_usage[i].time = 0;
+ }
+ dev->last_residency = 0;
+
+diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
+index be7917ec..8a1ace1 100644
+--- a/drivers/cpuidle/sysfs.c
++++ b/drivers/cpuidle/sysfs.c
+@@ -216,7 +216,8 @@ static struct kobj_type ktype_cpuidle = {
+
+ struct cpuidle_state_attr {
+ struct attribute attr;
+- ssize_t (*show)(struct cpuidle_state *, char *);
++ ssize_t (*show)(struct cpuidle_state *, \
++ struct cpuidle_state_usage *, char *);
+ ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
+ };
+
+@@ -224,19 +225,22 @@ struct cpuidle_state_attr {
+ static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
+
+ #define define_show_state_function(_name) \
+-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
++static ssize_t show_state_##_name(struct cpuidle_state *state, \
++ struct cpuidle_state_usage *state_usage, char *buf) \
+ { \
+ return sprintf(buf, "%u\n", state->_name);\
+ }
+
+ #define define_show_state_ull_function(_name) \
+-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
++static ssize_t show_state_##_name(struct cpuidle_state *state, \
++ struct cpuidle_state_usage *state_usage, char *buf) \
+ { \
+- return sprintf(buf, "%llu\n", state->_name);\
++ return sprintf(buf, "%llu\n", state_usage->_name);\
+ }
+
+ #define define_show_state_str_function(_name) \
+-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
++static ssize_t show_state_##_name(struct cpuidle_state *state, \
++ struct cpuidle_state_usage *state_usage, char *buf) \
+ { \
+ if (state->_name[0] == '\0')\
+ return sprintf(buf, "<null>\n");\
+@@ -269,16 +273,18 @@ static struct attribute *cpuidle_state_default_attrs[] = {
+
+ #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
+ #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
++#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
+ #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
+ static ssize_t cpuidle_state_show(struct kobject * kobj,
+ struct attribute * attr ,char * buf)
+ {
+ int ret = -EIO;
+ struct cpuidle_state *state = kobj_to_state(kobj);
++ struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
+ struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
+
+ if (cattr->show)
+- ret = cattr->show(state, buf);
++ ret = cattr->show(state, state_usage, buf);
+
+ return ret;
+ }
+@@ -323,6 +329,7 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+ if (!kobj)
+ goto error_state;
+ kobj->state = &device->states[i];
++ kobj->state_usage = &device->states_usage[i];
+ init_completion(&kobj->kobj_unregister);
+
+ ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
+diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
+index 8f056e1..b0c63e9 100644
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -109,7 +109,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C1 */
+ .name = "C1-NHM",
+ .desc = "MWAIT 0x00",
+- .driver_data = (void *) 0x00,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 3,
+ .target_residency = 6,
+@@ -117,7 +116,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C2 */
+ .name = "C3-NHM",
+ .desc = "MWAIT 0x10",
+- .driver_data = (void *) 0x10,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 20,
+ .target_residency = 80,
+@@ -125,7 +123,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C3 */
+ .name = "C6-NHM",
+ .desc = "MWAIT 0x20",
+- .driver_data = (void *) 0x20,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 200,
+ .target_residency = 800,
+@@ -137,7 +134,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C1 */
+ .name = "C1-SNB",
+ .desc = "MWAIT 0x00",
+- .driver_data = (void *) 0x00,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 1,
+ .target_residency = 1,
+@@ -145,7 +141,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C2 */
+ .name = "C3-SNB",
+ .desc = "MWAIT 0x10",
+- .driver_data = (void *) 0x10,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 80,
+ .target_residency = 211,
+@@ -153,7 +148,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C3 */
+ .name = "C6-SNB",
+ .desc = "MWAIT 0x20",
+- .driver_data = (void *) 0x20,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 104,
+ .target_residency = 345,
+@@ -161,7 +155,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C4 */
+ .name = "C7-SNB",
+ .desc = "MWAIT 0x30",
+- .driver_data = (void *) 0x30,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 109,
+ .target_residency = 345,
+@@ -173,7 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C1 */
+ .name = "C1-ATM",
+ .desc = "MWAIT 0x00",
+- .driver_data = (void *) 0x00,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 1,
+ .target_residency = 4,
+@@ -181,7 +173,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C2 */
+ .name = "C2-ATM",
+ .desc = "MWAIT 0x10",
+- .driver_data = (void *) 0x10,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 20,
+ .target_residency = 80,
+@@ -190,7 +181,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C4 */
+ .name = "C4-ATM",
+ .desc = "MWAIT 0x30",
+- .driver_data = (void *) 0x30,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 100,
+ .target_residency = 400,
+@@ -199,13 +189,41 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
+ { /* MWAIT C6 */
+ .name = "C6-ATM",
+ .desc = "MWAIT 0x52",
+- .driver_data = (void *) 0x52,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 140,
+ .target_residency = 560,
+ .enter = &intel_idle },
+ };
+
++static int get_driver_data(int cstate)
++{
++ int driver_data;
++ switch (cstate) {
++
++ case 1: /* MWAIT C1 */
++ driver_data = 0x00;
++ break;
++ case 2: /* MWAIT C2 */
++ driver_data = 0x10;
++ break;
++ case 3: /* MWAIT C3 */
++ driver_data = 0x20;
++ break;
++ case 4: /* MWAIT C4 */
++ driver_data = 0x30;
++ break;
++ case 5: /* MWAIT C5 */
++ driver_data = 0x40;
++ break;
++ case 6: /* MWAIT C6 */
++ driver_data = 0x52;
++ break;
++ default:
++ driver_data = 0x00;
++ }
++ return driver_data;
++}
++
+ /**
+ * intel_idle
+ * @dev: cpuidle_device
+@@ -216,7 +234,8 @@ static int intel_idle(struct cpuidle_device *dev, int index)
+ {
+ unsigned long ecx = 1; /* break on interrupt flag */
+ struct cpuidle_state *state = &dev->states[index];
+- unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
++ unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
+ unsigned int cstate;
+ ktime_t kt_before, kt_after;
+ s64 usec_delta;
+@@ -452,6 +471,9 @@ static int intel_idle_cpuidle_devices_init(void)
+ dev->states[dev->state_count] = /* structure copy */
+ cpuidle_state_table[cstate];
+
++ dev->states_usage[dev->state_count].driver_data =
++ (void *)get_driver_data(cstate);
++
+ dev->state_count += 1;
+ }
+
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index c6d85cf..0156540 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -28,19 +28,22 @@ struct cpuidle_device;
+ * CPUIDLE DEVICE INTERFACE *
+ ****************************/
+
++struct cpuidle_state_usage {
++ void *driver_data;
++
++ unsigned long long usage;
++ unsigned long long time; /* in US */
++};
++
+ struct cpuidle_state {
+ char name[CPUIDLE_NAME_LEN];
+ char desc[CPUIDLE_DESC_LEN];
+- void *driver_data;
+
+ unsigned int flags;
+ unsigned int exit_latency; /* in US */
+ unsigned int power_usage; /* in mW */
+ unsigned int target_residency; /* in US */
+
+- unsigned long long usage;
+- unsigned long long time; /* in US */
+-
+ int (*enter) (struct cpuidle_device *dev,
+ int index);
+ };
+@@ -52,26 +55,27 @@ struct cpuidle_state {
+
+ /**
+ * cpuidle_get_statedata - retrieves private driver state data
+- * @state: the state
++ * @st_usage: the state usage statistics
+ */
+-static inline void * cpuidle_get_statedata(struct cpuidle_state *state)
++static inline void *cpuidle_get_statedata(struct cpuidle_state_usage *st_usage)
+ {
+- return state->driver_data;
++ return st_usage->driver_data;
+ }
+
+ /**
+ * cpuidle_set_statedata - stores private driver state data
+- * @state: the state
++ * @st_usage: the state usage statistics
+ * @data: the private data
+ */
+ static inline void
+-cpuidle_set_statedata(struct cpuidle_state *state, void *data)
++cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data)
+ {
+- state->driver_data = data;
++ st_usage->driver_data = data;
+ }
+
+ struct cpuidle_state_kobj {
+ struct cpuidle_state *state;
++ struct cpuidle_state_usage *state_usage;
+ struct completion kobj_unregister;
+ struct kobject kobj;
+ };
+@@ -85,6 +89,7 @@ struct cpuidle_device {
+ int last_residency;
+ int state_count;
+ struct cpuidle_state states[CPUIDLE_STATE_MAX];
++ struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
+ struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
+
+ struct list_head device_list;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0045-cpuidle-Single-Global-registration-of-idle-states.patch b/patches.kzm9g/0045-cpuidle-Single-Global-registration-of-idle-states.patch
new file mode 100644
index 00000000000000..b6aa221bd0d115
--- /dev/null
+++ b/patches.kzm9g/0045-cpuidle-Single-Global-registration-of-idle-states.patch
@@ -0,0 +1,1520 @@
+From a50a3085d47712f6a11024570ffc8bf6b90fb126 Mon Sep 17 00:00:00 2001
+From: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Date: Fri, 28 Oct 2011 16:20:42 +0530
+Subject: cpuidle: Single/Global registration of idle states
+
+This patch makes the cpuidle_states structure global (single copy)
+instead of per-cpu. The statistics needed on per-cpu basis
+by the governor are kept per-cpu. This simplifies the cpuidle
+subsystem as state registration is done by single cpu only.
+Having single copy of cpuidle_states saves memory. Rare case
+of asymmetric C-states can be handled within the cpuidle driver
+and architectures such as POWER do not have asymmetric C-states.
+
+Having single/global registration of all the idle states,
+dynamic C-state transitions on x86 are handled by
+the boot cpu. Here, the boot cpu would disable all the devices,
+re-populate the states and later enable all the devices,
+irrespective of the cpu that would receive the notification first.
+
+Reference:
+https://lkml.org/lkml/2011/4/25/83
+
+Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com>
+Tested-by: Jean Pihet <j-pihet@ti.com>
+Reviewed-by: Kevin Hilman <khilman@ti.com>
+Acked-by: Arjan van de Ven <arjan@linux.intel.com>
+Acked-by: Kevin Hilman <khilman@ti.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit 46bcfad7a819bd17ac4e831b04405152d59784ab)
+
+Conflicts:
+
+ drivers/idle/intel_idle.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-at91/cpuidle.c | 31 +++---
+ arch/arm/mach-davinci/cpuidle.c | 39 +++----
+ arch/arm/mach-exynos4/cpuidle.c | 23 ++--
+ arch/arm/mach-kirkwood/cpuidle.c | 30 +++---
+ arch/arm/mach-omap2/cpuidle34xx.c | 73 ++++++++-----
+ arch/sh/kernel/cpu/shmobile/cpuidle.c | 18 ++--
+ drivers/acpi/processor_driver.c | 20 +---
+ drivers/acpi/processor_idle.c | 191 ++++++++++++++++++++++++++++-----
+ drivers/cpuidle/cpuidle.c | 45 +++-----
+ drivers/cpuidle/driver.c | 25 +++++
+ drivers/cpuidle/governors/ladder.c | 28 +++--
+ drivers/cpuidle/governors/menu.c | 20 ++--
+ drivers/cpuidle/sysfs.c | 3 +-
+ drivers/idle/intel_idle.c | 80 ++++++++++----
+ include/acpi/processor.h | 1 +
+ include/linux/cpuidle.h | 19 ++--
+ 16 files changed, 439 insertions(+), 207 deletions(-)
+
+diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
+index d76a600..a851e6c 100644
+--- a/arch/arm/mach-at91/cpuidle.c
++++ b/arch/arm/mach-at91/cpuidle.c
+@@ -34,6 +34,7 @@ static struct cpuidle_driver at91_idle_driver = {
+
+ /* Actual code that puts the SoC in different idle states */
+ static int at91_enter_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ struct timeval before, after;
+@@ -65,27 +66,29 @@ static int at91_enter_idle(struct cpuidle_device *dev,
+ static int at91_init_cpuidle(void)
+ {
+ struct cpuidle_device *device;
+-
+- cpuidle_register_driver(&at91_idle_driver);
++ struct cpuidle_driver *driver = &at91_idle_driver;
+
+ device = &per_cpu(at91_cpuidle_device, smp_processor_id());
+ device->state_count = AT91_MAX_STATES;
++ driver->state_count = AT91_MAX_STATES;
+
+ /* Wait for interrupt state */
+- device->states[0].enter = at91_enter_idle;
+- device->states[0].exit_latency = 1;
+- device->states[0].target_residency = 10000;
+- device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+- strcpy(device->states[0].name, "WFI");
+- strcpy(device->states[0].desc, "Wait for interrupt");
++ driver->states[0].enter = at91_enter_idle;
++ driver->states[0].exit_latency = 1;
++ driver->states[0].target_residency = 10000;
++ driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
++ strcpy(driver->states[0].name, "WFI");
++ strcpy(driver->states[0].desc, "Wait for interrupt");
+
+ /* Wait for interrupt and RAM self refresh state */
+- device->states[1].enter = at91_enter_idle;
+- device->states[1].exit_latency = 10;
+- device->states[1].target_residency = 10000;
+- device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+- strcpy(device->states[1].name, "RAM_SR");
+- strcpy(device->states[1].desc, "WFI and RAM Self Refresh");
++ driver->states[1].enter = at91_enter_idle;
++ driver->states[1].exit_latency = 10;
++ driver->states[1].target_residency = 10000;
++ driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
++ strcpy(driver->states[1].name, "RAM_SR");
++ strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");
++
++ cpuidle_register_driver(&at91_idle_driver);
+
+ if (cpuidle_register_device(device)) {
+ printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
+diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
+index dda6d2f..ed7fb95 100644
+--- a/arch/arm/mach-davinci/cpuidle.c
++++ b/arch/arm/mach-davinci/cpuidle.c
+@@ -79,6 +79,7 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
+
+ /* Actual code that puts the SoC in different idle states */
+ static int davinci_enter_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+@@ -110,6 +111,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
+ {
+ int ret;
+ struct cpuidle_device *device;
++ struct cpuidle_driver *driver = &davinci_idle_driver;
+ struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
+
+ device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
+@@ -121,32 +123,33 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
+
+ ddr2_reg_base = pdata->ddr2_ctlr_base;
+
+- ret = cpuidle_register_driver(&davinci_idle_driver);
+- if (ret) {
+- dev_err(&pdev->dev, "failed to register driver\n");
+- return ret;
+- }
+-
+ /* Wait for interrupt state */
+- device->states[0].enter = davinci_enter_idle;
+- device->states[0].exit_latency = 1;
+- device->states[0].target_residency = 10000;
+- device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+- strcpy(device->states[0].name, "WFI");
+- strcpy(device->states[0].desc, "Wait for interrupt");
++ driver->states[0].enter = davinci_enter_idle;
++ driver->states[0].exit_latency = 1;
++ driver->states[0].target_residency = 10000;
++ driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
++ strcpy(driver->states[0].name, "WFI");
++ strcpy(driver->states[0].desc, "Wait for interrupt");
+
+ /* Wait for interrupt and DDR self refresh state */
+- device->states[1].enter = davinci_enter_idle;
+- device->states[1].exit_latency = 10;
+- device->states[1].target_residency = 10000;
+- device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+- strcpy(device->states[1].name, "DDR SR");
+- strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
++ driver->states[1].enter = davinci_enter_idle;
++ driver->states[1].exit_latency = 10;
++ driver->states[1].target_residency = 10000;
++ driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
++ strcpy(driver->states[1].name, "DDR SR");
++ strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
+ if (pdata->ddr2_pdown)
+ davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
+ cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
+
+ device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
++ driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;
++
++ ret = cpuidle_register_driver(&davinci_idle_driver);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to register driver\n");
++ return ret;
++ }
+
+ ret = cpuidle_register_device(device);
+ if (ret) {
+diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c
+index ea026e7..35f6502 100644
+--- a/arch/arm/mach-exynos4/cpuidle.c
++++ b/arch/arm/mach-exynos4/cpuidle.c
+@@ -16,6 +16,7 @@
+ #include <asm/proc-fns.h>
+
+ static int exynos4_enter_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index);
+
+ static struct cpuidle_state exynos4_cpuidle_set[] = {
+@@ -37,6 +38,7 @@ static struct cpuidle_driver exynos4_idle_driver = {
+ };
+
+ static int exynos4_enter_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ struct timeval before, after;
+@@ -60,22 +62,23 @@ static int __init exynos4_init_cpuidle(void)
+ {
+ int i, max_cpuidle_state, cpu_id;
+ struct cpuidle_device *device;
+-
++ struct cpuidle_driver *drv = &exynos4_idle_driver;
++
++ /* Setup cpuidle driver */
++ drv->state_count = (sizeof(exynos4_cpuidle_set) /
++ sizeof(struct cpuidle_state));
++ max_cpuidle_state = drv->state_count;
++ for (i = 0; i < max_cpuidle_state; i++) {
++ memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
++ sizeof(struct cpuidle_state));
++ }
+ cpuidle_register_driver(&exynos4_idle_driver);
+
+ for_each_cpu(cpu_id, cpu_online_mask) {
+ device = &per_cpu(exynos4_cpuidle_device, cpu_id);
+ device->cpu = cpu_id;
+
+- device->state_count = (sizeof(exynos4_cpuidle_set) /
+- sizeof(struct cpuidle_state));
+-
+- max_cpuidle_state = device->state_count;
+-
+- for (i = 0; i < max_cpuidle_state; i++) {
+- memcpy(&device->states[i], &exynos4_cpuidle_set[i],
+- sizeof(struct cpuidle_state));
+- }
++ device->state_count = drv->state_count;
+
+ if (cpuidle_register_device(device)) {
+ printk(KERN_ERR "CPUidle register device failed\n,");
+diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c
+index 53d6049..7088180 100644
+--- a/arch/arm/mach-kirkwood/cpuidle.c
++++ b/arch/arm/mach-kirkwood/cpuidle.c
+@@ -33,6 +33,7 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
+
+ /* Actual code that puts the SoC in different idle states */
+ static int kirkwood_enter_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ struct timeval before, after;
+@@ -69,28 +70,29 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
+ static int kirkwood_init_cpuidle(void)
+ {
+ struct cpuidle_device *device;
+-
+- cpuidle_register_driver(&kirkwood_idle_driver);
++ struct cpuidle_driver *driver = &kirkwood_idle_driver;
+
+ device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
+ device->state_count = KIRKWOOD_MAX_STATES;
++ driver->state_count = KIRKWOOD_MAX_STATES;
+
+ /* Wait for interrupt state */
+- device->states[0].enter = kirkwood_enter_idle;
+- device->states[0].exit_latency = 1;
+- device->states[0].target_residency = 10000;
+- device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+- strcpy(device->states[0].name, "WFI");
+- strcpy(device->states[0].desc, "Wait for interrupt");
++ driver->states[0].enter = kirkwood_enter_idle;
++ driver->states[0].exit_latency = 1;
++ driver->states[0].target_residency = 10000;
++ driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
++ strcpy(driver->states[0].name, "WFI");
++ strcpy(driver->states[0].desc, "Wait for interrupt");
+
+ /* Wait for interrupt and DDR self refresh state */
+- device->states[1].enter = kirkwood_enter_idle;
+- device->states[1].exit_latency = 10;
+- device->states[1].target_residency = 10000;
+- device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+- strcpy(device->states[1].name, "DDR SR");
+- strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
++ driver->states[1].enter = kirkwood_enter_idle;
++ driver->states[1].exit_latency = 10;
++ driver->states[1].target_residency = 10000;
++ driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
++ strcpy(driver->states[1].name, "DDR SR");
++ strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
+
++ cpuidle_register_driver(&kirkwood_idle_driver);
+ if (cpuidle_register_device(device)) {
+ printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
+ return -EIO;
+diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
+index d3fce7b..1fe35c2 100644
+--- a/arch/arm/mach-omap2/cpuidle34xx.c
++++ b/arch/arm/mach-omap2/cpuidle34xx.c
+@@ -88,12 +88,14 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
+ /**
+ * omap3_enter_idle - Programs OMAP3 to enter the specified state
+ * @dev: cpuidle device
++ * @drv: cpuidle driver
+ * @index: the index of state to be entered
+ *
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ */
+ static int omap3_enter_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ struct omap3_idle_statedata *cx =
+@@ -148,6 +150,7 @@ return_sleep_time:
+ /**
+ * next_valid_state - Find next valid C-state
+ * @dev: cpuidle device
++ * @drv: cpuidle driver
+ * @index: Index of currently selected c-state
+ *
+ * If the state corresponding to index is valid, index is returned back
+@@ -158,10 +161,11 @@ return_sleep_time:
+ * if it satisfies the enable_off_mode condition.
+ */
+ static int next_valid_state(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
+- struct cpuidle_state *curr = &dev->states[index];
++ struct cpuidle_state *curr = &drv->states[index];
+ struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
+ u32 mpu_deepest_state = PWRDM_POWER_RET;
+ u32 core_deepest_state = PWRDM_POWER_RET;
+@@ -188,7 +192,7 @@ static int next_valid_state(struct cpuidle_device *dev,
+
+ /* Reach the current state starting at highest C-state */
+ for (; idx >= 0; idx--) {
+- if (&dev->states[idx] == curr) {
++ if (&drv->states[idx] == curr) {
+ next_index = idx;
+ break;
+ }
+@@ -224,12 +228,14 @@ static int next_valid_state(struct cpuidle_device *dev,
+ /**
+ * omap3_enter_idle_bm - Checks for any bus activity
+ * @dev: cpuidle device
++ * @drv: cpuidle driver
+ * @index: array index of target state to be programmed
+ *
+ * This function checks for any pending activity and then programs
+ * the device to the specified or a safer state.
+ */
+ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ int new_state_idx;
+@@ -238,7 +244,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ int ret;
+
+ if (!omap3_can_sleep()) {
+- new_state_idx = dev->safe_state_index;
++ new_state_idx = drv->safe_state_index;
+ goto select_state;
+ }
+
+@@ -248,7 +254,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ */
+ cam_state = pwrdm_read_pwrst(cam_pd);
+ if (cam_state == PWRDM_POWER_ON) {
+- new_state_idx = dev->safe_state_index;
++ new_state_idx = drv->safe_state_index;
+ goto select_state;
+ }
+
+@@ -275,10 +281,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
+ if (per_next_state != per_saved_state)
+ pwrdm_set_next_pwrst(per_pd, per_next_state);
+
+- new_state_idx = next_valid_state(dev, index);
++ new_state_idx = next_valid_state(dev, drv, index);
+
+ select_state:
+- ret = omap3_enter_idle(dev, new_state_idx);
++ ret = omap3_enter_idle(dev, drv, new_state_idx);
+
+ /* Restore original PER state if it was modified */
+ if (per_next_state != per_saved_state)
+@@ -311,22 +317,30 @@ struct cpuidle_driver omap3_idle_driver = {
+ .owner = THIS_MODULE,
+ };
+
+-/* Helper to fill the C-state common data and register the driver_data */
+-static inline struct omap3_idle_statedata *_fill_cstate(
+- struct cpuidle_device *dev,
++/* Helper to fill the C-state common data*/
++static inline void _fill_cstate(struct cpuidle_driver *drv,
+ int idx, const char *descr)
+ {
+- struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
+- struct cpuidle_state *state = &dev->states[idx];
+- struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
++ struct cpuidle_state *state = &drv->states[idx];
+
+ state->exit_latency = cpuidle_params_table[idx].exit_latency;
+ state->target_residency = cpuidle_params_table[idx].target_residency;
+ state->flags = CPUIDLE_FLAG_TIME_VALID;
+ state->enter = omap3_enter_idle_bm;
+- cx->valid = cpuidle_params_table[idx].valid;
+ sprintf(state->name, "C%d", idx + 1);
+ strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
++
++}
++
++/* Helper to register the driver_data */
++static inline struct omap3_idle_statedata *_fill_cstate_usage(
++ struct cpuidle_device *dev,
++ int idx)
++{
++ struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
++ struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
++
++ cx->valid = cpuidle_params_table[idx].valid;
+ cpuidle_set_statedata(state_usage, cx);
+
+ return cx;
+@@ -341,6 +355,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
+ int __init omap3_idle_init(void)
+ {
+ struct cpuidle_device *dev;
++ struct cpuidle_driver *drv = &omap3_idle_driver;
+ struct omap3_idle_statedata *cx;
+
+ mpu_pd = pwrdm_lookup("mpu_pwrdm");
+@@ -348,45 +363,52 @@ int __init omap3_idle_init(void)
+ per_pd = pwrdm_lookup("per_pwrdm");
+ cam_pd = pwrdm_lookup("cam_pwrdm");
+
+- cpuidle_register_driver(&omap3_idle_driver);
++
++ drv->safe_state_index = -1;
+ dev = &per_cpu(omap3_idle_dev, smp_processor_id());
+- dev->safe_state_index = -1;
+
+ /* C1 . MPU WFI + Core active */
+- cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
+- (&dev->states[0])->enter = omap3_enter_idle;
+- dev->safe_state_index = 0;
++ _fill_cstate(drv, 0, "MPU ON + CORE ON");
++ (&drv->states[0])->enter = omap3_enter_idle;
++ drv->safe_state_index = 0;
++ cx = _fill_cstate_usage(dev, 0);
+ cx->valid = 1; /* C1 is always valid */
+ cx->mpu_state = PWRDM_POWER_ON;
+ cx->core_state = PWRDM_POWER_ON;
+
+ /* C2 . MPU WFI + Core inactive */
+- cx = _fill_cstate(dev, 1, "MPU ON + CORE ON");
++ _fill_cstate(drv, 1, "MPU ON + CORE ON");
++ cx = _fill_cstate_usage(dev, 1);
+ cx->mpu_state = PWRDM_POWER_ON;
+ cx->core_state = PWRDM_POWER_ON;
+
+ /* C3 . MPU CSWR + Core inactive */
+- cx = _fill_cstate(dev, 2, "MPU RET + CORE ON");
++ _fill_cstate(drv, 2, "MPU RET + CORE ON");
++ cx = _fill_cstate_usage(dev, 2);
+ cx->mpu_state = PWRDM_POWER_RET;
+ cx->core_state = PWRDM_POWER_ON;
+
+ /* C4 . MPU OFF + Core inactive */
+- cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON");
++ _fill_cstate(drv, 3, "MPU OFF + CORE ON");
++ cx = _fill_cstate_usage(dev, 3);
+ cx->mpu_state = PWRDM_POWER_OFF;
+ cx->core_state = PWRDM_POWER_ON;
+
+ /* C5 . MPU RET + Core RET */
+- cx = _fill_cstate(dev, 4, "MPU RET + CORE RET");
++ _fill_cstate(drv, 4, "MPU RET + CORE RET");
++ cx = _fill_cstate_usage(dev, 4);
+ cx->mpu_state = PWRDM_POWER_RET;
+ cx->core_state = PWRDM_POWER_RET;
+
+ /* C6 . MPU OFF + Core RET */
+- cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET");
++ _fill_cstate(drv, 5, "MPU OFF + CORE RET");
++ cx = _fill_cstate_usage(dev, 5);
+ cx->mpu_state = PWRDM_POWER_OFF;
+ cx->core_state = PWRDM_POWER_RET;
+
+ /* C7 . MPU OFF + Core OFF */
+- cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF");
++ _fill_cstate(drv, 6, "MPU OFF + CORE OFF");
++ cx = _fill_cstate_usage(dev, 6);
+ /*
+ * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
+ * enable OFF mode in a stable form for previous revisions.
+@@ -400,6 +422,9 @@ int __init omap3_idle_init(void)
+ cx->mpu_state = PWRDM_POWER_OFF;
+ cx->core_state = PWRDM_POWER_OFF;
+
++ drv->state_count = OMAP3_NUM_STATES;
++ cpuidle_register_driver(&omap3_idle_driver);
++
+ dev->state_count = OMAP3_NUM_STATES;
+ if (cpuidle_register_device(dev)) {
+ printk(KERN_ERR "%s: CPUidle register device failed\n",
+diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
+index 7be50d4c..ad1012a 100644
+--- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
++++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
+@@ -25,6 +25,7 @@ static unsigned long cpuidle_mode[] = {
+ };
+
+ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index)
+ {
+ unsigned long allowed_mode = arch_hwblk_sleep_mode();
+@@ -64,19 +65,19 @@ static struct cpuidle_driver cpuidle_driver = {
+ void sh_mobile_setup_cpuidle(void)
+ {
+ struct cpuidle_device *dev = &cpuidle_dev;
++ struct cpuidle_driver *drv = &cpuidle_driver;
+ struct cpuidle_state *state;
+ int i;
+
+- cpuidle_register_driver(&cpuidle_driver);
+
+ for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+- dev->states[i].name[0] = '\0';
+- dev->states[i].desc[0] = '\0';
++ drv->states[i].name[0] = '\0';
++ drv->states[i].desc[0] = '\0';
+ }
+
+ i = CPUIDLE_DRIVER_STATE_START;
+
+- state = &dev->states[i++];
++ state = &drv->states[i++];
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
+ strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
+ state->exit_latency = 1;
+@@ -86,10 +87,10 @@ void sh_mobile_setup_cpuidle(void)
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = cpuidle_sleep_enter;
+
+- dev->safe_state_index = i-1;
++ drv->safe_state_index = i-1;
+
+ if (sh_mobile_sleep_supported & SUSP_SH_SF) {
+- state = &dev->states[i++];
++ state = &drv->states[i++];
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
+ strncpy(state->desc, "SuperH Sleep Mode [SF]",
+ CPUIDLE_DESC_LEN);
+@@ -102,7 +103,7 @@ void sh_mobile_setup_cpuidle(void)
+ }
+
+ if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
+- state = &dev->states[i++];
++ state = &drv->states[i++];
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
+ strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
+ CPUIDLE_DESC_LEN);
+@@ -114,7 +115,10 @@ void sh_mobile_setup_cpuidle(void)
+ state->enter = cpuidle_sleep_enter;
+ }
+
++ drv->state_count = i;
+ dev->state_count = i;
+
++ cpuidle_register_driver(&cpuidle_driver);
++
+ cpuidle_register_device(dev);
+ }
+diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
+index a4e0f1b..9d7bc9f 100644
+--- a/drivers/acpi/processor_driver.c
++++ b/drivers/acpi/processor_driver.c
+@@ -426,7 +426,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
+
+ if (action == CPU_ONLINE && pr) {
+ acpi_processor_ppc_has_changed(pr, 0);
+- acpi_processor_cst_has_changed(pr);
++ acpi_processor_hotplug(pr);
+ acpi_processor_reevaluate_tstate(pr, action);
+ acpi_processor_tstate_has_changed(pr);
+ }
+@@ -503,8 +503,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
+-
+- if (cpuidle_get_driver() == &acpi_idle_driver)
++ if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr, device);
+
+ pr->cdev = thermal_cooling_device_register("Processor", device,
+@@ -800,17 +799,9 @@ static int __init acpi_processor_init(void)
+
+ memset(&errata, 0, sizeof(errata));
+
+- if (!cpuidle_register_driver(&acpi_idle_driver)) {
+- printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
+- acpi_idle_driver.name);
+- } else {
+- printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
+- cpuidle_get_driver()->name);
+- }
+-
+ result = acpi_bus_register_driver(&acpi_processor_driver);
+ if (result < 0)
+- goto out_cpuidle;
++ return result;
+
+ acpi_processor_install_hotplug_notify();
+
+@@ -821,11 +812,6 @@ static int __init acpi_processor_init(void)
+ acpi_processor_throttling_init();
+
+ return 0;
+-
+-out_cpuidle:
+- cpuidle_unregister_driver(&acpi_idle_driver);
+-
+- return result;
+ }
+
+ static void __exit acpi_processor_exit(void)
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index c7b89f0..da70c26 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -741,11 +741,13 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
+ /**
+ * acpi_idle_enter_c1 - enters an ACPI C1 state-type
+ * @dev: the target CPU
++ * @drv: cpuidle driver containing cpuidle state info
+ * @index: index of target state
+ *
+ * This is equivalent to the HALT instruction.
+ */
+-static int acpi_idle_enter_c1(struct cpuidle_device *dev, int index)
++static int acpi_idle_enter_c1(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
+ {
+ ktime_t kt1, kt2;
+ s64 idle_time;
+@@ -787,9 +789,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, int index)
+ /**
+ * acpi_idle_enter_simple - enters an ACPI state without BM handling
+ * @dev: the target CPU
++ * @drv: cpuidle driver with cpuidle state information
+ * @index: the index of suggested state
+ */
+-static int acpi_idle_enter_simple(struct cpuidle_device *dev, int index)
++static int acpi_idle_enter_simple(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
+ {
+ struct acpi_processor *pr;
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+@@ -869,11 +873,13 @@ static DEFINE_SPINLOCK(c3_lock);
+ /**
+ * acpi_idle_enter_bm - enters C3 with proper BM handling
+ * @dev: the target CPU
++ * @drv: cpuidle driver containing state data
+ * @index: the index of suggested state
+ *
+ * If BM is detected, the deepest non-C3 idle state is entered instead.
+ */
+-static int acpi_idle_enter_bm(struct cpuidle_device *dev, int index)
++static int acpi_idle_enter_bm(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
+ {
+ struct acpi_processor *pr;
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+@@ -896,9 +902,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, int index)
+ }
+
+ if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
+- if (dev->safe_state_index >= 0) {
+- return dev->states[dev->safe_state_index].enter(dev,
+- dev->safe_state_index);
++ if (drv->safe_state_index >= 0) {
++ return drv->states[drv->safe_state_index].enter(dev,
++ drv, drv->safe_state_index);
+ } else {
+ local_irq_disable();
+ acpi_safe_halt();
+@@ -993,14 +999,15 @@ struct cpuidle_driver acpi_idle_driver = {
+ };
+
+ /**
+- * acpi_processor_setup_cpuidle - prepares and configures CPUIDLE
++ * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE
++ * device i.e. per-cpu data
++ *
+ * @pr: the ACPI processor
+ */
+-static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
++static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
+ {
+ int i, count = CPUIDLE_DRIVER_STATE_START;
+ struct acpi_processor_cx *cx;
+- struct cpuidle_state *state;
+ struct cpuidle_state_usage *state_usage;
+ struct cpuidle_device *dev = &pr->power.dev;
+
+@@ -1012,18 +1019,12 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ }
+
+ dev->cpu = pr->id;
+- dev->safe_state_index = -1;
+- for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+- dev->states[i].name[0] = '\0';
+- dev->states[i].desc[0] = '\0';
+- }
+
+ if (max_cstate == 0)
+ max_cstate = 1;
+
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+ cx = &pr->power.states[i];
+- state = &dev->states[count];
+ state_usage = &dev->states_usage[count];
+
+ if (!cx->valid)
+@@ -1035,8 +1036,64 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+ continue;
+ #endif
++
+ cpuidle_set_statedata(state_usage, cx);
+
++ count++;
++ if (count == CPUIDLE_STATE_MAX)
++ break;
++ }
++
++ dev->state_count = count;
++
++ if (!count)
++ return -EINVAL;
++
++ return 0;
++}
++
++/**
++ * acpi_processor_setup_cpuidle states- prepares and configures cpuidle
++ * global state data i.e. idle routines
++ *
++ * @pr: the ACPI processor
++ */
++static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
++{
++ int i, count = CPUIDLE_DRIVER_STATE_START;
++ struct acpi_processor_cx *cx;
++ struct cpuidle_state *state;
++ struct cpuidle_driver *drv = &acpi_idle_driver;
++
++ if (!pr->flags.power_setup_done)
++ return -EINVAL;
++
++ if (pr->flags.power == 0)
++ return -EINVAL;
++
++ drv->safe_state_index = -1;
++ for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
++ drv->states[i].name[0] = '\0';
++ drv->states[i].desc[0] = '\0';
++ }
++
++ if (max_cstate == 0)
++ max_cstate = 1;
++
++ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
++ cx = &pr->power.states[i];
++
++ if (!cx->valid)
++ continue;
++
++#ifdef CONFIG_HOTPLUG_CPU
++ if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
++ !pr->flags.has_cst &&
++ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
++ continue;
++#endif
++
++ state = &drv->states[count];
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
+ strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
+ state->exit_latency = cx->latency;
+@@ -1049,13 +1106,13 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+
+ state->enter = acpi_idle_enter_c1;
+- dev->safe_state_index = count;
++ drv->safe_state_index = count;
+ break;
+
+ case ACPI_STATE_C2:
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = acpi_idle_enter_simple;
+- dev->safe_state_index = count;
++ drv->safe_state_index = count;
+ break;
+
+ case ACPI_STATE_C3:
+@@ -1071,7 +1128,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ break;
+ }
+
+- dev->state_count = count;
++ drv->state_count = count;
+
+ if (!count)
+ return -EINVAL;
+@@ -1079,7 +1136,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ return 0;
+ }
+
+-int acpi_processor_cst_has_changed(struct acpi_processor *pr)
++int acpi_processor_hotplug(struct acpi_processor *pr)
+ {
+ int ret = 0;
+
+@@ -1100,7 +1157,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+ cpuidle_disable_device(&pr->power.dev);
+ acpi_processor_get_power_info(pr);
+ if (pr->flags.power) {
+- acpi_processor_setup_cpuidle(pr);
++ acpi_processor_setup_cpuidle_cx(pr);
+ ret = cpuidle_enable_device(&pr->power.dev);
+ }
+ cpuidle_resume_and_unlock();
+@@ -1108,10 +1165,72 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+ return ret;
+ }
+
++int acpi_processor_cst_has_changed(struct acpi_processor *pr)
++{
++ int cpu;
++ struct acpi_processor *_pr;
++
++ if (disabled_by_idle_boot_param())
++ return 0;
++
++ if (!pr)
++ return -EINVAL;
++
++ if (nocst)
++ return -ENODEV;
++
++ if (!pr->flags.power_setup_done)
++ return -ENODEV;
++
++ /*
++ * FIXME: Design the ACPI notification to make it once per
++ * system instead of once per-cpu. This condition is a hack
++ * to make the code that updates C-States be called once.
++ */
++
++ if (smp_processor_id() == 0 &&
++ cpuidle_get_driver() == &acpi_idle_driver) {
++
++ cpuidle_pause_and_lock();
++ /* Protect against cpu-hotplug */
++ get_online_cpus();
++
++ /* Disable all cpuidle devices */
++ for_each_online_cpu(cpu) {
++ _pr = per_cpu(processors, cpu);
++ if (!_pr || !_pr->flags.power_setup_done)
++ continue;
++ cpuidle_disable_device(&_pr->power.dev);
++ }
++
++ /* Populate Updated C-state information */
++ acpi_processor_setup_cpuidle_states(pr);
++
++ /* Enable all cpuidle devices */
++ for_each_online_cpu(cpu) {
++ _pr = per_cpu(processors, cpu);
++ if (!_pr || !_pr->flags.power_setup_done)
++ continue;
++ acpi_processor_get_power_info(_pr);
++ if (_pr->flags.power) {
++ acpi_processor_setup_cpuidle_cx(_pr);
++ cpuidle_enable_device(&_pr->power.dev);
++ }
++ }
++ put_online_cpus();
++ cpuidle_resume_and_unlock();
++ }
++
++ return 0;
++}
++
++static int acpi_processor_registered;
++
+ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+ struct acpi_device *device)
+ {
+ acpi_status status = 0;
++ int retval;
+ static int first_run;
+
+ if (disabled_by_idle_boot_param())
+@@ -1148,9 +1267,26 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+ * platforms that only support C1.
+ */
+ if (pr->flags.power) {
+- acpi_processor_setup_cpuidle(pr);
+- if (cpuidle_register_device(&pr->power.dev))
+- return -EIO;
++ /* Register acpi_idle_driver if not already registered */
++ if (!acpi_processor_registered) {
++ acpi_processor_setup_cpuidle_states(pr);
++ retval = cpuidle_register_driver(&acpi_idle_driver);
++ if (retval)
++ return retval;
++ printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
++ acpi_idle_driver.name);
++ }
++ /* Register per-cpu cpuidle_device. Cpuidle driver
++ * must already be registered before registering device
++ */
++ acpi_processor_setup_cpuidle_cx(pr);
++ retval = cpuidle_register_device(&pr->power.dev);
++ if (retval) {
++ if (acpi_processor_registered == 0)
++ cpuidle_unregister_driver(&acpi_idle_driver);
++ return retval;
++ }
++ acpi_processor_registered++;
+ }
+ return 0;
+ }
+@@ -1161,8 +1297,13 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
+ if (disabled_by_idle_boot_param())
+ return 0;
+
+- cpuidle_unregister_device(&pr->power.dev);
+- pr->flags.power_setup_done = 0;
++ if (pr->flags.power) {
++ cpuidle_unregister_device(&pr->power.dev);
++ acpi_processor_registered--;
++ if (acpi_processor_registered == 0)
++ cpuidle_unregister_driver(&acpi_idle_driver);
++ }
+
++ pr->flags.power_setup_done = 0;
+ return 0;
+ }
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index 219a757..06ce268 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -62,6 +62,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
+ int cpuidle_idle_call(void)
+ {
+ struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
++ struct cpuidle_driver *drv = cpuidle_get_driver();
+ struct cpuidle_state *target_state;
+ int next_state, entered_state;
+
+@@ -85,18 +86,18 @@ int cpuidle_idle_call(void)
+ #endif
+
+ /* ask the governor for the next state */
+- next_state = cpuidle_curr_governor->select(dev);
++ next_state = cpuidle_curr_governor->select(drv, dev);
+ if (need_resched()) {
+ local_irq_enable();
+ return 0;
+ }
+
+- target_state = &dev->states[next_state];
++ target_state = &drv->states[next_state];
+
+ trace_power_start(POWER_CSTATE, next_state, dev->cpu);
+ trace_cpu_idle(next_state, dev->cpu);
+
+- entered_state = target_state->enter(dev, next_state);
++ entered_state = target_state->enter(dev, drv, next_state);
+
+ trace_power_end(dev->cpu);
+ trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
+@@ -164,7 +165,8 @@ void cpuidle_resume_and_unlock(void)
+ EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
+
+ #ifdef CONFIG_ARCH_HAS_CPU_RELAX
+-static int poll_idle(struct cpuidle_device *dev, int index)
++static int poll_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
+ {
+ ktime_t t1, t2;
+ s64 diff;
+@@ -184,12 +186,9 @@ static int poll_idle(struct cpuidle_device *dev, int index)
+ return index;
+ }
+
+-static void poll_idle_init(struct cpuidle_device *dev)
++static void poll_idle_init(struct cpuidle_driver *drv)
+ {
+- struct cpuidle_state *state = &dev->states[0];
+- struct cpuidle_state_usage *state_usage = &dev->states_usage[0];
+-
+- cpuidle_set_statedata(state_usage, NULL);
++ struct cpuidle_state *state = &drv->states[0];
+
+ snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
+ snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
+@@ -200,7 +199,7 @@ static void poll_idle_init(struct cpuidle_device *dev)
+ state->enter = poll_idle;
+ }
+ #else
+-static void poll_idle_init(struct cpuidle_device *dev) {}
++static void poll_idle_init(struct cpuidle_driver *drv) {}
+ #endif /* CONFIG_ARCH_HAS_CPU_RELAX */
+
+ /**
+@@ -227,13 +226,13 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
+ return ret;
+ }
+
+- poll_idle_init(dev);
++ poll_idle_init(cpuidle_get_driver());
+
+ if ((ret = cpuidle_add_state_sysfs(dev)))
+ return ret;
+
+ if (cpuidle_curr_governor->enable &&
+- (ret = cpuidle_curr_governor->enable(dev)))
++ (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
+ goto fail_sysfs;
+
+ for (i = 0; i < dev->state_count; i++) {
+@@ -274,7 +273,7 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
+ dev->enabled = 0;
+
+ if (cpuidle_curr_governor->disable)
+- cpuidle_curr_governor->disable(dev);
++ cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
+
+ cpuidle_remove_state_sysfs(dev);
+ enabled_devices--;
+@@ -302,26 +301,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
+
+ init_completion(&dev->kobj_unregister);
+
+- /*
+- * cpuidle driver should set the dev->power_specified bit
+- * before registering the device if the driver provides
+- * power_usage numbers.
+- *
+- * For those devices whose ->power_specified is not set,
+- * we fill in power_usage with decreasing values as the
+- * cpuidle code has an implicit assumption that state Cn
+- * uses less power than C(n-1).
+- *
+- * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
+- * an power value of -1. So we use -2, -3, etc, for other
+- * c-states.
+- */
+- if (!dev->power_specified) {
+- int i;
+- for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
+- dev->states[i].power_usage = -1 - i;
+- }
+-
+ per_cpu(cpuidle_devices, dev->cpu) = dev;
+ list_add(&dev->device_list, &cpuidle_detected_devices);
+ if ((ret = cpuidle_add_sysfs(sys_dev))) {
+diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
+index 3f7e3ce..284d7af 100644
+--- a/drivers/cpuidle/driver.c
++++ b/drivers/cpuidle/driver.c
+@@ -17,6 +17,30 @@
+ static struct cpuidle_driver *cpuidle_curr_driver;
+ DEFINE_SPINLOCK(cpuidle_driver_lock);
+
++static void __cpuidle_register_driver(struct cpuidle_driver *drv)
++{
++ int i;
++ /*
++ * cpuidle driver should set the drv->power_specified bit
++ * before registering if the driver provides
++ * power_usage numbers.
++ *
++ * If power_specified is not set,
++ * we fill in power_usage with decreasing values as the
++ * cpuidle code has an implicit assumption that state Cn
++ * uses less power than C(n-1).
++ *
++ * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
++ * an power value of -1. So we use -2, -3, etc, for other
++ * c-states.
++ */
++ if (!drv->power_specified) {
++ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
++ drv->states[i].power_usage = -1 - i;
++ }
++}
++
++
+ /**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+@@ -34,6 +58,7 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
+ spin_unlock(&cpuidle_driver_lock);
+ return -EBUSY;
+ }
++ __cpuidle_register_driver(drv);
+ cpuidle_curr_driver = drv;
+ spin_unlock(&cpuidle_driver_lock);
+
+diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
+index 78b06d2..261e57a 100644
+--- a/drivers/cpuidle/governors/ladder.c
++++ b/drivers/cpuidle/governors/ladder.c
+@@ -60,9 +60,11 @@ static inline void ladder_do_selection(struct ladder_device *ldev,
+
+ /**
+ * ladder_select_state - selects the next state to enter
++ * @drv: cpuidle driver
+ * @dev: the CPU
+ */
+-static int ladder_select_state(struct cpuidle_device *dev)
++static int ladder_select_state(struct cpuidle_driver *drv,
++ struct cpuidle_device *dev)
+ {
+ struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
+ struct ladder_device_state *last_state;
+@@ -77,15 +79,17 @@ static int ladder_select_state(struct cpuidle_device *dev)
+
+ last_state = &ldev->states[last_idx];
+
+- if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
+- last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
++ if (drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) {
++ last_residency = cpuidle_get_last_residency(dev) - \
++ drv->states[last_idx].exit_latency;
++ }
+ else
+ last_residency = last_state->threshold.promotion_time + 1;
+
+ /* consider promotion */
+- if (last_idx < dev->state_count - 1 &&
++ if (last_idx < drv->state_count - 1 &&
+ last_residency > last_state->threshold.promotion_time &&
+- dev->states[last_idx + 1].exit_latency <= latency_req) {
++ drv->states[last_idx + 1].exit_latency <= latency_req) {
+ last_state->stats.promotion_count++;
+ last_state->stats.demotion_count = 0;
+ if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
+@@ -96,11 +100,11 @@ static int ladder_select_state(struct cpuidle_device *dev)
+
+ /* consider demotion */
+ if (last_idx > CPUIDLE_DRIVER_STATE_START &&
+- dev->states[last_idx].exit_latency > latency_req) {
++ drv->states[last_idx].exit_latency > latency_req) {
+ int i;
+
+ for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
+- if (dev->states[i].exit_latency <= latency_req)
++ if (drv->states[i].exit_latency <= latency_req)
+ break;
+ }
+ ladder_do_selection(ldev, last_idx, i);
+@@ -123,9 +127,11 @@ static int ladder_select_state(struct cpuidle_device *dev)
+
+ /**
+ * ladder_enable_device - setup for the governor
++ * @drv: cpuidle driver
+ * @dev: the CPU
+ */
+-static int ladder_enable_device(struct cpuidle_device *dev)
++static int ladder_enable_device(struct cpuidle_driver *drv,
++ struct cpuidle_device *dev)
+ {
+ int i;
+ struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
+@@ -134,8 +140,8 @@ static int ladder_enable_device(struct cpuidle_device *dev)
+
+ ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
+
+- for (i = 0; i < dev->state_count; i++) {
+- state = &dev->states[i];
++ for (i = 0; i < drv->state_count; i++) {
++ state = &drv->states[i];
+ lstate = &ldev->states[i];
+
+ lstate->stats.promotion_count = 0;
+@@ -144,7 +150,7 @@ static int ladder_enable_device(struct cpuidle_device *dev)
+ lstate->threshold.promotion_count = PROMOTION_COUNT;
+ lstate->threshold.demotion_count = DEMOTION_COUNT;
+
+- if (i < dev->state_count - 1)
++ if (i < drv->state_count - 1)
+ lstate->threshold.promotion_time = state->exit_latency;
+ if (i > 0)
+ lstate->threshold.demotion_time = state->exit_latency;
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index 2072aeb..ad09526 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -183,7 +183,7 @@ static inline int performance_multiplier(void)
+
+ static DEFINE_PER_CPU(struct menu_device, menu_devices);
+
+-static void menu_update(struct cpuidle_device *dev);
++static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
+
+ /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
+ static u64 div_round64(u64 dividend, u32 divisor)
+@@ -229,9 +229,10 @@ static void detect_repeating_patterns(struct menu_device *data)
+
+ /**
+ * menu_select - selects the next idle state to enter
++ * @drv: cpuidle driver containing state data
+ * @dev: the CPU
+ */
+-static int menu_select(struct cpuidle_device *dev)
++static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
+ {
+ struct menu_device *data = &__get_cpu_var(menu_devices);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
+@@ -241,7 +242,7 @@ static int menu_select(struct cpuidle_device *dev)
+ struct timespec t;
+
+ if (data->needs_update) {
+- menu_update(dev);
++ menu_update(drv, dev);
+ data->needs_update = 0;
+ }
+
+@@ -286,8 +287,8 @@ static int menu_select(struct cpuidle_device *dev)
+ * Find the idle state with the lowest power while satisfying
+ * our constraints.
+ */
+- for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
+- struct cpuidle_state *s = &dev->states[i];
++ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
++ struct cpuidle_state *s = &drv->states[i];
+
+ if (s->target_residency > data->predicted_us)
+ continue;
+@@ -324,14 +325,15 @@ static void menu_reflect(struct cpuidle_device *dev, int index)
+
+ /**
+ * menu_update - attempts to guess what happened after entry
++ * @drv: cpuidle driver containing state data
+ * @dev: the CPU
+ */
+-static void menu_update(struct cpuidle_device *dev)
++static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
+ {
+ struct menu_device *data = &__get_cpu_var(menu_devices);
+ int last_idx = data->last_state_idx;
+ unsigned int last_idle_us = cpuidle_get_last_residency(dev);
+- struct cpuidle_state *target = &dev->states[last_idx];
++ struct cpuidle_state *target = &drv->states[last_idx];
+ unsigned int measured_us;
+ u64 new_factor;
+
+@@ -385,9 +387,11 @@ static void menu_update(struct cpuidle_device *dev)
+
+ /**
+ * menu_enable_device - scans a CPU's states and does setup
++ * @drv: cpuidle driver
+ * @dev: the CPU
+ */
+-static int menu_enable_device(struct cpuidle_device *dev)
++static int menu_enable_device(struct cpuidle_driver *drv,
++ struct cpuidle_device *dev)
+ {
+ struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+
+diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
+index 8a1ace1..1e756e1 100644
+--- a/drivers/cpuidle/sysfs.c
++++ b/drivers/cpuidle/sysfs.c
+@@ -322,13 +322,14 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+ {
+ int i, ret = -ENOMEM;
+ struct cpuidle_state_kobj *kobj;
++ struct cpuidle_driver *drv = cpuidle_get_driver();
+
+ /* state statistics */
+ for (i = 0; i < device->state_count; i++) {
+ kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
+ if (!kobj)
+ goto error_state;
+- kobj->state = &device->states[i];
++ kobj->state = &drv->states[i];
+ kobj->state_usage = &device->states_usage[i];
+ init_completion(&kobj->kobj_unregister);
+
+diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
+index b0c63e9..1f122c6 100644
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -81,7 +81,8 @@ static unsigned int mwait_substates;
+ static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
+
+ static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
+-static int intel_idle(struct cpuidle_device *dev, int index);
++static int intel_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index);
+
+ static struct cpuidle_state *cpuidle_state_table;
+
+@@ -227,13 +228,15 @@ static int get_driver_data(int cstate)
+ /**
+ * intel_idle
+ * @dev: cpuidle_device
++ * @drv: cpuidle driver
+ * @index: index of cpuidle state
+ *
+ */
+-static int intel_idle(struct cpuidle_device *dev, int index)
++static int intel_idle(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
+ {
+ unsigned long ecx = 1; /* break on interrupt flag */
+- struct cpuidle_state *state = &dev->states[index];
++ struct cpuidle_state *state = &drv->states[index];
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+ unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
+ unsigned int cstate;
+@@ -421,6 +424,60 @@ static void intel_idle_cpuidle_devices_uninit(void)
+ return;
+ }
+ /*
++ * intel_idle_cpuidle_driver_init()
++ * allocate, initialize cpuidle_states
++ */
++static int intel_idle_cpuidle_driver_init(void)
++{
++ int cstate;
++ struct cpuidle_driver *drv = &intel_idle_driver;
++
++ drv->state_count = 1;
++
++ for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
++ int num_substates;
++
++ if (cstate > max_cstate) {
++ printk(PREFIX "max_cstate %d reached\n",
++ max_cstate);
++ break;
++ }
++
++ /* does the state exist in CPUID.MWAIT? */
++ num_substates = (mwait_substates >> ((cstate) * 4))
++ & MWAIT_SUBSTATE_MASK;
++ if (num_substates == 0)
++ continue;
++ /* is the state not enabled? */
++ if (cpuidle_state_table[cstate].enter == NULL) {
++ /* does the driver not know about the state? */
++ if (*cpuidle_state_table[cstate].name == '\0')
++ pr_debug(PREFIX "unaware of model 0x%x"
++ " MWAIT %d please"
++ " contact lenb@kernel.org",
++ boot_cpu_data.x86_model, cstate);
++ continue;
++ }
++
++ if ((cstate > 2) &&
++ !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
++ mark_tsc_unstable("TSC halts in idle"
++ " states deeper than C2");
++
++ drv->states[drv->state_count] = /* structure copy */
++ cpuidle_state_table[cstate];
++
++ drv->state_count += 1;
++ }
++
++ if (auto_demotion_disable_flags)
++ smp_call_function(auto_demotion_disable, NULL, 1);
++
++ return 0;
++}
++
++
++/*
+ * intel_idle_cpuidle_devices_init()
+ * allocate, initialize, register cpuidle_devices
+ */
+@@ -454,23 +511,9 @@ static int intel_idle_cpuidle_devices_init(void)
+ continue;
+ /* is the state not enabled? */
+ if (cpuidle_state_table[cstate].enter == NULL) {
+- /* does the driver not know about the state? */
+- if (*cpuidle_state_table[cstate].name == '\0')
+- pr_debug(PREFIX "unaware of model 0x%x"
+- " MWAIT %d please"
+- " contact lenb@kernel.org",
+- boot_cpu_data.x86_model, cstate);
+ continue;
+ }
+
+- if ((cstate > 2) &&
+- !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+- mark_tsc_unstable("TSC halts in idle"
+- " states deeper than C2");
+-
+- dev->states[dev->state_count] = /* structure copy */
+- cpuidle_state_table[cstate];
+-
+ dev->states_usage[dev->state_count].driver_data =
+ (void *)get_driver_data(cstate);
+
+@@ -485,8 +528,6 @@ static int intel_idle_cpuidle_devices_init(void)
+ return -EIO;
+ }
+ }
+- if (auto_demotion_disable_flags)
+- on_each_cpu(auto_demotion_disable, NULL, 1);
+
+ return 0;
+ }
+@@ -504,6 +545,7 @@ static int __init intel_idle_init(void)
+ if (retval)
+ return retval;
+
++ intel_idle_cpuidle_driver_init();
+ retval = cpuidle_register_driver(&intel_idle_driver);
+ if (retval) {
+ printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
+diff --git a/include/acpi/processor.h b/include/acpi/processor.h
+index ba4928c..716e97b 100644
+--- a/include/acpi/processor.h
++++ b/include/acpi/processor.h
+@@ -329,6 +329,7 @@ extern void acpi_processor_throttling_init(void);
+ int acpi_processor_power_init(struct acpi_processor *pr,
+ struct acpi_device *device);
+ int acpi_processor_cst_has_changed(struct acpi_processor *pr);
++int acpi_processor_hotplug(struct acpi_processor *pr);
+ int acpi_processor_power_exit(struct acpi_processor *pr,
+ struct acpi_device *device);
+ int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index 0156540..c904188 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -22,6 +22,7 @@
+ #define CPUIDLE_DESC_LEN 32
+
+ struct cpuidle_device;
++struct cpuidle_driver;
+
+
+ /****************************
+@@ -45,6 +46,7 @@ struct cpuidle_state {
+ unsigned int target_residency; /* in US */
+
+ int (*enter) (struct cpuidle_device *dev,
++ struct cpuidle_driver *drv,
+ int index);
+ };
+
+@@ -83,12 +85,10 @@ struct cpuidle_state_kobj {
+ struct cpuidle_device {
+ unsigned int registered:1;
+ unsigned int enabled:1;
+- unsigned int power_specified:1;
+ unsigned int cpu;
+
+ int last_residency;
+ int state_count;
+- struct cpuidle_state states[CPUIDLE_STATE_MAX];
+ struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
+ struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
+
+@@ -96,7 +96,6 @@ struct cpuidle_device {
+ struct kobject kobj;
+ struct completion kobj_unregister;
+ void *governor_data;
+- int safe_state_index;
+ };
+
+ DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+@@ -120,6 +119,11 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
+ struct cpuidle_driver {
+ char name[CPUIDLE_NAME_LEN];
+ struct module *owner;
++
++ unsigned int power_specified:1;
++ struct cpuidle_state states[CPUIDLE_STATE_MAX];
++ int state_count;
++ int safe_state_index;
+ };
+
+ #ifdef CONFIG_CPU_IDLE
+@@ -166,10 +170,13 @@ struct cpuidle_governor {
+ struct list_head governor_list;
+ unsigned int rating;
+
+- int (*enable) (struct cpuidle_device *dev);
+- void (*disable) (struct cpuidle_device *dev);
++ int (*enable) (struct cpuidle_driver *drv,
++ struct cpuidle_device *dev);
++ void (*disable) (struct cpuidle_driver *drv,
++ struct cpuidle_device *dev);
+
+- int (*select) (struct cpuidle_device *dev);
++ int (*select) (struct cpuidle_driver *drv,
++ struct cpuidle_device *dev);
+ void (*reflect) (struct cpuidle_device *dev, int index);
+
+ struct module *owner;
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0046-cpuidle-Add-common-time-keeping-and-irq-enabling.patch b/patches.kzm9g/0046-cpuidle-Add-common-time-keeping-and-irq-enabling.patch
new file mode 100644
index 00000000000000..6e6e73f5646766
--- /dev/null
+++ b/patches.kzm9g/0046-cpuidle-Add-common-time-keeping-and-irq-enabling.patch
@@ -0,0 +1,285 @@
+From 578cf9ddd7dd3eee538113c2824ddfe3ca0b9857 Mon Sep 17 00:00:00 2001
+From: Robert Lee <rob.lee@linaro.org>
+Date: Tue, 20 Mar 2012 15:22:42 -0500
+Subject: cpuidle: Add common time keeping and irq enabling
+
+Make necessary changes to implement time keeping and irq enabling
+in the core cpuidle code. This will allow the removal of these
+functionalities from various platform cpuidle implementations whose
+timekeeping and irq enabling follows the form in this common code.
+
+Signed-off-by: Robert Lee <rob.lee@linaro.org>
+Tested-by: Jean Pihet <j-pihet@ti.com>
+Tested-by: Amit Daniel <amit.kachhap@linaro.org>
+Tested-by: Robert Lee <rob.lee@linaro.org>
+Reviewed-by: Kevin Hilman <khilman@ti.com>
+Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Reviewed-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
+Acked-by: Jean Pihet <j-pihet@ti.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+(cherry picked from commit e1689795a784a7c41ac4cf9032794986b095a133)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/include/asm/cpuidle.h | 29 ++++++++++++++++++
+ arch/arm/kernel/Makefile | 2 +-
+ arch/arm/kernel/cpuidle.c | 21 +++++++++++++
+ drivers/cpuidle/cpuidle.c | 66 +++++++++++++++++++++++++++++++++++-----
+ include/linux/cpuidle.h | 13 +++++++-
+ 5 files changed, 122 insertions(+), 9 deletions(-)
+ create mode 100644 arch/arm/include/asm/cpuidle.h
+ create mode 100644 arch/arm/kernel/cpuidle.c
+
+diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h
+new file mode 100644
+index 0000000..2fca60a
+--- /dev/null
++++ b/arch/arm/include/asm/cpuidle.h
+@@ -0,0 +1,29 @@
++#ifndef __ASM_ARM_CPUIDLE_H
++#define __ASM_ARM_CPUIDLE_H
++
++#ifdef CONFIG_CPU_IDLE
++extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index);
++#else
++static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index) { return -ENODEV; }
++#endif
++
++/* Common ARM WFI state */
++#define ARM_CPUIDLE_WFI_STATE_PWR(p) {\
++ .enter = arm_cpuidle_simple_enter,\
++ .exit_latency = 1,\
++ .target_residency = 1,\
++ .power_usage = p,\
++ .flags = CPUIDLE_FLAG_TIME_VALID,\
++ .name = "WFI",\
++ .desc = "ARM WFI",\
++}
++
++/*
++ * in case power_specified == 1, give a default WFI power value needed
++ * by some governors
++ */
++#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX)
++
++#endif
+diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
+index 816a481..086fe97 100644
+--- a/arch/arm/kernel/Makefile
++++ b/arch/arm/kernel/Makefile
+@@ -21,7 +21,7 @@ obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
+
+ obj-$(CONFIG_LEDS) += leds.o
+ obj-$(CONFIG_OC_ETM) += etm.o
+-
++obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+ obj-$(CONFIG_ISA_DMA_API) += dma.o
+ obj-$(CONFIG_ARCH_ACORN) += ecard.o
+ obj-$(CONFIG_FIQ) += fiq.o fiqasm.o
+diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c
+new file mode 100644
+index 0000000..89545f6
+--- /dev/null
++++ b/arch/arm/kernel/cpuidle.c
+@@ -0,0 +1,21 @@
++/*
++ * Copyright 2012 Linaro Ltd.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++#include <linux/cpuidle.h>
++#include <asm/proc-fns.h>
++
++int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
++{
++ cpu_do_idle();
++
++ return index;
++}
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index 06ce268..3d3bd98 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -53,6 +53,24 @@ static void cpuidle_kick_cpus(void) {}
+
+ static int __cpuidle_register_device(struct cpuidle_device *dev);
+
++static inline int cpuidle_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
++{
++ struct cpuidle_state *target_state = &drv->states[index];
++ return target_state->enter(dev, drv, index);
++}
++
++static inline int cpuidle_enter_tk(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index)
++{
++ return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter);
++}
++
++typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index);
++
++static cpuidle_enter_t cpuidle_enter_ops;
++
+ /**
+ * cpuidle_idle_call - the main idle loop
+ *
+@@ -63,7 +81,6 @@ int cpuidle_idle_call(void)
+ {
+ struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+ struct cpuidle_driver *drv = cpuidle_get_driver();
+- struct cpuidle_state *target_state;
+ int next_state, entered_state;
+
+ if (off)
+@@ -92,12 +109,10 @@ int cpuidle_idle_call(void)
+ return 0;
+ }
+
+- target_state = &drv->states[next_state];
+-
+ trace_power_start(POWER_CSTATE, next_state, dev->cpu);
+ trace_cpu_idle(next_state, dev->cpu);
+
+- entered_state = target_state->enter(dev, drv, next_state);
++ entered_state = cpuidle_enter_ops(dev, drv, next_state);
+
+ trace_power_end(dev->cpu);
+ trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
+@@ -110,6 +125,8 @@ int cpuidle_idle_call(void)
+ dev->states_usage[entered_state].time +=
+ (unsigned long long)dev->last_residency;
+ dev->states_usage[entered_state].usage++;
++ } else {
++ dev->last_residency = 0;
+ }
+
+ /* give the governor an opportunity to reflect on the outcome */
+@@ -164,6 +181,37 @@ void cpuidle_resume_and_unlock(void)
+
+ EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
+
++/**
++ * cpuidle_wrap_enter - performs timekeeping and irqen around enter function
++ * @dev: pointer to a valid cpuidle_device object
++ * @drv: pointer to a valid cpuidle_driver object
++ * @index: index of the target cpuidle state.
++ */
++int cpuidle_wrap_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index,
++ int (*enter)(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index))
++{
++ ktime_t time_start, time_end;
++ s64 diff;
++
++ time_start = ktime_get();
++
++ index = enter(dev, drv, index);
++
++ time_end = ktime_get();
++
++ local_irq_enable();
++
++ diff = ktime_to_us(ktime_sub(time_end, time_start));
++ if (diff > INT_MAX)
++ diff = INT_MAX;
++
++ dev->last_residency = (int) diff;
++
++ return index;
++}
++
+ #ifdef CONFIG_ARCH_HAS_CPU_RELAX
+ static int poll_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+@@ -212,10 +260,11 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
+ int cpuidle_enable_device(struct cpuidle_device *dev)
+ {
+ int ret, i;
++ struct cpuidle_driver *drv = cpuidle_get_driver();
+
+ if (dev->enabled)
+ return 0;
+- if (!cpuidle_get_driver() || !cpuidle_curr_governor)
++ if (!drv || !cpuidle_curr_governor)
+ return -EIO;
+ if (!dev->state_count)
+ return -EINVAL;
+@@ -226,13 +275,16 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
+ return ret;
+ }
+
+- poll_idle_init(cpuidle_get_driver());
++ cpuidle_enter_ops = drv->en_core_tk_irqen ?
++ cpuidle_enter_tk : cpuidle_enter;
++
++ poll_idle_init(drv);
+
+ if ((ret = cpuidle_add_state_sysfs(dev)))
+ return ret;
+
+ if (cpuidle_curr_governor->enable &&
+- (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
++ (ret = cpuidle_curr_governor->enable(drv, dev)))
+ goto fail_sysfs;
+
+ for (i = 0; i < dev->state_count; i++) {
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index c904188..fd11aa0 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -16,6 +16,7 @@
+ #include <linux/module.h>
+ #include <linux/kobject.h>
+ #include <linux/completion.h>
++#include <linux/hrtimer.h>
+
+ #define CPUIDLE_STATE_MAX 8
+ #define CPUIDLE_NAME_LEN 16
+@@ -121,6 +122,8 @@ struct cpuidle_driver {
+ struct module *owner;
+
+ unsigned int power_specified:1;
++ /* set to 1 to use the core cpuidle time keeping (for all states). */
++ unsigned int en_core_tk_irqen:1;
+ struct cpuidle_state states[CPUIDLE_STATE_MAX];
+ int state_count;
+ int safe_state_index;
+@@ -140,7 +143,10 @@ extern void cpuidle_pause_and_lock(void);
+ extern void cpuidle_resume_and_unlock(void);
+ extern int cpuidle_enable_device(struct cpuidle_device *dev);
+ extern void cpuidle_disable_device(struct cpuidle_device *dev);
+-
++extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index,
++ int (*enter)(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index));
+ #else
+ static inline void disable_cpuidle(void) { }
+ static inline int cpuidle_idle_call(void) { return -ENODEV; }
+@@ -158,6 +164,11 @@ static inline void cpuidle_resume_and_unlock(void) { }
+ static inline int cpuidle_enable_device(struct cpuidle_device *dev)
+ {return -ENODEV; }
+ static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
++static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index,
++ int (*enter)(struct cpuidle_device *dev,
++ struct cpuidle_driver *drv, int index))
++{ return -ENODEV; }
+
+ #endif
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0047-mm-add-vm_area_add_early.patch b/patches.kzm9g/0047-mm-add-vm_area_add_early.patch
new file mode 100644
index 00000000000000..6e00e80e95e5ae
--- /dev/null
+++ b/patches.kzm9g/0047-mm-add-vm_area_add_early.patch
@@ -0,0 +1,92 @@
+From faf323f0f552c0523cce81cf62b87a87b3eb0020 Mon Sep 17 00:00:00 2001
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Thu, 25 Aug 2011 00:24:21 -0400
+Subject: mm: add vm_area_add_early()
+
+The existing vm_area_register_early() allows for early vmalloc space
+allocation. However upcoming cleanups in the ARM architecture require
+that some fixed locations in the vmalloc area be reserved also very early.
+
+The name "vm_area_register_early" would have been a good name for the
+reservation part without the allocation. Since it is already in use with
+different semantics, let's create vm_area_add_early() instead.
+
+Both vm_area_register_early() and vm_area_add_early() can be used together
+meaning that the former is now implemented using the later where it is
+ensured that no conflicting areas are added, but no attempt is made to
+make the allocation scheme in vm_area_register_early() more sophisticated.
+After all, you must know what you're doing when using those functions.
+
+Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
+Acked-by: Andrew Morton <akpm@linux-foundation.org>
+Cc: linux-mm@kvack.org
+(cherry picked from commit be9b7335e70696bee731c152429b1737e42fe163)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/vmalloc.h | 1 +
+ mm/vmalloc.c | 29 +++++++++++++++++++++++++++--
+ 2 files changed, 28 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
+index 687fb11..4115d6a 100644
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -131,6 +131,7 @@ extern long vwrite(char *buf, char *addr, unsigned long count);
+ */
+ extern rwlock_t vmlist_lock;
+ extern struct vm_struct *vmlist;
++extern __init void vm_area_add_early(struct vm_struct *vm);
+ extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
+
+ #ifdef CONFIG_SMP
+diff --git a/mm/vmalloc.c b/mm/vmalloc.c
+index 43b44db..fb0d354 100644
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -1132,6 +1132,32 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
+ EXPORT_SYMBOL(vm_map_ram);
+
+ /**
++ * vm_area_add_early - add vmap area early during boot
++ * @vm: vm_struct to add
++ *
++ * This function is used to add fixed kernel vm area to vmlist before
++ * vmalloc_init() is called. @vm->addr, @vm->size, and @vm->flags
++ * should contain proper values and the other fields should be zero.
++ *
++ * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING.
++ */
++void __init vm_area_add_early(struct vm_struct *vm)
++{
++ struct vm_struct *tmp, **p;
++
++ BUG_ON(vmap_initialized);
++ for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
++ if (tmp->addr >= vm->addr) {
++ BUG_ON(tmp->addr < vm->addr + vm->size);
++ break;
++ } else
++ BUG_ON(tmp->addr + tmp->size > vm->addr);
++ }
++ vm->next = *p;
++ *p = vm;
++}
++
++/**
+ * vm_area_register_early - register vmap area early during boot
+ * @vm: vm_struct to register
+ * @align: requested alignment
+@@ -1153,8 +1179,7 @@ void __init vm_area_register_early(struct vm_struct *vm, size_t align)
+
+ vm->addr = (void *)addr;
+
+- vm->next = vmlist;
+- vmlist = vm;
++ vm_area_add_early(vm);
+ }
+
+ void __init vmalloc_init(void)
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0048-clockevents-Make-clockevents_config-a-global-symbol.patch b/patches.kzm9g/0048-clockevents-Make-clockevents_config-a-global-symbol.patch
new file mode 100644
index 00000000000000..c276f9f29d3b24
--- /dev/null
+++ b/patches.kzm9g/0048-clockevents-Make-clockevents_config-a-global-symbol.patch
@@ -0,0 +1,46 @@
+From fff14be80697fd2ad8584769e60a24f97ba0a704 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 9 May 2012 23:39:34 +0900
+Subject: clockevents: Make clockevents_config() a global symbol
+
+Make clockevents_config() into a global symbol to allow it
+to be used by compiled-in clockevent drivers. This is needed
+by drivers that want to update the timer frequency after
+registration time.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/clockchips.h | 1 +
+ kernel/time/clockevents.c | 3 +--
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
+index d6733e2..91d1b67 100644
+--- a/include/linux/clockchips.h
++++ b/include/linux/clockchips.h
+@@ -128,6 +128,7 @@ extern u64 clockevent_delta2ns(unsigned long latch,
+ struct clock_event_device *evt);
+ extern void clockevents_register_device(struct clock_event_device *dev);
+
++extern void clockevents_config(struct clock_event_device *dev, u32 freq);
+ extern void clockevents_config_and_register(struct clock_event_device *dev,
+ u32 freq, unsigned long min_delta,
+ unsigned long max_delta);
+diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
+index e4c699d..1029cbc 100644
+--- a/kernel/time/clockevents.c
++++ b/kernel/time/clockevents.c
+@@ -197,8 +197,7 @@ void clockevents_register_device(struct clock_event_device *dev)
+ }
+ EXPORT_SYMBOL_GPL(clockevents_register_device);
+
+-static void clockevents_config(struct clock_event_device *dev,
+- u32 freq)
++void clockevents_config(struct clock_event_device *dev, u32 freq)
+ {
+ u64 sec;
+
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0049-clocksource-em_sti-Emma-Mobile-STI-driver-V2.patch b/patches.kzm9g/0049-clocksource-em_sti-Emma-Mobile-STI-driver-V2.patch
new file mode 100644
index 00000000000000..826ec8002d1011
--- /dev/null
+++ b/patches.kzm9g/0049-clocksource-em_sti-Emma-Mobile-STI-driver-V2.patch
@@ -0,0 +1,484 @@
+From c97faaf620983062ebff15fd4db3f341a8e224b2 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 9 May 2012 23:39:42 +0900
+Subject: clocksource: em_sti: Emma Mobile STI driver V2
+
+This is V2 of the Emma Mobile STI timer driver.
+
+The STI hardware is based on a single 48-bit 32kHz
+counter that together with two individual compare
+registers can generate interrupts. There are no
+timer operating modes selectable which means that
+the timer can not clear on match.
+
+This driver is providing clocksource support for the
+48-bit counter. Clockevents are also supported using
+the same timer in periodic or oneshot modes.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+
+Conflicts:
+ drivers/clocksource/Makefile
+---
+ arch/arm/mach-shmobile/Kconfig | 6 +
+ drivers/clocksource/Makefile | 1 +
+ drivers/clocksource/em_sti.c | 418 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 425 insertions(+)
+ create mode 100644 drivers/clocksource/em_sti.c
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index 9020c1b..1e7656a 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -147,6 +147,12 @@ config SH_TIMER_TMU
+ help
+ This enables build of the TMU timer driver.
+
++config EM_TIMER_STI
++ bool "STI timer driver"
++ default y
++ help
++ This enables build of the STI timer driver.
++
+ endmenu
+
+ config SH_CLK_CPG
+diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
+index b995942..59eb37d 100644
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -6,5 +6,6 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o
+ obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
+ obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
+ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
++obj-$(CONFIG_EM_TIMER_STI) += em_sti.o
+ obj-$(CONFIG_CLKSRC_I8253) += i8253.o
+ obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
+diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
+new file mode 100644
+index 0000000..e8fc46d
+--- /dev/null
++++ b/drivers/clocksource/em_sti.c
+@@ -0,0 +1,418 @@
++/*
++ * Emma Mobile Timer Support - STI
++ *
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/irq.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR };
++
++struct em_sti_priv {
++ void __iomem *base;
++ struct clk *clk;
++ struct platform_device *pdev;
++ unsigned int active[USER_NR];
++ unsigned long rate;
++ unsigned long delta;
++ cycle_t next;
++ spinlock_t lock;
++ struct clock_event_device ced;
++ struct clocksource cs;
++};
++
++#define STI_CONTROL 0x00
++#define STI_COMPA_H 0x10
++#define STI_COMPA_L 0x14
++#define STI_COMPB_H 0x18
++#define STI_COMPB_L 0x1c
++#define STI_COUNT_H 0x20
++#define STI_COUNT_L 0x24
++#define STI_COUNT_RAW_H 0x28
++#define STI_COUNT_RAW_L 0x2c
++#define STI_SET_H 0x30
++#define STI_SET_L 0x34
++#define STI_INTSTATUS 0x40
++#define STI_INTRAWSTATUS 0x44
++#define STI_INTENSET 0x48
++#define STI_INTENCLR 0x4c
++#define STI_INTFFCLR 0x50
++
++static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs)
++{
++ return ioread32(p->base + offs);
++}
++
++static inline void em_sti_write(struct em_sti_priv *p, int offs,
++ unsigned long value)
++{
++ iowrite32(value, p->base + offs);
++}
++
++static int em_sti_enable(struct em_sti_priv *p)
++{
++ int ret;
++
++ /* enable clock */
++ ret = clk_enable(p->clk);
++ if (ret) {
++ dev_err(&p->pdev->dev, "cannot enable clock\n");
++ return ret;
++ }
++
++ /* configure channel, periodic mode and maximum timeout */
++ p->rate = clk_get_rate(p->clk);
++
++ /* reset the counter */
++ em_sti_write(p, STI_SET_H, 0x40000000);
++ em_sti_write(p, STI_SET_L, 0x00000000);
++
++ /* mask and clear pending interrupts */
++ em_sti_write(p, STI_INTENCLR, 3);
++ em_sti_write(p, STI_INTFFCLR, 3);
++
++ /* enable updates of counter registers */
++ em_sti_write(p, STI_CONTROL, 1);
++
++ return 0;
++}
++
++static void em_sti_disable(struct em_sti_priv *p)
++{
++ /* mask interrupts */
++ em_sti_write(p, STI_INTENCLR, 3);
++
++ /* stop clock */
++ clk_disable(p->clk);
++}
++
++static cycle_t em_sti_count(struct em_sti_priv *p)
++{
++ cycle_t ticks;
++ unsigned long flags;
++
++ /* the STI hardware buffers the 48-bit count, but to
++ * break it out into two 32-bit access the registers
++ * must be accessed in a certain order.
++ * Always read STI_COUNT_H before STI_COUNT_L.
++ */
++ spin_lock_irqsave(&p->lock, flags);
++ ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32;
++ ticks |= em_sti_read(p, STI_COUNT_L);
++ spin_unlock_irqrestore(&p->lock, flags);
++
++ return ticks;
++}
++
++static void em_sti_update(struct em_sti_priv *p)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&p->lock, flags);
++
++ /* update our cached counter */
++ p->next += p->delta;
++
++ /* mask compare A interrupt */
++ em_sti_write(p, STI_INTENCLR, 1);
++
++ /* update compare A value */
++ em_sti_write(p, STI_COMPA_H, p->next >> 32);
++ em_sti_write(p, STI_COMPA_L, p->next & 0xffffffff);
++
++ /* clear compare A interrupt source */
++ em_sti_write(p, STI_INTFFCLR, 1);
++
++ /* unmask compare A interrupt */
++ em_sti_write(p, STI_INTENSET, 1);
++
++ spin_unlock_irqrestore(&p->lock, flags);
++}
++
++static irqreturn_t em_sti_interrupt(int irq, void *dev_id)
++{
++ struct em_sti_priv *p = dev_id;
++
++ /* Always regprogram timer compare A */
++ if (p->ced.mode == CLOCK_EVT_MODE_PERIODIC)
++ em_sti_update(p);
++
++ p->ced.event_handler(&p->ced);
++ return IRQ_HANDLED;
++}
++
++static int em_sti_start(struct em_sti_priv *p, unsigned int user)
++{
++ unsigned long flags;
++ int used_before;
++ int ret = 0;
++
++ spin_lock_irqsave(&p->lock, flags);
++ used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
++ if (!used_before)
++ ret = em_sti_enable(p);
++
++ if (!ret)
++ p->active[user] = 1;
++ spin_unlock_irqrestore(&p->lock, flags);
++
++ return ret;
++}
++
++static void em_sti_stop(struct em_sti_priv *p, unsigned int user)
++{
++ unsigned long flags;
++ int used_before, used_after;
++
++ spin_lock_irqsave(&p->lock, flags);
++ used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
++ p->active[user] = 0;
++ used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
++
++ if (used_before && !used_after)
++ em_sti_disable(p);
++ spin_unlock_irqrestore(&p->lock, flags);
++}
++
++static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs)
++{
++ return container_of(cs, struct em_sti_priv, cs);
++}
++
++static cycle_t em_sti_clocksource_read(struct clocksource *cs)
++{
++ return em_sti_count(cs_to_em_sti(cs));
++}
++
++static int em_sti_clocksource_enable(struct clocksource *cs)
++{
++ int ret;
++ struct em_sti_priv *p = cs_to_em_sti(cs);
++
++ ret = em_sti_start(p, USER_CLOCKSOURCE);
++ if (!ret)
++ __clocksource_updatefreq_hz(cs, p->rate);
++ return ret;
++}
++
++static void em_sti_clocksource_disable(struct clocksource *cs)
++{
++ em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE);
++}
++
++static void em_sti_clocksource_resume(struct clocksource *cs)
++{
++ em_sti_clocksource_enable(cs);
++}
++
++static int em_sti_register_clocksource(struct em_sti_priv *p)
++{
++ struct clocksource *cs = &p->cs;
++
++ memset(cs, 0, sizeof(*cs));
++ cs->name = dev_name(&p->pdev->dev);
++ cs->rating = 200;
++ cs->read = em_sti_clocksource_read;
++ cs->enable = em_sti_clocksource_enable;
++ cs->disable = em_sti_clocksource_disable;
++ cs->suspend = em_sti_clocksource_disable;
++ cs->resume = em_sti_clocksource_resume;
++ cs->mask = CLOCKSOURCE_MASK(48);
++ cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
++
++ dev_info(&p->pdev->dev, "used as clock source\n");
++
++ /* Register with dummy 1 Hz value, gets updated in ->enable() */
++ clocksource_register_hz(cs, 1);
++ return 0;
++}
++
++static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced)
++{
++ return container_of(ced, struct em_sti_priv, ced);
++}
++
++static void em_sti_clock_event_mode(enum clock_event_mode mode,
++ struct clock_event_device *ced)
++{
++ struct em_sti_priv *p = ced_to_em_sti(ced);
++
++ /* deal with old setting first */
++ switch (ced->mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ case CLOCK_EVT_MODE_ONESHOT:
++ em_sti_stop(p, USER_CLOCKEVENT);
++ break;
++ default:
++ break;
++ }
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ dev_info(&p->pdev->dev, "used for periodic clock events\n");
++ em_sti_start(p, USER_CLOCKEVENT);
++ clockevents_config(&p->ced, p->rate);
++ p->delta = (p->rate + HZ/2) / HZ;
++ p->next = em_sti_count(p);
++ em_sti_update(p);
++ break;
++ case CLOCK_EVT_MODE_ONESHOT:
++ dev_info(&p->pdev->dev, "used for oneshot clock events\n");
++ em_sti_start(p, USER_CLOCKEVENT);
++ clockevents_config(&p->ced, p->rate);
++ break;
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ case CLOCK_EVT_MODE_UNUSED:
++ em_sti_stop(p, USER_CLOCKEVENT);
++ break;
++ default:
++ break;
++ }
++}
++
++static int em_sti_clock_event_next(unsigned long delta,
++ struct clock_event_device *ced)
++{
++ struct em_sti_priv *p = ced_to_em_sti(ced);
++ int safe;
++
++ p->delta = delta;
++ p->next = em_sti_count(p);
++ em_sti_update(p);
++
++ safe = em_sti_count(p) < (p->next - 1);
++
++ return !safe;
++}
++
++static void em_sti_register_clockevent(struct em_sti_priv *p)
++{
++ struct clock_event_device *ced = &p->ced;
++
++ memset(ced, 0, sizeof(*ced));
++ ced->name = dev_name(&p->pdev->dev);
++ ced->features = CLOCK_EVT_FEAT_PERIODIC;
++ ced->features |= CLOCK_EVT_FEAT_ONESHOT;
++ ced->rating = 200;
++ ced->cpumask = cpumask_of(0);
++ ced->set_next_event = em_sti_clock_event_next;
++ ced->set_mode = em_sti_clock_event_mode;
++
++ dev_info(&p->pdev->dev, "used for clock events\n");
++
++ /* Register with dummy 1 Hz value, gets updated in ->set_mode() */
++ clockevents_config_and_register(ced, 1, 2, 0xffffffff);
++}
++
++static int __devinit em_sti_probe(struct platform_device *pdev)
++{
++ struct em_sti_priv *p;
++ struct resource *res;
++ int irq, ret;
++
++ p = kzalloc(sizeof(*p), GFP_KERNEL);
++ if (p == NULL) {
++ dev_err(&pdev->dev, "failed to allocate driver data\n");
++ ret = -ENOMEM;
++ goto err0;
++ }
++
++ p->pdev = pdev;
++ platform_set_drvdata(pdev, p);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "failed to get I/O memory\n");
++ ret = -EINVAL;
++ goto err0;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "failed to get irq\n");
++ ret = -EINVAL;
++ goto err0;
++ }
++
++ /* map memory, let base point to the STI instance */
++ p->base = ioremap_nocache(res->start, resource_size(res));
++ if (p->base == NULL) {
++ dev_err(&pdev->dev, "failed to remap I/O memory\n");
++ ret = -ENXIO;
++ goto err0;
++ }
++
++ /* get hold of clock */
++ p->clk = clk_get(&pdev->dev, "sclk");
++ if (IS_ERR(p->clk)) {
++ dev_err(&pdev->dev, "cannot get clock\n");
++ ret = PTR_ERR(p->clk);
++ goto err1;
++ }
++
++ if (request_irq(irq, em_sti_interrupt,
++ IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
++ dev_name(&pdev->dev), p)) {
++ dev_err(&pdev->dev, "failed to request low IRQ\n");
++ ret = -ENOENT;
++ goto err2;
++ }
++
++ spin_lock_init(&p->lock);
++ em_sti_register_clockevent(p);
++ em_sti_register_clocksource(p);
++ return 0;
++
++err2:
++ clk_put(p->clk);
++err1:
++ iounmap(p->base);
++err0:
++ kfree(p);
++ return ret;
++}
++
++static int __devexit em_sti_remove(struct platform_device *pdev)
++{
++ return -EBUSY; /* cannot unregister clockevent and clocksource */
++}
++
++static struct platform_driver em_sti_device_driver = {
++ .probe = em_sti_probe,
++ .remove = __devexit_p(em_sti_remove),
++ .driver = {
++ .name = "em_sti",
++ }
++};
++
++module_platform_driver(em_sti_device_driver);
++
++MODULE_AUTHOR("Magnus Damm");
++MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver");
++MODULE_LICENSE("GPL v2");
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0050-ARM-move-initialization-of-the-high_memory-variable-.patch b/patches.kzm9g/0050-ARM-move-initialization-of-the-high_memory-variable-.patch
new file mode 100644
index 00000000000000..995ac0d9c826bd
--- /dev/null
+++ b/patches.kzm9g/0050-ARM-move-initialization-of-the-high_memory-variable-.patch
@@ -0,0 +1,63 @@
+From 778219539dbd4ac7a63ab82fdba8b529e61f1aeb Mon Sep 17 00:00:00 2001
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Sun, 18 Sep 2011 22:40:00 -0400
+Subject: ARM: move initialization of the high_memory variable earlier
+
+Some upcoming changes must know the VMALLOC_START value, which is based
+on high_memory, before bootmem_init() is called.
+
+The best location to set it is in sanity_check_meminfo() where the needed
+computation is already done, and in the non MMU case it is trivial to do
+now that the meminfo array is already sorted at that point.
+
+Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
+(cherry picked from commit 55a8173cfe1c6b489f8f5705282c762aed2e265e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mm/init.c | 2 --
+ arch/arm/mm/mmu.c | 1 +
+ arch/arm/mm/nommu.c | 2 ++
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
+index db04a3e5..0530019 100644
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -391,8 +391,6 @@ void __init bootmem_init(void)
+ */
+ arm_bootmem_free(min, max_low, max_high);
+
+- high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1;
+-
+ /*
+ * This doesn't seem to be used by the Linux memory manager any
+ * more, but is used by ll_rw_block. If we can get rid of it, we
+diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
+index 594d677..eefb8ed 100644
+--- a/arch/arm/mm/mmu.c
++++ b/arch/arm/mm/mmu.c
+@@ -852,6 +852,7 @@ void __init sanity_check_meminfo(void)
+ }
+ #endif
+ meminfo.nr_banks = j;
++ high_memory = __va(lowmem_limit - 1) + 1;
+ memblock_set_current_limit(lowmem_limit);
+ }
+
+diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
+index 941a98c..9348730 100644
+--- a/arch/arm/mm/nommu.c
++++ b/arch/arm/mm/nommu.c
+@@ -29,6 +29,8 @@ void __init arm_mm_memblock_reserve(void)
+
+ void __init sanity_check_meminfo(void)
+ {
++ phys_addr_t end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]);
++ high_memory = __va(end - 1) + 1;
+ }
+
+ /*
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0051-ARM-move-iotable-mappings-within-the-vmalloc-region.patch b/patches.kzm9g/0051-ARM-move-iotable-mappings-within-the-vmalloc-region.patch
new file mode 100644
index 00000000000000..720421b0e5fa32
--- /dev/null
+++ b/patches.kzm9g/0051-ARM-move-iotable-mappings-within-the-vmalloc-region.patch
@@ -0,0 +1,207 @@
+From dbc2d5048de20169fff5e5c5032e89a4129cfc3b Mon Sep 17 00:00:00 2001
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Thu, 25 Aug 2011 00:35:59 -0400
+Subject: ARM: move iotable mappings within the vmalloc region
+
+In order to remove the build time variation between different SOCs with
+regards to VMALLOC_END, the iotable mappings are now allocated inside
+the vmalloc region. This allows for VMALLOC_END to be identical across
+all machines.
+
+The value for VMALLOC_END is now set to 0xff000000 which is right where
+the consistent DMA area starts.
+
+To accommodate all static mappings on machines with possible highmem usage,
+the default vmalloc area size is changed to 240 MB so that VMALLOC_START
+is no higher than 0xf0000000 by default.
+
+Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
+Tested-by: Stephen Warren <swarren@nvidia.com>
+Tested-by: Kevin Hilman <khilman@ti.com>
+Tested-by: Jamie Iles <jamie@jamieiles.com>
+(cherry picked from commit 0536bdf33faff4d940ac094c77998cfac368cfff)
+
+Conflicts:
+ arch/arm/mm/mmu.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ Documentation/arm/memory.txt | 11 ++++-----
+ arch/arm/include/asm/pgtable.h | 8 +------
+ arch/arm/mm/mmu.c | 49 ++++++++++++++++++++++++++++------------
+ 3 files changed, 41 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt
+index 771d48d..208a2d4 100644
+--- a/Documentation/arm/memory.txt
++++ b/Documentation/arm/memory.txt
+@@ -51,15 +51,14 @@ ffc00000 ffefffff DMA memory mapping region. Memory returned
+ ff000000 ffbfffff Reserved for future expansion of DMA
+ mapping region.
+
+-VMALLOC_END feffffff Free for platform use, recommended.
+- VMALLOC_END must be aligned to a 2MB
+- boundary.
+-
+ VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space.
+ Memory returned by vmalloc/ioremap will
+ be dynamically placed in this region.
+- VMALLOC_START may be based upon the value
+- of the high_memory variable.
++ Machine specific static mappings are also
++ located here through iotable_init().
++ VMALLOC_START is based upon the value
++ of the high_memory variable, and VMALLOC_END
++ is equal to 0xff000000.
+
+ PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region.
+ This maps the platforms RAM, and typically
+diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
+index 5750704..950dee3 100644
+--- a/arch/arm/include/asm/pgtable.h
++++ b/arch/arm/include/asm/pgtable.h
+@@ -21,7 +21,6 @@
+ #else
+
+ #include <asm/memory.h>
+-#include <mach/vmalloc.h>
+ #include <asm/pgtable-hwdef.h>
+
+ /*
+@@ -31,15 +30,10 @@
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+- *
+- * Note that platforms may override VMALLOC_START, but they must provide
+- * VMALLOC_END. VMALLOC_END defines the (exclusive) limit of this space,
+- * which may not overlap IO space.
+ */
+-#ifndef VMALLOC_START
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#endif
++#define VMALLOC_END 0xff000000UL
+
+ /*
+ * Hardware-wise, we have a two level page table structure, where the first
+diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
+index eefb8ed..6a98c4a 100644
+--- a/arch/arm/mm/mmu.c
++++ b/arch/arm/mm/mmu.c
+@@ -15,6 +15,7 @@
+ #include <linux/nodemask.h>
+ #include <linux/memblock.h>
+ #include <linux/fs.h>
++#include <linux/vmalloc.h>
+
+ #include <asm/cputype.h>
+ #include <asm/sections.h>
+@@ -521,13 +522,18 @@ EXPORT_SYMBOL(phys_mem_access_prot);
+
+ #define vectors_base() (vectors_high() ? 0xffff0000 : 0)
+
+-static void __init *early_alloc(unsigned long sz)
++static void __init *early_alloc_aligned(unsigned long sz, unsigned long align)
+ {
+- void *ptr = __va(memblock_alloc(sz, sz));
++ void *ptr = __va(memblock_alloc(sz, align));
+ memset(ptr, 0, sz);
+ return ptr;
+ }
+
++static void __init *early_alloc(unsigned long sz)
++{
++ return early_alloc_aligned(sz, sz);
++}
++
+ static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
+ {
+ if (pmd_none(*pmd)) {
+@@ -677,9 +683,10 @@ static void __init create_mapping(struct map_desc *md)
+ }
+
+ if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+- md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
++ md->virtual >= PAGE_OFFSET &&
++ (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
+ printk(KERN_WARNING "BUG: mapping for 0x%08llx"
+- " at 0x%08lx overlaps vmalloc space\n",
++ " at 0x%08lx out of vmalloc space\n",
+ (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+ }
+
+@@ -721,18 +728,32 @@ static void __init create_mapping(struct map_desc *md)
+ */
+ void __init iotable_init(struct map_desc *io_desc, int nr)
+ {
+- int i;
++ struct map_desc *md;
++ struct vm_struct *vm;
++
++ if (!nr)
++ return;
+
+- for (i = 0; i < nr; i++)
+- create_mapping(io_desc + i);
++ vm = early_alloc_aligned(sizeof(*vm) * nr, __alignof__(*vm));
++
++ for (md = io_desc; nr; md++, nr--) {
++ create_mapping(md);
++ vm->addr = (void *)(md->virtual & PAGE_MASK);
++ vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
++ vm->phys_addr = __pfn_to_phys(md->pfn);
++ vm->flags = VM_IOREMAP;
++ vm->caller = iotable_init;
++ vm_area_add_early(vm++);
++ }
+ }
+
+-static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
++static void * __initdata vmalloc_min =
++ (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
+
+ /*
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the vmalloc
+- * area - the default is 128m.
++ * area - the default is 240m.
+ */
+ static int __init early_vmalloc(char *arg)
+ {
+@@ -883,10 +904,10 @@ static inline void prepare_page_table(void)
+
+ /*
+ * Clear out all the kernel space mappings, except for the first
+- * memory bank, up to the end of the vmalloc region.
++ * memory bank, up to the vmalloc region.
+ */
+ for (addr = __phys_to_virt(end);
+- addr < VMALLOC_END; addr += PGDIR_SIZE)
++ addr < VMALLOC_START; addr += PGDIR_SIZE)
+ pmd_clear(pmd_off_k(addr));
+ }
+
+@@ -911,8 +932,8 @@ void __init arm_mm_memblock_reserve(void)
+ }
+
+ /*
+- * Set up device the mappings. Since we clear out the page tables for all
+- * mappings above VMALLOC_END, we will remove any debug device mappings.
++ * Set up the device mappings. Since we clear out the page tables for all
++ * mappings above VMALLOC_START, we will remove any debug device mappings.
+ * This means you have to be careful how you debug this function, or any
+ * called function. This means you can't use any function or debugging
+ * method which may touch any device, otherwise the kernel _will_ crash.
+@@ -927,7 +948,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
+ */
+ vectors_page = early_alloc(PAGE_SIZE);
+
+- for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
++ for (addr = VMALLOC_START; addr; addr += PGDIR_SIZE)
+ pmd_clear(pmd_off_k(addr));
+
+ /*
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0052-ARM-simplify-__iounmap-when-dealing-with-section-bas.patch b/patches.kzm9g/0052-ARM-simplify-__iounmap-when-dealing-with-section-bas.patch
new file mode 100644
index 00000000000000..85b4c27b1b4d48
--- /dev/null
+++ b/patches.kzm9g/0052-ARM-simplify-__iounmap-when-dealing-with-section-bas.patch
@@ -0,0 +1,66 @@
+From 9c711a650671536e915cea3661fc7caa2a4ab487 Mon Sep 17 00:00:00 2001
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Thu, 15 Sep 2011 22:12:19 -0400
+Subject: ARM: simplify __iounmap() when dealing with section based mapping
+
+Firstly, there is no need to have a double pointer here as we're only
+walking the vmlist and not modifying it.
+
+Secondly, for the same reason, we don't need a write lock but only a
+read lock here, since the lock only protects the coherency of the list
+nothing else.
+
+Lastly, the reason for holding a lock is not what the comment says, so
+let's remove that misleading piece of information.
+
+Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
+(cherry picked from commit 6ee723a6570a897208b76ab3e9a495e9106b2f8c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mm/ioremap.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
+index ab50627..1ddcd8a 100644
+--- a/arch/arm/mm/ioremap.c
++++ b/arch/arm/mm/ioremap.c
+@@ -293,26 +293,24 @@ void __iounmap(volatile void __iomem *io_addr)
+ {
+ void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
+ #ifndef CONFIG_SMP
+- struct vm_struct **p, *tmp;
++ struct vm_struct *vm;
+
+ /*
+ * If this is a section based mapping we need to handle it
+ * specially as the VM subsystem does not know how to handle
+- * such a beast. We need the lock here b/c we need to clear
+- * all the mappings before the area can be reclaimed
+- * by someone else.
++ * such a beast.
+ */
+- write_lock(&vmlist_lock);
+- for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
+- if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
+- if (tmp->flags & VM_ARM_SECTION_MAPPING) {
+- unmap_area_sections((unsigned long)tmp->addr,
+- tmp->size);
++ read_lock(&vmlist_lock);
++ for (vm = vmlist; vm; vm = vm->next) {
++ if ((vm->flags & VM_IOREMAP) && (vm->addr == addr)) {
++ if (vm->flags & VM_ARM_SECTION_MAPPING) {
++ unmap_area_sections((unsigned long)vm->addr,
++ vm->size);
+ }
+ break;
+ }
+ }
+- write_unlock(&vmlist_lock);
++ read_unlock(&vmlist_lock);
+ #endif
+
+ vunmap(addr);
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0053-ARM-add-generic-ioremap-optimization-by-reusing-stat.patch b/patches.kzm9g/0053-ARM-add-generic-ioremap-optimization-by-reusing-stat.patch
new file mode 100644
index 00000000000000..1ecd497ee2d9bd
--- /dev/null
+++ b/patches.kzm9g/0053-ARM-add-generic-ioremap-optimization-by-reusing-stat.patch
@@ -0,0 +1,177 @@
+From 5be0e66269ddfd8ca3dee6512e573b1f461a6faf Mon Sep 17 00:00:00 2001
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Fri, 16 Sep 2011 01:14:23 -0400
+Subject: ARM: add generic ioremap optimization by reusing static mappings
+
+Now that we have all the static mappings from iotable_init() located
+in the vmalloc area, it is trivial to optimize ioremap by reusing those
+static mappings when the requested physical area fits in one of them,
+and so in a generic way for all platforms.
+
+Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
+Tested-by: Stephen Warren <swarren@nvidia.com>
+Tested-by: Kevin Hilman <khilman@ti.com>
+Tested-by: Jamie Iles <jamie@jamieiles.com>
+(cherry picked from commit 576d2f2525612ecb5af029a76f21f22a3b82563d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mm/ioremap.c | 72 ++++++++++++++++++++++++++++++++-----------------
+ arch/arm/mm/mm.h | 14 ++++++++++
+ arch/arm/mm/mmu.c | 3 ++-
+ 3 files changed, 64 insertions(+), 25 deletions(-)
+
+diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
+index 1ddcd8a..b5900f2 100644
+--- a/arch/arm/mm/ioremap.c
++++ b/arch/arm/mm/ioremap.c
+@@ -36,12 +36,6 @@
+ #include <asm/mach/map.h>
+ #include "mm.h"
+
+-/*
+- * Used by ioremap() and iounmap() code to mark (super)section-mapped
+- * I/O regions in vm_struct->flags field.
+- */
+-#define VM_ARM_SECTION_MAPPING 0x80000000
+-
+ int ioremap_page(unsigned long virt, unsigned long phys,
+ const struct mem_type *mtype)
+ {
+@@ -201,12 +195,6 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
+ if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
+ return NULL;
+
+- /*
+- * Don't allow RAM to be mapped - this causes problems with ARMv6+
+- */
+- if (WARN_ON(pfn_valid(pfn)))
+- return NULL;
+-
+ type = get_mem_type(mtype);
+ if (!type)
+ return NULL;
+@@ -216,6 +204,34 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
+ */
+ size = PAGE_ALIGN(offset + size);
+
++ /*
++ * Try to reuse one of the static mapping whenever possible.
++ */
++ read_lock(&vmlist_lock);
++ for (area = vmlist; area; area = area->next) {
++ if (!size || (sizeof(phys_addr_t) == 4 && pfn >= 0x100000))
++ break;
++ if (!(area->flags & VM_ARM_STATIC_MAPPING))
++ continue;
++ if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))
++ continue;
++ if (__phys_to_pfn(area->phys_addr) > pfn ||
++ __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)
++ continue;
++ /* we can drop the lock here as we know *area is static */
++ read_unlock(&vmlist_lock);
++ addr = (unsigned long)area->addr;
++ addr += __pfn_to_phys(pfn) - area->phys_addr;
++ return (void __iomem *) (offset + addr);
++ }
++ read_unlock(&vmlist_lock);
++
++ /*
++ * Don't allow RAM to be mapped - this causes problems with ARMv6+
++ */
++ if (WARN_ON(pfn_valid(pfn)))
++ return NULL;
++
+ area = get_vm_area_caller(size, VM_IOREMAP, caller);
+ if (!area)
+ return NULL;
+@@ -292,26 +308,34 @@ EXPORT_SYMBOL(__arm_ioremap);
+ void __iounmap(volatile void __iomem *io_addr)
+ {
+ void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
+-#ifndef CONFIG_SMP
+ struct vm_struct *vm;
+
+- /*
+- * If this is a section based mapping we need to handle it
+- * specially as the VM subsystem does not know how to handle
+- * such a beast.
+- */
+ read_lock(&vmlist_lock);
+ for (vm = vmlist; vm; vm = vm->next) {
+- if ((vm->flags & VM_IOREMAP) && (vm->addr == addr)) {
+- if (vm->flags & VM_ARM_SECTION_MAPPING) {
+- unmap_area_sections((unsigned long)vm->addr,
+- vm->size);
+- }
++ if (vm->addr > addr)
+ break;
++ if (!(vm->flags & VM_IOREMAP))
++ continue;
++ /* If this is a static mapping we must leave it alone */
++ if ((vm->flags & VM_ARM_STATIC_MAPPING) &&
++ (vm->addr <= addr) && (vm->addr + vm->size > addr)) {
++ read_unlock(&vmlist_lock);
++ return;
+ }
++#ifndef CONFIG_SMP
++ /*
++ * If this is a section based mapping we need to handle it
++ * specially as the VM subsystem does not know how to handle
++ * such a beast.
++ */
++ if ((vm->addr == addr) &&
++ (vm->flags & VM_ARM_SECTION_MAPPING)) {
++ unmap_area_sections((unsigned long)vm->addr, vm->size);
++ break;
++ }
++#endif
+ }
+ read_unlock(&vmlist_lock);
+-#endif
+
+ vunmap(addr);
+ }
+diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
+index 5b3d7d5..26f3a2c 100644
+--- a/arch/arm/mm/mm.h
++++ b/arch/arm/mm/mm.h
+@@ -21,6 +21,20 @@ const struct mem_type *get_mem_type(unsigned int type);
+
+ extern void __flush_dcache_page(struct address_space *mapping, struct page *page);
+
++/*
++ * ARM specific vm_struct->flags bits.
++ */
++
++/* (super)section-mapped I/O regions used by ioremap()/iounmap() */
++#define VM_ARM_SECTION_MAPPING 0x80000000
++
++/* permanent static mappings from iotable_init() */
++#define VM_ARM_STATIC_MAPPING 0x40000000
++
++/* mapping type (attributes) for permanent static mappings */
++#define VM_ARM_MTYPE(mt) ((mt) << 20)
++#define VM_ARM_MTYPE_MASK (0x1f << 20)
++
+ #endif
+
+ void __init bootmem_init(void);
+diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
+index 6a98c4a..ce0e427 100644
+--- a/arch/arm/mm/mmu.c
++++ b/arch/arm/mm/mmu.c
+@@ -741,7 +741,8 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
+ vm->addr = (void *)(md->virtual & PAGE_MASK);
+ vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
+ vm->phys_addr = __pfn_to_phys(md->pfn);
+- vm->flags = VM_IOREMAP;
++ vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
++ vm->flags |= VM_ARM_MTYPE(md->type);
+ vm->caller = iotable_init;
+ vm_area_add_early(vm++);
+ }
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0054-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch b/patches.kzm9g/0054-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch
new file mode 100644
index 00000000000000..df4fe7b07a5135
--- /dev/null
+++ b/patches.kzm9g/0054-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch
@@ -0,0 +1,72 @@
+From 4db83a8c2af822cc5ae76ea212c7a77b20a637b5 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 28 Mar 2012 19:22:30 +0900
+Subject: ARM: mach-shmobile: Introduce shmobile_setup_delay()
+
+Add the function shmobile_setup_delay() to let platforms
+configure their maximum loops per jiffy delay. With this
+jiffies calculation done the dependency on early timer
+is removed.
+
+In the future this allows us to assign timers
+using the regular driver model via the device tree.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 0f2c9f20e4e339de30cfd5613dfa9505e7b9c58b)
+
+Conflicts:
+ arch/arm/mach-shmobile/include/mach/common.h
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/common.h | 2 ++
+ arch/arm/mach-shmobile/timer.c | 17 +++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
+index c77b3a1..bc3aa3e 100644
+--- a/arch/arm/mach-shmobile/include/mach/common.h
++++ b/arch/arm/mach-shmobile/include/mach/common.h
+@@ -3,6 +3,8 @@
+
+ extern void shmobile_earlytimer_init(void);
+ extern struct sys_timer shmobile_timer;
++extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
++ unsigned int mult, unsigned int div);
+ extern void shmobile_setup_console(void);
+ extern void shmobile_secondary_vector(void);
+ struct clk;
+diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
+index be1ad70..b323e3c 100644
+--- a/arch/arm/mach-shmobile/timer.c
++++ b/arch/arm/mach-shmobile/timer.c
+@@ -19,8 +19,25 @@
+ *
+ */
+ #include <linux/platform_device.h>
++#include <linux/delay.h>
+ #include <asm/mach/time.h>
+
++void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
++ unsigned int mult, unsigned int div)
++{
++ /* calculate a worst-case loops-per-jiffy value
++ * based on maximum cpu core mhz setting and the
++ * __delay() implementation in arch/arm/lib/delay.S
++ *
++ * this will result in a longer delay than expected
++ * when the cpu core runs on lower frequencies.
++ */
++
++ unsigned int value = (1000000 * mult) / (HZ * div);
++
++ lpj_fine = max_cpu_core_mhz * value;
++}
++
+ static void __init shmobile_late_time_init(void)
+ {
+ /*
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0055-ARM-mach-shmobile-Allow-SoC-specific-CPU-kill-code.patch b/patches.kzm9g/0055-ARM-mach-shmobile-Allow-SoC-specific-CPU-kill-code.patch
new file mode 100644
index 00000000000000..4c08f8fffb2b53
--- /dev/null
+++ b/patches.kzm9g/0055-ARM-mach-shmobile-Allow-SoC-specific-CPU-kill-code.patch
@@ -0,0 +1,67 @@
+From 05f453548b4b9fdf0ab8e36a15c9ef74b21f27e2 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 28 Dec 2011 16:47:16 +0900
+Subject: ARM: mach-shmobile: Allow SoC specific CPU kill code
+
+Add the function shmobile_platform_kill_cpu() to allow
+SoC specific code to tie in their CPU shutdown code.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 8b306796995609c281f6d32b3cbaa814551ad5ac)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/hotplug.c | 3 ++-
+ arch/arm/mach-shmobile/include/mach/common.h | 1 +
+ arch/arm/mach-shmobile/platsmp.c | 5 +++++
+ 3 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
+index 238a0d9..aee3a10 100644
+--- a/arch/arm/mach-shmobile/hotplug.c
++++ b/arch/arm/mach-shmobile/hotplug.c
+@@ -12,10 +12,11 @@
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/smp.h>
++#include <mach/common.h>
+
+ int platform_cpu_kill(unsigned int cpu)
+ {
+- return 1;
++ return shmobile_platform_cpu_kill(cpu);
+ }
+
+ void platform_cpu_die(unsigned int cpu)
+diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
+index bc3aa3e..8b88b80 100644
+--- a/arch/arm/mach-shmobile/include/mach/common.h
++++ b/arch/arm/mach-shmobile/include/mach/common.h
+@@ -7,6 +7,7 @@ extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
+ unsigned int mult, unsigned int div);
+ extern void shmobile_setup_console(void);
+ extern void shmobile_secondary_vector(void);
++extern int shmobile_platform_cpu_kill(unsigned int cpu);
+ struct clk;
+ extern int shmobile_clk_init(void);
+ extern void shmobile_handle_irq_intc(struct pt_regs *);
+diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
+index 2cc8930..1103ce5 100644
+--- a/arch/arm/mach-shmobile/platsmp.c
++++ b/arch/arm/mach-shmobile/platsmp.c
+@@ -37,6 +37,11 @@ static void __init shmobile_smp_prepare_cpus(void)
+ sh73a0_smp_prepare_cpus();
+ }
+
++int shmobile_platform_cpu_kill(unsigned int cpu)
++{
++ return 1;
++}
++
+ void __cpuinit platform_secondary_init(unsigned int cpu)
+ {
+ trace_hardirqs_off();
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0056-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch b/patches.kzm9g/0056-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch
new file mode 100644
index 00000000000000..3b83af24fe5af5
--- /dev/null
+++ b/patches.kzm9g/0056-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch
@@ -0,0 +1,46 @@
+From 0d710173dcca9b9e7c5ec0ddf109e9bbaa6d4a79 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Thu, 10 May 2012 00:37:48 +0200
+Subject: ARM / mach-shmobile: Use preset_lpj with calibrate_delay()
+
+Update the mach-shmobile shared delay calibration code for late
+timers. All existing in-tree non-DT socs are however using early
+timers today and they are unaffected by this change.
+
+The patch modifies shmobile_setup_delay() from using lpj_fine
+to preset_lpj. This change allows us to preset the worst case
+loops-per-jiffy value to all CPU cores on the system.
+
+The old code which made use of lpj_fine did not affect the
+secondary CPU cores which made it impossible to boot on SMP
+without early timers.
+
+Needed for SMP SoCs using late timers like EMEV2 or any other
+mach-shmobile SMP SoC that makes use of late timers via DT.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 173bf69a7af142e0325fa514954f6eeb2d20cc1d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/timer.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
+index b323e3c..a169cea 100644
+--- a/arch/arm/mach-shmobile/timer.c
++++ b/arch/arm/mach-shmobile/timer.c
+@@ -35,7 +35,8 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
+
+ unsigned int value = (1000000 * mult) / (HZ * div);
+
+- lpj_fine = max_cpu_core_mhz * value;
++ if (!preset_lpj)
++ preset_lpj = max_cpu_core_mhz * value;
+ }
+
+ static void __init shmobile_late_time_init(void)
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0057-ARM-Undelete-KZM9D-mach-type.patch b/patches.kzm9g/0057-ARM-Undelete-KZM9D-mach-type.patch
new file mode 100644
index 00000000000000..5e93acec0931ad
--- /dev/null
+++ b/patches.kzm9g/0057-ARM-Undelete-KZM9D-mach-type.patch
@@ -0,0 +1,32 @@
+From cc8618aa381c26c3aaeb40ac9617adeaac14dbfc Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Mon, 14 May 2012 19:54:51 +0900
+Subject: ARM: Undelete KZM9D mach-type
+
+Undelete the KZM9D mach-type to allow build of board
+for EMEV2 SoC support.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+
+N.B: Not present upstream
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/tools/mach-types | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
+index 2997e56..e2e0d3f 100644
+--- a/arch/arm/tools/mach-types
++++ b/arch/arm/tools/mach-types
+@@ -462,6 +462,7 @@ msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705
+ msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706
+ msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707
+ qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708
++kzm9d MACH_KZM9D KZM9D 3246
+ mx53_evk MACH_MX53_EVK MX53_EVK 2716
+ igep0030 MACH_IGEP0030 IGEP0030 2717
+ sbc3530 MACH_SBC3530 SBC3530 2722
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0058-gpio-Emma-Mobile-GPIO-driver.patch b/patches.kzm9g/0058-gpio-Emma-Mobile-GPIO-driver.patch
new file mode 100644
index 00000000000000..fd825b1f193902
--- /dev/null
+++ b/patches.kzm9g/0058-gpio-Emma-Mobile-GPIO-driver.patch
@@ -0,0 +1,481 @@
+From 1ed76280e95d4cba220d465a58caec2ba5c20632 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Fri, 11 May 2012 18:41:03 +0900
+Subject: gpio: Emma Mobile GPIO driver
+
+This patch adds a GPIO driver for the Emma Mobile line
+of SoCs. The driver is designed to be reusable between
+multiple SoCs that share the same basic building block,
+but so far it has only been used on Emma Mobile EV2.
+
+Each driver instance handles 32 GPIOs with individually
+maskable IRQs. The driver operates on two I/O memory
+ranges and the 32 GPIOs are hooked up to two interrupts.
+
+In the case of Emma Mobile EV2 this GPIO building block
+is used as main external interrupt controller hooking up
+159 GPIOS as 159 interrupts via 5 driver instances and
+10 interrupts to the GIC and the Cortex-A9 Dual.
+
+This version of the driver gets all configuration via
+struct resource and platform data, but DT bindings are
+currently in development and such support will be sent
+as a individual feature patch in the near future.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+
+N.B: This driver has been merged upsteram
+as commit a07e103ef08c6907d695a06467d7ee950796fccf.
+However, this code is an earlier version of
+the driver that doesn't make use of infrastructure
+that isn't present in Linux 3.0.
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/gpio/Kconfig | 6 +
+ drivers/gpio/Makefile | 1 +
+ drivers/gpio/gpio-em.c | 385 +++++++++++++++++++++++++++++++++
+ include/linux/platform_data/gpio-em.h | 10 +
+ 4 files changed, 402 insertions(+)
+ create mode 100644 drivers/gpio/gpio-em.c
+ create mode 100644 include/linux/platform_data/gpio-em.h
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 2967002..6450431 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -86,6 +86,12 @@ config GPIO_IT8761E
+ help
+ Say yes here to support GPIO functionality of IT8761E super I/O chip.
+
++config GPIO_EM
++ tristate "Emma Mobile GPIO"
++ depends on ARM
++ help
++ Say yes here to support GPIO on Renesas Emma Mobile SoCs.
++
+ config GPIO_EXYNOS4
+ def_bool y
+ depends on CPU_EXYNOS4210
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index b605f8e..d5ae36e 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
+ obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
+ obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
+ obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o
++obj-$(CONFIG_GPIO_EM) += gpio-em.o
+ obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
+ obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o
+ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
+diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
+new file mode 100644
+index 0000000..8873429
+--- /dev/null
++++ b/drivers/gpio/gpio-em.c
+@@ -0,0 +1,385 @@
++/*
++ * Emma Mobile GPIO Support - GIO
++ *
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <linux/err.h>
++#include <linux/gpio.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/platform_data/gpio-em.h>
++
++struct em_gio_priv {
++ void __iomem *base0;
++ void __iomem *base1;
++ unsigned int irq_base;
++ spinlock_t sense_lock;
++ struct gpio_chip gpio_chip;
++ struct irq_chip irq_chip;
++};
++
++#define GIO_E1 0x00
++#define GIO_E0 0x04
++#define GIO_EM 0x04
++#define GIO_OL 0x08
++#define GIO_OH 0x0c
++#define GIO_I 0x10
++#define GIO_IIA 0x14
++#define GIO_IEN 0x18
++#define GIO_IDS 0x1c
++#define GIO_IIM 0x1c
++#define GIO_RAW 0x20
++#define GIO_MST 0x24
++#define GIO_IIR 0x28
++
++#define GIO_IDT0 0x40
++#define GIO_IDT1 0x44
++#define GIO_IDT2 0x48
++#define GIO_IDT3 0x4c
++#define GIO_RAWBL 0x50
++#define GIO_RAWBH 0x54
++#define GIO_IRBL 0x58
++#define GIO_IRBH 0x5c
++
++#define GIO_IDT(n) GIO_IDT0 + ((n) * 4)
++
++static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs)
++{
++ if (offs < GIO_IDT0)
++ return ioread32(p->base0 + offs);
++ else
++ return ioread32(p->base1 + (offs - GIO_IDT0));
++}
++
++static inline void em_gio_write(struct em_gio_priv *p, int offs,
++ unsigned long value)
++{
++ if (offs < GIO_IDT0)
++ iowrite32(value, p->base0 + offs);
++ else
++ iowrite32(value, p->base1 + (offs - GIO_IDT0));
++}
++
++static struct em_gio_priv *irq_to_priv(unsigned int irq)
++{
++ struct irq_chip *chip = irq_get_chip(irq);
++ return container_of(chip, struct em_gio_priv, irq_chip);
++}
++
++static void em_gio_irq_disable(struct irq_data *data)
++{
++ struct em_gio_priv *p = irq_to_priv(data->irq);
++ int offset = data->irq - p->irq_base;
++
++ em_gio_write(p, GIO_IDS, 1 << offset);
++}
++
++static void em_gio_irq_enable(struct irq_data *data)
++{
++ struct em_gio_priv *p = irq_to_priv(data->irq);
++ int offset = data->irq - p->irq_base;
++
++ em_gio_write(p, GIO_IEN, 1 << offset);
++}
++
++#define GIO_ASYNC(x) (x + 8)
++
++static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
++ [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00),
++ [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01),
++ [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02),
++ [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03),
++ [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04),
++};
++
++static int em_gio_irq_set_type(struct irq_data *data, unsigned int type)
++{
++ unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
++ struct em_gio_priv *p = irq_to_priv(data->irq);
++ unsigned int reg, offset, shift;
++ unsigned long flags;
++ unsigned long tmp;
++
++ if (!value)
++ return -EINVAL;
++
++ offset = data->irq - p->irq_base;
++
++ pr_debug("gio: sense irq = %d, irq = %d, mode = %d, sw base = %d\n",
++ offset, data->irq, value, p->irq_base);
++
++ /* 8 x 4 bit fields in 4 IDT registers */
++ reg = GIO_IDT(offset >> 3);
++ shift = (offset & 0x07) << 4;
++
++ spin_lock_irqsave(&p->sense_lock, flags);
++
++ /* disable the interrupt in IIA */
++ tmp = em_gio_read(p, GIO_IIA);
++ tmp &= ~(1 << offset);
++ em_gio_write(p, GIO_IIA, tmp);
++
++ /* change the sense setting in IDT */
++ tmp = em_gio_read(p, reg);
++ tmp &= ~(0xf << shift);
++ tmp |= value << shift;
++ em_gio_write(p, reg, tmp);
++
++ /* clear pending interrupts */
++ em_gio_write(p, GIO_IIR, 1 << offset);
++
++ /* enable the interrupt in IIA */
++ tmp = em_gio_read(p, GIO_IIA);
++ tmp |= 1 << offset;
++ em_gio_write(p, GIO_IIA, tmp);
++
++ spin_unlock_irqrestore(&p->sense_lock, flags);
++
++ return 0;
++}
++
++static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
++{
++ struct em_gio_priv *p = dev_id;
++ unsigned long tmp, status;
++ unsigned int offset;
++
++ status = tmp = em_gio_read(p, GIO_MST);
++ if (!status)
++ return IRQ_NONE;
++
++ while (status) {
++ offset = __ffs(status);
++ generic_handle_irq(p->irq_base + offset);
++ status &= ~(1 << offset);
++ }
++
++ em_gio_write(p, GIO_IIR, tmp);
++
++ return IRQ_HANDLED;
++}
++
++static struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip)
++{
++ return container_of(chip, struct em_gio_priv, gpio_chip);
++}
++
++static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++ em_gio_write(gpio_to_priv(chip), GIO_E0, 1 << offset);
++ return 0;
++}
++
++static int em_gio_get(struct gpio_chip *chip, unsigned offset)
++{
++ return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & (1 << offset));
++}
++
++static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
++ unsigned shift, int value)
++{
++ /* upper 16 bits contains mask and lower 16 actual value */
++ em_gio_write(gpio_to_priv(chip), reg,
++ (1 << (shift + 16)) | (value << shift));
++}
++
++static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ /* output is split into two registers */
++ if (offset < 16)
++ __em_gio_set(chip, GIO_OL, offset, value);
++ else
++ __em_gio_set(chip, GIO_OH, offset - 16, value);
++}
++
++static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ /* write GPIO value to output before selecting output mode of pin */
++ em_gio_set(chip, offset, value);
++ em_gio_write(gpio_to_priv(chip), GIO_E1, 1 << offset);
++ return 0;
++}
++
++static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
++{
++ return gpio_to_priv(chip)->irq_base + offset;
++}
++
++static int __devinit em_gio_probe(struct platform_device *pdev)
++{
++ struct gpio_em_config *pdata = pdev->dev.platform_data;
++ struct em_gio_priv *p;
++ struct resource *io[2], *irq[2];
++ struct gpio_chip *gpio_chip;
++ struct irq_chip *irq_chip;
++ const char *name = dev_name(&pdev->dev);
++ int k, ret;
++
++ p = kzalloc(sizeof(*p), GFP_KERNEL);
++ if (!p) {
++ dev_err(&pdev->dev, "failed to allocate driver data\n");
++ ret = -ENOMEM;
++ goto err0;
++ }
++
++ gpio_chip = &p->gpio_chip;
++ irq_chip = &p->irq_chip;
++ platform_set_drvdata(pdev, p);
++ spin_lock_init(&p->sense_lock);
++
++ io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
++
++ if (!io[0] || !io[1] || !irq[0] || !irq[1] || !pdata) {
++ dev_err(&pdev->dev, "missing IRQ, IOMEM or configuration\n");
++ ret = -EINVAL;
++ goto err1;
++ }
++
++ p->base0 = ioremap_nocache(io[0]->start, resource_size(io[0]));
++ if (!p->base0) {
++ dev_err(&pdev->dev, "failed to remap low I/O memory\n");
++ ret = -ENXIO;
++ goto err1;
++ }
++
++ p->base1 = ioremap_nocache(io[1]->start, resource_size(io[1]));
++ if (!p->base1) {
++ dev_err(&pdev->dev, "failed to remap high I/O memory\n");
++ ret = -ENXIO;
++ goto err2;
++ }
++
++ p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
++ pdata->number_of_pins, numa_node_id());
++ if (IS_ERR_VALUE(p->irq_base)) {
++ dev_err(&pdev->dev, "cannot get irq_desc\n");
++ ret = -ENXIO;
++ goto err3;
++ }
++
++ pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
++ pdata->gpio_base, pdata->number_of_pins, p->irq_base);
++
++ irq_chip->name = name;
++ irq_chip->irq_mask = em_gio_irq_disable;
++ irq_chip->irq_unmask = em_gio_irq_enable;
++ irq_chip->irq_enable = em_gio_irq_enable;
++ irq_chip->irq_disable = em_gio_irq_disable;
++ irq_chip->irq_set_type = em_gio_irq_set_type;
++ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
++
++ for (k = p->irq_base; k < (p->irq_base + pdata->number_of_pins); k++) {
++ irq_set_chip_and_handler_name(k, irq_chip, handle_level_irq,
++ "level");
++ set_irq_flags(k, IRQF_VALID); /* kill me now */
++ }
++
++ if (request_irq(irq[0]->start, em_gio_irq_handler, 0, name, p)) {
++ dev_err(&pdev->dev, "failed to request low IRQ\n");
++ ret = -ENOENT;
++ goto err4;
++ }
++
++ if (request_irq(irq[1]->start, em_gio_irq_handler, 0, name, p)) {
++ dev_err(&pdev->dev, "failed to request high IRQ\n");
++ ret = -ENOENT;
++ goto err5;
++ }
++
++ gpio_chip->direction_input = em_gio_direction_input;
++ gpio_chip->get = em_gio_get;
++ gpio_chip->direction_output = em_gio_direction_output;
++ gpio_chip->set = em_gio_set;
++
++ gpio_chip->to_irq = em_gio_to_irq;
++
++ gpio_chip->label = name;
++ gpio_chip->owner = THIS_MODULE;
++
++ gpio_chip->base = pdata->gpio_base;
++ gpio_chip->ngpio = pdata->number_of_pins;
++
++ ret = gpiochip_add(gpio_chip);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to add GPIO cntroller\n");
++ goto err6;
++ }
++ return 0;
++
++err6:
++ free_irq(irq[1]->start, pdev);
++err5:
++ free_irq(irq[0]->start, pdev);
++err4:
++ irq_free_descs(p->irq_base, pdata->number_of_pins);
++err3:
++ iounmap(p->base1);
++err2:
++ iounmap(p->base0);
++err1:
++ kfree(p);
++err0:
++ return ret;
++}
++
++static int __devexit em_gio_remove(struct platform_device *pdev)
++{
++ struct gpio_em_config *pdata = pdev->dev.platform_data;
++ struct em_gio_priv *p = platform_get_drvdata(pdev);
++ struct resource *irq[2];
++ int ret;
++
++ ret = gpiochip_remove(&p->gpio_chip);
++ if (ret)
++ return ret;
++
++ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
++
++ free_irq(irq[1]->start, pdev);
++ free_irq(irq[0]->start, pdev);
++ irq_free_descs(p->irq_base, pdata->number_of_pins);
++ iounmap(p->base1);
++ iounmap(p->base0);
++ kfree(p);
++ return 0;
++}
++
++static struct platform_driver em_gio_device_driver = {
++ .probe = em_gio_probe,
++ .remove = __devexit_p(em_gio_remove),
++ .driver = {
++ .name = "em_gio",
++ }
++};
++
++module_platform_driver(em_gio_device_driver);
++
++MODULE_AUTHOR("Magnus Damm");
++MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/platform_data/gpio-em.h b/include/linux/platform_data/gpio-em.h
+new file mode 100644
+index 0000000..573edfb
+--- /dev/null
++++ b/include/linux/platform_data/gpio-em.h
+@@ -0,0 +1,10 @@
++#ifndef __GPIO_EM_H__
++#define __GPIO_EM_H__
++
++struct gpio_em_config {
++ unsigned int gpio_base;
++ unsigned int irq_base;
++ unsigned int number_of_pins;
++};
++
++#endif /* __GPIO_EM_H__ */
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0059-mach-shmobile-Emma-Mobile-EV2-SoC-base-support-V3.patch b/patches.kzm9g/0059-mach-shmobile-Emma-Mobile-EV2-SoC-base-support-V3.patch
new file mode 100644
index 00000000000000..0706510e984c1a
--- /dev/null
+++ b/patches.kzm9g/0059-mach-shmobile-Emma-Mobile-EV2-SoC-base-support-V3.patch
@@ -0,0 +1,493 @@
+From a60f89d7c6f7b301845e6943c6e2ec4c6d6197be Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 16 May 2012 15:44:58 +0900
+Subject: mach-shmobile: Emma Mobile EV2 SoC base support V3
+
+This is V3 of the Emma Mobile EV2 SoC support.
+Included here is support for serial and timer
+devices which is just about enough to boot a kernel.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 7f627f0380cb5ba3e05bcaac31ecf40c1f508ec1)
+
+Conflicts:
+ arch/arm/mach-shmobile/Kconfig
+ arch/arm/mach-shmobile/Makefile
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Kconfig | 5 +
+ arch/arm/mach-shmobile/Makefile | 1 +
+ arch/arm/mach-shmobile/clock-emev2.c | 226 +++++++++++++++++++++++++++
+ arch/arm/mach-shmobile/include/mach/emev2.h | 9 ++
+ arch/arm/mach-shmobile/setup-emev2.c | 180 +++++++++++++++++++++
+ 5 files changed, 421 insertions(+)
+ create mode 100644 arch/arm/mach-shmobile/clock-emev2.c
+ create mode 100644 arch/arm/mach-shmobile/include/mach/emev2.h
+ create mode 100644 arch/arm/mach-shmobile/setup-emev2.c
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index 1e7656a..cabb9af 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -33,6 +33,11 @@ config ARCH_R8A7740
+ select SH_CLK_CPG
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+
++config ARCH_EMEV2
++ bool "Emma Mobile EV2"
++ select CPU_V7
++ select ARM_GIC
++
+ comment "SH-Mobile Board Type"
+
+ config MACH_G3EVM
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index 36bd37d..624f721 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_ARCH_SH7377) += setup-sh7377.o clock-sh7377.o intc-sh7377.o
+ obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
+ obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
+ obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
++obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
+
+ # SMP objects
+ smp-y := platsmp.o headsmp.o
+diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
+new file mode 100644
+index 0000000..73a1216
+--- /dev/null
++++ b/arch/arm/mach-shmobile/clock-emev2.c
+@@ -0,0 +1,226 @@
++/*
++ * Emma Mobile EV2 clock framework support
++ *
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/sh_clk.h>
++#include <linux/clkdev.h>
++#include <mach/common.h>
++
++#define EMEV2_SMU_BASE 0xe0110000
++
++/* EMEV2 SMU registers */
++#define USIAU0_RSTCTRL 0x094
++#define USIBU1_RSTCTRL 0x0ac
++#define USIBU2_RSTCTRL 0x0b0
++#define USIBU3_RSTCTRL 0x0b4
++#define STI_RSTCTRL 0x124
++#define USIAU0GCLKCTRL 0x4a0
++#define USIBU1GCLKCTRL 0x4b8
++#define USIBU2GCLKCTRL 0x4bc
++#define USIBU3GCLKCTRL 0x04c0
++#define STIGCLKCTRL 0x528
++#define USIAU0SCLKDIV 0x61c
++#define USIB2SCLKDIV 0x65c
++#define USIB3SCLKDIV 0x660
++#define STI_CLKSEL 0x688
++
++/* not pretty, but hey */
++static void __iomem *smu_base;
++
++static void emev2_smu_write(unsigned long value, int offs)
++{
++ BUG_ON(!smu_base || (offs >= PAGE_SIZE));
++ iowrite32(value, smu_base + offs);
++}
++
++static struct clk_mapping smu_mapping = {
++ .phys = EMEV2_SMU_BASE,
++ .len = PAGE_SIZE,
++};
++
++/* Fixed 32 KHz root clock from C32K pin */
++static struct clk c32k_clk = {
++ .rate = 32768,
++ .mapping = &smu_mapping,
++};
++
++/* PLL3 multiplies C32K with 7000 */
++static unsigned long pll3_recalc(struct clk *clk)
++{
++ return clk->parent->rate * 7000;
++}
++
++static struct sh_clk_ops pll3_clk_ops = {
++ .recalc = pll3_recalc,
++};
++
++static struct clk pll3_clk = {
++ .ops = &pll3_clk_ops,
++ .parent = &c32k_clk,
++};
++
++static struct clk *main_clks[] = {
++ &c32k_clk,
++ &pll3_clk,
++};
++
++enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3,
++ SCLKDIV_NR };
++
++#define SCLKDIV(_reg, _shift) \
++{ \
++ .parent = &pll3_clk, \
++ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
++ .enable_bit = _shift, \
++}
++
++static struct clk sclkdiv_clks[SCLKDIV_NR] = {
++ [SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0),
++ [SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16),
++ [SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0),
++ [SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0),
++};
++
++enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK,
++ GCLK_STI_SCLK,
++ GCLK_NR };
++
++#define GCLK_SCLK(_parent, _reg) \
++{ \
++ .parent = _parent, \
++ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
++ .enable_bit = 1, /* SCLK_GCC */ \
++}
++
++static struct clk gclk_clks[GCLK_NR] = {
++ [GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0],
++ USIAU0GCLKCTRL),
++ [GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1],
++ USIBU1GCLKCTRL),
++ [GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2],
++ USIBU2GCLKCTRL),
++ [GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3],
++ USIBU3GCLKCTRL),
++ [GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL),
++};
++
++static int emev2_gclk_enable(struct clk *clk)
++{
++ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
++ clk->mapped_reg);
++ return 0;
++}
++
++static void emev2_gclk_disable(struct clk *clk)
++{
++ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
++ clk->mapped_reg);
++}
++
++static struct sh_clk_ops emev2_gclk_clk_ops = {
++ .enable = emev2_gclk_enable,
++ .disable = emev2_gclk_disable,
++ .recalc = followparent_recalc,
++};
++
++static int __init emev2_gclk_register(struct clk *clks, int nr)
++{
++ struct clk *clkp;
++ int ret = 0;
++ int k;
++
++ for (k = 0; !ret && (k < nr); k++) {
++ clkp = clks + k;
++ clkp->ops = &emev2_gclk_clk_ops;
++ ret |= clk_register(clkp);
++ }
++
++ return ret;
++}
++
++static unsigned long emev2_sclkdiv_recalc(struct clk *clk)
++{
++ unsigned int sclk_div;
++
++ sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff;
++
++ return clk->parent->rate / (sclk_div + 1);
++}
++
++static struct sh_clk_ops emev2_sclkdiv_clk_ops = {
++ .recalc = emev2_sclkdiv_recalc,
++};
++
++static int __init emev2_sclkdiv_register(struct clk *clks, int nr)
++{
++ struct clk *clkp;
++ int ret = 0;
++ int k;
++
++ for (k = 0; !ret && (k < nr); k++) {
++ clkp = clks + k;
++ clkp->ops = &emev2_sclkdiv_clk_ops;
++ ret |= clk_register(clkp);
++ }
++
++ return ret;
++}
++
++static struct clk_lookup lookups[] = {
++ CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]),
++ CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]),
++ CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]),
++ CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]),
++ CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]),
++};
++
++void __init emev2_clock_init(void)
++{
++ int k, ret = 0;
++
++ smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
++ BUG_ON(!smu_base);
++
++ /* setup STI timer to run on 37.768 kHz and deassert reset */
++ emev2_smu_write(0, STI_CLKSEL);
++ emev2_smu_write(1, STI_RSTCTRL);
++
++ /* deassert reset for UART0->UART3 */
++ emev2_smu_write(2, USIAU0_RSTCTRL);
++ emev2_smu_write(2, USIBU1_RSTCTRL);
++ emev2_smu_write(2, USIBU2_RSTCTRL);
++ emev2_smu_write(2, USIBU3_RSTCTRL);
++
++ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
++ ret = clk_register(main_clks[k]);
++
++ if (!ret)
++ ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR);
++
++ if (!ret)
++ ret = emev2_gclk_register(gclk_clks, GCLK_NR);
++
++ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
++
++ if (!ret)
++ shmobile_clk_init();
++ else
++ panic("failed to setup emev2 clocks\n");
++}
+diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
+new file mode 100644
+index 0000000..92646c1
+--- /dev/null
++++ b/arch/arm/mach-shmobile/include/mach/emev2.h
+@@ -0,0 +1,9 @@
++#ifndef __ASM_EMEV2_H__
++#define __ASM_EMEV2_H__
++
++extern void emev2_init_irq(void);
++extern void emev2_add_early_devices(void);
++extern void emev2_add_standard_devices(void);
++extern void emev2_clock_init(void);
++
++#endif /* __ASM_EMEV2_H__ */
+diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
+new file mode 100644
+index 0000000..9fff623
+--- /dev/null
++++ b/arch/arm/mach-shmobile/setup-emev2.c
+@@ -0,0 +1,180 @@
++/*
++ * Emma Mobile EV2 processor support
++ *
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/io.h>
++#include <mach/hardware.h>
++#include <mach/common.h>
++#include <mach/emev2.h>
++#include <mach/irqs.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/time.h>
++#include <asm/hardware/gic.h>
++
++/* UART */
++static struct resource uart0_resources[] = {
++ [0] = {
++ .start = 0xe1020000,
++ .end = 0xe1020037,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 40,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static struct platform_device uart0_device = {
++ .name = "serial8250-em",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(uart0_resources),
++ .resource = uart0_resources,
++};
++
++static struct resource uart1_resources[] = {
++ [0] = {
++ .start = 0xe1030000,
++ .end = 0xe1030037,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 41,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static struct platform_device uart1_device = {
++ .name = "serial8250-em",
++ .id = 1,
++ .num_resources = ARRAY_SIZE(uart1_resources),
++ .resource = uart1_resources,
++};
++
++static struct resource uart2_resources[] = {
++ [0] = {
++ .start = 0xe1040000,
++ .end = 0xe1040037,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 42,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static struct platform_device uart2_device = {
++ .name = "serial8250-em",
++ .id = 2,
++ .num_resources = ARRAY_SIZE(uart2_resources),
++ .resource = uart2_resources,
++};
++
++static struct resource uart3_resources[] = {
++ [0] = {
++ .start = 0xe1050000,
++ .end = 0xe1050037,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 43,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static struct platform_device uart3_device = {
++ .name = "serial8250-em",
++ .id = 3,
++ .num_resources = ARRAY_SIZE(uart3_resources),
++ .resource = uart3_resources,
++};
++
++/* STI */
++static struct resource sti_resources[] = {
++ [0] = {
++ .name = "STI",
++ .start = 0xe0180000,
++ .end = 0xe0180053,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 157,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device sti_device = {
++ .name = "em_sti",
++ .id = 0,
++ .resource = sti_resources,
++ .num_resources = ARRAY_SIZE(sti_resources),
++};
++
++static struct platform_device *emev2_early_devices[] __initdata = {
++ &uart0_device,
++ &uart1_device,
++ &uart2_device,
++ &uart3_device,
++};
++
++static struct platform_device *emev2_late_devices[] __initdata = {
++ &sti_device,
++};
++
++void __init emev2_add_standard_devices(void)
++{
++ emev2_clock_init();
++
++ platform_add_devices(emev2_early_devices,
++ ARRAY_SIZE(emev2_early_devices));
++
++ platform_add_devices(emev2_late_devices,
++ ARRAY_SIZE(emev2_late_devices));
++}
++
++void __init emev2_add_early_devices(void)
++{
++ shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
++
++ early_platform_add_devices(emev2_early_devices,
++ ARRAY_SIZE(emev2_early_devices));
++
++ /* setup early console here as well */
++ shmobile_setup_console();
++}
++
++void __init emev2_init_irq(void)
++{
++ void __iomem *gic_dist_base;
++ void __iomem *gic_cpu_base;
++
++ /* Static mappings, never released */
++ gic_dist_base = ioremap(0xe0028000, PAGE_SIZE);
++ gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE);
++ BUG_ON(!gic_dist_base || !gic_cpu_base);
++
++ /* Use GIC to handle interrupts */
++ gic_init(0, 29, gic_dist_base, gic_cpu_base);
++}
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0060-mach-shmobile-KZM9D-board-support-V3.patch b/patches.kzm9g/0060-mach-shmobile-KZM9D-board-support-V3.patch
new file mode 100644
index 00000000000000..ca4b244a9b6109
--- /dev/null
+++ b/patches.kzm9g/0060-mach-shmobile-KZM9D-board-support-V3.patch
@@ -0,0 +1,110 @@
+From e11d7a5d8be762494c2bf51a6585f61bdf8b290c Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 16 May 2012 15:45:16 +0900
+Subject: mach-shmobile: KZM9D board support V3
+
+V3 of basic KZM9D board support. At this point a quite
+thin layer that makes use of the Emma Mobile EV2 SoC code.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit c050fb10c425cf189da5ca9b84e948ec2fc99049)
+
+Conflicts:
+ arch/arm/mach-shmobile/Makefile
+ arch/arm/mach-shmobile/clock-emev2.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Kconfig | 4 ++++
+ arch/arm/mach-shmobile/Makefile | 1 +
+ arch/arm/mach-shmobile/board-kzm9d.c | 36 ++++++++++++++++++++++++++++++++++
+ arch/arm/mach-shmobile/clock-emev2.c | 2 ++
+ 4 files changed, 43 insertions(+)
+ create mode 100644 arch/arm/mach-shmobile/board-kzm9d.c
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index cabb9af..d4dc4ee 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -92,6 +92,10 @@ config MACH_KZM9G
+ select ARCH_REQUIRE_GPIOLIB
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
+
++config MACH_KZM9D
++ bool "KZM9D board"
++ depends on ARCH_EMEV2
++
+ comment "SH-Mobile System Configuration"
+
+ config CPU_HAS_INTEVT
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index 624f721..bdd4383 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -47,6 +47,7 @@ obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o
+ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
+ obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
+ obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o
++obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o
+
+ # Framework support
+ obj-$(CONFIG_SMP) += $(smp-y)
+diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
+new file mode 100644
+index 0000000..e743f90
+--- /dev/null
++++ b/arch/arm/mach-shmobile/board-kzm9d.c
+@@ -0,0 +1,36 @@
++/*
++ * kzm9d board support
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <mach/common.h>
++#include <mach/emev2.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/hardware/gic.h>
++
++MACHINE_START(KZM9D, "kzm9d")
++ .init_early = emev2_add_early_devices,
++ .nr_irqs = NR_IRQS_LEGACY,
++ .init_irq = emev2_init_irq,
++ .handle_irq = gic_handle_irq,
++ .init_machine = emev2_add_standard_devices,
++ .timer = &shmobile_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
+index 73a1216..64d4a56 100644
+--- a/arch/arm/mach-shmobile/clock-emev2.c
++++ b/arch/arm/mach-shmobile/clock-emev2.c
+@@ -84,6 +84,8 @@ static struct clk *main_clks[] = {
+ enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3,
+ SCLKDIV_NR };
+
++#define IOMEM(x) ((void __force __iomem *)(x))
++
+ #define SCLKDIV(_reg, _shift) \
+ { \
+ .parent = &pll3_clk, \
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0061-mach-shmobile-Emma-Mobile-EV2-SMP-support-V3.patch b/patches.kzm9g/0061-mach-shmobile-Emma-Mobile-EV2-SMP-support-V3.patch
new file mode 100644
index 00000000000000..12ddf536a6297b
--- /dev/null
+++ b/patches.kzm9g/0061-mach-shmobile-Emma-Mobile-EV2-SMP-support-V3.patch
@@ -0,0 +1,329 @@
+From 0af702823eae60eceedd80cbd4bd0670285a2cca Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 16 May 2012 15:45:25 +0900
+Subject: mach-shmobile: Emma Mobile EV2 SMP support V3
+
+This is V3 of Emma Mobile EV2 SMP support.
+
+At this point only the most basic form of SMP operation
+is supported. TWD and CPU Hotplug support is excluded.
+
+Tied to both the Emma Mobile EV2 and the KZM9D board
+due to the need to switch on board in platsmp.c and
+the newly introduced need for static mappings.
+
+The static mappings are needed to allow hardware
+acces early during boot when SMP is initialized.
+This early requirement forces us to also map in
+the SMU registers.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit bd5a875d90c878be4d23f54ea565253734ae2377)
+
+Conflicts:
+ arch/arm/mach-shmobile/Makefile
+ arch/arm/mach-shmobile/platsmp.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Makefile | 1 +
+ arch/arm/mach-shmobile/board-kzm9d.c | 1 +
+ arch/arm/mach-shmobile/clock-emev2.c | 18 +++++
+ arch/arm/mach-shmobile/include/mach/emev2.h | 7 ++
+ arch/arm/mach-shmobile/platsmp.c | 17 +++++
+ arch/arm/mach-shmobile/setup-emev2.c | 24 +++++++
+ arch/arm/mach-shmobile/smp-emev2.c | 97 +++++++++++++++++++++++++++
+ 7 files changed, 165 insertions(+)
+ create mode 100644 arch/arm/mach-shmobile/smp-emev2.c
+
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index bdd4383..a2c56d5 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -18,6 +18,7 @@ smp-y := platsmp.o headsmp.o
+ smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+ smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+ smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
++smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
+
+ # Pinmux setup
+ pfc-y :=
+diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
+index e743f90..42fc479 100644
+--- a/arch/arm/mach-shmobile/board-kzm9d.c
++++ b/arch/arm/mach-shmobile/board-kzm9d.c
+@@ -27,6 +27,7 @@
+ #include <asm/hardware/gic.h>
+
+ MACHINE_START(KZM9D, "kzm9d")
++ .map_io = emev2_map_io,
+ .init_early = emev2_add_early_devices,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = emev2_init_irq,
+diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
+index 64d4a56..9414383 100644
+--- a/arch/arm/mach-shmobile/clock-emev2.c
++++ b/arch/arm/mach-shmobile/clock-emev2.c
+@@ -40,6 +40,7 @@
+ #define USIB2SCLKDIV 0x65c
+ #define USIB3SCLKDIV 0x660
+ #define STI_CLKSEL 0x688
++#define SMU_GENERAL_REG0 0x7c0
+
+ /* not pretty, but hey */
+ static void __iomem *smu_base;
+@@ -50,6 +51,11 @@ static void emev2_smu_write(unsigned long value, int offs)
+ iowrite32(value, smu_base + offs);
+ }
+
++void emev2_set_boot_vector(unsigned long value)
++{
++ emev2_smu_write(value, SMU_GENERAL_REG0);
++}
++
+ static struct clk_mapping smu_mapping = {
+ .phys = EMEV2_SMU_BASE,
+ .len = PAGE_SIZE,
+@@ -196,6 +202,18 @@ static struct clk_lookup lookups[] = {
+ void __init emev2_clock_init(void)
+ {
+ int k, ret = 0;
++ static int is_setup;
++
++ /* yuck, this is ugly as hell, but the non-smp case of clocks
++ * code is now designed to rely on ioremap() instead of static
++ * entity maps. in the case of smp we need access to the SMU
++ * register earlier than ioremap() is actually working without
++ * any static maps. to enable SMP in ugly but with dynamic
++ * mappings we have to call emev2_clock_init() from different
++ * places depending on UP and SMP...
++ */
++ if (is_setup++)
++ return;
+
+ smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
+ BUG_ON(!smu_base);
+diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
+index 92646c1..3fc7184 100644
+--- a/arch/arm/mach-shmobile/include/mach/emev2.h
++++ b/arch/arm/mach-shmobile/include/mach/emev2.h
+@@ -1,9 +1,16 @@
+ #ifndef __ASM_EMEV2_H__
+ #define __ASM_EMEV2_H__
+
++extern void emev2_map_io(void);
+ extern void emev2_init_irq(void);
+ extern void emev2_add_early_devices(void);
+ extern void emev2_add_standard_devices(void);
+ extern void emev2_clock_init(void);
++extern void emev2_set_boot_vector(unsigned long value);
++extern unsigned int emev2_get_core_count(void);
++extern int emev2_platform_cpu_kill(unsigned int cpu);
++extern void emev2_secondary_init(unsigned int cpu);
++extern int emev2_boot_secondary(unsigned int cpu);
++extern void emev2_smp_prepare_cpus(void);
+
+ #endif /* __ASM_EMEV2_H__ */
+diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
+index 1103ce5..9e98f9e 100644
+--- a/arch/arm/mach-shmobile/platsmp.c
++++ b/arch/arm/mach-shmobile/platsmp.c
+@@ -20,14 +20,19 @@
+ #include <asm/localtimer.h>
+ #include <asm/mach-types.h>
+ #include <mach/common.h>
++#include <mach/emev2.h>
+
+ #define is_sh73a0() (machine_is_ag5evm() || machine_is_kzm9g())
++#define is_emev2() machine_is_kzm9d()
+
+ static unsigned int __init shmobile_smp_get_core_count(void)
+ {
+ if (is_sh73a0())
+ return sh73a0_get_core_count();
+
++ if (is_emev2())
++ return emev2_get_core_count();
++
+ return 1;
+ }
+
+@@ -35,10 +40,16 @@ static void __init shmobile_smp_prepare_cpus(void)
+ {
+ if (is_sh73a0())
+ sh73a0_smp_prepare_cpus();
++
++ if (is_emev2())
++ emev2_smp_prepare_cpus();
+ }
+
+ int shmobile_platform_cpu_kill(unsigned int cpu)
+ {
++ if (is_emev2())
++ return emev2_platform_cpu_kill(cpu);
++
+ return 1;
+ }
+
+@@ -48,6 +59,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
+
+ if (is_sh73a0())
+ sh73a0_secondary_init(cpu);
++
++ if (is_emev2())
++ emev2_secondary_init(cpu);
+ }
+
+ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+@@ -55,6 +69,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+ if (is_sh73a0())
+ return sh73a0_boot_secondary(cpu);
+
++ if (is_emev2())
++ return emev2_boot_secondary(cpu);
++
+ return -ENOSYS;
+ }
+
+diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
+index 9fff623..2a03a78 100644
+--- a/arch/arm/mach-shmobile/setup-emev2.c
++++ b/arch/arm/mach-shmobile/setup-emev2.c
+@@ -34,6 +34,30 @@
+ #include <asm/mach/time.h>
+ #include <asm/hardware/gic.h>
+
++static struct map_desc emev2_io_desc[] __initdata = {
++#ifdef CONFIG_SMP
++ /* 128K entity map for 0xe0100000 (SMU) */
++ {
++ .virtual = 0xe0100000,
++ .pfn = __phys_to_pfn(0xe0100000),
++ .length = SZ_128K,
++ .type = MT_DEVICE
++ },
++ /* 2M mapping for SCU + L2 controller */
++ {
++ .virtual = 0xf0000000,
++ .pfn = __phys_to_pfn(0x1e000000),
++ .length = SZ_2M,
++ .type = MT_DEVICE
++ },
++#endif
++};
++
++void __init emev2_map_io(void)
++{
++ iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
++}
++
+ /* UART */
+ static struct resource uart0_resources[] = {
+ [0] = {
+diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
+new file mode 100644
+index 0000000..6a35c4a
+--- /dev/null
++++ b/arch/arm/mach-shmobile/smp-emev2.c
+@@ -0,0 +1,97 @@
++/*
++ * SMP support for Emma Mobile EV2
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ * Copyright (C) 2012 Magnus Damm
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <mach/common.h>
++#include <mach/emev2.h>
++#include <asm/smp_plat.h>
++#include <asm/smp_scu.h>
++#include <asm/hardware/gic.h>
++#include <asm/cacheflush.h>
++
++#define EMEV2_SCU_BASE 0x1e000000
++
++static DEFINE_SPINLOCK(scu_lock);
++static void __iomem *scu_base;
++
++static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
++{
++ unsigned long tmp;
++
++ /* we assume this code is running on a different cpu
++ * than the one that is changing coherency setting */
++ spin_lock(&scu_lock);
++ tmp = readl(scu_base + 8);
++ tmp &= ~clr;
++ tmp |= set;
++ writel(tmp, scu_base + 8);
++ spin_unlock(&scu_lock);
++
++}
++
++unsigned int __init emev2_get_core_count(void)
++{
++ if (!scu_base) {
++ scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
++ emev2_clock_init(); /* need ioremapped SMU */
++ }
++
++ WARN_ON_ONCE(!scu_base);
++
++ return scu_base ? scu_get_core_count(scu_base) : 1;
++}
++
++int emev2_platform_cpu_kill(unsigned int cpu)
++{
++ return 0; /* not supported yet */
++}
++
++void __cpuinit emev2_secondary_init(unsigned int cpu)
++{
++ gic_secondary_init(0);
++}
++
++int __cpuinit emev2_boot_secondary(unsigned int cpu)
++{
++ cpu = cpu_logical_map(cpu);
++
++ /* enable cache coherency */
++ modify_scu_cpu_psr(0, 3 << (cpu * 8));
++
++ /* Tell ROM loader about our vector (in headsmp.S) */
++ emev2_set_boot_vector(__pa(shmobile_secondary_vector));
++
++ gic_raise_softirq(cpumask_of(cpu), 1);
++ return 0;
++}
++
++void __init emev2_smp_prepare_cpus(void)
++{
++ int cpu = cpu_logical_map(0);
++
++ scu_enable(scu_base);
++
++ /* enable cache coherency on CPU0 */
++ modify_scu_cpu_psr(0, 3 << (cpu * 8));
++}
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0062-mach-shmobile-Emma-Mobile-EV2-GPIO-support-V3.patch b/patches.kzm9g/0062-mach-shmobile-Emma-Mobile-EV2-GPIO-support-V3.patch
new file mode 100644
index 00000000000000..7604f5b5fbef4e
--- /dev/null
+++ b/patches.kzm9g/0062-mach-shmobile-Emma-Mobile-EV2-GPIO-support-V3.patch
@@ -0,0 +1,280 @@
+From dbf1eecc80eac3500e8456e46d12601641756cd1 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 16 May 2012 15:45:34 +0900
+Subject: mach-shmobile: Emma Mobile EV2 GPIO support V3
+
+Tie in the Emma Mobile GPIO driver "em-gio" to
+support the GPIOs on Emma Mobile EV2.
+
+A static IRQ range is used to allow boards to
+hook up their platform devices to the GPIOs.
+
+DT support is still on the TODO for the GPIO driver,
+so only platform device support is included here.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 088efd9273b5076a0aead479aa31f1066d182b3e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Kconfig | 1 +
+ arch/arm/mach-shmobile/include/mach/emev2.h | 3 +
+ arch/arm/mach-shmobile/setup-emev2.c | 203 +++++++++++++++++++++++++++
+ 3 files changed, 207 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index d4dc4ee..4ce90f3 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -37,6 +37,7 @@ config ARCH_EMEV2
+ bool "Emma Mobile EV2"
+ select CPU_V7
+ select ARM_GIC
++ select ARCH_WANT_OPTIONAL_GPIOLIB
+
+ comment "SH-Mobile Board Type"
+
+diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
+index 3fc7184..e6b0c1b 100644
+--- a/arch/arm/mach-shmobile/include/mach/emev2.h
++++ b/arch/arm/mach-shmobile/include/mach/emev2.h
+@@ -13,4 +13,7 @@ extern void emev2_secondary_init(unsigned int cpu);
+ extern int emev2_boot_secondary(unsigned int cpu);
+ extern void emev2_smp_prepare_cpus(void);
+
++#define EMEV2_GPIO_BASE 200
++#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
++
+ #endif /* __ASM_EMEV2_H__ */
+diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
+index 2a03a78..d40fede 100644
+--- a/arch/arm/mach-shmobile/setup-emev2.c
++++ b/arch/arm/mach-shmobile/setup-emev2.c
+@@ -21,6 +21,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/gpio-em.h>
+ #include <linux/delay.h>
+ #include <linux/input.h>
+ #include <linux/io.h>
+@@ -156,6 +157,203 @@ static struct platform_device sti_device = {
+ .num_resources = ARRAY_SIZE(sti_resources),
+ };
+
++
++/* GIO */
++static struct gpio_em_config gio0_config = {
++ .gpio_base = 0,
++ .irq_base = EMEV2_GPIO_IRQ(0),
++ .number_of_pins = 32,
++};
++
++static struct resource gio0_resources[] = {
++ [0] = {
++ .name = "GIO_000",
++ .start = 0xe0050000,
++ .end = 0xe005002b,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .name = "GIO_000",
++ .start = 0xe0050040,
++ .end = 0xe005005f,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = 99,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 100,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device gio0_device = {
++ .name = "em_gio",
++ .id = 0,
++ .resource = gio0_resources,
++ .num_resources = ARRAY_SIZE(gio0_resources),
++ .dev = {
++ .platform_data = &gio0_config,
++ },
++};
++
++static struct gpio_em_config gio1_config = {
++ .gpio_base = 32,
++ .irq_base = EMEV2_GPIO_IRQ(32),
++ .number_of_pins = 32,
++};
++
++static struct resource gio1_resources[] = {
++ [0] = {
++ .name = "GIO_032",
++ .start = 0xe0050080,
++ .end = 0xe00500ab,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .name = "GIO_032",
++ .start = 0xe00500c0,
++ .end = 0xe00500df,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = 101,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 102,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device gio1_device = {
++ .name = "em_gio",
++ .id = 1,
++ .resource = gio1_resources,
++ .num_resources = ARRAY_SIZE(gio1_resources),
++ .dev = {
++ .platform_data = &gio1_config,
++ },
++};
++
++static struct gpio_em_config gio2_config = {
++ .gpio_base = 64,
++ .irq_base = EMEV2_GPIO_IRQ(64),
++ .number_of_pins = 32,
++};
++
++static struct resource gio2_resources[] = {
++ [0] = {
++ .name = "GIO_064",
++ .start = 0xe0050100,
++ .end = 0xe005012b,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .name = "GIO_064",
++ .start = 0xe0050140,
++ .end = 0xe005015f,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = 103,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 104,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device gio2_device = {
++ .name = "em_gio",
++ .id = 2,
++ .resource = gio2_resources,
++ .num_resources = ARRAY_SIZE(gio2_resources),
++ .dev = {
++ .platform_data = &gio2_config,
++ },
++};
++
++static struct gpio_em_config gio3_config = {
++ .gpio_base = 96,
++ .irq_base = EMEV2_GPIO_IRQ(96),
++ .number_of_pins = 32,
++};
++
++static struct resource gio3_resources[] = {
++ [0] = {
++ .name = "GIO_096",
++ .start = 0xe0050100,
++ .end = 0xe005012b,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .name = "GIO_096",
++ .start = 0xe0050140,
++ .end = 0xe005015f,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = 105,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 106,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device gio3_device = {
++ .name = "em_gio",
++ .id = 3,
++ .resource = gio3_resources,
++ .num_resources = ARRAY_SIZE(gio3_resources),
++ .dev = {
++ .platform_data = &gio3_config,
++ },
++};
++
++static struct gpio_em_config gio4_config = {
++ .gpio_base = 128,
++ .irq_base = EMEV2_GPIO_IRQ(128),
++ .number_of_pins = 31,
++};
++
++static struct resource gio4_resources[] = {
++ [0] = {
++ .name = "GIO_128",
++ .start = 0xe0050200,
++ .end = 0xe005022b,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .name = "GIO_128",
++ .start = 0xe0050240,
++ .end = 0xe005025f,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = 107,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 108,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device gio4_device = {
++ .name = "em_gio",
++ .id = 4,
++ .resource = gio4_resources,
++ .num_resources = ARRAY_SIZE(gio4_resources),
++ .dev = {
++ .platform_data = &gio4_config,
++ },
++};
++
+ static struct platform_device *emev2_early_devices[] __initdata = {
+ &uart0_device,
+ &uart1_device,
+@@ -165,6 +363,11 @@ static struct platform_device *emev2_early_devices[] __initdata = {
+
+ static struct platform_device *emev2_late_devices[] __initdata = {
+ &sti_device,
++ &gio0_device,
++ &gio1_device,
++ &gio2_device,
++ &gio3_device,
++ &gio4_device,
+ };
+
+ void __init emev2_add_standard_devices(void)
+--
+1.7.10.1.362.g242cab3
+
diff --git a/patches.kzm9g/0063-mach-shmobile-KZM9D-board-Ethernet-support-V3.patch b/patches.kzm9g/0063-mach-shmobile-KZM9D-board-Ethernet-support-V3.patch
new file mode 100644
index 00000000000000..78f4bbc6106e82
--- /dev/null
+++ b/patches.kzm9g/0063-mach-shmobile-KZM9D-board-Ethernet-support-V3.patch
@@ -0,0 +1,82 @@
+From adaf8f8c3a969904f01b38f842fb7416858ea4cc Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 16 May 2012 15:45:42 +0900
+Subject: mach-shmobile: KZM9D board Ethernet support V3
+
+Tie in the on-board Ethernet controller on KZM9D
+and make use of the GPIO controller for external
+IRQ pin support.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 0c73f7bc124e1657a583d9dfb0d168a69005e2d3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-kzm9d.c | 44 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 43 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/mach-shmobile/board-kzm9d.c
++++ b/arch/arm/mach-shmobile/board-kzm9d.c
+@@ -20,18 +20,60 @@
+
+ #include <linux/kernel.h>
+ #include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/smsc911x.h>
+ #include <mach/common.h>
+ #include <mach/emev2.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/hardware/gic.h>
+
++/* Ether */
++static struct resource smsc911x_resources[] = {
++ [0] = {
++ .start = 0x20000000,
++ .end = 0x2000ffff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = EMEV2_GPIO_IRQ(1),
++ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
++ },
++};
++
++static struct smsc911x_platform_config smsc911x_platdata = {
++ .flags = SMSC911X_USE_32BIT,
++ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
++ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
++};
++
++static struct platform_device smsc91x_device = {
++ .name = "smsc911x",
++ .id = 0,
++ .dev = {
++ .platform_data = &smsc911x_platdata,
++ },
++ .num_resources = ARRAY_SIZE(smsc911x_resources),
++ .resource = smsc911x_resources,
++};
++
++static struct platform_device *kzm9d_devices[] __initdata = {
++ &smsc91x_device,
++};
++
++void __init kzm9d_add_standard_devices(void)
++{
++ emev2_add_standard_devices();
++
++ platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices));
++}
++
+ MACHINE_START(KZM9D, "kzm9d")
+ .map_io = emev2_map_io,
+ .init_early = emev2_add_early_devices,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = emev2_init_irq,
+ .handle_irq = gic_handle_irq,
+- .init_machine = emev2_add_standard_devices,
++ .init_machine = kzm9d_add_standard_devices,
+ .timer = &shmobile_timer,
+ MACHINE_END
diff --git a/series b/series
index 595c637789d3b6..857c31e36af78d 100644
--- a/series
+++ b/series
@@ -791,3 +791,69 @@ patches.kzm9g/0202-ARM-mach-shmobile-kzm9g-add-PCF8757-gpio-key.patch
patches.kzm9g/0203-ARM-mach-shmobile-kzm9g-defconfig-update.patch
patches.kzm9g/0204-ARM-mach-shmobile-clock-sh73a0-add-FSI-clock.patch
patches.kzm9g/0205-ARM-mach-shmobile-kzm9g-add-FSI-AK4648-support.patch
+
+patches.kzm9g/0001-tty-serial-allow-ports-to-override-the-irq-handler.patch
+patches.kzm9g/0002-serial-introduce-generic-port-in-out-helpers.patch
+patches.kzm9g/0003-serial-8250-increase-PASS_LIMIT.patch
+patches.kzm9g/0004-serial-Fix-wakeup-init-logic-to-speed-up-startup.patch
+patches.kzm9g/0005-tty-serial8250-allow-platforms-to-override-irq-handl.patch
+patches.kzm9g/0006-tty-serial8250-remove-UPIO_DWAPB-32.patch
+patches.kzm9g/0007-tty-8250-export-serial8250_handle_irq.patch
+patches.kzm9g/0008-serial-8250-Move-UPIO_TSI-to-powerpc.patch
+patches.kzm9g/0009-serial-Support-the-EFR-register-of-XR1715x-uarts.patch
+patches.kzm9g/0010-8250-ratelimit-LSR-safety-check-engaged-warning.patch
+patches.kzm9g/0011-serial-8250-replace-hardcoded-0xbf-with-define.patch
+patches.kzm9g/0012-serial-move-struct-uart_8250_port-from-8250.c-to-825.patch
+patches.kzm9g/0013-serial-clean-up-parameter-passing-for-8250-Rx-IRQ-ha.patch
+patches.kzm9g/0014-serial-export-the-key-functions-for-an-8250-IRQ-hand.patch
+patches.kzm9g/0015-serial-make-8250-timeout-use-the-specified-IRQ-handl.patch
+patches.kzm9g/0016-serial-manually-inline-serial8250_handle_port.patch
+patches.kzm9g/0017-serial-group-all-the-8250-related-code-together.patch
+patches.kzm9g/0018-serial-Kill-off-NO_IRQ.patch
+patches.kzm9g/0019-tty-fix-a-build-failure-on-sparc.patch
+patches.kzm9g/0020-tty-sparc-rename-drivers-tty-serial-suncore.h-includ.patch
+patches.kzm9g/0021-serial-delete-last-unused-traces-of-pausing-I-O-in-8.patch
+patches.kzm9g/0022-serial-make-8250-s-serial_in-shareable-to-other-driv.patch
+patches.kzm9g/0023-serial-delete-useless-void-casts-in-8250.c.patch
+patches.kzm9g/0024-serial-reduce-number-of-indirections-in-8250-code.patch
+patches.kzm9g/0025-serial-use-serial_port_in-out-vs-serial_in-out-in-82.patch
+patches.kzm9g/0026-serial-remove-back-and-forth-conversions-in-serial_o.patch
+patches.kzm9g/0027-serial-8250_pci-add-a-force-background-timer-flag-an.patch
+patches.kzm9g/0028-8250.c-less-than-2400-baud-fix.patch
+patches.kzm9g/0029-serial8250-Add-dl_read-dl_write-callbacks.patch
+patches.kzm9g/0030-serial8250-Use-dl_read-dl_write-on-Alchemy.patch
+patches.kzm9g/0031-serial8250-Use-dl_read-dl_write-on-RM9K.patch
+patches.kzm9g/0032-serial8250-Clean-up-default-map-and-dl-code.patch
+patches.kzm9g/0033-serial8250-Introduce-serial8250_register_8250_port.patch
+patches.kzm9g/0034-serial8250-em-Emma-Mobile-UART-driver-V2.patch
+patches.kzm9g/0035-serial8250-em-clk_get-IS_ERR-error-handling-fix.patch
+patches.kzm9g/0036-cpuidle-create-bootparam-cpuidle.off-1.patch
+patches.kzm9g/0037-cpuidle-replace-xen-access-to-x86-pm_idle-and-defaul.patch
+patches.kzm9g/0038-cpuidle-stop-depending-on-pm_idle.patch
+patches.kzm9g/0039-cpuidle-Consistent-spelling-of-cpuidle_idle_call.patch
+patches.kzm9g/0040-sh-Fix-up-fallout-from-cpuidle-changes.patch
+patches.kzm9g/0041-cpuidle-Add-module.h-to-drivers-cpuidle-files-as-req.patch
+patches.kzm9g/0042-cpuidle-Move-dev-last_residency-update-to-driver-ent.patch
+patches.kzm9g/0043-cpuidle-Remove-CPUIDLE_FLAG_IGNORE-and-dev-prepare.patch
+patches.kzm9g/0044-cpuidle-Split-cpuidle_state-structure-and-move-per-c.patch
+patches.kzm9g/0045-cpuidle-Single-Global-registration-of-idle-states.patch
+patches.kzm9g/0046-cpuidle-Add-common-time-keeping-and-irq-enabling.patch
+patches.kzm9g/0047-mm-add-vm_area_add_early.patch
+patches.kzm9g/0048-clockevents-Make-clockevents_config-a-global-symbol.patch
+patches.kzm9g/0049-clocksource-em_sti-Emma-Mobile-STI-driver-V2.patch
+patches.kzm9g/0050-ARM-move-initialization-of-the-high_memory-variable-.patch
+patches.kzm9g/0051-ARM-move-iotable-mappings-within-the-vmalloc-region.patch
+patches.kzm9g/0052-ARM-simplify-__iounmap-when-dealing-with-section-bas.patch
+patches.kzm9g/0053-ARM-add-generic-ioremap-optimization-by-reusing-stat.patch
+patches.kzm9g/0054-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch
+patches.kzm9g/0055-ARM-mach-shmobile-Allow-SoC-specific-CPU-kill-code.patch
+patches.kzm9g/0056-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch
+patches.kzm9g/0057-ARM-Undelete-KZM9D-mach-type.patch
+patches.kzm9g/0058-gpio-Emma-Mobile-GPIO-driver.patch
+patches.kzm9g/0059-mach-shmobile-Emma-Mobile-EV2-SoC-base-support-V3.patch
+patches.kzm9g/0060-mach-shmobile-KZM9D-board-support-V3.patch
+patches.kzm9g/0061-mach-shmobile-Emma-Mobile-EV2-SMP-support-V3.patch
+patches.kzm9g/0062-mach-shmobile-Emma-Mobile-EV2-GPIO-support-V3.patch
+patches.kzm9g/0063-mach-shmobile-KZM9D-board-Ethernet-support-V3.patch
+
+