Merge branch 'omap-boards' into omap-for-linus
diff --git a/arch/arm/configs/ams_delta_defconfig b/arch/arm/configs/ams_delta_defconfig
index 1d0e8926..6d8a0c8 100644
--- a/arch/arm/configs/ams_delta_defconfig
+++ b/arch/arm/configs/ams_delta_defconfig
@@ -699,6 +699,7 @@
 CONFIG_SERIO_SERPORT=y
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_AMS_DELTA=y
 # CONFIG_GAMEPORT is not set
 
 #
diff --git a/arch/arm/configs/omap3_defconfig b/arch/arm/configs/omap3_defconfig
index d6ad921..1efb833 100644
--- a/arch/arm/configs/omap3_defconfig
+++ b/arch/arm/configs/omap3_defconfig
@@ -264,7 +264,7 @@
 # OMAP Core Type
 #
 CONFIG_ARCH_OMAP2420=y
-# CONFIG_ARCH_OMAP2430 is not set
+CONFIG_ARCH_OMAP2430=y
 CONFIG_ARCH_OMAP3430=y
 CONFIG_OMAP_PACKAGE_CBB=y
 CONFIG_OMAP_PACKAGE_CUS=y
@@ -276,8 +276,9 @@
 CONFIG_MACH_OMAP2_TUSB6010=y
 CONFIG_MACH_OMAP_H4=y
 CONFIG_MACH_OMAP_APOLLON=y
-# CONFIG_MACH_OMAP_2430SDP is not set
+CONFIG_MACH_OMAP_2430SDP=y
 CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_DEVKIT8000=y
 CONFIG_MACH_OMAP_LDP=y
 CONFIG_MACH_OVERO=y
 CONFIG_MACH_OMAP3EVM=y
@@ -390,7 +391,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyS2,115200"
 # CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
 CONFIG_ATAGS_PROC=y
@@ -443,7 +444,7 @@
 #
 CONFIG_PM=y
 CONFIG_PM_DEBUG=y
-CONFIG_PM_VERBOSE=y
+# CONFIG_PM_VERBOSE is not set
 CONFIG_CAN_PM_TRACE=y
 CONFIG_PM_SLEEP=y
 CONFIG_SUSPEND=y
@@ -1262,7 +1263,7 @@
 # CONFIG_SENSORS_LIS3_I2C is not set
 # CONFIG_THERMAL is not set
 CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
 
 #
 # Watchdog Device Drivers
@@ -1291,9 +1292,9 @@
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_TPS65010 is not set
-# CONFIG_MENELAUS is not set
+CONFIG_MENELAUS=y
 CONFIG_TWL4030_CORE=y
-# CONFIG_TWL4030_POWER is not set
+CONFIG_TWL4030_POWER=y
 CONFIG_TWL4030_CODEC=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
@@ -1312,7 +1313,7 @@
 # CONFIG_AB4500_CORE is not set
 CONFIG_REGULATOR=y
 # CONFIG_REGULATOR_DEBUG is not set
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
 # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
@@ -1320,8 +1321,8 @@
 # CONFIG_REGULATOR_MAX8660 is not set
 CONFIG_REGULATOR_TWL4030=y
 # CONFIG_REGULATOR_LP3971 is not set
-# CONFIG_REGULATOR_TPS65023 is not set
-# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
 # CONFIG_MEDIA_SUPPORT is not set
 
 #
@@ -1358,16 +1359,8 @@
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
 # CONFIG_FB_BROADSHEET is not set
-CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP is not set
 CONFIG_FB_OMAP_LCD_VGA=y
-# CONFIG_FB_OMAP_031M3R is not set
-# CONFIG_FB_OMAP_048M3R is not set
-CONFIG_FB_OMAP_079M3R=y
-# CONFIG_FB_OMAP_092M9R is not set
-# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
-# CONFIG_FB_OMAP_LCD_MIPID is not set
-# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
-CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
 # CONFIG_OMAP2_DSS is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
@@ -1686,7 +1679,7 @@
 # MMC/SD/SDIO Host Controller Drivers
 #
 # CONFIG_MMC_SDHCI is not set
-# CONFIG_MMC_OMAP is not set
+CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 # CONFIG_MMC_AT91 is not set
 # CONFIG_MMC_ATMELMCI is not set
@@ -1751,6 +1744,7 @@
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_BQ32K is not set
+CONFIG_RTC_DRV_TWL92330=y
 CONFIG_RTC_DRV_TWL4030=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 27f4897..b18d7c2 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -152,6 +152,16 @@
 	  Support for the Amstrad E3 (codename Delta) videophone. Say Y here
 	  if you have such a device.
 
+config AMS_DELTA_FIQ
+	bool "Fast Interrupt Request (FIQ) support for the E3"
+	depends on MACH_AMS_DELTA
+	select FIQ
+	help
+	  Provide a FIQ handler for the E3.
+	  This allows for fast handling of interrupts generated
+	  by the clock line of the E3 mailboard (or a PS/2 keyboard)
+	  connected to the GPIO based external keyboard port.
+
 config MACH_OMAP_GENERIC
 	bool "Generic OMAP board"
 	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index b6a537c..ea231c7 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_MACH_OMAP_PALMTT)		+= board-palmtt.o
 obj-$(CONFIG_MACH_NOKIA770)		+= board-nokia770.o
 obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o
+obj-$(CONFIG_AMS_DELTA_FIQ)		+= ams-delta-fiq.o ams-delta-fiq-handler.o
 obj-$(CONFIG_MACH_SX1)			+= board-sx1.o board-sx1-mmc.o
 obj-$(CONFIG_MACH_HERALD)		+= board-htcherald.o
 
diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
new file mode 100644
index 0000000..927d5a1
--- /dev/null
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -0,0 +1,278 @@
+/*
+ *  linux/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+ *
+ *  Based on  linux/arch/arm/lib/floppydma.S
+ *  Renamed and modified to work with 2.6 kernel by Matt Callow
+ *  Copyright (C) 1995, 1996 Russell King
+ *  Copyright (C) 2004 Pete Trapps
+ *  Copyright (C) 2006 Matt Callow
+ *  Copyright (C) 2010 Janusz Krzysztofik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+#include <plat/io.h>
+#include <plat/board-ams-delta.h>
+
+#include <mach/ams-delta-fiq.h>
+
+/*
+ * GPIO related definitions, copied from arch/arm/plat-omap/gpio.c.
+ * Unfortunately, those were not placed in a separate header file.
+ */
+#define OMAP1510_GPIO_BASE		0xFFFCE000
+#define OMAP1510_GPIO_DATA_INPUT	0x00
+#define OMAP1510_GPIO_DATA_OUTPUT	0x04
+#define OMAP1510_GPIO_DIR_CONTROL	0x08
+#define OMAP1510_GPIO_INT_CONTROL	0x0c
+#define OMAP1510_GPIO_INT_MASK		0x10
+#define OMAP1510_GPIO_INT_STATUS	0x14
+#define OMAP1510_GPIO_PIN_CONTROL	0x18
+
+/* GPIO register bitmasks */
+#define KEYBRD_DATA_MASK		(0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_DATA)
+#define KEYBRD_CLK_MASK			(0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_CLK)
+#define MODEM_IRQ_MASK			(0x1 << AMS_DELTA_GPIO_PIN_MODEM_IRQ)
+#define HOOK_SWITCH_MASK		(0x1 << AMS_DELTA_GPIO_PIN_HOOK_SWITCH)
+#define OTHERS_MASK			(MODEM_IRQ_MASK | HOOK_SWITCH_MASK)
+
+/* IRQ handler register bitmasks */
+#define DEFERRED_FIQ_MASK		(0x1 << (INT_DEFERRED_FIQ % IH2_BASE))
+#define GPIO_BANK1_MASK  		(0x1 << INT_GPIO_BANK1)
+
+/* Driver buffer byte offsets */
+#define BUF_MASK			(FIQ_MASK * 4)
+#define BUF_STATE			(FIQ_STATE * 4)
+#define BUF_KEYS_CNT			(FIQ_KEYS_CNT * 4)
+#define BUF_TAIL_OFFSET			(FIQ_TAIL_OFFSET * 4)
+#define BUF_HEAD_OFFSET			(FIQ_HEAD_OFFSET * 4)
+#define BUF_BUF_LEN			(FIQ_BUF_LEN * 4)
+#define BUF_KEY				(FIQ_KEY * 4)
+#define BUF_MISSED_KEYS			(FIQ_MISSED_KEYS * 4)
+#define BUF_BUFFER_START		(FIQ_BUFFER_START * 4)
+#define BUF_GPIO_INT_MASK		(FIQ_GPIO_INT_MASK * 4)
+#define BUF_KEYS_HICNT			(FIQ_KEYS_HICNT * 4)
+#define BUF_IRQ_PEND			(FIQ_IRQ_PEND * 4)
+#define BUF_SIR_CODE_L1			(FIQ_SIR_CODE_L1 * 4)
+#define BUF_SIR_CODE_L2			(IRQ_SIR_CODE_L2 * 4)
+#define BUF_CNT_INT_00			(FIQ_CNT_INT_00 * 4)
+#define BUF_CNT_INT_KEY			(FIQ_CNT_INT_KEY * 4)
+#define BUF_CNT_INT_MDM			(FIQ_CNT_INT_MDM * 4)
+#define BUF_CNT_INT_03			(FIQ_CNT_INT_03 * 4)
+#define BUF_CNT_INT_HSW			(FIQ_CNT_INT_HSW * 4)
+#define BUF_CNT_INT_05			(FIQ_CNT_INT_05 * 4)
+#define BUF_CNT_INT_06			(FIQ_CNT_INT_06 * 4)
+#define BUF_CNT_INT_07			(FIQ_CNT_INT_07 * 4)
+#define BUF_CNT_INT_08			(FIQ_CNT_INT_08 * 4)
+#define BUF_CNT_INT_09			(FIQ_CNT_INT_09 * 4)
+#define BUF_CNT_INT_10			(FIQ_CNT_INT_10 * 4)
+#define BUF_CNT_INT_11			(FIQ_CNT_INT_11 * 4)
+#define BUF_CNT_INT_12			(FIQ_CNT_INT_12 * 4)
+#define BUF_CNT_INT_13			(FIQ_CNT_INT_13 * 4)
+#define BUF_CNT_INT_14			(FIQ_CNT_INT_14 * 4)
+#define BUF_CNT_INT_15			(FIQ_CNT_INT_15 * 4)
+#define BUF_CIRC_BUFF			(FIQ_CIRC_BUFF * 4)
+
+
+/*
+ * Register useage
+ * r8  - temporary
+ * r9  - the driver buffer
+ * r10 - temporary
+ * r11 - interrupts mask
+ * r12 - base pointers
+ * r13 - interrupts status
+ */
+
+	.text
+
+	.global qwerty_fiqin_end
+
+ENTRY(qwerty_fiqin_start)
+	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+	@ FIQ intrrupt handler
+	ldr r12, omap_ih1_base			@ set pointer to level1 handler
+
+	ldr r11, [r12, #IRQ_MIR_REG_OFFSET]	@ fetch interrupts mask
+
+	ldr r13, [r12, #IRQ_ITR_REG_OFFSET]	@ fetch interrupts status
+	bics r13, r13, r11			@ clear masked - any left?
+	beq exit				@ none - spurious FIQ? exit
+
+	ldr r10, [r12, #IRQ_SIR_FIQ_REG_OFFSET]	@ get requested interrupt number
+
+	mov r8, #2				@ reset FIQ agreement
+	str r8, [r12, #IRQ_CONTROL_REG_OFFSET]
+
+	cmp r10, #INT_GPIO_BANK1		@ is it GPIO bank interrupt?
+	beq gpio				@ yes - process it
+
+	mov r8, #1
+	orr r8, r11, r8, lsl r10		@ mask spurious interrupt
+	str r8, [r12, #IRQ_MIR_REG_OFFSET]
+exit:
+	subs	pc, lr, #4			@ return from FIQ
+	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+	@@@@@@@@@@@@@@@@@@@@@@@@@@@
+gpio:	@ GPIO bank interrupt handler
+	ldr r12, omap1510_gpio_base		@ set base pointer to GPIO bank
+
+	ldr r11, [r12, #OMAP1510_GPIO_INT_MASK]	@ fetch GPIO interrupts mask
+restart:
+	ldr r13, [r12, #OMAP1510_GPIO_INT_STATUS]	@ fetch status bits
+	bics r13, r13, r11			@ clear masked - any left?
+	beq exit				@ no - spurious interrupt? exit
+
+	orr r11, r11, r13			@ mask all requested interrupts
+	str r11, [r12, #OMAP1510_GPIO_INT_MASK]
+
+	ands r10, r13, #KEYBRD_CLK_MASK		@ extract keyboard status - set?
+	beq hksw				@ no - try next source
+
+
+	@@@@@@@@@@@@@@@@@@@@@@
+	@ Keyboard clock FIQ mode interrupt handler
+	@ r10 now contains KEYBRD_CLK_MASK, use it
+	str r10, [r12, #OMAP1510_GPIO_INT_STATUS]	@ ack the interrupt
+	bic r11, r11, r10				@ unmask it
+	str r11, [r12, #OMAP1510_GPIO_INT_MASK]
+
+	@ Process keyboard data
+	ldr r8, [r12, #OMAP1510_GPIO_DATA_INPUT]	@ fetch GPIO input
+
+	ldr r10, [r9, #BUF_STATE]		@ fetch kbd interface state
+	cmp r10, #0				@ are we expecting start bit?
+	bne data				@ no - go to data processing
+
+	ands r8, r8, #KEYBRD_DATA_MASK		@ check start bit - detected?
+	beq hksw				@ no - try next source
+
+	@ r8 contains KEYBRD_DATA_MASK, use it
+	str r8, [r9, #BUF_STATE]		@ enter data processing state
+	@ r10 already contains 0, reuse it
+	str r10, [r9, #BUF_KEY]			@ clear keycode
+	mov r10, #2				@ reset input bit mask
+	str r10, [r9, #BUF_MASK]
+
+	@ Mask other GPIO line interrupts till key done
+	str r11, [r9, #BUF_GPIO_INT_MASK]	@ save mask for later restore
+	mvn r11, #KEYBRD_CLK_MASK		@ prepare all except kbd mask
+	str r11, [r12, #OMAP1510_GPIO_INT_MASK]	@ store into the mask register
+
+	b restart				@ restart
+
+data:	ldr r10, [r9, #BUF_MASK]		@ fetch current input bit mask
+
+	@ r8 still contains GPIO input bits
+	ands r8, r8, #KEYBRD_DATA_MASK		@ is keyboard data line low?
+	ldreq r8, [r9, #BUF_KEY]		@ yes - fetch collected so far,
+	orreq r8, r8, r10			@ set 1 at current mask position
+	streq r8, [r9, #BUF_KEY]		@ and save back
+
+	mov r10, r10, lsl #1			@ shift mask left
+	bics r10, r10, #0x800			@ have we got all the bits?
+	strne r10, [r9, #BUF_MASK]		@ not yet - store the mask
+	bne restart				@ and restart
+
+	@ r10 already contains 0, reuse it
+	str r10, [r9, #BUF_STATE]		@ reset state to start
+
+	@ Key done - restore interrupt mask
+	ldr r10, [r9, #BUF_GPIO_INT_MASK]	@ fetch saved mask
+	and r11, r11, r10			@ unmask all saved as unmasked
+	str r11, [r12, #OMAP1510_GPIO_INT_MASK]	@ restore into the mask register
+
+	@ Try appending the keycode to the circular buffer
+	ldr r10, [r9, #BUF_KEYS_CNT]		@ get saved keystrokes count
+	ldr r8, [r9, #BUF_BUF_LEN]		@ get buffer size
+	cmp r10, r8				@ is buffer full?
+	beq hksw				@ yes - key lost, next source
+
+	add r10, r10, #1			@ incremet keystrokes counter
+	str r10, [r9, #BUF_KEYS_CNT]
+
+	ldr r10, [r9, #BUF_TAIL_OFFSET]		@ get buffer tail offset
+	@ r8 already contains buffer size
+	cmp r10, r8				@ end of buffer?
+	moveq r10, #0				@ yes - rewind to buffer start
+
+	ldr r12, [r9, #BUF_BUFFER_START]	@ get buffer start address
+	add r12, r12, r10, LSL #2		@ calculate buffer tail address
+	ldr r8, [r9, #BUF_KEY]			@ get last keycode
+	str r8, [r12]				@ append it to the buffer tail
+
+	add r10, r10, #1			@ increment buffer tail offset
+	str r10, [r9, #BUF_TAIL_OFFSET]
+
+	ldr r10, [r9, #BUF_CNT_INT_KEY]		@ increment interrupts counter
+	add r10, r10, #1
+	str r10, [r9, #BUF_CNT_INT_KEY]
+	@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+hksw:	@Is hook switch interrupt requested?
+	tst r13, #HOOK_SWITCH_MASK 		@ is hook switch status bit set?
+	beq mdm					@ no - try next source
+
+
+	@@@@@@@@@@@@@@@@@@@@@@@@
+	@ Hook switch interrupt FIQ mode simple handler
+
+	@ Don't toggle active edge, the switch always bounces
+
+	@ Increment hook switch interrupt counter
+	ldr r10, [r9, #BUF_CNT_INT_HSW]
+	add r10, r10, #1
+	str r10, [r9, #BUF_CNT_INT_HSW]
+	@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+mdm:	@Is it a modem interrupt?
+	tst r13, #MODEM_IRQ_MASK 		@ is modem status bit set?
+	beq irq					@ no - check for next interrupt
+
+
+	@@@@@@@@@@@@@@@@@@@@@@@@
+	@ Modem FIQ mode interrupt handler stub
+
+	@ Increment modem interrupt counter
+	ldr r10, [r9, #BUF_CNT_INT_MDM]
+	add r10, r10, #1
+	str r10, [r9, #BUF_CNT_INT_MDM]
+	@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+irq:	@ Place deferred_fiq interrupt request
+	ldr r12, deferred_fiq_ih_base		@ set pointer to IRQ handler
+	mov r10, #DEFERRED_FIQ_MASK		@ set deferred_fiq bit
+	str r10, [r12, #IRQ_ISR_REG_OFFSET] 	@ place it in the ISR register
+
+	ldr r12, omap1510_gpio_base		@ set pointer back to GPIO bank
+	b restart				@ check for next GPIO interrupt
+	@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+/*
+ * Virtual addresses for IO
+ */
+omap_ih1_base:
+	.word OMAP1_IO_ADDRESS(OMAP_IH1_BASE)
+deferred_fiq_ih_base:
+	.word OMAP1_IO_ADDRESS(DEFERRED_FIQ_IH_BASE)
+omap1510_gpio_base:
+	.word OMAP1_IO_ADDRESS(OMAP1510_GPIO_BASE)
+qwerty_fiqin_end:
+
+/*
+ * Check the size of the FIQ,
+ * it cannot go beyond 0xffff0200, and is copied to 0xffff001c
+ */
+.if (qwerty_fiqin_end - qwerty_fiqin_start) > (0x200 - 0x1c)
+	.err
+.endif
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
new file mode 100644
index 0000000..6c994e2
--- /dev/null
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -0,0 +1,155 @@
+/*
+ *  Amstrad E3 FIQ handling
+ *
+ *  Copyright (C) 2009 Janusz Krzysztofik
+ *  Copyright (c) 2006 Matt Callow
+ *  Copyright (c) 2004 Amstrad Plc
+ *  Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Parts of this code are taken from linux/arch/arm/mach-omap/irq.c
+ * in the MontaVista 2.4 kernel (and the Amstrad changes therein)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <plat/board-ams-delta.h>
+
+#include <asm/fiq.h>
+#include <mach/ams-delta-fiq.h>
+
+static struct fiq_handler fh = {
+	.name	= "ams-delta-fiq"
+};
+
+/*
+ * This buffer is shared between FIQ and IRQ contexts.
+ * The FIQ and IRQ isrs can both read and write it.
+ * It is structured as a header section several 32bit slots,
+ * followed by the circular buffer where the FIQ isr stores
+ * keystrokes received from the qwerty keyboard.
+ * See ams-delta-fiq.h for details of offsets.
+ */
+unsigned int fiq_buffer[1024];
+EXPORT_SYMBOL(fiq_buffer);
+
+static unsigned int irq_counter[16];
+
+static irqreturn_t deferred_fiq(int irq, void *dev_id)
+{
+	struct irq_desc *irq_desc;
+	struct irq_chip *irq_chip = NULL;
+	int gpio, irq_num, fiq_count;
+
+	irq_desc = irq_to_desc(IH_GPIO_BASE);
+	if (irq_desc)
+		irq_chip = irq_desc->chip;
+
+	/*
+	 * For each handled GPIO interrupt, keep calling its interrupt handler
+	 * until the IRQ counter catches the FIQ incremented interrupt counter.
+	 */
+	for (gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK;
+			gpio <= AMS_DELTA_GPIO_PIN_HOOK_SWITCH; gpio++) {
+		irq_num = gpio_to_irq(gpio);
+		fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio];
+
+		while (irq_counter[gpio] < fiq_count) {
+			if (gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
+				/*
+				 * It looks like handle_edge_irq() that
+				 * OMAP GPIO edge interrupts default to,
+				 * expects interrupt already unmasked.
+				 */
+				if (irq_chip && irq_chip->unmask)
+					irq_chip->unmask(irq_num);
+			}
+			generic_handle_irq(irq_num);
+
+			irq_counter[gpio]++;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+void __init ams_delta_init_fiq(void)
+{
+	void *fiqhandler_start;
+	unsigned int fiqhandler_length;
+	struct pt_regs FIQ_regs;
+	unsigned long val, offset;
+	int i, retval;
+
+	fiqhandler_start = &qwerty_fiqin_start;
+	fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
+	pr_info("Installing fiq handler from %p, length 0x%x\n",
+			fiqhandler_start, fiqhandler_length);
+
+	retval = claim_fiq(&fh);
+	if (retval) {
+		pr_err("ams_delta_init_fiq(): couldn't claim FIQ, ret=%d\n",
+				retval);
+		return;
+	}
+
+	retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
+			IRQ_TYPE_EDGE_RISING, "deferred_fiq", 0);
+	if (retval < 0) {
+		pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
+		release_fiq(&fh);
+		return;
+	}
+	/*
+	 * Since no set_type() method is provided by OMAP irq chip,
+	 * switch to edge triggered interrupt type manually.
+	 */
+	offset = IRQ_ILR0_REG_OFFSET + INT_DEFERRED_FIQ * 0x4;
+	val = omap_readl(DEFERRED_FIQ_IH_BASE + offset) & ~(1 << 1);
+	omap_writel(val, DEFERRED_FIQ_IH_BASE + offset);
+
+	set_fiq_handler(fiqhandler_start, fiqhandler_length);
+
+	/*
+	 * Initialise the buffer which is shared
+	 * between FIQ mode and IRQ mode
+	 */
+	fiq_buffer[FIQ_GPIO_INT_MASK]	= 0;
+	fiq_buffer[FIQ_MASK]		= 0;
+	fiq_buffer[FIQ_STATE]		= 0;
+	fiq_buffer[FIQ_KEY]		= 0;
+	fiq_buffer[FIQ_KEYS_CNT]	= 0;
+	fiq_buffer[FIQ_KEYS_HICNT]	= 0;
+	fiq_buffer[FIQ_TAIL_OFFSET]	= 0;
+	fiq_buffer[FIQ_HEAD_OFFSET]	= 0;
+	fiq_buffer[FIQ_BUF_LEN]		= 256;
+	fiq_buffer[FIQ_MISSED_KEYS]	= 0;
+	fiq_buffer[FIQ_BUFFER_START]	=
+			(unsigned int) &fiq_buffer[FIQ_CIRC_BUFF];
+
+	for (i = FIQ_CNT_INT_00; i <= FIQ_CNT_INT_15; i++)
+		fiq_buffer[i] = 0;
+
+	/*
+	 * FIQ mode r9 always points to the fiq_buffer, becauses the FIQ isr
+	 * will run in an unpredictable context. The fiq_buffer is the FIQ isr's
+	 * only means of communication with the IRQ level and other kernel
+	 * context code.
+	 */
+	FIQ_regs.ARM_r9 = (unsigned int)fiq_buffer;
+	set_fiq_regs(&FIQ_regs);
+
+	pr_info("request_fiq(): fiq_buffer = %p\n", fiq_buffer);
+
+	/*
+	 * Redirect GPIO interrupts to FIQ
+	 */
+	offset = IRQ_ILR0_REG_OFFSET + INT_GPIO_BANK1 * 0x4;
+	val = omap_readl(OMAP_IH1_BASE + offset) | 1;
+	omap_writel(val, OMAP_IH1_BASE + offset);
+}
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 7fc11c3..fdd1dd5 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -33,6 +33,8 @@
 #include <plat/board.h>
 #include <plat/common.h>
 
+#include <mach/ams-delta-fiq.h>
+
 static u8 ams_delta_latch1_reg;
 static u16 ams_delta_latch2_reg;
 
@@ -236,6 +238,10 @@
 	omap_usb_init(&ams_delta_usb_config);
 	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
+#ifdef CONFIG_AMS_DELTA_FIQ
+	ams_delta_init_fiq();
+#endif
+
 	omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
 }
 
@@ -263,8 +269,18 @@
 
 static int __init ams_delta_modem_init(void)
 {
+	int err;
+
 	omap_cfg_reg(M14_1510_GPIO2);
-	ams_delta_modem_ports[0].irq = gpio_to_irq(2);
+	ams_delta_modem_ports[0].irq =
+			gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+
+	err = gpio_request(AMS_DELTA_GPIO_PIN_MODEM_IRQ, "modem");
+	if (err) {
+		pr_err("Couldn't request gpio pin for modem\n");
+		return err;
+	}
+	gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
 
 	ams_delta_latch2_write(
 		AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC,
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
new file mode 100644
index 0000000..7a2df29
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
@@ -0,0 +1,79 @@
+/*
+ * arch/arm/mach-omap1/include/ams-delta-fiq.h
+ *
+ * Taken from the original Amstrad modifications to fiq.h
+ *
+ * Copyright (c) 2004 Amstrad Plc
+ * Copyright (c) 2006 Matt Callow
+ * Copyright (c) 2010 Janusz Krzysztofik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __AMS_DELTA_FIQ_H
+#define __AMS_DELTA_FIQ_H
+
+#include <plat/irqs.h>
+
+/*
+ * Interrupt number used for passing control from FIQ to IRQ.
+ * IRQ12, described as reserved, has been selected.
+ */
+#define INT_DEFERRED_FIQ	INT_1510_RES12
+/*
+ * Base address of an interrupt handler that the INT_DEFERRED_FIQ belongs to.
+ */
+#if (INT_DEFERRED_FIQ < IH2_BASE)
+#define DEFERRED_FIQ_IH_BASE	OMAP_IH1_BASE
+#else
+#define DEFERRED_FIQ_IH_BASE	OMAP_IH2_BASE
+#endif
+
+/*
+ * These are the offsets from the begining of the fiq_buffer. They are put here
+ * since the buffer and header need to be accessed by drivers servicing devices
+ * which generate GPIO interrupts - e.g. keyboard, modem, hook switch.
+ */
+#define FIQ_MASK		 0
+#define FIQ_STATE		 1
+#define FIQ_KEYS_CNT		 2
+#define FIQ_TAIL_OFFSET		 3
+#define FIQ_HEAD_OFFSET		 4
+#define FIQ_BUF_LEN		 5
+#define FIQ_KEY			 6
+#define FIQ_MISSED_KEYS		 7
+#define FIQ_BUFFER_START	 8
+#define FIQ_GPIO_INT_MASK	 9
+#define FIQ_KEYS_HICNT		10
+#define FIQ_IRQ_PEND		11
+#define FIQ_SIR_CODE_L1		12
+#define IRQ_SIR_CODE_L2		13
+
+#define FIQ_CNT_INT_00		14
+#define FIQ_CNT_INT_KEY		15
+#define FIQ_CNT_INT_MDM		16
+#define FIQ_CNT_INT_03		17
+#define FIQ_CNT_INT_HSW		18
+#define FIQ_CNT_INT_05		19
+#define FIQ_CNT_INT_06		20
+#define FIQ_CNT_INT_07		21
+#define FIQ_CNT_INT_08		22
+#define FIQ_CNT_INT_09		23
+#define FIQ_CNT_INT_10		24
+#define FIQ_CNT_INT_11		25
+#define FIQ_CNT_INT_12		26
+#define FIQ_CNT_INT_13		27
+#define FIQ_CNT_INT_14		28
+#define FIQ_CNT_INT_15		29
+
+#define FIQ_CIRC_BUFF		30      /*Start of circular buffer */
+
+#ifndef __ASSEMBLER__
+extern unsigned int fiq_buffer[];
+extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
+
+extern void __init ams_delta_init_fiq(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
index b6d9584..e8a8cf3 100644
--- a/arch/arm/mach-omap1/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -13,6 +13,8 @@
 
 #include <linux/serial_reg.h>
 
+#include <asm/memory.h>
+
 #include <plat/serial.h>
 
 		.pushsection .data
@@ -37,23 +39,12 @@
 		cmp	\rx, #0			@ is port configured?
 		bne	99f			@ already configured
 
-		/* Check 7XX UART1 scratchpad register for uart to use */
+		/* Check the debug UART configuration set in uncompress.h */
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0xff000000	@ physical base address
-		movne	\rx, #0xfe000000	@ virtual base
-		orr	\rx, \rx, #0x00fb0000	@ OMAP1UART1
-		ldrb	\rx, [\rx, #(UART_SCR << OMAP7XX_PORT_SHIFT)]
-		cmp	\rx, #0			@ anything in 7XX scratchpad?
-		bne	10f			@ found 7XX uart
-
-		/* Check 15xx/16xx UART1 scratchpad register for uart to use */
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0xff000000	@ physical base address
-		movne	\rx, #0xfe000000	@ virtual base
-		orr	\rx, \rx, #0x00fb0000	@ OMAP1UART1
-		ldrb	\rx, [\rx, #(UART_SCR << OMAP_PORT_SHIFT)]
+		ldreq	\rx, =OMAP_UART_INFO
+		ldrne	\rx, =__phys_to_virt(OMAP_UART_INFO)
+		ldr	\rx, [\rx, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
 10:		cmp	\rx, #0			@ no port configured?
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 2de4f79..e679a2c 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -45,6 +45,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <plat/display.h>
+#include <plat/mcspi.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index e15d2e8..1d7f827 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -82,7 +82,7 @@
 
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
-		.mapbase	= 0x10000000,
+		.mapbase	= ZOOM_UART_BASE,
 		.irq		= OMAP_GPIO_IRQ(102),
 		.flags		= UPF_BOOT_AUTOCONF|UPF_IOREMAP|UPF_SHARE_IRQ,
 		.irqflags	= IRQF_SHARED | IRQF_TRIGGER_RISING,
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 9a26f84..803ef14 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -91,8 +91,8 @@
 }
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
+	.phys_io	= ZOOM_UART_BASE,
+	.io_pg_offst	= (ZOOM_UART_VIRT >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_zoom2_map_io,
 	.init_irq	= omap_zoom2_init_irq,
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index cd3e40c..3314704 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -73,8 +73,8 @@
 }
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
+	.phys_io	= ZOOM_UART_BASE,
+	.io_pg_offst	= (ZOOM_UART_VIRT >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_zoom_map_io,
 	.init_irq	= omap_zoom_init_irq,
diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S
index 4a63a2e..35b2440 100644
--- a/arch/arm/mach-omap2/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap2/include/mach/debug-macro.S
@@ -13,6 +13,8 @@
 
 #include <linux/serial_reg.h>
 
+#include <asm/memory.h>
+
 #include <plat/serial.h>
 
 #define UART_OFFSET(addr)	((addr) & 0x00ffffff)
@@ -40,13 +42,12 @@
 		cmp	\rx, #0			@ is port configured?
 		bne	99f			@ already configured
 
-		/* Check UART1 scratchpad register for uart to use */
+		/* Check the debug UART configuration set in uncompress.h */
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x48000000	@ physical base address
-		movne	\rx, #0xfa000000	@ virtual base
-		orr	\rx, \rx, #0x0006a000	@ uart1 on omap2/3/4
-		ldrb	\rx, [\rx, #(UART_SCR << OMAP_PORT_SHIFT)] @ scratchpad
+		ldreq	\rx, =OMAP_UART_INFO
+		ldrne	\rx, =__phys_to_virt(OMAP_UART_INFO)
+		ldr	\rx, [\rx, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
 		cmp	\rx, #0			@ no port configured?
@@ -87,10 +88,10 @@
 		b	98f
 44:		mov	\rx, #UART_OFFSET(OMAP4_UART4_BASE)
 		b	98f
-95:		mov	\rx, #ZOOM_UART_BASE
+95:		ldr	\rx, =ZOOM_UART_BASE
 		ldr	\tmp, =omap_uart_phys
 		str	\rx, [\tmp, #0]
-		mov	\rx, #ZOOM_UART_VIRT
+		ldr	\rx, =ZOOM_UART_VIRT
 		ldr	\tmp, =omap_uart_virt
 		str	\rx, [\tmp, #0]
 		mov	\rx, #(UART_LSR << ZOOM_PORT_SHIFT)
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 87f676a..3cfb425 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -166,6 +166,15 @@
 		.length		= L4_EMU_34XX_SIZE,
 		.type		= MT_DEVICE
 	},
+#if defined(CONFIG_DEBUG_LL) &&							\
+	(defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3))
+	{
+		.virtual	= ZOOM_UART_VIRT,
+		.pfn		= __phys_to_pfn(ZOOM_UART_BASE),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	},
+#endif
 };
 #endif
 #ifdef	CONFIG_ARCH_OMAP4
diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c
index 07aa7b3..2ff4dce 100644
--- a/arch/arm/mach-omap2/mux34xx.c
+++ b/arch/arm/mach-omap2/mux34xx.c
@@ -1901,26 +1901,15 @@
 	_OMAP3_BALLENTRY(GPMC_A8, "m3", "ab18"),
 	_OMAP3_BALLENTRY(GPMC_A9, "l3", "ac19"),
 	_OMAP3_BALLENTRY(GPMC_CLK, "t4", "w2"),
-	_OMAP3_BALLENTRY(GPMC_D0, "k1", "m2"),
-	_OMAP3_BALLENTRY(GPMC_D1, "l1", "m1"),
 	_OMAP3_BALLENTRY(GPMC_D10, "p1", "ab4"),
 	_OMAP3_BALLENTRY(GPMC_D11, "r1", "ac4"),
 	_OMAP3_BALLENTRY(GPMC_D12, "r2", "ab6"),
 	_OMAP3_BALLENTRY(GPMC_D13, "t2", "ac6"),
 	_OMAP3_BALLENTRY(GPMC_D14, "w1", "ab7"),
 	_OMAP3_BALLENTRY(GPMC_D15, "y1", "ac7"),
-	_OMAP3_BALLENTRY(GPMC_D2, "l2", "n2"),
-	_OMAP3_BALLENTRY(GPMC_D3, "p2", "n1"),
-	_OMAP3_BALLENTRY(GPMC_D4, "t1", "r2"),
-	_OMAP3_BALLENTRY(GPMC_D5, "v1", "r1"),
-	_OMAP3_BALLENTRY(GPMC_D6, "v2", "t2"),
-	_OMAP3_BALLENTRY(GPMC_D7, "w2", "t1"),
-	_OMAP3_BALLENTRY(GPMC_D8, "h2", "ab3"),
 	_OMAP3_BALLENTRY(GPMC_D9, "k2", "ac3"),
-	_OMAP3_BALLENTRY(GPMC_NADV_ALE, "f3", "w1"),
 	_OMAP3_BALLENTRY(GPMC_NBE0_CLE, "g3", "ac12"),
 	_OMAP3_BALLENTRY(GPMC_NBE1, "u3", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS0, "g4", "y2"),
 	_OMAP3_BALLENTRY(GPMC_NCS1, "h3", "y1"),
 	_OMAP3_BALLENTRY(GPMC_NCS2, "v8", NULL),
 	_OMAP3_BALLENTRY(GPMC_NCS3, "u8", NULL),
@@ -1928,10 +1917,7 @@
 	_OMAP3_BALLENTRY(GPMC_NCS5, "r8", NULL),
 	_OMAP3_BALLENTRY(GPMC_NCS6, "p8", NULL),
 	_OMAP3_BALLENTRY(GPMC_NCS7, "n8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NOE, "g2", "v2"),
-	_OMAP3_BALLENTRY(GPMC_NWE, "f4", "v1"),
 	_OMAP3_BALLENTRY(GPMC_NWP, "h1", "ab10"),
-	_OMAP3_BALLENTRY(GPMC_WAIT0, "m8", "ab12"),
 	_OMAP3_BALLENTRY(GPMC_WAIT1, "l8", "ac10"),
 	_OMAP3_BALLENTRY(GPMC_WAIT2, "k8", NULL),
 	_OMAP3_BALLENTRY(GPMC_WAIT3, "j8", NULL),
@@ -1948,8 +1934,6 @@
 	_OMAP3_BALLENTRY(HSUSB0_DIR, "r28", NULL),
 	_OMAP3_BALLENTRY(HSUSB0_NXT, "t26", NULL),
 	_OMAP3_BALLENTRY(HSUSB0_STP, "t25", NULL),
-	_OMAP3_BALLENTRY(I2C1_SCL, "k21", NULL),
-	_OMAP3_BALLENTRY(I2C1_SDA, "j21", NULL),
 	_OMAP3_BALLENTRY(I2C2_SCL, "af15", NULL),
 	_OMAP3_BALLENTRY(I2C2_SDA, "ae15", NULL),
 	_OMAP3_BALLENTRY(I2C3_SCL, "af14", NULL),
@@ -1958,11 +1942,6 @@
 	_OMAP3_BALLENTRY(I2C4_SDA, "ae26", NULL),
 	_OMAP3_BALLENTRY(JTAG_EMU0, "aa11", NULL),
 	_OMAP3_BALLENTRY(JTAG_EMU1, "aa10", NULL),
-	_OMAP3_BALLENTRY(JTAG_RTCK, "aa12", NULL),
-	_OMAP3_BALLENTRY(JTAG_TCK, "aa13", NULL),
-	_OMAP3_BALLENTRY(JTAG_TDI, "aa20", NULL),
-	_OMAP3_BALLENTRY(JTAG_TDO, "aa19", NULL),
-	_OMAP3_BALLENTRY(JTAG_TMS_TMSC, "aa18", NULL),
 	_OMAP3_BALLENTRY(MCBSP1_CLKR, "y21", NULL),
 	_OMAP3_BALLENTRY(MCBSP1_CLKX, "w21", NULL),
 	_OMAP3_BALLENTRY(MCBSP1_DR, "u21", NULL),
@@ -2010,77 +1989,12 @@
 	_OMAP3_BALLENTRY(SDMMC2_DAT5, "ah3", NULL),
 	_OMAP3_BALLENTRY(SDMMC2_DAT6, "af3", NULL),
 	_OMAP3_BALLENTRY(SDMMC2_DAT7, "ae3", NULL),
-	_OMAP3_BALLENTRY(SDRC_A0, NULL, "n22"),
-	_OMAP3_BALLENTRY(SDRC_A1, NULL, "n23"),
-	_OMAP3_BALLENTRY(SDRC_A10, NULL, "v22"),
-	_OMAP3_BALLENTRY(SDRC_A11, NULL, "v23"),
-	_OMAP3_BALLENTRY(SDRC_A12, NULL, "w22"),
-	_OMAP3_BALLENTRY(SDRC_A13, NULL, "w23"),
-	_OMAP3_BALLENTRY(SDRC_A14, NULL, "y22"),
-	_OMAP3_BALLENTRY(SDRC_A2, NULL, "p22"),
-	_OMAP3_BALLENTRY(SDRC_A3, NULL, "p23"),
-	_OMAP3_BALLENTRY(SDRC_A4, NULL, "r22"),
-	_OMAP3_BALLENTRY(SDRC_A5, NULL, "r23"),
-	_OMAP3_BALLENTRY(SDRC_A6, NULL, "t22"),
-	_OMAP3_BALLENTRY(SDRC_A7, NULL, "t23"),
-	_OMAP3_BALLENTRY(SDRC_A8, NULL, "u22"),
-	_OMAP3_BALLENTRY(SDRC_A9, NULL, "u23"),
-	_OMAP3_BALLENTRY(SDRC_BA0, "h9", "ab21"),
-	_OMAP3_BALLENTRY(SDRC_BA1, "h10", "ac21"),
 	_OMAP3_BALLENTRY(SDRC_CKE0, "h16", "j22"),
 	_OMAP3_BALLENTRY(SDRC_CKE1, "h17", "j23"),
-	_OMAP3_BALLENTRY(SDRC_CLK, "a13", "a11"),
-	_OMAP3_BALLENTRY(SDRC_D0, NULL, "j2"),
-	_OMAP3_BALLENTRY(SDRC_D1, NULL, "j1"),
-	_OMAP3_BALLENTRY(SDRC_D10, "c15", "b14"),
-	_OMAP3_BALLENTRY(SDRC_D11, "b16", "a14"),
-	_OMAP3_BALLENTRY(SDRC_D12, "d17", "b16"),
-	_OMAP3_BALLENTRY(SDRC_D13, "c17", "a16"),
-	_OMAP3_BALLENTRY(SDRC_D14, "b17", "b19"),
-	_OMAP3_BALLENTRY(SDRC_D15, "d18", "a19"),
-	_OMAP3_BALLENTRY(SDRC_D16, NULL, "b3"),
-	_OMAP3_BALLENTRY(SDRC_D17, NULL, "a3"),
-	_OMAP3_BALLENTRY(SDRC_D18, NULL, "b5"),
-	_OMAP3_BALLENTRY(SDRC_D19, NULL, "a5"),
-	_OMAP3_BALLENTRY(SDRC_D2, NULL, "g2"),
-	_OMAP3_BALLENTRY(SDRC_D20, NULL, "b8"),
-	_OMAP3_BALLENTRY(SDRC_D21, NULL, "a8"),
-	_OMAP3_BALLENTRY(SDRC_D22, NULL, "b9"),
-	_OMAP3_BALLENTRY(SDRC_D23, NULL, "a9"),
-	_OMAP3_BALLENTRY(SDRC_D24, NULL, "b21"),
-	_OMAP3_BALLENTRY(SDRC_D25, NULL, "a21"),
-	_OMAP3_BALLENTRY(SDRC_D26, NULL, "d22"),
-	_OMAP3_BALLENTRY(SDRC_D27, NULL, "d23"),
-	_OMAP3_BALLENTRY(SDRC_D28, NULL, "e22"),
-	_OMAP3_BALLENTRY(SDRC_D29, NULL, "e23"),
-	_OMAP3_BALLENTRY(SDRC_D3, NULL, "g1"),
-	_OMAP3_BALLENTRY(SDRC_D30, NULL, "g22"),
-	_OMAP3_BALLENTRY(SDRC_D31, NULL, "g23"),
-	_OMAP3_BALLENTRY(SDRC_D4, NULL, "f2"),
-	_OMAP3_BALLENTRY(SDRC_D5, NULL, "f1"),
-	_OMAP3_BALLENTRY(SDRC_D6, NULL, "d2"),
-	_OMAP3_BALLENTRY(SDRC_D7, NULL, "d1"),
-	_OMAP3_BALLENTRY(SDRC_D8, "c14", "b13"),
-	_OMAP3_BALLENTRY(SDRC_D9, "b14", "a13"),
-	_OMAP3_BALLENTRY(SDRC_DM0, NULL, "c1"),
-	_OMAP3_BALLENTRY(SDRC_DM1, "a16", "a17"),
-	_OMAP3_BALLENTRY(SDRC_DM2, NULL, "a6"),
-	_OMAP3_BALLENTRY(SDRC_DM3, NULL, "a20"),
-	_OMAP3_BALLENTRY(SDRC_DQS0, NULL, "c2"),
-	_OMAP3_BALLENTRY(SDRC_DQS1, "a17", "b17"),
-	_OMAP3_BALLENTRY(SDRC_DQS2, NULL, "b6"),
-	_OMAP3_BALLENTRY(SDRC_DQS3, NULL, "b20"),
-	_OMAP3_BALLENTRY(SDRC_NCAS, "h13", "l22"),
-	_OMAP3_BALLENTRY(SDRC_NCLK, "a14", "b11"),
-	_OMAP3_BALLENTRY(SDRC_NCS0, "h11", "m22"),
-	_OMAP3_BALLENTRY(SDRC_NCS1, "h12", "m23"),
-	_OMAP3_BALLENTRY(SDRC_NRAS, "h14", "l23"),
-	_OMAP3_BALLENTRY(SDRC_NWE, "h15", "k23"),
 	_OMAP3_BALLENTRY(SIM_CLK, "p26", NULL),
 	_OMAP3_BALLENTRY(SIM_IO, "p27", NULL),
 	_OMAP3_BALLENTRY(SIM_PWRCTRL, "r27", NULL),
 	_OMAP3_BALLENTRY(SIM_RST, "r25", NULL),
-	_OMAP3_BALLENTRY(SYS_32K, "ae25", NULL),
 	_OMAP3_BALLENTRY(SYS_BOOT0, "ah26", NULL),
 	_OMAP3_BALLENTRY(SYS_BOOT1, "ag26", NULL),
 	_OMAP3_BALLENTRY(SYS_BOOT2, "ae14", NULL),
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 4017019..c01d9f0 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -428,4 +428,8 @@
 
 #include <mach/hardware.h>
 
+#ifdef CONFIG_FIQ
+#define FIQ_START		1024
+#endif
+
 #endif
diff --git a/arch/arm/plat-omap/include/plat/multi.h b/arch/arm/plat-omap/include/plat/multi.h
index f235d32..ffd909f 100644
--- a/arch/arm/plat-omap/include/plat/multi.h
+++ b/arch/arm/plat-omap/include/plat/multi.h
@@ -61,9 +61,9 @@
 #  define OMAP_NAME omap16xx
 # endif
 #endif
-#if (defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3))
+#ifdef CONFIG_ARCH_OMAP2PLUS
 # if (defined(OMAP_NAME) || defined(MULTI_OMAP1))
-#  error "OMAP1 and OMAP2 can't be selected at the same time"
+#  error "OMAP1 and OMAP2PLUS can't be selected at the same time"
 # endif
 #endif
 #ifdef CONFIG_ARCH_OMAP2420
@@ -82,12 +82,20 @@
 #  define OMAP_NAME omap2430
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP3430
+#ifdef CONFIG_ARCH_OMAP3
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP2
 #  define MULTI_OMAP2
 # else
-#  define OMAP_NAME omap3430
+#  define OMAP_NAME omap3
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap4
 # endif
 #endif
 
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 83dce4c..19145f5 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -15,6 +15,20 @@
 
 #include <linux/init.h>
 
+/*
+ * Memory entry used for the DEBUG_LL UART configuration. See also
+ * uncompress.h and debug-macro.S.
+ *
+ * Note that using a memory location for storing the UART configuration
+ * has at least two limitations:
+ *
+ * 1. Kernel uncompress code cannot overlap OMAP_UART_INFO as the
+ *    uncompress code could then partially overwrite itself
+ * 2. We assume printascii is called at least once before paging_init,
+ *    and addruart has a chance to read OMAP_UART_INFO
+ */
+#define OMAP_UART_INFO		(PHYS_OFFSET + 0x3ffc)
+
 /* OMAP1 serial ports */
 #define OMAP1_UART1_BASE	0xfffb0000
 #define OMAP1_UART2_BASE	0xfffb0800
@@ -39,7 +53,7 @@
 
 /* External port on Zoom2/3 */
 #define ZOOM_UART_BASE		0x10000000
-#define ZOOM_UART_VIRT		0xfb000000
+#define ZOOM_UART_VIRT		0xfa400000
 
 #define OMAP_PORT_SHIFT		2
 #define OMAP7XX_PORT_SHIFT	0
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index 81d9ec5..bbedd71 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -20,27 +20,21 @@
 #include <linux/types.h>
 #include <linux/serial_reg.h>
 
+#include <asm/memory.h>
 #include <asm/mach-types.h>
 
 #include <plat/serial.h>
 
-static volatile u8 *uart1_base;
-static int uart1_shift;
-
 static volatile u8 *uart_base;
 static int uart_shift;
 
 /*
- * Store the DEBUG_LL uart number into UART1 scratchpad register.
+ * Store the DEBUG_LL uart number into memory.
  * See also debug-macro.S, and serial.c for related code.
- *
- * Please note that we currently assume that:
- * - UART1 clocks are enabled for register access
- * - UART1 scratchpad register can be used
  */
-static void set_uart1_scratchpad(unsigned char port)
+static void set_omap_uart_info(unsigned char port)
 {
-	uart1_base[UART_SCR << uart1_shift] = port;
+	*(volatile u32 *)OMAP_UART_INFO = port;
 }
 
 static void putc(int c)
@@ -60,42 +54,38 @@
 /*
  * Macros to configure UART1 and debug UART
  */
-#define _DEBUG_LL_ENTRY(mach, uart1_phys, uart1_shft,			\
-			dbg_uart, dbg_shft, dbg_id)			\
+#define _DEBUG_LL_ENTRY(mach, dbg_uart, dbg_shft, dbg_id)		\
 	if (machine_is_##mach()) {					\
-		uart1_base = (volatile u8 *)(uart1_phys);		\
-		uart1_shift = (uart1_shft);				\
 		uart_base = (volatile u8 *)(dbg_uart);			\
 		uart_shift = (dbg_shft);				\
 		port = (dbg_id);					\
-		set_uart1_scratchpad(port);				\
+		set_omap_uart_info(port);				\
 		break;							\
 	}
 
 #define DEBUG_LL_OMAP7XX(p, mach)					\
-	_DEBUG_LL_ENTRY(mach, OMAP1_UART1_BASE, OMAP7XX_PORT_SHIFT,	\
-		OMAP1_UART##p##_BASE, OMAP7XX_PORT_SHIFT, OMAP1UART##p)
+	_DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP7XX_PORT_SHIFT,	\
+		OMAP1UART##p)
 
 #define DEBUG_LL_OMAP1(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP1_UART1_BASE, OMAP_PORT_SHIFT,	\
-		OMAP1_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP1UART##p)
+	_DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP1UART##p)
 
 #define DEBUG_LL_OMAP2(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP2_UART1_BASE, OMAP_PORT_SHIFT,	\
-		OMAP2_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP2UART##p)
+	_DEBUG_LL_ENTRY(mach, OMAP2_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP2UART##p)
 
 #define DEBUG_LL_OMAP3(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP3_UART1_BASE, OMAP_PORT_SHIFT,	\
-		OMAP3_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP3UART##p)
+	_DEBUG_LL_ENTRY(mach, OMAP3_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP3UART##p)
 
 #define DEBUG_LL_OMAP4(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP4_UART1_BASE, OMAP_PORT_SHIFT,	\
-		OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP4UART##p)
+	_DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP4UART##p)
 
 /* Zoom2/3 shift is different for UART1 and external port */
 #define DEBUG_LL_ZOOM(mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP2_UART1_BASE, OMAP_PORT_SHIFT,	\
-		ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
+	_DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
 
 static inline void __arch_decomp_setup(unsigned long arch_id)
 {
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 51f4dfb..226b2e8 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -437,6 +437,20 @@
 }
 #endif
 
+#ifdef CONFIG_ARCH_OMAP4
+int __init omap44xx_sram_init(void)
+{
+	printk(KERN_ERR "FIXME: %s not implemented\n", __func__);
+
+	return -ENODEV;
+}
+#else
+static inline int omap44xx_sram_init(void)
+{
+	return 0;
+}
+#endif
+
 int __init omap_sram_init(void)
 {
 	omap_detect_sram();
@@ -451,7 +465,7 @@
 	else if (cpu_is_omap34xx())
 		omap34xx_sram_init();
 	else if (cpu_is_omap44xx())
-		omap34xx_sram_init(); /* FIXME: */
+		omap44xx_sram_init();
 
 	return 0;
 }
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 7e319d6..f34f1db 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -209,4 +209,20 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called altera_ps2.
 
+config SERIO_AMS_DELTA
+	tristate "Amstrad Delta (E3) mailboard support"
+	depends on MACH_AMS_DELTA
+	default y
+	select AMS_DELTA_FIQ
+	---help---
+	  Say Y here if you have an E3 and want to use its mailboard,
+	  or any standard AT keyboard connected to the mailboard port.
+
+	  When used for the E3 mailboard, a non-standard key table
+	  must be loaded from userspace, possibly using udev extras
+	  provided keymap helper utility.
+
+	  To compile this driver as a module, choose M here;
+	  the module will be called ams_delta_serio.
+
 endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index bf945f7..84c80bf 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -21,5 +21,6 @@
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)	+= libps2.o
 obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
+obj-$(CONFIG_SERIO_AMS_DELTA)	+= ams_delta_serio.o
 obj-$(CONFIG_SERIO_XILINX_XPS_PS2)	+= xilinx_ps2.o
 obj-$(CONFIG_SERIO_ALTERA_PS2)	+= altera_ps2.o
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
new file mode 100644
index 0000000..8f1770e
--- /dev/null
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -0,0 +1,177 @@
+/*
+ *  Amstrad E3 (Delta) keyboard port driver
+ *
+ *  Copyright (c) 2006 Matt Callow
+ *  Copyright (c) 2010 Janusz Krzysztofik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Thanks to Cliff Lawson for his help
+ *
+ * The Amstrad Delta keyboard (aka mailboard) uses normal PC-AT style serial
+ * transmission.  The keyboard port is formed of two GPIO lines, for clock
+ * and data.  Due to strict timing requirements of the interface,
+ * the serial data stream is read and processed by a FIQ handler.
+ * The resulting words are fetched by this driver from a circular buffer.
+ *
+ * Standard AT keyboard driver (atkbd) is used for handling the keyboard data.
+ * However, when used with the E3 mailboard that producecs non-standard
+ * scancodes, a custom key table must be prepared and loaded from userspace.
+ */
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+
+#include <asm/mach-types.h>
+#include <plat/board-ams-delta.h>
+
+#include <mach/ams-delta-fiq.h>
+
+MODULE_AUTHOR("Matt Callow");
+MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
+MODULE_LICENSE("GPL");
+
+static struct serio *ams_delta_serio;
+
+static int check_data(int data)
+{
+	int i, parity = 0;
+
+	/* check valid stop bit */
+	if (!(data & 0x400)) {
+		dev_warn(&ams_delta_serio->dev,
+				"invalid stop bit, data=0x%X\n",
+				data);
+		return SERIO_FRAME;
+	}
+	/* calculate the parity */
+	for (i = 1; i < 10; i++) {
+		if (data & (1 << i))
+			parity++;
+	}
+	/* it should be odd */
+	if (!(parity & 0x01)) {
+		dev_warn(&ams_delta_serio->dev,
+				"paritiy check failed, data=0x%X parity=0x%X\n",
+				data, parity);
+		return SERIO_PARITY;
+	}
+	return 0;
+}
+
+static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
+{
+	int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
+	int data, dfl;
+	u8 scancode;
+
+	fiq_buffer[FIQ_IRQ_PEND] = 0;
+
+	/*
+	 * Read data from the circular buffer, check it
+	 * and then pass it on the serio
+	 */
+	while (fiq_buffer[FIQ_KEYS_CNT] > 0) {
+
+		data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++];
+		fiq_buffer[FIQ_KEYS_CNT]--;
+		if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
+			fiq_buffer[FIQ_HEAD_OFFSET] = 0;
+
+		dfl = check_data(data);
+		scancode = (u8) (data >> 1) & 0xFF;
+		serio_interrupt(ams_delta_serio, scancode, dfl);
+	}
+	return IRQ_HANDLED;
+}
+
+static int ams_delta_serio_open(struct serio *serio)
+{
+	/* enable keyboard */
+	ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR,
+			AMD_DELTA_LATCH2_KEYBRD_PWR);
+
+	return 0;
+}
+
+static void ams_delta_serio_close(struct serio *serio)
+{
+	/* disable keyboard */
+	ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, 0);
+}
+
+static int __init ams_delta_serio_init(void)
+{
+	int err;
+
+	if (!machine_is_ams_delta())
+		return -ENODEV;
+
+	ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ams_delta_serio)
+		return -ENOMEM;
+
+	ams_delta_serio->id.type = SERIO_8042;
+	ams_delta_serio->open = ams_delta_serio_open;
+	ams_delta_serio->close = ams_delta_serio_close;
+	strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
+			sizeof(ams_delta_serio->name));
+	strlcpy(ams_delta_serio->phys, "GPIO/serio0",
+			sizeof(ams_delta_serio->phys));
+
+	err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_DATA, "serio-data");
+	if (err) {
+		pr_err("ams_delta_serio: Couldn't request gpio pin for data\n");
+		goto serio;
+	}
+	gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
+
+	err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_CLK, "serio-clock");
+	if (err) {
+		pr_err("ams_delta_serio: couldn't request gpio pin for clock\n");
+		goto gpio_data;
+	}
+	gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
+
+	err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
+			ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
+			"ams-delta-serio", 0);
+	if (err < 0) {
+		pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
+				gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
+		goto gpio_clk;
+	}
+	/*
+	 * Since GPIO register handling for keyboard clock pin is performed
+	 * at FIQ level, switch back from edge to simple interrupt handler
+	 * to avoid bad interaction.
+	 */
+	set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
+			handle_simple_irq);
+
+	serio_register_port(ams_delta_serio);
+	dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
+
+	return 0;
+gpio_clk:
+	gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
+gpio_data:
+	gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
+serio:
+	kfree(ams_delta_serio);
+	return err;
+}
+module_init(ams_delta_serio_init);
+
+static void __exit ams_delta_serio_exit(void)
+{
+	serio_unregister_port(ams_delta_serio);
+	free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
+	gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
+	gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
+	kfree(ams_delta_serio);
+}
+module_exit(ams_delta_serio_exit);