Merge branch 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block

* 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block:
  [PATCH] splice: fix page stealing LRU handling.
  [PATCH] splice: page stealing needs to wait_on_page_writeback()
  [PATCH] splice: export generic_splice_sendpage
  [PATCH] splice: add a SPLICE_F_MORE flag
  [PATCH] splice: add comments documenting more of the code
  [PATCH] splice: improve writeback and clean up page stealing
  [PATCH] splice: fix shadow[] filling logic
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 7d87dd7..5a2882d 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -2,7 +2,7 @@
 # This makefile is used to generate the kernel documentation,
 # primarily based on in-line comments in various source files.
 # See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
-# to ducument the SRC - and how to read it.
+# to document the SRC - and how to read it.
 # To add a new book the only step required is to add the book to the
 # list of DOCBOOKS.
 
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 8c9c670..ca02e04 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -322,7 +322,6 @@
   <chapter id="sysfs">
      <title>The Filesystem for Exporting Kernel Objects</title>
 !Efs/sysfs/file.c
-!Efs/sysfs/dir.c
 !Efs/sysfs/symlink.c
 !Efs/sysfs/bin.c
   </chapter>
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
index 744f1ae..38040fa 100644
--- a/Documentation/acpi-hotkey.txt
+++ b/Documentation/acpi-hotkey.txt
@@ -30,7 +30,7 @@
 echo "event_num:event_type:event_argument" > 
 	/proc/acpi/hotkey/action.
 The result of the execution of this aml method is 
-attached to /proc/acpi/hotkey/poll_method, which is dnyamically
+attached to /proc/acpi/hotkey/poll_method, which is dynamically
 created.  Please use command "cat /proc/acpi/hotkey/polling_method" 
 to retrieve it.
 
diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt
index 0ed9b0a..8b0a5fc 100644
--- a/Documentation/fujitsu/frv/kernel-ABI.txt
+++ b/Documentation/fujitsu/frv/kernel-ABI.txt
@@ -1,17 +1,19 @@
-				 =================================
-				 INTERNAL KERNEL ABI FOR FR-V ARCH
-				 =================================
+			=================================
+			INTERNAL KERNEL ABI FOR FR-V ARCH
+			=================================
 
-The internal FRV kernel ABI is not quite the same as the userspace ABI. A number of the registers
-are used for special purposed, and the ABI is not consistent between modules vs core, and MMU vs
-no-MMU.
+The internal FRV kernel ABI is not quite the same as the userspace ABI. A
+number of the registers are used for special purposed, and the ABI is not
+consistent between modules vs core, and MMU vs no-MMU.
 
-This partly stems from the fact that FRV CPUs do not have a separate supervisor stack pointer, and
-most of them do not have any scratch registers, thus requiring at least one general purpose
-register to be clobbered in such an event. Also, within the kernel core, it is possible to simply
-jump or call directly between functions using a relative offset. This cannot be extended to modules
-for the displacement is likely to be too far. Thus in modules the address of a function to call
-must be calculated in a register and then used, requiring two extra instructions.
+This partly stems from the fact that FRV CPUs do not have a separate
+supervisor stack pointer, and most of them do not have any scratch
+registers, thus requiring at least one general purpose register to be
+clobbered in such an event. Also, within the kernel core, it is possible to
+simply jump or call directly between functions using a relative offset.
+This cannot be extended to modules for the displacement is likely to be too
+far. Thus in modules the address of a function to call must be calculated
+in a register and then used, requiring two extra instructions.
 
 This document has the following sections:
 
@@ -39,7 +41,8 @@
 CPU OPERATING MODES
 ===================
 
-The FR-V CPU has three basic operating modes. In order of increasing capability:
+The FR-V CPU has three basic operating modes. In order of increasing
+capability:
 
   (1) User mode.
 
@@ -47,42 +50,46 @@
 
   (2) Kernel mode.
 
-      Normal kernel mode. There are many additional control registers available that may be
-      accessed in this mode, in addition to all the stuff available to user mode. This has two
-      submodes:
+      Normal kernel mode. There are many additional control registers
+      available that may be accessed in this mode, in addition to all the
+      stuff available to user mode. This has two submodes:
 
       (a) Exceptions enabled (PSR.T == 1).
 
-      	  Exceptions will invoke the appropriate normal kernel mode handler. On entry to the
-      	  handler, the PSR.T bit will be cleared.
+	  Exceptions will invoke the appropriate normal kernel mode
+	  handler. On entry to the handler, the PSR.T bit will be cleared.
 
       (b) Exceptions disabled (PSR.T == 0).
 
-      	  No exceptions or interrupts may happen. Any mandatory exceptions will cause the CPU to
-      	  halt unless the CPU is told to jump into debug mode instead.
+	  No exceptions or interrupts may happen. Any mandatory exceptions
+	  will cause the CPU to halt unless the CPU is told to jump into
+	  debug mode instead.
 
   (3) Debug mode.
 
-      No exceptions may happen in this mode. Memory protection and management exceptions will be
-      flagged for later consideration, but the exception handler won't be invoked. Debugging traps
-      such as hardware breakpoints and watchpoints will be ignored. This mode is entered only by
-      debugging events obtained from the other two modes.
+      No exceptions may happen in this mode. Memory protection and
+      management exceptions will be flagged for later consideration, but
+      the exception handler won't be invoked. Debugging traps such as
+      hardware breakpoints and watchpoints will be ignored. This mode is
+      entered only by debugging events obtained from the other two modes.
 
-      All kernel mode registers may be accessed, plus a few extra debugging specific registers.
+      All kernel mode registers may be accessed, plus a few extra debugging
+      specific registers.
 
 
 =================================
 INTERNAL KERNEL-MODE REGISTER ABI
 =================================
 
-There are a number of permanent register assignments that are set up by entry.S in the exception
-prologue. Note that there is a complete set of exception prologues for each of user->kernel
-transition and kernel->kernel transition. There are also user->debug and kernel->debug mode
-transition prologues.
+There are a number of permanent register assignments that are set up by
+entry.S in the exception prologue. Note that there is a complete set of
+exception prologues for each of user->kernel transition and kernel->kernel
+transition. There are also user->debug and kernel->debug mode transition
+prologues.
 
 
 	REGISTER	FLAVOUR	USE
-	===============	=======	====================================================
+	===============	=======	==============================================
 	GR1			Supervisor stack pointer
 	GR15			Current thread info pointer
 	GR16			GP-Rel base register for small data
@@ -92,10 +99,12 @@
 	GR31		NOMMU	Destroyed by debug mode entry
 	GR31		MMU	Destroyed by TLB miss kernel mode entry
 	CCR.ICC2		Virtual interrupt disablement tracking
-	CCCR.CC3		Cleared by exception prologue (atomic op emulation)
+	CCCR.CC3		Cleared by exception prologue 
+				(atomic op emulation)
 	SCR0		MMU	See mmu-layout.txt.
 	SCR1		MMU	See mmu-layout.txt.
-	SCR2		MMU	Save for EAR0 (destroyed by icache insns in debug mode)
+	SCR2		MMU	Save for EAR0 (destroyed by icache insns 
+					       in debug mode)
 	SCR3		MMU	Save for GR31 during debug exceptions
 	DAMR/IAMR	NOMMU	Fixed memory protection layout.
 	DAMR/IAMR	MMU	See mmu-layout.txt.
@@ -104,18 +113,21 @@
 Certain registers are also used or modified across function calls:
 
 	REGISTER	CALL				RETURN
-	===============	===============================	===============================
+	===============	===============================	======================
 	GR0		Fixed Zero			-
 	GR2		Function call frame pointer
 	GR3		Special				Preserved
 	GR3-GR7		-				Clobbered
-	GR8		Function call arg #1		Return value (or clobbered)
-	GR9		Function call arg #2		Return value MSW (or clobbered)
+	GR8		Function call arg #1		Return value 
+							(or clobbered)
+	GR9		Function call arg #2		Return value MSW 
+							(or clobbered)
 	GR10-GR13	Function call arg #3-#6		Clobbered
 	GR14		-				Clobbered
 	GR15-GR16	Special				Preserved
 	GR17-GR27	-				Preserved
-	GR28-GR31	Special				Only accessed explicitly
+	GR28-GR31	Special				Only accessed 
+							explicitly
 	LR		Return address after CALL	Clobbered
 	CCR/CCCR	-				Mostly Clobbered
 
@@ -124,46 +136,53 @@
 INTERNAL DEBUG-MODE REGISTER ABI
 ================================
 
-This is the same as the kernel-mode register ABI for functions calls. The difference is that in
-debug-mode there's a different stack and a different exception frame. Almost all the global
-registers from kernel-mode (including the stack pointer) may be changed.
+This is the same as the kernel-mode register ABI for functions calls. The
+difference is that in debug-mode there's a different stack and a different
+exception frame. Almost all the global registers from kernel-mode
+(including the stack pointer) may be changed.
 
 	REGISTER	FLAVOUR	USE
-	===============	=======	====================================================
+	===============	=======	==============================================
 	GR1			Debug stack pointer
 	GR16			GP-Rel base register for small data
-	GR31			Current debug exception frame pointer (__debug_frame)
+	GR31			Current debug exception frame pointer 
+				(__debug_frame)
 	SCR3		MMU	Saved value of GR31
 
 
-Note that debug mode is able to interfere with the kernel's emulated atomic ops, so it must be
-exceedingly careful not to do any that would interact with the main kernel in this regard. Hence
-the debug mode code (gdbstub) is almost completely self-contained. The only external code used is
-the sprintf family of functions.
+Note that debug mode is able to interfere with the kernel's emulated atomic
+ops, so it must be exceedingly careful not to do any that would interact
+with the main kernel in this regard. Hence the debug mode code (gdbstub) is
+almost completely self-contained. The only external code used is the
+sprintf family of functions.
 
-Futhermore, break.S is so complicated because single-step mode does not switch off on entry to an
-exception. That means unless manually disabled, single-stepping will blithely go on stepping into
-things like interrupts. See gdbstub.txt for more information.
+Futhermore, break.S is so complicated because single-step mode does not
+switch off on entry to an exception. That means unless manually disabled,
+single-stepping will blithely go on stepping into things like interrupts.
+See gdbstub.txt for more information.
 
 
 ==========================
 VIRTUAL INTERRUPT HANDLING
 ==========================
 
-Because accesses to the PSR is so slow, and to disable interrupts we have to access it twice (once
-to read and once to write), we don't actually disable interrupts at all if we don't have to. What
-we do instead is use the ICC2 condition code flags to note virtual disablement, such that if we
-then do take an interrupt, we note the flag, really disable interrupts, set another flag and resume
-execution at the point the interrupt happened. Setting condition flags as a side effect of an
-arithmetic or logical instruction is really fast. This use of the ICC2 only occurs within the
+Because accesses to the PSR is so slow, and to disable interrupts we have
+to access it twice (once to read and once to write), we don't actually
+disable interrupts at all if we don't have to. What we do instead is use
+the ICC2 condition code flags to note virtual disablement, such that if we
+then do take an interrupt, we note the flag, really disable interrupts, set
+another flag and resume execution at the point the interrupt happened.
+Setting condition flags as a side effect of an arithmetic or logical
+instruction is really fast. This use of the ICC2 only occurs within the
 kernel - it does not affect userspace.
 
 The flags we use are:
 
  (*) CCR.ICC2.Z [Zero flag]
 
-     Set to virtually disable interrupts, clear when interrupts are virtually enabled. Can be
-     modified by logical instructions without affecting the Carry flag.
+     Set to virtually disable interrupts, clear when interrupts are
+     virtually enabled. Can be modified by logical instructions without
+     affecting the Carry flag.
 
  (*) CCR.ICC2.C [Carry flag]
 
@@ -176,8 +195,9 @@
 
 	ICC2.Z is 0, ICC2.C is 1.
 
- (2) An interrupt occurs. The exception prologue examines ICC2.Z and determines that nothing needs
-     doing. This is done simply with an unlikely BEQ instruction.
+ (2) An interrupt occurs. The exception prologue examines ICC2.Z and
+     determines that nothing needs doing. This is done simply with an
+     unlikely BEQ instruction.
 
  (3) The interrupts are disabled (local_irq_disable)
 
@@ -187,48 +207,56 @@
 
 	ICC2.Z would be set to 0.
 
-     A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would be used to trap if
-     interrupts were now virtually enabled, but physically disabled - which they're not, so the
-     trap isn't taken. The kernel would then be back to state (1).
+     A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
+     be used to trap if interrupts were now virtually enabled, but
+     physically disabled - which they're not, so the trap isn't taken. The
+     kernel would then be back to state (1).
 
- (5) An interrupt occurs. The exception prologue examines ICC2.Z and determines that the interrupt
-     shouldn't actually have happened. It jumps aside, and there disabled interrupts by setting
-     PSR.PIL to 14 and then it clears ICC2.C.
+ (5) An interrupt occurs. The exception prologue examines ICC2.Z and
+     determines that the interrupt shouldn't actually have happened. It
+     jumps aside, and there disabled interrupts by setting PSR.PIL to 14
+     and then it clears ICC2.C.
 
  (6) If interrupts were then saved and disabled again (local_irq_save):
 
-	ICC2.Z would be shifted into the save variable and masked off (giving a 1).
+	ICC2.Z would be shifted into the save variable and masked off 
+	(giving a 1).
 
-	ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be unaffected (ie: 0).
+	ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
+	unaffected (ie: 0).
 
  (7) If interrupts were then restored from state (6) (local_irq_restore):
 
-	ICC2.Z would be set to indicate the result of XOR'ing the saved value (ie: 1) with 1, which
-	gives a result of 0 - thus leaving ICC2.Z set.
+	ICC2.Z would be set to indicate the result of XOR'ing the saved
+	value (ie: 1) with 1, which gives a result of 0 - thus leaving
+	ICC2.Z set.
 
 	ICC2.C would remain unaffected (ie: 0).
 
-     A TIHI #2 instruction would be used to again assay the current state, but this would do
-     nothing as Z==1.
+     A TIHI #2 instruction would be used to again assay the current state,
+     but this would do nothing as Z==1.
 
  (8) If interrupts were then enabled (local_irq_enable):
 
-	ICC2.Z would be cleared. ICC2.C would be left unaffected. Both flags would now be 0.
+	ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
+	flags would now be 0.
 
-     A TIHI #2 instruction again issued to assay the current state would then trap as both Z==0
-     [interrupts virtually enabled] and C==0 [interrupts really disabled] would then be true.
+     A TIHI #2 instruction again issued to assay the current state would
+     then trap as both Z==0 [interrupts virtually enabled] and C==0
+     [interrupts really disabled] would then be true.
 
- (9) The trap #2 handler would simply enable hardware interrupts (set PSR.PIL to 0), set ICC2.C to
-     1 and return.
+ (9) The trap #2 handler would simply enable hardware interrupts 
+     (set PSR.PIL to 0), set ICC2.C to 1 and return.
 
 (10) Immediately upon returning, the pending interrupt would be taken.
 
-(11) The interrupt handler would take the path of actually processing the interrupt (ICC2.Z is
-     clear, BEQ fails as per step (2)).
+(11) The interrupt handler would take the path of actually processing the
+     interrupt (ICC2.Z is clear, BEQ fails as per step (2)).
 
-(12) The interrupt handler would then set ICC2.C to 1 since hardware interrupts are definitely
-     enabled - or else the kernel wouldn't be here.
+(12) The interrupt handler would then set ICC2.C to 1 since hardware
+     interrupts are definitely enabled - or else the kernel wouldn't be here.
 
 (13) On return from the interrupt handler, things would be back to state (1).
 
-This trap (#2) is only available in kernel mode. In user mode it will result in SIGILL.
+This trap (#2) is only available in kernel mode. In user mode it will
+result in SIGILL.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8cb55c..b3a6187 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1,4 +1,4 @@
-February 2003             Kernel Parameters                     v2.5.59
+                          Kernel Parameters
                           ~~~~~~~~~~~~~~~~~
 
 The following is a consolidated list of the kernel parameters as implemented
@@ -17,9 +17,17 @@
 
 	usbcore.blinkenlights=1
 
-The text in square brackets at the beginning of the description states the
-restrictions on the kernel for the said kernel parameter to be valid. The
-restrictions referred to are that the relevant option is valid if:
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+The parameters listed below are only valid if certain kernel build options were
+enabled and if respective hardware is present. The text in square brackets at
+the beginning of each description states the restrictions within which a
+parameter is applicable:
 
 	ACPI	ACPI support is enabled.
 	ALSA	ALSA sound support is enabled.
@@ -1046,10 +1054,10 @@
 	noltlbs		[PPC] Do not use large page/tlb entries for kernel
 			lowmem mapping on PPC40x.
 
-	nomce		[IA-32] Machine Check Exception
-
 	nomca		[IA-64] Disable machine check abort handling
 
+	nomce		[IA-32] Machine Check Exception
+
 	noresidual	[PPC] Don't use residual data on PReP machines.
 
 	noresume	[SWSUSP] Disables resume and restores original swap
@@ -1682,20 +1690,6 @@
 
 
 ______________________________________________________________________
-Changelog:
-
-2000-06-??	Mr. Unknown
-	The last known update (for 2.4.0) - the changelog was not kept before.
-
-2002-11-24	Petr Baudis <pasky@ucw.cz>
-		Randy Dunlap <randy.dunlap@verizon.net>
-	Update for 2.5.49, description for most of the options introduced,
-	references to other documentation (C files, READMEs, ..), added S390,
-	PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and
-	reformatting.
-
-2005-10-19	Randy Dunlap <rdunlap@xenotime.net>
-	Lots of typos, whitespace, some reformatting.
 
 TODO:
 
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 4fc8e98..aaf99d5 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -254,7 +254,7 @@
 
 	<block number> * <block size> / <frame size>
 
-Suposse the following parameters, which apply for 2.6 kernel and an
+Suppose the following parameters, which apply for 2.6 kernel and an
 i386 architecture:
 
 	<size-max> = 131072 bytes
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index ec3d109..76750fb 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -138,7 +138,7 @@
 ethernet frames when using tap.
 
 5. What is the difference between BPF and TUN/TAP driver?
-BFP is an advanced packet filter. It can be attached to existing
+BPF is an advanced packet filter. It can be attached to existing
 network interface. It does not provide a virtual network interface.
 A TUN/TAP driver does provide a virtual network interface and it is possible
 to attach BPF to this interface.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 1def604..0ee2c7d 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -120,6 +120,34 @@
     enable  	- enable card
 		- Default: enabled, for PCI and ISA PnP cards
 
+  Module snd-adlib
+  ----------------
+
+    Module for AdLib FM cards.
+
+    port	- port # for OPL chip
+
+    This module supports multiple cards. It does not support autoprobe, so
+    the port must be specified. For actual AdLib FM cards it will be 0x388.
+    Note that this card does not have PCM support and no mixer; only FM
+    synthesis.
+
+    Make sure you have "sbiload" from the alsa-tools package available and,
+    after loading the module, find out the assigned ALSA sequencer port
+    number through "sbiload -l". Example output:
+
+      Port     Client name                       Port name
+      64:0     OPL2 FM synth                     OPL2 FM Port
+
+    Load the std.sb and drums.sb patches also supplied by sbiload:
+
+      sbiload -p 64:0 std.sb drums.sb
+
+    If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
+    instead. To have the card produce sound, use aplaymidi from alsa-utils:
+
+      aplaymidi -p 64:0 foo.mid
+
   Module snd-ad1816a
   ------------------
 
@@ -190,6 +218,15 @@
 
     The power-management is supported.
 
+  Module snd-als300
+  -----------------
+
+    Module for  Avance Logic ALS300 and ALS300+
+
+    This module supports multiple cards.
+
+    The power-management is supported.
+
   Module snd-als4000
   ------------------
 
@@ -701,6 +738,7 @@
 	  uniwill	3-jack
 	  F1734		2-jack
 	  lg		LG laptop (m1 express dual)
+	  lg-lw		LG LW20 laptop
 	  test		for testing/debugging purpose, almost all controls can be
 			adjusted.  Appearing only when compiled with
 			$CONFIG_SND_DEBUG=y
@@ -1013,6 +1051,23 @@
 
     The power-management is supported.
 
+  Module snd-miro
+  ---------------
+
+    Module for Miro soundcards: miroSOUND PCM 1 pro, 
+				miroSOUND PCM 12,
+				miroSOUND PCM 20 Radio.
+
+    port	- Port # (0x530,0x604,0xe80,0xf40)
+    irq		- IRQ # (5,7,9,10,11)
+    dma1	- 1st dma # (0,1,3)
+    dma2	- 2nd dma # (0,1)
+    mpu_port	- MPU-401 port # (0x300,0x310,0x320,0x330)
+    mpu_irq	- MPU-401 irq # (5,7,9,10)
+    fm_port	- FM Port # (0x388)
+    wss		- enable WSS mode
+    ide		- enable onboard ide support
+
   Module snd-mixart
   -----------------
 
@@ -1202,6 +1257,20 @@
 
     The power-management is supported.
 
+  Module snd-riptide
+  ------------------
+
+    Module for Conexant Riptide chip
+
+      joystick_port	- Joystick port # (default: 0x200)
+      mpu_port		- MPU401 port # (default: 0x330)
+      opl3_port		- OPL3 port # (default: 0x388)
+
+    This module supports multiple cards.
+    The driver requires the firmware loader support on kernel.
+    You need to install the firmware file "riptide.hex" to the standard
+    firmware path (e.g. /lib/firmware).
+
   Module snd-rme32
   ----------------
 
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 1fe73d1..9e1c1cc 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -379,7 +379,7 @@
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
 CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
 
 #
 # NAND Flash Device Drivers
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index b7d934c..6e0805a 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -370,7 +370,7 @@
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
 CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
 
 #
 # NAND Flash Device Drivers
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 1574941..ee083b3 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -100,23 +100,12 @@
 #endif
 
 	/* string / mem functions */
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(__memzero);
 
@@ -190,8 +179,6 @@
 
 	/* syscalls */
 EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7cd280..4375284 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -252,6 +252,9 @@
 			dump_cache("cache", cpu, CACHE_ISIZE(info));
 		}
 	}
+
+	if (arch_is_coherent())
+		printk("Cache coherency enabled\n");
 }
 
 int cpu_architecture(void)
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index 75e6ee3..ef88c41 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -16,11 +16,12 @@
 #obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
 
 # LEDs support
-#led-$(CONFIG_ARCH_AT91RM9200DK)	+= leds.o
-#led-$(CONFIG_MACH_AT91RM9200EK)	+= leds.o
-#led-$(CONFIG_MACH_CSB337)	+= leds.o
-#led-$(CONFIG_MACH_CSB637)	+= leds.o
+led-$(CONFIG_ARCH_AT91RM9200DK)	+= leds.o
+led-$(CONFIG_MACH_AT91RM9200EK)	+= leds.o
+led-$(CONFIG_MACH_CSB337)	+= leds.o
+led-$(CONFIG_MACH_CSB637)	+= leds.o
 #led-$(CONFIG_MACH_KB9200)	+= leds.o
+#led-$(CONFIG_MACH_KAFA)	+= leds.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # VGA support
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 54022e5..f45104c 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -67,6 +67,9 @@
 	/* Initialize clocks: 3.6864 MHz crystal */
 	at91_clock_init(3686400);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = CSB337_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index 8195f9d..f2c2d6e 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -67,6 +67,9 @@
 	/* Initialize clocks: 3.6864 MHz crystal */
 	at91_clock_init(3686400);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = CSB637_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 8a78336..2d7200e 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -70,6 +70,9 @@
 	/* Initialize clocks: 18.432 MHz crystal */
 	at91_clock_init(18432000);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = DK_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
@@ -118,9 +121,14 @@
 	at91_add_device_udc(&dk_udc_data);
 	/* Compact Flash */
 	at91_add_device_cf(&dk_cf_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	/* DataFlash card */
+	at91_set_gpio_output(AT91_PIN_PB7, 0);
+#else
 	/* MMC */
-	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
 	at91_add_device_mmc(&dk_mmc_data);
+#endif
 	/* VGA */
 //	dk_add_device_video();
 }
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index fd0752e..80d90f5 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -70,6 +70,9 @@
 	/* Initialize clocks: 18.432 MHz crystal */
 	at91_clock_init(18432000);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = EK_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
@@ -111,9 +114,14 @@
 	at91_add_device_usbh(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	/* DataFlash card */
+	at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
 	/* MMC */
-	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
 	at91_add_device_mmc(&ek_mmc_data);
+#endif
 	/* VGA */
 //	ek_add_device_video();
 }
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index 57eedd5..1781b8f 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -28,10 +28,10 @@
 static u64 ohci_dmamask = 0xffffffffUL;
 static struct at91_usbh_data usbh_data;
 
-static struct resource at91rm9200_usbh_resource[] = {
+static struct resource at91_usbh_resource[] = {
 	[0] = {
 		.start	= AT91_UHP_BASE,
-		.end	= AT91_UHP_BASE + SZ_1M -1,
+		.end	= AT91_UHP_BASE + SZ_1M - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -49,8 +49,8 @@
 				.coherent_dma_mask	= 0xffffffff,
 				.platform_data		= &usbh_data,
 	},
-	.resource	= at91rm9200_usbh_resource,
-	.num_resources	= ARRAY_SIZE(at91rm9200_usbh_resource),
+	.resource	= at91_usbh_resource,
+	.num_resources	= ARRAY_SIZE(at91_usbh_resource),
 };
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -121,6 +121,19 @@
 static u64 eth_dmamask = 0xffffffffUL;
 static struct at91_eth_data eth_data;
 
+static struct resource at91_eth_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_EMAC,
+		.end	= AT91_BASE_EMAC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_EMAC,
+		.end	= AT91_ID_EMAC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 static struct platform_device at91rm9200_eth_device = {
 	.name		= "at91_ether",
 	.id		= -1,
@@ -129,7 +142,8 @@
 				.coherent_dma_mask	= 0xffffffff,
 				.platform_data		= &eth_data,
 	},
-	.num_resources	= 0,
+	.resource	= at91_eth_resources,
+	.num_resources	= ARRAY_SIZE(at91_eth_resources),
 };
 
 void __init at91_add_device_eth(struct at91_eth_data *data)
@@ -224,15 +238,20 @@
 static struct at91_mmc_data mmc_data;
 
 static struct resource at91_mmc_resources[] = {
-	{
+	[0] = {
 		.start	= AT91_BASE_MCI,
 		.end	= AT91_BASE_MCI + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= AT91_ID_MCI,
+		.end	= AT91_ID_MCI,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device at91rm9200_mmc_device = {
-	.name		= "at91rm9200_mci",
+	.name		= "at91_mci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -290,4 +309,123 @@
 void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+static struct resource at91_nand_resources[] = {
+	{
+		.start	= AT91_SMARTMEDIA_BASE,
+		.end	= AT91_SMARTMEDIA_BASE + SZ_8M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91_nand_device = {
+	.name		= "at91_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= at91_nand_resources,
+	.num_resources	= ARRAY_SIZE(at91_nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+	if (!data)
+		return;
+
+	/* enable pin */
+	if (data->enable_pin)
+		at91_set_gpio_output(data->enable_pin, 1);
+
+	/* ready/busy pin */
+	if (data->rdy_pin)
+		at91_set_gpio_input(data->rdy_pin, 1);
+
+	/* card detect pin */
+	if (data->det_pin)
+		at91_set_gpio_input(data->det_pin, 1);
+
+	at91_set_A_periph(AT91_PIN_PC1, 0);		/* SMOE */
+	at91_set_A_periph(AT91_PIN_PC3, 0);		/* SMWE */
+
+	nand_data = *data;
+	platform_device_register(&at91_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+static struct platform_device at91rm9200_twi_device = {
+	.name		= "at91_i2c",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+void __init at91_add_device_i2c(void)
+{
+	/* pins used for TWI interface */
+	at91_set_A_periph(AT91_PIN_PA25, 0);		/* TWD */
+	at91_set_multi_drive(AT91_PIN_PA25, 1);
+
+	at91_set_A_periph(AT91_PIN_PA26, 0);		/* TWCK */
+	at91_set_multi_drive(AT91_PIN_PA26, 1);
+
+	platform_device_register(&at91rm9200_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+	.name		= "at91_rtc",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+void __init at91_add_device_rtc(void)
+{
+	platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+	at91_leds_cpu   = cpu_led;
+	at91_leds_timer = timer_led;
+}
+
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
 /* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c
new file mode 100644
index 0000000..28150e8
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/leds.c
@@ -0,0 +1,100 @@
+/*
+ * LED driver for Atmel AT91-based boards.
+ *
+ *  Copyright (C) SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+static inline void at91_led_on(unsigned int led)
+{
+	at91_set_gpio_value(led, 0);
+}
+
+static inline void at91_led_off(unsigned int led)
+{
+	at91_set_gpio_value(led, 1);
+}
+
+static inline void at91_led_toggle(unsigned int led)
+{
+	unsigned long is_off = at91_get_gpio_value(led);
+	if (is_off)
+		at91_led_on(led);
+	else
+		at91_led_off(led);
+}
+
+
+/*
+ * Handle LED events.
+ */
+static void at91_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch(evt) {
+	case led_start:		/* System startup */
+		at91_led_on(at91_leds_cpu);
+		break;
+
+	case led_stop:		/* System stop / suspend */
+		at91_led_off(at91_leds_cpu);
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:		/* Every 50 timer ticks */
+		at91_led_toggle(at91_leds_timer);
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:	/* Entering idle state */
+		at91_led_off(at91_leds_cpu);
+		break;
+
+	case led_idle_end:	/* Exit idle state */
+		at91_led_on(at91_leds_cpu);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+
+static int __init leds_init(void)
+{
+	if (!at91_leds_timer || !at91_leds_cpu)
+		return -ENODEV;
+
+	/* Enable PIO to access the LEDs */
+	at91_set_gpio_output(at91_leds_timer, 1);
+	at91_set_gpio_output(at91_leds_cpu, 1);
+
+	leds_event = at91_leds_event;
+
+	leds_event(led_start);
+	return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 2d892e4..dcd4176 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -424,6 +424,14 @@
 	.periphid	= 0x00041010,
 };
 
+
+static struct platform_device ep93xx_rtc_device = {
+       .name           = "ep93xx-rtc",
+       .id             = -1,
+       .num_resources  = 0,
+};
+
+
 void __init ep93xx_init_devices(void)
 {
 	unsigned int v;
@@ -439,4 +447,6 @@
 	amba_device_register(&uart1_device, &iomem_resource);
 	amba_device_register(&uart2_device, &iomem_resource);
 	amba_device_register(&uart3_device, &iomem_resource);
+
+	platform_device_register(&ep93xx_rtc_device);
 }
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 777e75d..9be01b0c 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -17,6 +17,8 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -39,6 +41,16 @@
 		.pfn		= __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
 		.length		= TS72XX_OPTIONS2_SIZE,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_RTC_INDEX_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
+		.length		= TS72XX_RTC_INDEX_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_RTC_DATA_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+		.length		= TS72XX_RTC_DATA_SIZE,
+		.type		= MT_DEVICE,
 	}
 };
 
@@ -99,11 +111,38 @@
 	}
 }
 
+static unsigned char ts72xx_rtc_readb(unsigned long addr)
+{
+	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+	return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr)
+{
+	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+	__raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static struct m48t86_ops ts72xx_rtc_ops = {
+	.readb			= ts72xx_rtc_readb,
+	.writeb			= ts72xx_rtc_writeb,
+};
+
+static struct platform_device ts72xx_rtc_device = {
+	.name			= "rtc-m48t86",
+	.id			= -1,
+	.dev			= {
+		.platform_data		= &ts72xx_rtc_ops,
+	},
+	.num_resources		= 0,
+};
+
 static void __init ts72xx_init_machine(void)
 {
 	ep93xx_init_devices();
 	if (board_is_ts7200())
 		physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+	platform_device_register(&ts72xx_rtc_device);
 }
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 71a59e1..4ca51dc 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -7,11 +7,18 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *
- *  03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ *  2004-03-03 Sascha Hauer <sascha@saschahauer.de>
  *             initial version heavily inspired by
  *             linux/arch/arm/mach-pxa/dma.c
+ *
+ *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Changed to support scatter gather DMA
+ *             by taking Russell's code from RiscPC
+ *
  */
 
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -22,69 +29,368 @@
 #include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/dma.h>
+#include <asm/arch/imx-dma.h>
 
-static struct dma_channel {
-	char *name;
-	void (*irq_handler) (int, void *, struct pt_regs *);
-	void (*err_handler) (int, void *, struct pt_regs *);
-	void *data;
-} dma_channels[11];
+struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
 
-/* set err_handler to NULL to have the standard info-only error handler */
-int
-imx_request_dma(char *name, imx_dma_prio prio,
-		void (*irq_handler) (int, void *, struct pt_regs *),
-		void (*err_handler) (int, void *, struct pt_regs *), void *data)
+/*
+ * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @lastcount: number of bytes transferred during last transfer
+ *
+ * Functions prepares DMA controller for next sg data chunk transfer.
+ * The @lastcount argument informs function about number of bytes transferred
+ * during last block. Zero value can be used for @lastcount to setup DMA
+ * for the first chunk.
+ */
+static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount)
 {
-	unsigned long flags;
-	int i, found = 0;
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned int nextcount;
+	unsigned int nextaddr;
 
-	/* basic sanity checks */
-	if (!name || !irq_handler)
-		return -EINVAL;
+	if (!imxdma->name) {
+		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return 0;
+	}
 
-	local_irq_save(flags);
+	imxdma->resbytes -= lastcount;
 
-	/* try grabbing a DMA channel with the requested priority */
-	for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
-		if (!dma_channels[i].name) {
-			found = 1;
-			break;
+	if (!imxdma->sg) {
+		pr_debug("imxdma%d: no sg data\n", dma_ch);
+		return 0;
+	}
+
+	imxdma->sgbc += lastcount;
+	if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) {
+		if ((imxdma->sgcount <= 1) || !imxdma->resbytes) {
+			pr_debug("imxdma%d: sg transfer limit reached\n",
+				 dma_ch);
+			imxdma->sgcount=0;
+			imxdma->sg = NULL;
+			return 0;
+		} else {
+			imxdma->sgcount--;
+			imxdma->sg++;
+			imxdma->sgbc = 0;
 		}
 	}
+	nextcount = imxdma->sg->length - imxdma->sgbc;
+	nextaddr = imxdma->sg->dma_address + imxdma->sgbc;
 
-	if (!found) {
-		/* requested prio group is full, try hier priorities */
-		for (i = prio - 1; i >= 0; i--) {
-			if (!dma_channels[i].name) {
-				found = 1;
-				break;
-			}
-		}
-	}
+	if(imxdma->resbytes < nextcount)
+		nextcount = imxdma->resbytes;
 
-	if (found) {
-		DIMR &= ~(1 << i);
-		dma_channels[i].name = name;
-		dma_channels[i].irq_handler = irq_handler;
-		dma_channels[i].err_handler = err_handler;
-		dma_channels[i].data = data;
-	} else {
-		printk(KERN_WARNING "No more available DMA channels for %s\n",
-		       name);
-		i = -ENODEV;
-	}
+	if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
+		DAR(dma_ch) = nextaddr;
+	else
+		SAR(dma_ch) = nextaddr;
 
-	local_irq_restore(flags);
-	return i;
+	CNTR(dma_ch) = nextcount;
+	pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n",
+		 dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch));
+
+	return nextcount;
 }
 
-void
-imx_free_dma(int dma_ch)
+/*
+ * imx_dma_setup_sg_base - scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ *
+ * Functions sets up i.MX DMA state for emulated scatter-gather transfer
+ * and sets up channel registers to be ready for the first chunk
+ */
+static int
+imx_dma_setup_sg_base(imx_dmach_t dma_ch,
+		      struct scatterlist *sg, unsigned int sgcount)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	imxdma->sg = sg;
+	imxdma->sgcount = sgcount;
+	imxdma->sgbc = 0;
+	return imx_dma_sg_next(dma_ch, 0);
+}
+
+/**
+ * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @dma_address: the DMA/physical memory address of the linear data block
+ *		to transfer
+ * @dma_length: length of the data block in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ *           or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel source and destination addresses for transfer
+ * specified by provided parameters. The scatter-gather emulation is disabled,
+ * because linear data block
+ * form the physical address range is transfered.
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ *		Zero indicates success.
+ */
+int
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+		     unsigned int dma_length, unsigned int dev_addr,
+		     dmamode_t dmamode)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	imxdma->sg = NULL;
+	imxdma->sgcount = 0;
+	imxdma->dma_mode = dmamode;
+	imxdma->resbytes = dma_length;
+
+	if (!dma_address) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if (!dma_length) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+		pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n",
+			dma_ch, (unsigned int)dma_address, dma_length,
+			dev_addr);
+		SAR(dma_ch) = dev_addr;
+		DAR(dma_ch) = (unsigned int)dma_address;
+	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+		pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n",
+			dma_ch, (unsigned int)dma_address, dma_length,
+			dev_addr);
+		SAR(dma_ch) = (unsigned int)dma_address;
+		DAR(dma_ch) = dev_addr;
+	} else {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	CNTR(dma_ch) = dma_length;
+
+	return 0;
+}
+
+/**
+ * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ * @dma_length: total length of the transfer request in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ *           or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel state and registers to be ready for transfer
+ * specified by provided parameters. The scatter-gather emulation is set up
+ * according to the parameters.
+ *
+ * The full preparation of the transfer requires setup of more register
+ * by the caller before imx_dma_enable() can be called.
+ *
+ * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes
+ *
+ * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx
+ *
+ * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical
+ * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified
+ *
+ * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
+ *
+ * The typical setup for %DMA_MODE_WRITE is specified by next options combination
+ *
+ * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
+ *
+ * Be carefull there and do not mistakenly mix source and target device
+ * port sizes constants, they are really different:
+ * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
+ * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
+ *
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+		 struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+		 unsigned int dev_addr, dmamode_t dmamode)
+{
+	int res;
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	imxdma->sg = NULL;
+	imxdma->sgcount = 0;
+	imxdma->dma_mode = dmamode;
+	imxdma->resbytes = dma_length;
+
+	if (!sg || !sgcount) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if (!sg->length) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+		pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n",
+			dma_ch, sg, sgcount, dma_length, dev_addr);
+		SAR(dma_ch) = dev_addr;
+	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+		pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n",
+			dma_ch, sg, sgcount, dma_length, dev_addr);
+		DAR(dma_ch) = dev_addr;
+	} else {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	res = imx_dma_setup_sg_base(dma_ch, sg, sgcount);
+	if (res <= 0) {
+		printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers
+ * @dma_ch: i.MX DMA channel number
+ * @irq_handler: the pointer to the function called if the transfer
+ *		ends successfully
+ * @err_handler: the pointer to the function called if the premature
+ *		end caused by error occurs
+ * @data: user specified value to be passed to the handlers
+ */
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+		       void (*irq_handler) (int, void *, struct pt_regs *),
+		       void (*err_handler) (int, void *, struct pt_regs *),
+		       void *data)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned long flags;
+
+	if (!imxdma->name) {
+		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return -ENODEV;
+	}
+
+	local_irq_save(flags);
+	DISR = (1 << dma_ch);
+	imxdma->irq_handler = irq_handler;
+	imxdma->err_handler = err_handler;
+	imxdma->data = data;
+	local_irq_restore(flags);
+	return 0;
+}
+
+/**
+ * imx_dma_enable - function to start i.MX DMA channel operation
+ * @dma_ch: i.MX DMA channel number
+ *
+ * The channel has to be allocated by driver through imx_dma_request()
+ * or imx_dma_request_by_prio() function.
+ * The transfer parameters has to be set to the channel registers through
+ * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
+ * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to
+ * be set prior this function call by the channel user.
+ */
+void imx_dma_enable(imx_dmach_t dma_ch)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned long flags;
+
+	pr_debug("imxdma%d: imx_dma_enable\n", dma_ch);
+
+	if (!imxdma->name) {
+		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	DISR = (1 << dma_ch);
+	DIMR &= ~(1 << dma_ch);
+	CCR(dma_ch) |= CCR_CEN;
+	local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_disable - stop, finish i.MX DMA channel operatin
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_disable(imx_dmach_t dma_ch)
 {
 	unsigned long flags;
 
-	if (!dma_channels[dma_ch].name) {
+	pr_debug("imxdma%d: imx_dma_disable\n", dma_ch);
+
+	local_irq_save(flags);
+	DIMR |= (1 << dma_ch);
+	CCR(dma_ch) &= ~CCR_CEN;
+	DISR = (1 << dma_ch);
+	local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_request - request/allocate specified channel number
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ */
+int imx_dma_request(imx_dmach_t dma_ch, const char *name)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned long flags;
+
+	/* basic sanity checks */
+	if (!name)
+		return -EINVAL;
+
+	if (dma_ch >= IMX_DMA_CHANNELS) {
+		printk(KERN_CRIT "%s: called for  non-existed channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return -EINVAL;
+	}
+
+	local_irq_save(flags);
+	if (imxdma->name) {
+		local_irq_restore(flags);
+		return -ENODEV;
+	}
+
+	imxdma->name = name;
+	imxdma->irq_handler = NULL;
+	imxdma->err_handler = NULL;
+	imxdma->data = NULL;
+	imxdma->sg = NULL;
+	local_irq_restore(flags);
+	return 0;
+}
+
+/**
+ * imx_dma_free - release previously acquired channel
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_free(imx_dmach_t dma_ch)
+{
+	unsigned long flags;
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	if (!imxdma->name) {
 		printk(KERN_CRIT
 		       "%s: trying to free channel %d which is already freed\n",
 		       __FUNCTION__, dma_ch);
@@ -92,27 +398,84 @@
 	}
 
 	local_irq_save(flags);
-	DIMR &= ~(1 << dma_ch);
-	dma_channels[dma_ch].name = NULL;
+	/* Disable interrupts */
+	DIMR |= (1 << dma_ch);
+	CCR(dma_ch) &= ~CCR_CEN;
+	imxdma->name = NULL;
 	local_irq_restore(flags);
 }
 
-static irqreturn_t
-dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+/**
+ * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ * @prio: one of the hardware distinguished priority level:
+ *        %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW
+ *
+ * This function tries to find free channel in the specified priority group
+ * if the priority cannot be achieved it tries to look for free channel
+ * in the higher and then even lower priority groups.
+ *
+ * Return value: If there is no free channel to allocate, -%ENODEV is returned.
+ *               Zero value indicates successful channel allocation.
+ */
+int
+imx_dma_request_by_prio(imx_dmach_t * pdma_ch, const char *name,
+			imx_dma_prio prio)
+{
+	int i;
+	int best;
+
+	switch (prio) {
+	case (DMA_PRIO_HIGH):
+		best = 8;
+		break;
+	case (DMA_PRIO_MEDIUM):
+		best = 4;
+		break;
+	case (DMA_PRIO_LOW):
+	default:
+		best = 0;
+		break;
+	}
+
+	for (i = best; i < IMX_DMA_CHANNELS; i++) {
+		if (!imx_dma_request(i, name)) {
+			*pdma_ch = i;
+			return 0;
+		}
+	}
+
+	for (i = best - 1; i >= 0; i--) {
+		if (!imx_dma_request(i, name)) {
+			*pdma_ch = i;
+			return 0;
+		}
+	}
+
+	printk(KERN_ERR "%s: no free DMA channel found\n", __FUNCTION__);
+
+	return -ENODEV;
+}
+
+static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i, disr = DISR;
-	struct dma_channel *channel;
+	struct imx_dma_channel *channel;
 	unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
 
 	DISR = disr;
-	for (i = 0; i < 11; i++) {
-		channel = &dma_channels[i];
+	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+		channel = &imx_dma_channels[i];
 
-		if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+		if ((err_mask & 1 << i) && channel->name
+		    && channel->err_handler) {
 			channel->err_handler(i, channel->data, regs);
 			continue;
 		}
 
+		imx_dma_channels[i].sg = NULL;
+
 		if (DBTOSR & (1 << i)) {
 			printk(KERN_WARNING
 			       "Burst timeout on channel %d (%s)\n",
@@ -141,17 +504,27 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i, disr = DISR;
 
+	pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
+		     disr);
+
 	DISR = disr;
-	for (i = 0; i < 11; i++) {
+	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
 		if (disr & (1 << i)) {
-			struct dma_channel *channel = &dma_channels[i];
-			if (channel->name && channel->irq_handler) {
-				channel->irq_handler(i, channel->data, regs);
+			struct imx_dma_channel *channel = &imx_dma_channels[i];
+			if (channel->name) {
+				if (imx_dma_sg_next(i, CNTR(i))) {
+					CCR(i) &= ~CCR_CEN;
+					mb();
+					CCR(i) |= CCR_CEN;
+				} else {
+					if (channel->irq_handler)
+						channel->irq_handler(i,
+							channel->data, regs);
+				}
 			} else {
 				/*
 				 * IRQ for an unregistered DMA channel:
@@ -165,10 +538,10 @@
 	return IRQ_HANDLED;
 }
 
-static int __init
-imx_dma_init(void)
+static int __init imx_dma_init(void)
 {
 	int ret;
+	int i;
 
 	/* reset DMA module */
 	DCR = DCR_DRST;
@@ -189,15 +562,27 @@
 	DCR = DCR_DEN;
 
 	/* clear all interrupts */
-	DISR = 0x3ff;
+	DISR = (1 << IMX_DMA_CHANNELS) - 1;
 
 	/* enable interrupts */
-	DIMR = 0;
+	DIMR = (1 << IMX_DMA_CHANNELS) - 1;
+
+	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+		imx_dma_channels[i].sg = NULL;
+		imx_dma_channels[i].dma_num = i;
+	}
 
 	return ret;
 }
 
 arch_initcall(imx_dma_init);
 
-EXPORT_SYMBOL(imx_request_dma);
-EXPORT_SYMBOL(imx_free_dma);
+EXPORT_SYMBOL(imx_dma_setup_single);
+EXPORT_SYMBOL(imx_dma_setup_sg);
+EXPORT_SYMBOL(imx_dma_setup_handlers);
+EXPORT_SYMBOL(imx_dma_enable);
+EXPORT_SYMBOL(imx_dma_disable);
+EXPORT_SYMBOL(imx_dma_request);
+EXPORT_SYMBOL(imx_dma_free);
+EXPORT_SYMBOL(imx_dma_request_by_prio);
+EXPORT_SYMBOL(imx_dma_channels);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 37613ad6..9d8331b 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -33,6 +33,7 @@
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
+#include <asm/arch/mmc.h>
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -175,13 +176,25 @@
 	},
 };
 
+static u64 imxmmmc_dmamask = 0xffffffffUL;
+
 static struct platform_device imx_mmc_device = {
 	.name		= "imx-mmc",
 	.id		= 0,
+	.dev		= {
+		.dma_mask = &imxmmmc_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
 	.num_resources	= ARRAY_SIZE(imx_mmc_resources),
 	.resource	= imx_mmc_resources,
 };
 
+void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
+{
+	imx_mmc_device.dev.platform_data = info;
+}
+EXPORT_SYMBOL(imx_set_mmc_info);
+
 static struct resource imx_uart1_resources[] = {
 	[0] = {
 		.start	= 0x00206000,
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index 8ab1b04..e34d0df 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -25,6 +25,7 @@
 #include <asm/mach-types.h>
 
 #include <asm/mach/arch.h>
+#include <asm/arch/mmc.h>
 #include <linux/interrupt.h>
 #include "generic.h"
 
@@ -51,12 +52,29 @@
 	&cs89x0_device,
 };
 
+#ifdef CONFIG_MMC_IMX
+static int mx1ads_mmc_card_present(void)
+{
+	/* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */
+	return (SSR(1) & (1 << 20) ? 0 : 1);
+}
+
+static struct imxmmc_platform_data mx1ads_mmc_info = {
+       .card_present = mx1ads_mmc_card_present,
+};
+#endif
+
 static void __init
 mx1ads_init(void)
 {
 #ifdef CONFIG_LEDS
 	imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2);
 #endif
+#ifdef CONFIG_MMC_IMX
+	/* SD/MMC card detect */
+	imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
+	imx_set_mmc_info(&mx1ads_mmc_info);
+#endif
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index 2327c97..bf688c1 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -44,6 +44,15 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/pci.h>
 
+static int __init espresso_pci_init(void)
+{
+	if (machine_is_espresso())
+		ixp23xx_pci_slave_init();
+
+	return 0;
+};
+subsys_initcall(espresso_pci_init);
+
 static void __init espresso_init(void)
 {
 	physmap_configure(0x90000000, 0x02000000, 2, NULL);
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index 5330ad7..ac72f94 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -201,7 +201,7 @@
 	return 0;
 }
 
-void __init ixp23xx_pci_preinit(void)
+static void __init ixp23xx_pci_common_init(void)
 {
 #ifdef __ARMEB__
 	*IXP23XX_PCI_CONTROL |= 0x20000;	/* set I/O swapping */
@@ -219,7 +219,18 @@
 		*IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
 	} else {
 		*IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
+
+		/*
+		 * Enable coherency on A2 silicon.
+		 */
+		if (arch_is_coherent())
+			*IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
 	}
+}
+
+void __init ixp23xx_pci_preinit(void)
+{
+	ixp23xx_pci_common_init();
 
 	hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
 			"PCI config cycle to non-existent device");
@@ -273,3 +284,8 @@
 
 	return 1;
 }
+
+void ixp23xx_pci_slave_init(void)
+{
+	ixp23xx_pci_common_init();
+}
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 86a0f0d..f8d716c 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -69,12 +69,6 @@
 	  Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
 	  such a board.
 
-config MACH_NETSTAR
-	bool "NetStar"
-	depends on ARCH_OMAP1 && ARCH_OMAP15XX
-	help
-	  Support for NetStar PBX. Say Y here if you have such a board.
-
 config MACH_OMAP_PALMTE
 	bool "Palm Tungsten E"
 	depends on ARCH_OMAP1 && ARCH_OMAP15XX
@@ -85,6 +79,20 @@
           informations.
           Say Y here if you have such a PDA, say NO otherwise.
 
+config MACH_NOKIA770
+	bool "Nokia 770"
+	depends on ARCH_OMAP1 && ARCH_OMAP16XX
+	help
+	  Support for the Nokia 770 Internet Tablet. Say Y here if you
+	  have such a device.
+
+config MACH_AMS_DELTA
+	bool "Amstrad E3 (Delta)"
+	depends on ARCH_OMAP1 && ARCH_OMAP15XX
+	help
+	  Support for the Amstrad E3 (codename Delta) videophone. Say Y here
+	  if you have such a device.
+
 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 b0b0015..9ea7195 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,13 @@
 #
 
 # Common support
-obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o
+obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+
+obj-$(CONFIG_OMAP_MPU_TIMER)		+= time.o
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
 led-y := leds.o
 
 # Specific board support
@@ -14,8 +20,9 @@
 obj-$(CONFIG_MACH_OMAP_OSK)		+= board-osk.o
 obj-$(CONFIG_MACH_OMAP_H3)		+= board-h3.o
 obj-$(CONFIG_MACH_VOICEBLUE)		+= board-voiceblue.o
-obj-$(CONFIG_MACH_NETSTAR)		+= board-netstar.o
 obj-$(CONFIG_MACH_OMAP_PALMTE)		+= board-palmte.o
+obj-$(CONFIG_MACH_NOKIA770)		+= board-nokia770.o
+obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o
 
 ifeq ($(CONFIG_ARCH_OMAP15XX),y)
 # Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
new file mode 100644
index 0000000..6178f04
--- /dev/null
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-omap1/board-ams-delta.c
+ *
+ * Modified from board-generic.c
+ *
+ * Board specific inits for the Amstrad E3 (codename Delta) videophone
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board-ams-delta.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+
+static u8 ams_delta_latch1_reg;
+static u16 ams_delta_latch2_reg;
+
+void ams_delta_latch1_write(u8 mask, u8 value)
+{
+	ams_delta_latch1_reg &= ~mask;
+	ams_delta_latch1_reg |= value;
+	*(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg;
+}
+
+void ams_delta_latch2_write(u16 mask, u16 value)
+{
+	ams_delta_latch2_reg &= ~mask;
+	ams_delta_latch2_reg |= value;
+	*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
+}
+
+static void __init ams_delta_init_irq(void)
+{
+	omap1_init_common_hw();
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+static struct map_desc ams_delta_io_desc[] __initdata = {
+	// AMS_DELTA_LATCH1
+	{
+		.virtual	= AMS_DELTA_LATCH1_VIRT,
+		.pfn		= __phys_to_pfn(AMS_DELTA_LATCH1_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	},
+	// AMS_DELTA_LATCH2
+	{
+		.virtual	= AMS_DELTA_LATCH2_VIRT,
+		.pfn		= __phys_to_pfn(AMS_DELTA_LATCH2_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	},
+	// AMS_DELTA_MODEM
+	{
+		.virtual	= AMS_DELTA_MODEM_VIRT,
+		.pfn		= __phys_to_pfn(AMS_DELTA_MODEM_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	}
+};
+
+static struct omap_uart_config ams_delta_uart_config __initdata = {
+	.enabled_uarts = 1,
+};
+
+static struct omap_board_config_kernel ams_delta_config[] = {
+	{ OMAP_TAG_UART,	&ams_delta_uart_config },
+};
+
+static void __init ams_delta_init(void)
+{
+	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+
+	omap_board_config = ams_delta_config;
+	omap_board_config_size = ARRAY_SIZE(ams_delta_config);
+	omap_serial_init();
+
+	/* Clear latch2 (NAND, LCD, modem enable) */
+	ams_delta_latch2_write(~0, 0);
+}
+
+static void __init ams_delta_map_io(void)
+{
+	omap1_map_common_io();
+}
+
+MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
+	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
+	.phys_io	= 0xfff00000,
+	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
+	.boot_params	= 0x10000100,
+	.map_io		= ams_delta_map_io,
+	.init_irq	= ams_delta_init_irq,
+	.init_machine	= ams_delta_init,
+	.timer		= &omap_timer,
+MACHINE_END
+
+EXPORT_SYMBOL(ams_delta_latch1_write);
+EXPORT_SYMBOL(ams_delta_latch2_write);
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index a177e78..33d01ad 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -88,7 +88,7 @@
 static void __init omap_generic_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		generic_config[0].data = &generic1510_usb_config;
 	}
 #endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 89f0cc7..cd3a06d 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -24,7 +24,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -35,12 +37,55 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
 
 extern int omap_gpio_init(void);
 
-static struct mtd_partition h2_partitions[] = {
+static int h2_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_3),
+	KEY(0, 3, KEY_F10),
+	KEY(0, 4, KEY_F5),
+	KEY(0, 5, KEY_9),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_2),
+	KEY(1, 3, KEY_F9),
+	KEY(1, 4, KEY_F7),
+	KEY(1, 5, KEY_0),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_6),
+	KEY(2, 2, KEY_1),
+	KEY(2, 3, KEY_F2),
+	KEY(2, 4, KEY_F6),
+	KEY(2, 5, KEY_HOME),
+	KEY(3, 0, KEY_8),
+	KEY(3, 1, KEY_5),
+	KEY(3, 2, KEY_F12),
+	KEY(3, 3, KEY_F3),
+	KEY(3, 4, KEY_F8),
+	KEY(3, 5, KEY_END),
+	KEY(4, 0, KEY_7),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_F11),
+	KEY(4, 3, KEY_F1),
+	KEY(4, 4, KEY_F4),
+	KEY(4, 5, KEY_ESC),
+	KEY(5, 0, KEY_F13),
+	KEY(5, 1, KEY_F14),
+	KEY(5, 2, KEY_F15),
+	KEY(5, 3, KEY_F16),
+	KEY(5, 4, KEY_SLEEP),
+	0
+};
+
+static struct mtd_partition h2_nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
 	      .name		= "bootloader",
@@ -71,26 +116,26 @@
 	}
 };
 
-static struct flash_platform_data h2_flash_data = {
+static struct flash_platform_data h2_nor_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-	.parts		= h2_partitions,
-	.nr_parts	= ARRAY_SIZE(h2_partitions),
+	.parts		= h2_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(h2_nor_partitions),
 };
 
-static struct resource h2_flash_resource = {
+static struct resource h2_nor_resource = {
 	/* This is on CS3, wherever it's mapped */
 	.flags		= IORESOURCE_MEM,
 };
 
-static struct platform_device h2_flash_device = {
+static struct platform_device h2_nor_device = {
 	.name		= "omapflash",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &h2_flash_data,
+		.platform_data	= &h2_nor_data,
 	},
 	.num_resources	= 1,
-	.resource	= &h2_flash_resource,
+	.resource	= &h2_nor_resource,
 };
 
 static struct resource h2_smc91x_resources[] = {
@@ -113,9 +158,119 @@
 	.resource	= h2_smc91x_resources,
 };
 
+static struct resource h2_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data h2_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = h2_keymap,
+	.rep	= 1,
+};
+
+static struct platform_device h2_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &h2_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(h2_kp_resources),
+	.resource	= h2_kp_resources,
+};
+
+#define H2_IRDA_FIRSEL_GPIO_PIN	17
+
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+static int h2_transceiver_mode(struct device *dev, int state)
+{
+	if (state & IR_SIRMODE)
+		omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+	else    /* MIR/FIR */
+		omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1);
+
+	return 0;
+}
+#endif
+
+static struct omap_irda_config h2_irda_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+	.rx_channel		= OMAP_DMA_UART3_RX,
+	.tx_channel		= OMAP_DMA_UART3_TX,
+	.dest_start		= UART3_THR,
+	.src_start		= UART3_RHR,
+	.tx_trigger		= 0,
+	.rx_trigger		= 0,
+};
+
+static struct resource h2_irda_resources[] = {
+	[0] = {
+		.start	= INT_UART3,
+		.end	= INT_UART3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+static struct platform_device h2_irda_device = {
+	.name		= "omapirda",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &h2_irda_data,
+	},
+	.num_resources	= ARRAY_SIZE(h2_irda_resources),
+	.resource	= h2_irda_resources,
+};
+
+static struct platform_device h2_lcd_device = {
+	.name		= "lcd_h2",
+	.id		= -1,
+};
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+	.spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+	.spcr1 = RINTM(3) | RRST,
+	.rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+                RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+	.rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+	.xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+                XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+	.xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+	.srgr1 = FWID(15),
+	.srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+	.pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+	//.pcr0 = CLKXP | CLKRP,        /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+	.name                   = "H2 TSC2101",
+	.mcbsp_regs_alsa        = &mcbsp_regs,
+	.codec_configure_dev    = NULL, // tsc2101_configure,
+	.codec_set_samplerate   = NULL, // tsc2101_set_samplerate,
+	.codec_clock_setup      = NULL, // tsc2101_clock_setup,
+	.codec_clock_on         = NULL, // tsc2101_clock_on,
+	.codec_clock_off        = NULL, // tsc2101_clock_off,
+	.get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h2_mcbsp1_device = {
+	.name	= "omap_alsa_mcbsp",
+	.id	= 1,
+	.dev = {
+		.platform_data	= &alsa_config,
+	},
+};
+
 static struct platform_device *h2_devices[] __initdata = {
-	&h2_flash_device,
+	&h2_nor_device,
 	&h2_smc91x_device,
+	&h2_irda_device,
+	&h2_kp_device,
+	&h2_lcd_device,
+	&h2_mcbsp1_device,
 };
 
 static void __init h2_init_smc91x(void)
@@ -164,7 +319,6 @@
 };
 
 static struct omap_lcd_config h2_lcd_config __initdata = {
-	.panel_name	= "h2",
 	.ctrl_name	= "internal",
 };
 
@@ -177,16 +331,34 @@
 
 static void __init h2_init(void)
 {
-	/* NOTE: revC boards support NAND-boot, which can put NOR on CS2B
-	 * and NAND (either 16bit or 8bit) on CS3.
+	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
+	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
+	 * notice whether a NAND chip is enabled at probe time.
+	 *
+	 * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
+	 * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3.  Try
+	 * detecting that in code here, to avoid probing every possible flash
+	 * configuration...
 	 */
-	h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
-	h2_flash_resource.end += SZ_32M - 1;
+	h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+	h2_nor_resource.end += SZ_32M - 1;
+
+	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+	omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
 
 	/* MMC:  card detect and WP */
 	// omap_cfg_reg(U19_ARMIO1);		/* CD */
 	omap_cfg_reg(BALLOUT_V8_ARMIO3);	/* WP */
 
+	/* Irda */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+	omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);
+	if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) {
+		omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+		h2_irda_data.transceiver_mode = h2_transceiver_mode;
+	}
+#endif
+
 	platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
 	omap_board_config = h2_config;
 	omap_board_config_size = ARRAY_SIZE(h2_config);
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index d9f3862..4b8d0ec 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -21,8 +21,11 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/errno.h>
+#include <linux/workqueue.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
@@ -33,15 +36,59 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/dma.h>
 #include <asm/arch/common.h>
 
 extern int omap_gpio_init(void);
 
-static struct mtd_partition h3_partitions[] = {
+static int h3_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_3),
+	KEY(0, 3, KEY_F10),
+	KEY(0, 4, KEY_F5),
+	KEY(0, 5, KEY_9),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_2),
+	KEY(1, 3, KEY_F9),
+	KEY(1, 4, KEY_F7),
+	KEY(1, 5, KEY_0),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_6),
+	KEY(2, 2, KEY_1),
+	KEY(2, 3, KEY_F2),
+	KEY(2, 4, KEY_F6),
+	KEY(2, 5, KEY_HOME),
+	KEY(3, 0, KEY_8),
+	KEY(3, 1, KEY_5),
+	KEY(3, 2, KEY_F12),
+	KEY(3, 3, KEY_F3),
+	KEY(3, 4, KEY_F8),
+	KEY(3, 5, KEY_END),
+	KEY(4, 0, KEY_7),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_F11),
+	KEY(4, 3, KEY_F1),
+	KEY(4, 4, KEY_F4),
+	KEY(4, 5, KEY_ESC),
+	KEY(5, 0, KEY_F13),
+	KEY(5, 1, KEY_F14),
+	KEY(5, 2, KEY_F15),
+	KEY(5, 3, KEY_F16),
+	KEY(5, 4, KEY_SLEEP),
+	0
+};
+
+
+static struct mtd_partition nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
 	      .name		= "bootloader",
@@ -72,26 +119,80 @@
 	}
 };
 
-static struct flash_platform_data h3_flash_data = {
+static struct flash_platform_data nor_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-	.parts		= h3_partitions,
-	.nr_parts	= ARRAY_SIZE(h3_partitions),
+	.parts		= nor_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_partitions),
 };
 
-static struct resource h3_flash_resource = {
+static struct resource nor_resource = {
 	/* This is on CS3, wherever it's mapped */
 	.flags		= IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
+static struct platform_device nor_device = {
 	.name		= "omapflash",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &h3_flash_data,
+		.platform_data	= &nor_data,
 	},
 	.num_resources	= 1,
-	.resource	= &h3_flash_resource,
+	.resource	= &nor_resource,
+};
+
+static struct mtd_partition nand_partitions[] = {
+#if 0
+	/* REVISIT: enable these partitions if you make NAND BOOT work */
+	{
+		.name		= "xloader",
+		.offset		= 0,
+		.size		= 64 * 1024,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "bootloader",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 256 * 1024,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 192 * 1024,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 2 * SZ_1M,
+	},
+#endif
+	{
+		.name		= "filesystem",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
+	},
+};
+
+/* dip switches control NAND chip access:  8 bit, 16 bit, or neither */
+static struct nand_platform_data nand_data = {
+	.options	= NAND_SAMSUNG_LP_OPTIONS,
+	.parts		= nand_partitions,
+	.nr_parts	= ARRAY_SIZE(nand_partitions),
+};
+
+static struct resource nand_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+	.name		= "omapnand",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &nand_resource,
 };
 
 static struct resource smc91x_resources[] = {
@@ -138,10 +239,136 @@
 	.resource       = intlat_resources,
 };
 
+static struct resource h3_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data h3_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = h3_keymap,
+	.rep	= 1,
+};
+
+static struct platform_device h3_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &h3_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(h3_kp_resources),
+	.resource	= h3_kp_resources,
+};
+
+
+/* Select between the IrDA and aGPS module
+ */
+static int h3_select_irda(struct device *dev, int state)
+{
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x26))) {
+		printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+		return err;
+	}
+
+	/* 'P6' enable/disable IRDA_TX and IRDA_RX */
+	if (state & IR_SEL) { /* IrDA */
+		if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
+			printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+			return err;
+		}
+	} else {
+		if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
+			printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+			return err;
+		}
+	}
+	return err;
+}
+
+static void set_trans_mode(void *data)
+{
+	int *mode = data;
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
+		printk(KERN_ERR "Error reading from I/O expander\n");
+	}
+
+	expa &= ~0x03;
+
+	if (*mode & IR_SIRMODE) {
+		expa |= 0x01;
+	} else { /* MIR/FIR */
+		expa |= 0x03;
+	}
+
+	if ((err = write_gpio_expa(expa, 0x27)) != 0) {
+		printk(KERN_ERR "Error writing to I/O expander\n");
+	}
+}
+
+static int h3_transceiver_mode(struct device *dev, int mode)
+{
+	struct omap_irda_config *irda_config = dev->platform_data;
+
+	cancel_delayed_work(&irda_config->gpio_expa);
+	PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+	schedule_work(&irda_config->gpio_expa);
+
+	return 0;
+}
+
+static struct omap_irda_config h3_irda_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+	.transceiver_mode	= h3_transceiver_mode,
+	.select_irda	 	= h3_select_irda,
+	.rx_channel		= OMAP_DMA_UART3_RX,
+	.tx_channel		= OMAP_DMA_UART3_TX,
+	.dest_start		= UART3_THR,
+	.src_start		= UART3_RHR,
+	.tx_trigger		= 0,
+	.rx_trigger		= 0,
+};
+
+static struct resource h3_irda_resources[] = {
+	[0] = {
+		.start	= INT_UART3,
+		.end	= INT_UART3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device h3_irda_device = {
+	.name		= "omapirda",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &h3_irda_data,
+	},
+	.num_resources	= ARRAY_SIZE(h3_irda_resources),
+	.resource	= h3_irda_resources,
+};
+
+static struct platform_device h3_lcd_device = {
+	.name		= "lcd_h3",
+	.id		= -1,
+};
+
 static struct platform_device *devices[] __initdata = {
-	&flash_device,
+	&nor_device,
+	&nand_device,
         &smc91x_device,
 	&intlat_device,
+	&h3_irda_device,
+	&h3_kp_device,
+	&h3_lcd_device,
 };
 
 static struct omap_usb_config h3_usb_config __initdata = {
@@ -171,7 +398,6 @@
 };
 
 static struct omap_lcd_config h3_lcd_config __initdata = {
-	.panel_name	= "h3",
 	.ctrl_name	= "internal",
 };
 
@@ -182,11 +408,36 @@
 	{ OMAP_TAG_LCD,		&h3_lcd_config },
 };
 
+#define H3_NAND_RB_GPIO_PIN	10
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+	return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+}
+
 static void __init h3_init(void)
 {
-	h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys();
-	h3_flash_resource.end += OMAP_CS3_SIZE - 1;
-	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
+	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
+	 * notice whether a NAND chip is enabled at probe time.
+	 *
+	 * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
+	 * (which on H2 may be 16bit) on CS3.  Try detecting that in code here,
+	 * to avoid probing every possible flash configuration...
+	 */
+	nor_resource.end = nor_resource.start = omap_cs3_phys();
+	nor_resource.end += SZ_32M - 1;
+
+	nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
+	nand_resource.end += SZ_4K - 1;
+	if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN)))
+		nand_data.dev_ready = nand_dev_ready;
+
+	/* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+	/* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+	omap_cfg_reg(V2_1710_GPIO10);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 	omap_board_config = h3_config;
 	omap_board_config_size = ARRAY_SIZE(h3_config);
 	omap_serial_init();
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index a04e433..e90c137 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -34,8 +35,22 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
 
+static int innovator_keymap[] = {
+	KEY(0, 0, KEY_F1),
+	KEY(0, 3, KEY_DOWN),
+	KEY(1, 1, KEY_F2),
+	KEY(1, 2, KEY_RIGHT),
+	KEY(2, 0, KEY_F3),
+	KEY(2, 1, KEY_F4),
+	KEY(2, 2, KEY_UP),
+	KEY(3, 2, KEY_ENTER),
+	KEY(3, 3, KEY_LEFT),
+	0
+};
+
 static struct mtd_partition innovator_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -97,6 +112,31 @@
 	.resource	= &innovator_flash_resource,
 };
 
+static struct resource innovator_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data innovator_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = innovator_keymap,
+};
+
+static struct platform_device innovator_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &innovator_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(innovator_kp_resources),
+	.resource	= innovator_kp_resources,
+};
+
+
 #ifdef CONFIG_ARCH_OMAP15XX
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -129,9 +169,16 @@
 	.resource	= innovator1510_smc91x_resources,
 };
 
+static struct platform_device innovator1510_lcd_device = {
+	.name		= "lcd_inn1510",
+	.id		= -1,
+};
+
 static struct platform_device *innovator1510_devices[] __initdata = {
 	&innovator_flash_device,
 	&innovator1510_smc91x_device,
+	&innovator_kp_device,
+	&innovator1510_lcd_device,
 };
 
 #endif /* CONFIG_ARCH_OMAP15XX */
@@ -158,9 +205,16 @@
 	.resource	= innovator1610_smc91x_resources,
 };
 
+static struct platform_device innovator1610_lcd_device = {
+	.name		= "inn1610_lcd",
+	.id		= -1,
+};
+
 static struct platform_device *innovator1610_devices[] __initdata = {
 	&innovator_flash_device,
 	&innovator1610_smc91x_device,
+	&innovator_kp_device,
+	&innovator1610_lcd_device,
 };
 
 #endif /* CONFIG_ARCH_OMAP16XX */
@@ -206,7 +260,6 @@
 };
 
 static struct omap_lcd_config innovator1510_lcd_config __initdata = {
-	.panel_name	= "inn1510",
 	.ctrl_name	= "internal",
 };
 #endif
@@ -228,7 +281,6 @@
 };
 
 static struct omap_lcd_config innovator1610_lcd_config __initdata = {
-	.panel_name	= "inn1610",
 	.ctrl_name	= "internal",
 };
 #endif
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
deleted file mode 100644
index 7520e60..0000000
--- a/arch/arm/mach-omap1/board-netstar.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Modified from board-generic.c
- *
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Code for Netstar OMAP board.
- *
- * 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/delay.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/usb.h>
-#include <asm/arch/common.h>
-
-extern void __init omap_init_time(void);
-extern int omap_gpio_init(void);
-
-static struct resource netstar_smc91x_resources[] = {
-	[0] = {
-		.start	= OMAP_CS1_PHYS + 0x300,
-		.end	= OMAP_CS1_PHYS + 0x300 + 16,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= OMAP_GPIO_IRQ(8),
-		.end	= OMAP_GPIO_IRQ(8),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device netstar_smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(netstar_smc91x_resources),
-	.resource	= netstar_smc91x_resources,
-};
-
-static struct platform_device *netstar_devices[] __initdata = {
-	&netstar_smc91x_device,
-};
-
-static struct omap_uart_config netstar_uart_config __initdata = {
-	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
-};
-
-static struct omap_board_config_kernel netstar_config[] = {
-	{ OMAP_TAG_UART,	&netstar_uart_config },
-};
-
-static void __init netstar_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap_init_irq();
-	omap_gpio_init();
-}
-
-static void __init netstar_init(void)
-{
-	/* green LED */
-	omap_request_gpio(4);
-	omap_set_gpio_direction(4, 0);
-	/* smc91x reset */
-	omap_request_gpio(7);
-	omap_set_gpio_direction(7, 0);
-	omap_set_gpio_dataout(7, 1);
-	udelay(2);	/* wait at least 100ns */
-	omap_set_gpio_dataout(7, 0);
-	mdelay(50);	/* 50ms until PHY ready */
-	/* smc91x interrupt pin */
-	omap_request_gpio(8);
-
-	omap_request_gpio(12);
-	omap_request_gpio(13);
-	omap_request_gpio(14);
-	omap_request_gpio(15);
-	set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING);
-	set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING);
-	set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING);
-	set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING);
-
-	platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
-
-	/* Switch on green LED */
-	omap_set_gpio_dataout(4, 0);
-	/* Switch off red LED */
-	omap_writeb(0x00, OMAP_LPG1_PMR);	/* Disable clock */
-	omap_writeb(0x80, OMAP_LPG1_LCR);
-
-	omap_board_config = netstar_config;
-	omap_board_config_size = ARRAY_SIZE(netstar_config);
-	omap_serial_init();
-}
-
-static void __init netstar_map_io(void)
-{
-	omap1_map_common_io();
-}
-
-#define MACHINE_PANICED		1
-#define MACHINE_REBOOTING	2
-#define MACHINE_REBOOT		4
-static unsigned long machine_state;
-
-static int panic_event(struct notifier_block *this, unsigned long event,
-	 void *ptr)
-{
-	if (test_and_set_bit(MACHINE_PANICED, &machine_state))
-		return NOTIFY_DONE;
-
-	/* Switch off green LED */
-	omap_set_gpio_dataout(4, 1);
-	/* Flash red LED */
-	omap_writeb(0x78, OMAP_LPG1_LCR);
-	omap_writeb(0x01, OMAP_LPG1_PMR);	/* Enable clock */
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
-	.notifier_call	= panic_event,
-};
-
-static int __init netstar_late_init(void)
-{
-	/* TODO: Setup front panel switch here */
-
-	/* Setup panic notifier */
-	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
-
-	return 0;
-}
-
-postcore_initcall(netstar_late_init);
-
-MACHINE_START(NETSTAR, "NetStar OMAP5910")
-	/* Maintainer: Ladislav Michl <michl@2n.cz> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
-	.boot_params	= 0x10000100,
-	.map_io		= netstar_map_io,
-	.init_irq	= netstar_init_irq,
-	.init_machine	= netstar_init,
-	.timer		= &omap_timer,
-MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
new file mode 100644
index 0000000..02b980d
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -0,0 +1,268 @@
+/*
+ * linux/arch/arm/mach-omap1/board-nokia770.c
+ *
+ * Modified from board-generic.c
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/aic23.h>
+#include <asm/arch/gpio.h>
+
+static void __init omap_nokia770_init_irq(void)
+{
+	/* On Nokia 770, the SleepX signal is masked with an
+	 * MPUIO line by default.  It has to be unmasked for it
+	 * to become functional */
+
+	/* SleepX mask direction */
+	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+	/* Unmask SleepX signal */
+	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
+	omap1_init_common_hw();
+	omap_init_irq();
+}
+
+static int nokia770_keymap[] = {
+	KEY(0, 1, GROUP_0 | KEY_UP),
+	KEY(0, 2, GROUP_1 | KEY_F5),
+	KEY(1, 0, GROUP_0 | KEY_LEFT),
+	KEY(1, 1, GROUP_0 | KEY_ENTER),
+	KEY(1, 2, GROUP_0 | KEY_RIGHT),
+	KEY(2, 0, GROUP_1 | KEY_ESC),
+	KEY(2, 1, GROUP_0 | KEY_DOWN),
+	KEY(2, 2, GROUP_1 | KEY_F4),
+	KEY(3, 0, GROUP_2 | KEY_F7),
+	KEY(3, 1, GROUP_2 | KEY_F8),
+	KEY(3, 2, GROUP_2 | KEY_F6),
+	0
+};
+
+static struct resource nokia770_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data nokia770_kp_data = {
+	.rows   = 8,
+	.cols   = 8,
+	.keymap = nokia770_keymap
+};
+
+static struct platform_device nokia770_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &nokia770_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(nokia770_kp_resources),
+	.resource	= nokia770_kp_resources,
+};
+
+static struct platform_device *nokia770_devices[] __initdata = {
+        &nokia770_kp_device,
+};
+
+static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
+	.x_max		= 0x0fff,
+	.y_max		= 0x0fff,
+	.x_plate_ohms	= 180,
+	.pressure_max	= 255,
+	.debounce_max	= 10,
+	.debounce_tol	= 3,
+};
+
+static struct spi_board_info nokia770_spi_board_info[] __initdata = {
+	[0] = {
+		.modalias       = "lcd_lph8923",
+		.bus_num        = 2,
+		.chip_select    = 3,
+		.max_speed_hz   = 12000000,
+	},
+	[1] = {
+		.modalias       = "ads7846",
+		.bus_num        = 2,
+		.chip_select    = 0,
+		.max_speed_hz   = 2500000,
+		.irq		= OMAP_GPIO_IRQ(15),
+		.platform_data	= &nokia770_ads7846_platform_data,
+	},
+};
+
+
+/* assume no Mini-AB port */
+
+static struct omap_usb_config nokia770_usb_config __initdata = {
+	.otg		= 1,
+	.register_host	= 1,
+	.register_dev	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 6,
+};
+
+static struct omap_mmc_config nokia770_mmc_config __initdata = {
+	.mmc[0] = {
+		.enabled	= 0,
+		.wire4		= 0,
+		.wp_pin		= -1,
+		.power_pin	= -1,
+		.switch_pin	= -1,
+	},
+	.mmc[1] = {
+		.enabled	= 0,
+		.wire4		= 0,
+		.wp_pin		= -1,
+		.power_pin	= -1,
+		.switch_pin	= -1,
+	},
+};
+
+static struct omap_board_config_kernel nokia770_config[] = {
+	{ OMAP_TAG_USB,		NULL },
+	{ OMAP_TAG_MMC,		&nokia770_mmc_config },
+};
+
+/*
+ * audio power control
+ */
+#define	HEADPHONE_GPIO		14
+#define	AMPLIFIER_CTRL_GPIO	58
+
+static struct clk *dspxor_ck;
+static DECLARE_MUTEX(audio_pwr_sem);
+/*
+ * audio_pwr_state
+ * +--+-------------------------+---------------------------------------+
+ * |-1|down			|power-up request -> 0			|
+ * +--+-------------------------+---------------------------------------+
+ * | 0|up			|power-down(1) request -> 1		|
+ * |  |				|power-down(2) request -> (ignore)	|
+ * +--+-------------------------+---------------------------------------+
+ * | 1|up,			|power-up request -> 0			|
+ * |  |received down(1) request	|power-down(2) request -> -1		|
+ * +--+-------------------------+---------------------------------------+
+ */
+static int audio_pwr_state = -1;
+
+/*
+ * audio_pwr_up / down should be called under audio_pwr_sem
+ */
+static void nokia770_audio_pwr_up(void)
+{
+	clk_enable(dspxor_ck);
+
+	/* Turn on codec */
+	tlv320aic23_power_up();
+
+	if (omap_get_gpio_datain(HEADPHONE_GPIO))
+		/* HP not connected, turn on amplifier */
+		omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1);
+	else
+		/* HP connected, do not turn on amplifier */
+		printk("HP connected\n");
+}
+
+static void codec_delayed_power_down(void *arg)
+{
+	down(&audio_pwr_sem);
+	if (audio_pwr_state == -1)
+		tlv320aic23_power_down();
+	clk_disable(dspxor_ck);
+	up(&audio_pwr_sem);
+}
+
+static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL);
+
+static void nokia770_audio_pwr_down(void)
+{
+	/* Turn off amplifier */
+	omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0);
+
+	/* Turn off codec: schedule delayed work */
+	schedule_delayed_work(&codec_power_down_work, HZ / 20);	/* 50ms */
+}
+
+void nokia770_audio_pwr_up_request(int stage)
+{
+	down(&audio_pwr_sem);
+	if (audio_pwr_state == -1)
+		nokia770_audio_pwr_up();
+	/* force audio_pwr_state = 0, even if it was 1. */
+	audio_pwr_state = 0;
+	up(&audio_pwr_sem);
+}
+
+void nokia770_audio_pwr_down_request(int stage)
+{
+	down(&audio_pwr_sem);
+	switch (stage) {
+	case 1:
+		if (audio_pwr_state == 0)
+			audio_pwr_state = 1;
+		break;
+	case 2:
+		if (audio_pwr_state == 1) {
+			nokia770_audio_pwr_down();
+			audio_pwr_state = -1;
+		}
+		break;
+	}
+	up(&audio_pwr_sem);
+}
+
+static void __init omap_nokia770_init(void)
+{
+	nokia770_config[0].data = &nokia770_usb_config;
+
+	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
+	spi_register_board_info(nokia770_spi_board_info,
+				ARRAY_SIZE(nokia770_spi_board_info));
+	omap_board_config = nokia770_config;
+	omap_board_config_size = ARRAY_SIZE(nokia770_config);
+	omap_serial_init();
+	omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request;
+	omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request;
+	dspxor_ck = clk_get(0, "dspxor_ck");
+}
+
+static void __init omap_nokia770_map_io(void)
+{
+	omap1_map_common_io();
+}
+
+MACHINE_START(NOKIA770, "Nokia 770")
+	.phys_io	= 0xfff00000,
+	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
+	.boot_params	= 0x10000100,
+	.map_io		= omap_nokia770_map_io,
+	.init_irq	= omap_nokia770_init_irq,
+	.init_machine	= omap_nokia770_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 543fa13..1160093 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -33,6 +33,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -44,7 +45,24 @@
 #include <asm/arch/usb.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
+
+static int osk_keymap[] = {
+	KEY(0, 0, KEY_F1),
+	KEY(0, 3, KEY_UP),
+	KEY(1, 1, KEY_LEFTCTRL),
+	KEY(1, 2, KEY_LEFT),
+	KEY(2, 0, KEY_SPACE),
+	KEY(2, 1, KEY_ESC),
+	KEY(2, 2, KEY_DOWN),
+	KEY(3, 2, KEY_ENTER),
+	KEY(3, 3, KEY_RIGHT),
+	0
+};
+
 
 static struct mtd_partition osk_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
@@ -133,9 +151,69 @@
 	.resource	= osk5912_cf_resources,
 };
 
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+	.spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+	.spcr1 = RINTM(3) | RRST,
+	.rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+	    RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+	.rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+	.xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+	    XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+	.xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+	.srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+	.srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+	/*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
+	.pcr0 = CLKXP | CLKRP,  /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+	.name			= "OSK AIC23",
+	.mcbsp_regs_alsa	= &mcbsp_regs,
+	.codec_configure_dev	= NULL, // aic23_configure,
+	.codec_set_samplerate	= NULL, // aic23_set_samplerate,
+	.codec_clock_setup	= NULL, // aic23_clock_setup,
+	.codec_clock_on		= NULL, // aic23_clock_on,
+	.codec_clock_off	= NULL, // aic23_clock_off,
+	.get_default_samplerate	= NULL, // aic23_get_default_samplerate,
+};
+
 static struct platform_device osk5912_mcbsp1_device = {
-	.name		= "omap_mcbsp",
-	.id		= 1,
+	.name	= "omap_alsa_mcbsp",
+ 	.id	= 1,
+	.dev = {
+		.platform_data	= &alsa_config,
+	},
+};
+
+static struct resource osk5912_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data osk_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = osk_keymap,
+};
+
+static struct platform_device osk5912_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &osk_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(osk5912_kp_resources),
+	.resource	= osk5912_kp_resources,
+};
+
+static struct platform_device osk5912_lcd_device = {
+	.name		= "lcd_osk",
+	.id		= -1,
 };
 
 static struct platform_device *osk5912_devices[] __initdata = {
@@ -143,6 +221,8 @@
 	&osk5912_smc91x_device,
 	&osk5912_cf_device,
 	&osk5912_mcbsp1_device,
+	&osk5912_kp_device,
+	&osk5912_lcd_device,
 };
 
 static void __init osk_init_smc91x(void)
@@ -197,7 +277,6 @@
 };
 
 static struct omap_lcd_config osk_lcd_config __initdata = {
-	.panel_name	= "osk",
 	.ctrl_name	= "internal",
 };
 
@@ -255,8 +334,18 @@
 static void __init osk_mistral_init(void) { }
 #endif
 
+#define EMIFS_CS3_VAL	(0x88013141)
+
 static void __init osk_init(void)
 {
+	/* Workaround for wrong CS3 (NOR flash) timing
+	 * There are some U-Boot versions out there which configure
+	 * wrong CS3 memory timings. This mainly leads to CRC
+	 * or similiar errors if you use NOR flash (e.g. with JFFS2)
+	 */
+	if (EMIFS_CCS(3) != EMIFS_CS3_VAL)
+		EMIFS_CCS(3) = EMIFS_CS3_VAL;
+
 	osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys();
 	osk_flash_resource.end += SZ_32M - 1;
 	platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index e488f72..4bc8a62 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -38,6 +38,15 @@
 	omap_init_irq();
 }
 
+static struct platform_device palmte_lcd_device = {
+	.name		= "lcd_palmte",
+	.id		= -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&palmte_lcd_device,
+};
+
 static struct omap_usb_config palmte_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0,
@@ -55,7 +64,6 @@
 };
 
 static struct omap_lcd_config palmte_lcd_config __initdata = {
-	.panel_name	= "palmte",
 	.ctrl_name	= "internal",
 };
 
@@ -69,6 +77,8 @@
 {
 	omap_board_config = palmte_config;
 	omap_board_config_size = ARRAY_SIZE(palmte_config);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3913a3c..64b45d8 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -16,7 +16,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -28,9 +30,44 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
 #include <asm/arch/board.h>
 
+static int p2_keymap[] = {
+	KEY(0,0,KEY_UP),
+	KEY(0,1,KEY_RIGHT),
+	KEY(0,2,KEY_LEFT),
+	KEY(0,3,KEY_DOWN),
+	KEY(0,4,KEY_CENTER),
+	KEY(0,5,KEY_0_5),
+	KEY(1,0,KEY_SOFT2),
+	KEY(1,1,KEY_SEND),
+	KEY(1,2,KEY_END),
+	KEY(1,3,KEY_VOLUMEDOWN),
+	KEY(1,4,KEY_VOLUMEUP),
+	KEY(1,5,KEY_RECORD),
+	KEY(2,0,KEY_SOFT1),
+	KEY(2,1,KEY_3),
+	KEY(2,2,KEY_6),
+	KEY(2,3,KEY_9),
+	KEY(2,4,KEY_SHARP),
+	KEY(2,5,KEY_2_5),
+	KEY(3,0,KEY_BACK),
+	KEY(3,1,KEY_2),
+	KEY(3,2,KEY_5),
+	KEY(3,3,KEY_8),
+	KEY(3,4,KEY_0),
+	KEY(3,5,KEY_HEADSETHOOK),
+	KEY(4,0,KEY_HOME),
+	KEY(4,1,KEY_1),
+	KEY(4,2,KEY_4),
+	KEY(4,3,KEY_7),
+	KEY(4,4,KEY_STAR),
+	KEY(4,5,KEY_POWER),
+	0
+};
+
 static struct resource smc91x_resources[] = {
 	[0] = {
 		.start	= H2P2_DBG_FPGA_ETHR_START,	/* Physical */
@@ -44,7 +81,7 @@
 	},
 };
 
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
 	      .name		= "bootloader",
@@ -75,27 +112,47 @@
 	},
 };
 
-static struct flash_platform_data p2_flash_data = {
+static struct flash_platform_data nor_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-	.parts		= p2_partitions,
-	.nr_parts	= ARRAY_SIZE(p2_partitions),
+	.parts		= nor_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_partitions),
 };
 
-static struct resource p2_flash_resource = {
+static struct resource nor_resource = {
 	.start		= OMAP_CS0_PHYS,
 	.end		= OMAP_CS0_PHYS + SZ_32M - 1,
 	.flags		= IORESOURCE_MEM,
 };
 
-static struct platform_device p2_flash_device = {
+static struct platform_device nor_device = {
 	.name		= "omapflash",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &p2_flash_data,
+		.platform_data	= &nor_data,
 	},
 	.num_resources	= 1,
-	.resource	= &p2_flash_resource,
+	.resource	= &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+	.options	= NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+	.start		= OMAP_CS3_PHYS,
+	.end		= OMAP_CS3_PHYS + SZ_4K - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+	.name		= "omapnand",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &nand_resource,
 };
 
 static struct platform_device smc91x_device = {
@@ -105,17 +162,55 @@
 	.resource	= smc91x_resources,
 };
 
-static struct platform_device *devices[] __initdata = {
-	&p2_flash_device,
-	&smc91x_device,
+static struct resource kp_resources[] = {
+	[0] = {
+		.start	= INT_730_MPUIO_KEYPAD,
+		.end	= INT_730_MPUIO_KEYPAD,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
+static struct omap_kp_platform_data kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = p2_keymap,
+};
+
+static struct platform_device kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(kp_resources),
+	.resource	= kp_resources,
+};
+
+static struct platform_device lcd_device = {
+	.name		= "lcd_p2",
+	.id		= -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&nor_device,
+	&nand_device,
+	&smc91x_device,
+	&kp_device,
+	&lcd_device,
+};
+
+#define P2_NAND_RB_GPIO_PIN	62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+	return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
 static struct omap_uart_config perseus2_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1)),
 };
 
 static struct omap_lcd_config perseus2_lcd_config __initdata = {
-	.panel_name	= "p2",
 	.ctrl_name	= "internal",
 };
 
@@ -126,7 +221,13 @@
 
 static void __init omap_perseus2_init(void)
 {
-	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+	if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+		nand_data.dev_ready = nand_dev_ready;
+
+	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+	omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	omap_board_config = perseus2_config;
 	omap_board_config_size = ARRAY_SIZE(perseus2_config);
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 52e4a9d..447a586 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -155,9 +155,9 @@
 };
 
 static struct omap_board_config_kernel voiceblue_config[] = {
-	{ OMAP_TAG_USB, &voiceblue_usb_config },
-	{ OMAP_TAG_MMC, &voiceblue_mmc_config },
-	{ OMAP_TAG_UART,	&voiceblue_uart_config },
+	{ OMAP_TAG_USB,  &voiceblue_usb_config },
+	{ OMAP_TAG_MMC,  &voiceblue_mmc_config },
+	{ OMAP_TAG_UART, &voiceblue_uart_config },
 };
 
 static void __init voiceblue_init_irq(void)
@@ -235,7 +235,7 @@
 static int __init voiceblue_setup(void)
 {
 	/* Setup panic notifier */
-	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+	notifier_chain_register(&panic_notifier_list, &panic_block);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 75110ba..619db18 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -345,7 +345,7 @@
 	 */
 	for (dsor = 2; dsor < 96; ++dsor) {
 		if ((dsor & 1) && dsor > 8)
-		  	continue;
+			continue;
 		if (rate >= 96000000 / dsor)
 			break;
 	}
@@ -687,6 +687,11 @@
 			clk_register(*clkp);
 			continue;
 		}
+
+		if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) {
+			clk_register(*clkp);
+			continue;
+		}
 	}
 
 	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
@@ -784,7 +789,7 @@
 	clk_enable(&armxor_ck.clk);
 	clk_enable(&armtim_ck.clk); /* This should be done by timer code */
 
-	if (cpu_is_omap1510())
+	if (cpu_is_omap15xx())
 		clk_enable(&arm_gpio_ck);
 
 	return 0;
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 4f18d1b..b7c6881 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -151,7 +151,7 @@
 	.name		= "ck_ref",
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -160,7 +160,7 @@
 	.name		= "ck_dpll1",
 	.parent		= &ck_ref,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_PROPAGATES | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -183,7 +183,8 @@
 	.name		= "arm_ck",
 	.parent		= &ck_dpll1,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
+			  ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_ARMDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
 	.enable		= &omap1_clk_enable_generic,
@@ -195,7 +196,8 @@
 		.name		= "armper_ck",
 		.parent		= &ck_dpll1,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  RATE_CKCTL | CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | RATE_CKCTL |
+				  CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_PERCK,
 		.rate_offset	= CKCTL_PERDIV_OFFSET,
@@ -209,7 +211,7 @@
 static struct clk arm_gpio_ck = {
 	.name		= "arm_gpio_ck",
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP1510,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
 	.enable_reg	= (void __iomem *)ARM_IDLECT2,
 	.enable_bit	= EN_GPIOCK,
 	.recalc		= &followparent_recalc,
@@ -222,7 +224,7 @@
 		.name		= "armxor_ck",
 		.parent		= &ck_ref,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_XORPCK,
 		.recalc		= &followparent_recalc,
@@ -237,7 +239,7 @@
 		.name		= "armtim_ck",
 		.parent		= &ck_ref,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_TIMCK,
 		.recalc		= &followparent_recalc,
@@ -252,7 +254,7 @@
 		.name		= "armwdt_ck",
 		.parent		= &ck_ref,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_WDTCK,
 		.recalc		= &omap1_watchdog_recalc,
@@ -344,9 +346,9 @@
 		.name		= "tc_ck",
 		.parent		= &ck_dpll1,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP730 | RATE_CKCTL |
-				  RATE_PROPAGATES | ALWAYS_ENABLED |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
+				  RATE_CKCTL | RATE_PROPAGATES |
+				  ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
 		.rate_offset	= CKCTL_TCDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
 		.enable		= &omap1_clk_enable_generic,
@@ -358,7 +360,8 @@
 static struct clk arminth_ck1510 = {
 	.name		= "arminth_ck",
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	/* Note: On 1510 the frequency follows TC_CK
 	 *
@@ -372,7 +375,8 @@
 	/* No-idle controlled by "tc_ck" */
 	.name		= "tibp_ck",
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
@@ -417,7 +421,7 @@
 	.name		= "dma_ck",
 	.parent		= &tc_ck.clk,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
@@ -437,7 +441,7 @@
 		.name		= "api_ck",
 		.parent		= &tc_ck.clk,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_APICK,
 		.recalc		= &followparent_recalc,
@@ -451,7 +455,8 @@
 	.clk = {
 		.name		= "lb_ck",
 		.parent		= &tc_ck.clk,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL,
+		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+				  CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_LBCK,
 		.recalc		= &followparent_recalc,
@@ -495,8 +500,8 @@
 	.clk = {
 		.name		= "lcd_ck",
 		.parent		= &ck_dpll1,
-		.flags		= CLOCK_IN_OMAP1510 | RATE_CKCTL |
-				  CLOCK_IDLE_CONTROL,
+		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+				  RATE_CKCTL | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_LCDCK,
 		.rate_offset	= CKCTL_LCDDIV_OFFSET,
@@ -512,8 +517,9 @@
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
-			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 29,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
@@ -544,8 +550,8 @@
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
-			  CLOCK_NO_IDLE_PARENT,
+			  CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
+			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 30,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
@@ -559,8 +565,9 @@
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
-			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 31,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
@@ -590,7 +597,7 @@
 	/* Direct from ULPD, no parent */
 	.rate		= 6000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT,
+			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)ULPD_CLOCK_CTRL,
 	.enable_bit	= USB_MCLK_EN_BIT,
 	.enable		= &omap1_clk_enable_generic,
@@ -601,7 +608,7 @@
 	.name		= "usb_hhc_ck",
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
-	.flags		= CLOCK_IN_OMAP1510 |
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
 			  RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= USB_HOST_HHC_UHOST_EN,
@@ -637,7 +644,9 @@
 	.name		= "mclk",
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | RATE_FIXED,
+ 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
+ 	.enable_reg	= (void __iomem *)SOFT_REQ_REG,
+ 	.enable_bit	= 6,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -659,7 +668,7 @@
 	.name		= "bclk",
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | RATE_FIXED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -678,12 +687,14 @@
 };
 
 static struct clk mmc1_ck = {
-	.name		= "mmc1_ck",
+	.name		= "mmc_ck",
+	.id		= 1,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 23,
 	.enable		= &omap1_clk_enable_generic,
@@ -691,7 +702,8 @@
 };
 
 static struct clk mmc2_ck = {
-	.name		= "mmc2_ck",
+	.name		= "mmc_ck",
+	.id		= 2,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
@@ -706,7 +718,7 @@
 static struct clk virtual_ck_mpu = {
 	.name		= "mpu",
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  VIRTUAL_CLOCK | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
 	.parent		= &arm_ck, /* Is smarter alias for */
 	.recalc		= &followparent_recalc,
 	.set_rate	= &omap1_select_table_rate,
@@ -715,6 +727,20 @@
 	.disable	= &omap1_clk_disable_generic,
 };
 
+/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
+remains active during MPU idle whenever this is enabled */
+static struct clk i2c_fck = {
+	.name		= "i2c_fck",
+	.id		= 1,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+			  ALWAYS_ENABLED,
+	.parent		= &armxor_ck.clk,
+	.recalc		= &followparent_recalc,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
+};
+
 static struct clk * onchip_clks[] = {
 	/* non-ULPD clocks */
 	&ck_ref,
@@ -763,6 +789,7 @@
 	&mmc2_ck,
 	/* Virtual clocks */
 	&virtual_ck_mpu,
+	&i2c_fck,
 };
 
 #endif
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index ecbc475..876c38d 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -99,6 +99,45 @@
 static inline void omap_init_rtc(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP1_STI_BASE		IO_ADDRESS(0xfffea000)
+#define OMAP1_STI_CHANNEL_BASE	(OMAP1_STI_BASE + 0x400)
+
+static struct resource sti_resources[] = {
+	{
+		.start		= OMAP1_STI_BASE,
+		.end		= OMAP1_STI_BASE + SZ_1K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP1_STI_CHANNEL_BASE,
+		.end		= OMAP1_STI_CHANNEL_BASE + SZ_1K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= INT_1610_STI,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device sti_device = {
+	.name		= "sti",
+	.id		= -1,
+	.dev = {
+		.release	= omap_nop_release,
+	},
+	.num_resources	= ARRAY_SIZE(sti_resources),
+	.resource	= sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+	platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -129,6 +168,7 @@
 	 */
 	omap_init_irda();
 	omap_init_rtc();
+	omap_init_sti();
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 82d556b..be3a2a4 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,6 +18,7 @@
 #include <asm/io.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/omapfb.h>
 
 extern int omap1_clk_init(void);
 extern void omap_check_revision(void);
@@ -110,7 +111,7 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 	}
 #endif
@@ -121,6 +122,7 @@
 #endif
 
 	omap_sram_init();
+	omapfb_reserve_mem();
 }
 
 /*
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index ed65a7d..a0431c0 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -60,7 +60,7 @@
 	unsigned long wake_enable;
 };
 
-static unsigned int irq_bank_count = 0;
+static unsigned int irq_bank_count;
 static struct omap_irq_bank *irq_banks;
 
 static inline unsigned int irq_bank_readl(int bank, int offset)
@@ -142,28 +142,28 @@
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct omap_irq_bank omap730_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3f8e22f },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfdb9c1f2 },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3f8e22f },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xfdb9c1f2 },
 	{ .base_reg = OMAP_IH2_BASE + 0x100,	.trigger_map = 0x800040f3 },
 };
 #endif
 
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_irq_bank omap1510_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3febfff },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xffbfffed },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3febfff },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xffbfffed },
 };
 static struct omap_irq_bank omap310_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3faefc3 },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0x65b3c061 },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3faefc3 },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0x65b3c061 },
 };
 #endif
 
 #if defined(CONFIG_ARCH_OMAP16XX)
 
 static struct omap_irq_bank omap1610_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3fefe8f },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfdb7c1fd },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3fefe8f },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xfdb7c1fd },
 	{ .base_reg = OMAP_IH2_BASE + 0x100,	.trigger_map = 0xffffb7ff },
 	{ .base_reg = OMAP_IH2_BASE + 0x200,	.trigger_map = 0xffffffff },
 };
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index d4b8d62..10fe0b3 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -35,16 +35,20 @@
 
 #ifdef CONFIG_ARCH_OMAP730
 struct pin_config __initdata_or_module omap730_pins[] = {
-MUX_CFG_730("E2_730_KBR0",	12,   21,    0,	  0,   20,   1,	  NA,	 0,  0)
-MUX_CFG_730("J7_730_KBR1",	12,   25,    0,	  0,   24,   1,	  NA,	 0,  0)
-MUX_CFG_730("E1_730_KBR2",	12,   29,    0,	  0,   28,   1,	  NA,	 0,  0)
-MUX_CFG_730("F3_730_KBR3",	13,    1,    0,	  0,   0,    1,	  NA,	 0,  0)
-MUX_CFG_730("D2_730_KBR4",	13,    5,    0,	  0,   4,    1,	  NA,	 0,  0)
-MUX_CFG_730("C2_730_KBC0",	13,    9,    0,	  0,	8,   1,	  NA,	 0,  0)
-MUX_CFG_730("D3_730_KBC1",	13,   13,    0,	  0,   12,   1,	  NA,	 0,  0)
-MUX_CFG_730("E4_730_KBC2",	13,   17,    0,	  0,   16,   1,	  NA,	 0,  0)
-MUX_CFG_730("F4_730_KBC3",	13,   21,    0,	  0,   20,   1,	  NA,	 0,  0)
-MUX_CFG_730("E3_730_KBC4",	13,   25,    0,	  0,   24,   1,	  NA,	 0,  0)
+MUX_CFG_730("E2_730_KBR0",        12,   21,    0,   20,   1, 0)
+MUX_CFG_730("J7_730_KBR1",        12,   25,    0,   24,   1, 0)
+MUX_CFG_730("E1_730_KBR2",        12,   29,    0,   28,   1, 0)
+MUX_CFG_730("F3_730_KBR3",        13,    1,    0,    0,   1, 0)
+MUX_CFG_730("D2_730_KBR4",        13,    5,    0,    4,   1, 0)
+MUX_CFG_730("C2_730_KBC0",        13,    9,    0,    8,   1, 0)
+MUX_CFG_730("D3_730_KBC1",        13,   13,    0,   12,   1, 0)
+MUX_CFG_730("E4_730_KBC2",        13,   17,    0,   16,   1, 0)
+MUX_CFG_730("F4_730_KBC3",        13,   21,    0,   20,   1, 0)
+MUX_CFG_730("E3_730_KBC4",        13,   25,    0,   24,   1, 0)
+
+MUX_CFG_730("AA17_730_USB_DM",     2,   21,    0,   20,   0, 0)
+MUX_CFG_730("W16_730_USB_PU_EN",   2,   25,    0,   24,   0, 0)
+MUX_CFG_730("W17_730_USB_VBUSI",   2,   29,    0,   28,   0, 0)
 };
 #endif
 
@@ -73,8 +77,8 @@
 MUX_CFG("Y15_1610_UART3_RTS",	 A,    0,    1,	  2,   6,   0,	 NA,	 0,  0)
 
 /* PWT & PWL, conflicts with UART3 */
-MUX_CFG("PWT",		 	 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
-MUX_CFG("PWL",		 	 6,    3,    1,	  0,  31,   1,	 NA,	 0,  0)
+MUX_CFG("PWT",			 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
+MUX_CFG("PWL",			 6,    3,    1,	  0,  31,   1,	 NA,	 0,  0)
 
 /* USB internal master generic */
 MUX_CFG("R18_USB_VBUS",		 7,    9,    2,	  1,  11,   0,	 NA,	 0,  1)
@@ -151,7 +155,7 @@
 
 /* Misc ballouts */
 MUX_CFG("BALLOUT_V8_ARMIO3",	 B,   18,    0,	  2,  25,   1,	 NA,	 0,  1)
-MUX_CFG("N20_HDQ",	       6,   18,    1,   1,   4,   0,    1,     4,  0)
+MUX_CFG("N20_HDQ",		 6,   18,    1,   1,   4,   0,    1,     4,  0)
 
 /* OMAP-1610 MMC2 */
 MUX_CFG("W8_1610_MMC2_DAT0",	 B,   21,    6,	  2,  23,   1,	  2,	 1,  1)
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
new file mode 100644
index 0000000..ddf6b07
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.c
@@ -0,0 +1,770 @@
+/*
+ * linux/arch/arm/mach-omap1/pm.c
+ *
+ * OMAP Power Management Routines
+ *
+ * Original code for the SA11x0:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Modified for the PXA250 by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Modified for the OMAP1510 by David Singleton:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/dmtimer.h>
+
+static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
+static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
+static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+static unsigned short enable_dyn_sleep = 1;
+
+static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+{
+	return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+					      const char * buf,
+					      size_t n)
+{
+	unsigned short value;
+	if (sscanf(buf, "%hu", &value) != 1 ||
+	    (value != 0 && value != 1)) {
+		printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+		return -EINVAL;
+	}
+	enable_dyn_sleep = value;
+	return n;
+}
+
+static struct subsys_attribute sleep_while_idle_attr = {
+	.attr   = {
+		.name = __stringify(sleep_while_idle),
+		.mode = 0644,
+	},
+	.show   = omap_pm_sleep_while_idle_show,
+	.store  = omap_pm_sleep_while_idle_store,
+};
+
+extern struct subsystem power_subsys;
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
+/*
+ * Let's power down on idle, but only if we are really
+ * idle, because once we start down the path of
+ * going idle we continue to do idle even if we get
+ * a clock tick interrupt . .
+ */
+void omap_pm_idle(void)
+{
+	extern __u32 arm_idlect1_mask;
+	__u32 use_idlect1 = arm_idlect1_mask;
+#ifndef CONFIG_OMAP_MPU_TIMER
+	int do_sleep;
+#endif
+
+	local_irq_disable();
+	local_fiq_disable();
+	if (need_resched()) {
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+
+	/*
+	 * Since an interrupt may set up a timer, we don't want to
+	 * reprogram the hardware timer with interrupts enabled.
+	 * Re-enable interrupts only after returning from idle.
+	 */
+	timer_dyn_reprogram();
+
+#ifdef CONFIG_OMAP_MPU_TIMER
+#warning Enable 32kHz OS timer in order to allow sleep states in idle
+	use_idlect1 = use_idlect1 & ~(1 << 9);
+#else
+
+	do_sleep = 0;
+	while (enable_dyn_sleep) {
+
+#ifdef CONFIG_CBUS_TAHVO_USB
+		extern int vbus_active;
+		/* Clock requirements? */
+		if (vbus_active)
+			break;
+#endif
+		do_sleep = 1;
+		break;
+	}
+
+#ifdef CONFIG_OMAP_DM_TIMER
+	use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
+#endif
+
+	if (omap_dma_running()) {
+		use_idlect1 &= ~(1 << 6);
+		if (omap_lcd_dma_ext_running())
+			use_idlect1 &= ~(1 << 12);
+	}
+
+	/* We should be able to remove the do_sleep variable and multiple
+	 * tests above as soon as drivers, timer and DMA code have been fixed.
+	 * Even the sleep block count should become obsolete. */
+	if ((use_idlect1 != ~0) || !do_sleep) {
+
+		__u32 saved_idlect1 = omap_readl(ARM_IDLECT1);
+		if (cpu_is_omap15xx())
+			use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST;
+		else
+			use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL;
+		omap_writel(use_idlect1, ARM_IDLECT1);
+		__asm__ volatile ("mcr	p15, 0, r0, c7, c0, 4");
+		omap_writel(saved_idlect1, ARM_IDLECT1);
+
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+	omap_sram_suspend(omap_readl(ARM_IDLECT1),
+			  omap_readl(ARM_IDLECT2));
+#endif
+
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+/*
+ * Configuration of the wakeup event is board specific. For the
+ * moment we put it into this helper function. Later it may move
+ * to board specific files.
+ */
+static void omap_pm_wakeup_setup(void)
+{
+	u32 level1_wake = 0;
+	u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
+
+	/*
+	 * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
+	 * and the L2 wakeup interrupts: keypad and UART2. Note that the
+	 * drivers must still separately call omap_set_gpio_wakeup() to
+	 * wake up to a GPIO interrupt.
+	 */
+	if (cpu_is_omap730())
+		level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
+			OMAP_IRQ_BIT(INT_730_IH2_IRQ);
+	else if (cpu_is_omap15xx())
+		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+			OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
+	else if (cpu_is_omap16xx())
+		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+			OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
+
+	omap_writel(~level1_wake, OMAP_IH1_MIR);
+
+	if (cpu_is_omap730()) {
+		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+		omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) |
+				OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)),
+				OMAP_IH2_1_MIR);
+	} else if (cpu_is_omap15xx()) {
+		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+		omap_writel(~level2_wake,  OMAP_IH2_MIR);
+	} else if (cpu_is_omap16xx()) {
+		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+
+		/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
+		omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ),
+			    OMAP_IH2_1_MIR);
+		omap_writel(~0x0, OMAP_IH2_2_MIR);
+		omap_writel(~0x0, OMAP_IH2_3_MIR);
+	}
+
+	/*  New IRQ agreement, recalculate in cascade order */
+	omap_writel(1, OMAP_IH2_CONTROL);
+	omap_writel(1, OMAP_IH1_CONTROL);
+}
+
+#define EN_DSPCK	13	/* ARM_CKCTL */
+#define EN_APICK	6	/* ARM_IDLECT2 */
+#define DSP_EN		1	/* ARM_RSTCT1 */
+
+void omap_pm_suspend(void)
+{
+	unsigned long arg0 = 0, arg1 = 0;
+
+	printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
+
+	omap_serial_wake_trigger(1);
+
+	if (machine_is_omap_osk()) {
+		/* Stop LED1 (D9) blink */
+		tps65010_set_led(LED1, OFF);
+	}
+
+	omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+
+	/*
+	 * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
+	 */
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	/*
+	 * Step 2: save registers
+	 *
+	 * The omap is a strange/beautiful device. The caches, memory
+	 * and register state are preserved across power saves.
+	 * We have to save and restore very little register state to
+	 * idle the omap.
+         *
+	 * Save interrupt, MPUI, ARM and UPLD control registers.
+	 */
+
+	if (cpu_is_omap730()) {
+		MPUI730_SAVE(OMAP_IH1_MIR);
+		MPUI730_SAVE(OMAP_IH2_0_MIR);
+		MPUI730_SAVE(OMAP_IH2_1_MIR);
+		MPUI730_SAVE(MPUI_CTRL);
+		MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI730_SAVE(EMIFS_CONFIG);
+		MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+
+	} else if (cpu_is_omap15xx()) {
+		MPUI1510_SAVE(OMAP_IH1_MIR);
+		MPUI1510_SAVE(OMAP_IH2_MIR);
+		MPUI1510_SAVE(MPUI_CTRL);
+		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1510_SAVE(EMIFS_CONFIG);
+		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_SAVE(OMAP_IH1_MIR);
+		MPUI1610_SAVE(OMAP_IH2_0_MIR);
+		MPUI1610_SAVE(OMAP_IH2_1_MIR);
+		MPUI1610_SAVE(OMAP_IH2_2_MIR);
+		MPUI1610_SAVE(OMAP_IH2_3_MIR);
+		MPUI1610_SAVE(MPUI_CTRL);
+		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1610_SAVE(EMIFS_CONFIG);
+		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+	}
+
+	ARM_SAVE(ARM_CKCTL);
+	ARM_SAVE(ARM_IDLECT1);
+	ARM_SAVE(ARM_IDLECT2);
+	if (!(cpu_is_omap15xx()))
+		ARM_SAVE(ARM_IDLECT3);
+	ARM_SAVE(ARM_EWUPCT);
+	ARM_SAVE(ARM_RSTCT1);
+	ARM_SAVE(ARM_RSTCT2);
+	ARM_SAVE(ARM_SYSST);
+	ULPD_SAVE(ULPD_CLOCK_CTRL);
+	ULPD_SAVE(ULPD_STATUS_REQ);
+
+	/* (Step 3 removed - we now allow deep sleep by default) */
+
+	/*
+	 * Step 4: OMAP DSP Shutdown
+	 */
+
+	/* stop DSP */
+	omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1);
+
+	/* shut down dsp_ck */
+	omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL);
+
+	/* temporarily enabling api_ck to access DSP registers */
+	omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+	/* save DSP registers */
+	DSP_SAVE(DSP_IDLECT2);
+
+	/* Stop all DSP domain clocks */
+	__raw_writew(0, DSP_IDLECT2);
+
+	/*
+	 * Step 5: Wakeup Event Setup
+	 */
+
+	omap_pm_wakeup_setup();
+
+	/*
+	 * Step 6: ARM and Traffic controller shutdown
+	 */
+
+	/* disable ARM watchdog */
+	omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
+	omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
+
+	/*
+	 * Step 6b: ARM and Traffic controller shutdown
+	 *
+	 * Step 6 continues here. Prepare jump to power management
+	 * assembly code in internal SRAM.
+	 *
+	 * Since the omap_cpu_suspend routine has been copied to
+	 * SRAM, we'll do an indirect procedure call to it and pass the
+	 * contents of arm_idlect1 and arm_idlect2 so it can restore
+	 * them when it wakes up and it will return.
+	 */
+
+	arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
+	arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
+
+	/*
+	 * Step 6c: ARM and Traffic controller shutdown
+	 *
+	 * Jump to assembly code. The processor will stay there
+	 * until wake up.
+	 */
+        omap_sram_suspend(arg0, arg1);
+
+	/*
+	 * If we are here, processor is woken up!
+	 */
+
+	/*
+	 * Restore DSP clocks
+	 */
+
+	/* again temporarily enabling api_ck to access DSP registers */
+	omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+	/* Restore DSP domain clocks */
+	DSP_RESTORE(DSP_IDLECT2);
+
+	/*
+	 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
+	 */
+
+	if (!(cpu_is_omap15xx()))
+		ARM_RESTORE(ARM_IDLECT3);
+	ARM_RESTORE(ARM_CKCTL);
+	ARM_RESTORE(ARM_EWUPCT);
+	ARM_RESTORE(ARM_RSTCT1);
+	ARM_RESTORE(ARM_RSTCT2);
+	ARM_RESTORE(ARM_SYSST);
+	ULPD_RESTORE(ULPD_CLOCK_CTRL);
+	ULPD_RESTORE(ULPD_STATUS_REQ);
+
+	if (cpu_is_omap730()) {
+		MPUI730_RESTORE(EMIFS_CONFIG);
+		MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
+		MPUI730_RESTORE(OMAP_IH1_MIR);
+		MPUI730_RESTORE(OMAP_IH2_0_MIR);
+		MPUI730_RESTORE(OMAP_IH2_1_MIR);
+	} else if (cpu_is_omap15xx()) {
+		MPUI1510_RESTORE(MPUI_CTRL);
+		MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
+		MPUI1510_RESTORE(EMIFS_CONFIG);
+		MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
+		MPUI1510_RESTORE(OMAP_IH1_MIR);
+		MPUI1510_RESTORE(OMAP_IH2_MIR);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_RESTORE(MPUI_CTRL);
+		MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
+		MPUI1610_RESTORE(EMIFS_CONFIG);
+		MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
+
+		MPUI1610_RESTORE(OMAP_IH1_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_0_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_1_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_2_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_3_MIR);
+	}
+
+	omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
+	/*
+	 * Reenable interrupts
+	 */
+
+	local_irq_enable();
+	local_fiq_enable();
+
+	omap_serial_wake_trigger(0);
+
+	printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
+
+	if (machine_is_omap_osk()) {
+		/* Let LED1 (D9) blink again */
+		tps65010_set_led(LED1, BLINK);
+	}
+}
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+static int g_read_completed;
+
+/*
+ * Read system PM registers for debugging
+ */
+static int omap_pm_read_proc(
+	char *page_buffer,
+	char **my_first_byte,
+	off_t virtual_start,
+	int length,
+	int *eof,
+	void *data)
+{
+	int my_buffer_offset = 0;
+	char * const my_base = page_buffer;
+
+	ARM_SAVE(ARM_CKCTL);
+	ARM_SAVE(ARM_IDLECT1);
+	ARM_SAVE(ARM_IDLECT2);
+	if (!(cpu_is_omap15xx()))
+		ARM_SAVE(ARM_IDLECT3);
+	ARM_SAVE(ARM_EWUPCT);
+	ARM_SAVE(ARM_RSTCT1);
+	ARM_SAVE(ARM_RSTCT2);
+	ARM_SAVE(ARM_SYSST);
+
+	ULPD_SAVE(ULPD_IT_STATUS);
+	ULPD_SAVE(ULPD_CLOCK_CTRL);
+	ULPD_SAVE(ULPD_SOFT_REQ);
+	ULPD_SAVE(ULPD_STATUS_REQ);
+	ULPD_SAVE(ULPD_DPLL_CTRL);
+	ULPD_SAVE(ULPD_POWER_CTRL);
+
+	if (cpu_is_omap730()) {
+		MPUI730_SAVE(MPUI_CTRL);
+		MPUI730_SAVE(MPUI_DSP_STATUS);
+		MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI730_SAVE(EMIFS_CONFIG);
+	} else if (cpu_is_omap15xx()) {
+		MPUI1510_SAVE(MPUI_CTRL);
+		MPUI1510_SAVE(MPUI_DSP_STATUS);
+		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI1510_SAVE(EMIFS_CONFIG);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_SAVE(MPUI_CTRL);
+		MPUI1610_SAVE(MPUI_DSP_STATUS);
+		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI1610_SAVE(EMIFS_CONFIG);
+	}
+
+	if (virtual_start == 0) {
+		g_read_completed = 0;
+
+		my_buffer_offset += sprintf(my_base + my_buffer_offset,
+		   "ARM_CKCTL_REG:            0x%-8x     \n"
+		   "ARM_IDLECT1_REG:          0x%-8x     \n"
+		   "ARM_IDLECT2_REG:          0x%-8x     \n"
+		   "ARM_IDLECT3_REG:	      0x%-8x     \n"
+		   "ARM_EWUPCT_REG:           0x%-8x     \n"
+		   "ARM_RSTCT1_REG:           0x%-8x     \n"
+		   "ARM_RSTCT2_REG:           0x%-8x     \n"
+		   "ARM_SYSST_REG:            0x%-8x     \n"
+		   "ULPD_IT_STATUS_REG:       0x%-4x     \n"
+		   "ULPD_CLOCK_CTRL_REG:      0x%-4x     \n"
+		   "ULPD_SOFT_REQ_REG:        0x%-4x     \n"
+		   "ULPD_DPLL_CTRL_REG:       0x%-4x     \n"
+		   "ULPD_STATUS_REQ_REG:      0x%-4x     \n"
+		   "ULPD_POWER_CTRL_REG:      0x%-4x     \n",
+		   ARM_SHOW(ARM_CKCTL),
+		   ARM_SHOW(ARM_IDLECT1),
+		   ARM_SHOW(ARM_IDLECT2),
+		   ARM_SHOW(ARM_IDLECT3),
+		   ARM_SHOW(ARM_EWUPCT),
+		   ARM_SHOW(ARM_RSTCT1),
+		   ARM_SHOW(ARM_RSTCT2),
+		   ARM_SHOW(ARM_SYSST),
+		   ULPD_SHOW(ULPD_IT_STATUS),
+		   ULPD_SHOW(ULPD_CLOCK_CTRL),
+		   ULPD_SHOW(ULPD_SOFT_REQ),
+		   ULPD_SHOW(ULPD_DPLL_CTRL),
+		   ULPD_SHOW(ULPD_STATUS_REQ),
+		   ULPD_SHOW(ULPD_POWER_CTRL));
+
+		if (cpu_is_omap730()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI730_CTRL_REG	     0x%-8x \n"
+			   "MPUI730_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+			   "MPUI730_DSP_API_CONFIG_REG:  0x%-8x \n"
+			   "MPUI730_SDRAM_CONFIG_REG:    0x%-8x \n"
+			   "MPUI730_EMIFS_CONFIG_REG:    0x%-8x \n",
+			   MPUI730_SHOW(MPUI_CTRL),
+			   MPUI730_SHOW(MPUI_DSP_STATUS),
+			   MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
+			   MPUI730_SHOW(MPUI_DSP_API_CONFIG),
+			   MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
+			   MPUI730_SHOW(EMIFS_CONFIG));
+		} else if (cpu_is_omap15xx()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI1510_CTRL_REG             0x%-8x \n"
+			   "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+			   "MPUI1510_DSP_API_CONFIG_REG:  0x%-8x \n"
+			   "MPUI1510_SDRAM_CONFIG_REG:    0x%-8x \n"
+			   "MPUI1510_EMIFS_CONFIG_REG:    0x%-8x \n",
+			   MPUI1510_SHOW(MPUI_CTRL),
+			   MPUI1510_SHOW(MPUI_DSP_STATUS),
+			   MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
+			   MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
+			   MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
+			   MPUI1510_SHOW(EMIFS_CONFIG));
+		} else if (cpu_is_omap16xx()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI1610_CTRL_REG             0x%-8x \n"
+			   "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+			   "MPUI1610_DSP_API_CONFIG_REG:  0x%-8x \n"
+			   "MPUI1610_SDRAM_CONFIG_REG:    0x%-8x \n"
+			   "MPUI1610_EMIFS_CONFIG_REG:    0x%-8x \n",
+			   MPUI1610_SHOW(MPUI_CTRL),
+			   MPUI1610_SHOW(MPUI_DSP_STATUS),
+			   MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
+			   MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
+			   MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
+			   MPUI1610_SHOW(EMIFS_CONFIG));
+		}
+
+		g_read_completed++;
+	} else if (g_read_completed >= 1) {
+		 *eof = 1;
+		 return 0;
+	}
+	g_read_completed++;
+
+	*my_first_byte = page_buffer;
+	return  my_buffer_offset;
+}
+
+static void omap_pm_init_proc(void)
+{
+	struct proc_dir_entry *entry;
+
+	entry = create_proc_read_entry("driver/omap_pm",
+				       S_IWUSR | S_IRUGO, NULL,
+				       omap_pm_read_proc, NULL);
+}
+
+#endif /* DEBUG && CONFIG_PROC_FS */
+
+static void (*saved_idle)(void) = NULL;
+
+/*
+ *	omap_pm_prepare - Do preliminary suspend work.
+ *	@state:		suspend state we're entering.
+ *
+ */
+static int omap_pm_prepare(suspend_state_t state)
+{
+	int error = 0;
+
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return error;
+}
+
+
+/*
+ *	omap_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+
+static int omap_pm_enter(suspend_state_t state)
+{
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		omap_pm_suspend();
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/**
+ *	omap_pm_finish - Finish up suspend sequence.
+ *	@state:		State we're coming out of.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+
+static int omap_pm_finish(suspend_state_t state)
+{
+	pm_idle = saved_idle;
+	return 0;
+}
+
+
+static irqreturn_t  omap_wakeup_interrupt(int  irq, void *  dev,
+				     struct pt_regs *  regs)
+{
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+	.name		= "peripheral wakeup",
+	.flags		= SA_INTERRUPT,
+	.handler	= omap_wakeup_interrupt
+};
+
+
+
+static struct pm_ops omap_pm_ops ={
+	.pm_disk_mode	= 0,
+	.prepare	= omap_pm_prepare,
+	.enter		= omap_pm_enter,
+	.finish		= omap_pm_finish,
+};
+
+static int __init omap_pm_init(void)
+{
+	printk("Power Management for TI OMAP.\n");
+
+	/*
+	 * We copy the assembler sleep/wakeup routines to SRAM.
+	 * These routines need to be in SRAM as that's the only
+	 * memory the MPU can see when it wakes up.
+	 */
+	if (cpu_is_omap730()) {
+		omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
+						omap730_idle_loop_suspend_sz);
+		omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
+						   omap730_cpu_suspend_sz);
+	} else if (cpu_is_omap15xx()) {
+		omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+						omap1510_idle_loop_suspend_sz);
+		omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+						   omap1510_cpu_suspend_sz);
+	} else if (cpu_is_omap16xx()) {
+		omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+						omap1610_idle_loop_suspend_sz);
+		omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+						   omap1610_cpu_suspend_sz);
+	}
+
+	if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+		printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+		return -ENODEV;
+	}
+
+	pm_idle = omap_pm_idle;
+
+	if (cpu_is_omap730())
+		setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
+	else if (cpu_is_omap16xx())
+		setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+
+	/* Program new power ramp-up time
+	 * (0 for most boards since we don't lower voltage when in deep sleep)
+	 */
+	omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
+
+	/* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
+	omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
+
+	/* Configure IDLECT3 */
+	if (cpu_is_omap730())
+		omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
+	else if (cpu_is_omap16xx())
+		omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
+	pm_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+	omap_pm_init_proc();
+#endif
+
+	subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+
+	if (cpu_is_omap16xx()) {
+		/* configure LOW_PWR pin */
+		omap_cfg_reg(T20_1610_LOW_PWR);
+	}
+
+	return 0;
+}
+__initcall(omap_pm_init);
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index e924e0c..9b4cd69 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -30,9 +30,9 @@
 #include <asm/arch/pm.h>
 #endif
 
-static struct clk * uart1_ck = NULL;
-static struct clk * uart2_ck = NULL;
-static struct clk * uart3_ck = NULL;
+static struct clk * uart1_ck;
+static struct clk * uart2_ck;
+static struct clk * uart3_ck;
 
 static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
 					  int offset)
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/mach-omap1/sleep.S
similarity index 92%
rename from arch/arm/plat-omap/sleep.S
rename to arch/arm/mach-omap1/sleep.S
index 4cd7d29..e58295e 100644
--- a/arch/arm/plat-omap/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/plat-omap/sleep.S
+ * linux/arch/arm/mach-omap1/sleep.S
  *
  * Low-level OMAP730/1510/1610 sleep/wakeUp support
  *
@@ -383,60 +383,133 @@
 	mcr	p15, 0, r0, c7, c10, 4
 	nop
 
-	@ load base address of Traffic Controller
+	@ Load base address of Traffic Controller
 	mov	r6, #TCMIF_ASM_BASE & 0xff000000
 	orr	r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
 	orr	r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
 
-	@ prepare to put SDRAM into self-refresh manually
+	@ Prepare to put SDRAM into self-refresh manually
 	ldr	r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 	orr	r9, r7, #SELF_REFRESH_MODE & 0xff000000
 	orr	r9, r9, #SELF_REFRESH_MODE & 0x000000ff
 	str	r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 
-	@ prepare to put EMIFS to Sleep
+	@ Prepare to put EMIFS to Sleep
 	ldr	r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 	orr	r9, r8, #IDLE_EMIFS_REQUEST & 0xff
 	str	r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 
-	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
+	@ Load base address of ARM_IDLECT1 and ARM_IDLECT2
 	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
 	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
 	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
 
-	@ turn off clock domains
-	@ do not disable PERCK (0x04)
+	@ Turn off clock domains
+	@ Do not disable PERCK (0x04)
 	mov	r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
 	orr	r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
 	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 
-	@ request ARM idle
+	@ Request ARM idle
 	mov	r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
 	orr	r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
 	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
-	@ disable instruction cache
-	mrc	p15, 0, r9, c1, c0, 0
-	bic	r2, r9, #0x1000
-	mcr	p15, 0, r2, c1, c0, 0
-	nop
-
 /*
  * Let's wait for the next wake up event to wake us up. r0 can't be
  * used here because r0 holds ARM_IDLECT1
  */
 	mov	r2, #0
 	mcr	p15, 0, r2, c7, c0, 4		@ wait for interrupt
+
+	@ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
+	@ according to this formula:
+	@ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
+	@ Max DPLL_MULT = 18
+	@ DPLL_DIV = 1
+	@ ARMDIV = 1
+	@ => 74 nop-instructions
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@10
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@20
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@30
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@40
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@50
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@60
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@70
+	nop
+	nop
+	nop
+	nop	@74
 /*
  * omap1610_cpu_suspend()'s resume point.
  *
  * It will just start executing here, so we'll restore stuff from the
  * stack.
  */
-	@ re-enable Icache
-	mcr	p15, 0, r9, c1, c0, 0
-
-	@ reset the ARM_IDLECT1 and ARM_IDLECT2.
+	@ Restore the ARM_IDLECT1 and ARM_IDLECT2.
 	strh	r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 	strh	r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
@@ -444,7 +517,7 @@
 	str	r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 	str	r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 
-	@ restore regs and return
+	@ Restore regs and return
 	ldmfd	sp!, {r0 - r12, pc}
 
 ENTRY(omap1610_cpu_suspend_sz)
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index cdbf4d7..a85fe60 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -51,8 +51,6 @@
 
 struct sys_timer omap_timer;
 
-#ifdef CONFIG_OMAP_MPU_TIMER
-
 /*
  * ---------------------------------------------------------------------------
  * MPU timer
@@ -222,195 +220,6 @@
 
 	return cycles_2_ns(ticks64);
 }
-#endif	/* CONFIG_OMAP_MPU_TIMER */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-
-#ifdef CONFIG_ARCH_OMAP15XX
-#error OMAP 32KHz timer does not currently work on 15XX!
-#endif
-
-/*
- * ---------------------------------------------------------------------------
- * 32KHz OS timer
- *
- * This currently works only on 16xx, as 1510 does not have the continuous
- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
- * on 1510 would be possible, but the timer would not be as accurate as
- * with the 32KHz synchronized timer.
- * ---------------------------------------------------------------------------
- */
-#define OMAP_32K_TIMER_BASE		0xfffb9000
-#define OMAP_32K_TIMER_CR		0x08
-#define OMAP_32K_TIMER_TVR		0x00
-#define OMAP_32K_TIMER_TCR		0x04
-
-#define OMAP_32K_TICKS_PER_HZ		(32768 / HZ)
-
-/*
- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
- * so with HZ = 100, TVR = 327.68.
- */
-#define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
-#define TIMER_32K_SYNCHRONIZED		0xfffbc410
-
-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
-				(((nr_jiffies) * (clock_rate)) / HZ)
-
-static inline void omap_32k_timer_write(int val, int reg)
-{
-	omap_writew(val, reg + OMAP_32K_TIMER_BASE);
-}
-
-static inline unsigned long omap_32k_timer_read(int reg)
-{
-	return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
-}
-
-/*
- * The 32KHz synchronized timer is an additional timer on 16xx.
- * It is always running.
- */
-static inline unsigned long omap_32k_sync_timer_read(void)
-{
-	return omap_readl(TIMER_32K_SYNCHRONIZED);
-}
-
-static inline void omap_32k_timer_start(unsigned long load_val)
-{
-	omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
-	omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
-}
-
-static inline void omap_32k_timer_stop(void)
-{
-	omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
-}
-
-/*
- * Rounds down to nearest usec. Note that this will overflow for larger values.
- */
-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
-{
-	return (ticks_32k * 5*5*5*5*5*5) >> 9;
-}
-
-/*
- * Rounds down to nearest nsec.
- */
-static inline unsigned long long
-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
-{
-	return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
-}
-
-static unsigned long omap_32k_last_tick = 0;
-
-/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
-	unsigned long now = omap_32k_sync_timer_read();
-	return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
-	return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
-}
-
-/*
- * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
- * function is also called from other interrupts to remove latency
- * issues with dynamic tick. In the dynamic tick case, we need to lock
- * with irqsave.
- */
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
-					    struct pt_regs *regs)
-{
-	unsigned long flags;
-	unsigned long now;
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-	now = omap_32k_sync_timer_read();
-
-	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
-		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
-		timer_tick(regs);
-	}
-
-	/* Restart timer so we don't drift off due to modulo or dynamic tick.
-	 * By default we program the next timer to be continuous to avoid
-	 * latencies during high system load. During dynamic tick operation the
-	 * continuous timer can be overridden from pm_idle to be longer.
-	 */
-	omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-/*
- * Programs the next timer interrupt needed. Called when dynamic tick is
- * enabled, and to reprogram the ticks to skip from pm_idle. Note that
- * we can keep the timer continuous, and don't need to set it to run in
- * one-shot mode. This is because the timer will get reprogrammed again
- * after next interrupt.
- */
-void omap_32k_timer_reprogram(unsigned long next_tick)
-{
-	omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
-}
-
-static struct irqaction omap_32k_timer_irq;
-extern struct timer_update_handler timer_update;
-
-static int omap_32k_timer_enable_dyn_tick(void)
-{
-	/* No need to reprogram timer, just use the next interrupt */
-	return 0;
-}
-
-static int omap_32k_timer_disable_dyn_tick(void)
-{
-	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-	return 0;
-}
-
-static struct dyn_tick_timer omap_dyn_tick_timer = {
-	.enable		= omap_32k_timer_enable_dyn_tick,
-	.disable	= omap_32k_timer_disable_dyn_tick,
-	.reprogram	= omap_32k_timer_reprogram,
-	.handler	= omap_32k_timer_interrupt,
-};
-#endif	/* CONFIG_NO_IDLE_HZ */
-
-static struct irqaction omap_32k_timer_irq = {
-	.name		= "32KHz timer",
-	.flags		= SA_INTERRUPT | SA_TIMER,
-	.handler	= omap_32k_timer_interrupt,
-};
-
-static __init void omap_init_32k_timer(void)
-{
-
-#ifdef CONFIG_NO_IDLE_HZ
-	omap_timer.dyn_tick = &omap_dyn_tick_timer;
-#endif
-
-	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
-	omap_timer.offset  = omap_32k_timer_gettimeoffset;
-	omap_32k_last_tick = omap_32k_sync_timer_read();
-	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-}
-#endif	/* CONFIG_OMAP_32K_TIMER */
 
 /*
  * ---------------------------------------------------------------------------
@@ -419,13 +228,7 @@
  */
 static void __init omap_timer_init(void)
 {
-#if defined(CONFIG_OMAP_MPU_TIMER)
 	omap_init_mpu_timer();
-#elif defined(CONFIG_OMAP_32K_TIMER)
-	omap_init_32k_timer();
-#else
-#error No system timer selected in Kconfig!
-#endif
 }
 
 struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 5788809..537dd2e 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -20,3 +20,6 @@
 	bool "OMAP 2420 H4 board"
 	depends on ARCH_OMAP2 && ARCH_OMAP24XX
 
+config MACH_OMAP_APOLLON
+	bool "OMAP 2420 Apollon board"
+	depends on ARCH_OMAP2 && ARCH_OMAP24XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 4204116..111eaa6 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,11 +3,15 @@
 #
 
 # Common support
-obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o
 
 obj-$(CONFIG_OMAP_MPU_TIMER)		+= timer-gp.o
 
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
+obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
 
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
new file mode 100644
index 0000000..6c6ba17
--- /dev/null
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -0,0 +1,285 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-apollon.c
+ *
+ * Copyright (C) 2005,2006 Samsung Electronics
+ * Author: Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Modified from mach-omap/omap2/board-h4.c
+ *
+ * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
+ * the bootloader passes the board-specific data to the kernel.
+ * Do not put any board specific code to this file; create a new machine
+ * type if you need custom low-level initializations.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include "prcm-regs.h"
+
+/* LED & Switch macros */
+#define LED0_GPIO13		13
+#define LED1_GPIO14		14
+#define LED2_GPIO15		15
+#define SW_ENTER_GPIO16		16
+#define SW_UP_GPIO17		17
+#define SW_DOWN_GPIO58		58
+
+static struct mtd_partition apollon_partitions[] = {
+	{
+		.name		= "X-Loader + U-Boot",
+		.offset		= 0,
+		.size		= SZ_128K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_128K,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M,
+	},
+	{
+		.name		= "rootfs",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_16M,
+	},
+	{
+		.name		= "filesystem00",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_32M,
+	},
+	{
+		.name		= "filesystem01",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data apollon_flash_data = {
+	.parts		= apollon_partitions,
+	.nr_parts	= ARRAY_SIZE(apollon_partitions),
+};
+
+static struct resource apollon_flash_resource = {
+	.start		= APOLLON_CS0_BASE,
+	.end		= APOLLON_CS0_BASE + SZ_128K,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device apollon_onenand_device = {
+	.name		= "onenand",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &apollon_flash_data,
+	},
+	.num_resources	= ARRAY_SIZE(&apollon_flash_resource),
+	.resource	= &apollon_flash_resource,
+};
+
+static struct resource apollon_smc91x_resources[] = {
+	[0] = {
+		.start	= APOLLON_ETHR_START,		/* Physical */
+		.end	= APOLLON_ETHR_START + 0xf,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+		.end	= OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device apollon_smc91x_device = {
+	.name		= "smc91x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(apollon_smc91x_resources),
+	.resource	= apollon_smc91x_resources,
+};
+
+static struct platform_device apollon_lcd_device = {
+	.name		= "apollon_lcd",
+	.id		= -1,
+};
+
+static struct platform_device *apollon_devices[] __initdata = {
+	&apollon_onenand_device,
+	&apollon_smc91x_device,
+	&apollon_lcd_device,
+};
+
+static inline void __init apollon_init_smc91x(void)
+{
+	/* Make sure CS1 timings are correct */
+	GPMC_CONFIG1_1 = 0x00011203;
+	GPMC_CONFIG2_1 = 0x001f1f01;
+	GPMC_CONFIG3_1 = 0x00080803;
+	GPMC_CONFIG4_1 = 0x1c091c09;
+	GPMC_CONFIG5_1 = 0x041f1f1f;
+	GPMC_CONFIG6_1 = 0x000004c4;
+	GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+	udelay(100);
+
+	omap_cfg_reg(W4__24XX_GPIO74);
+	if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+			APOLLON_ETHR_GPIO_IRQ);
+		return;
+	}
+	omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
+}
+
+static void __init omap_apollon_init_irq(void)
+{
+	omap2_init_common_hw();
+	omap_init_irq();
+	omap_gpio_init();
+	apollon_init_smc91x();
+}
+
+static struct omap_uart_config apollon_uart_config __initdata = {
+	.enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
+};
+
+static struct omap_mmc_config apollon_mmc_config __initdata = {
+	.mmc [0] = {
+		.enabled 	= 0,
+		.wire4		= 0,
+		.wp_pin		= -1,
+		.power_pin	= -1,
+		.switch_pin	= -1,
+	},
+};
+
+static struct omap_lcd_config apollon_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static struct omap_board_config_kernel apollon_config[] = {
+	{ OMAP_TAG_UART,	&apollon_uart_config },
+	{ OMAP_TAG_MMC,		&apollon_mmc_config },
+	{ OMAP_TAG_LCD,		&apollon_lcd_config },
+};
+
+static void __init apollon_led_init(void)
+{
+	/* LED0 - AA10 */
+	omap_cfg_reg(AA10_242X_GPIO13);
+	omap_request_gpio(LED0_GPIO13);
+	omap_set_gpio_direction(LED0_GPIO13, 0);
+	omap_set_gpio_dataout(LED0_GPIO13, 0);
+	/* LED1  - AA6 */
+	omap_cfg_reg(AA6_242X_GPIO14);
+	omap_request_gpio(LED1_GPIO14);
+	omap_set_gpio_direction(LED1_GPIO14, 0);
+	omap_set_gpio_dataout(LED1_GPIO14, 0);
+	/* LED2  - AA4 */
+	omap_cfg_reg(AA4_242X_GPIO15);
+	omap_request_gpio(LED2_GPIO15);
+	omap_set_gpio_direction(LED2_GPIO15, 0);
+	omap_set_gpio_dataout(LED2_GPIO15, 0);
+}
+
+static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+	static unsigned int led0, led1, led2;
+
+	if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16))
+		omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1);
+	else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17))
+		omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1);
+	else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58))
+		omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1);
+
+	return IRQ_HANDLED;
+}
+
+static void __init apollon_sw_init(void)
+{
+	/* Enter SW - Y11 */
+	omap_cfg_reg(Y11_242X_GPIO16);
+	omap_request_gpio(SW_ENTER_GPIO16);
+	omap_set_gpio_direction(SW_ENTER_GPIO16, 1);
+	/* Up SW - AA12 */
+	omap_cfg_reg(AA12_242X_GPIO17);
+	omap_request_gpio(SW_UP_GPIO17);
+	omap_set_gpio_direction(SW_UP_GPIO17, 1);
+	/* Down SW - AA8 */
+	omap_cfg_reg(AA8_242X_GPIO58);
+	omap_request_gpio(SW_DOWN_GPIO58);
+	omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
+
+	set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
+	if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
+				SA_SHIRQ, "enter sw",
+				&apollon_sw_interrupt))
+		return;
+	set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
+	if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
+				SA_SHIRQ, "up sw",
+				&apollon_sw_interrupt))
+		return;
+	set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
+	if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
+				SA_SHIRQ, "down sw",
+				&apollon_sw_interrupt))
+		return;
+}
+
+static void __init omap_apollon_init(void)
+{
+	apollon_led_init();
+	apollon_sw_init();
+
+	/* REVISIT: where's the correct place */
+	omap_cfg_reg(W19_24XX_SYS_NIRQ);
+
+	/*
+ 	 * Make sure the serial ports are muxed on at this point.
+	 * You have to mux them off in device drivers later on
+	 * if not needed.
+	 */
+	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
+	omap_board_config = apollon_config;
+	omap_board_config_size = ARRAY_SIZE(apollon_config);
+	omap_serial_init();
+}
+
+static void __init omap_apollon_map_io(void)
+{
+	omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= omap_apollon_map_io,
+	.init_irq	= omap_apollon_init_irq,
+	.init_machine	= omap_apollon_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index a300d63..4933fce 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -17,6 +17,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -25,15 +27,57 @@
 #include <asm/mach/flash.h>
 
 #include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/board.h>
 #include <asm/arch/common.h>
-#include <asm/arch/prcm.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/arch/dma.h>
+#include "prcm-regs.h"
 
 #include <asm/io.h>
 #include <asm/delay.h>
 
+static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+
+static int h4_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_A),
+	KEY(0, 3, KEY_B),
+	KEY(0, 4, KEY_C),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_F),
+	KEY(1, 4, KEY_G),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_I),
+	KEY(2, 2, KEY_J),
+	KEY(2, 3, KEY_K),
+	KEY(2, 4, KEY_3),
+	KEY(3, 0, KEY_M),
+	KEY(3, 1, KEY_N),
+	KEY(3, 2, KEY_O),
+	KEY(3, 3, KEY_P),
+	KEY(3, 4, KEY_Q),
+	KEY(4, 0, KEY_R),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_T),
+	KEY(4, 3, KEY_U),
+	KEY(4, 4, KEY_ENTER),
+	KEY(5, 0, KEY_V),
+	KEY(5, 1, KEY_W),
+	KEY(5, 2, KEY_L),
+	KEY(5, 3, KEY_S),
+	KEY(5, 4, KEY_ENTER),
+	0
+};
+
 static struct mtd_partition h4_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -108,9 +152,123 @@
 	.resource	= h4_smc91x_resources,
 };
 
+/* Select between the IrDA and aGPS module
+ */
+static int h4_select_irda(struct device *dev, int state)
+{
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x21))) {
+		printk(KERN_ERR "Error reading from I/O expander\n");
+		return err;
+	}
+
+	/* 'P6' enable/disable IRDA_TX and IRDA_RX */
+	if (state & IR_SEL) {	/* IrDa */
+		if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
+			printk(KERN_ERR "Error writing to I/O expander\n");
+			return err;
+		}
+	} else {
+		if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
+			printk(KERN_ERR "Error writing to I/O expander\n");
+			return err;
+		}
+	}
+	return err;
+}
+
+static void set_trans_mode(void *data)
+{
+	int *mode = data;
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
+		printk(KERN_ERR "Error reading from I/O expander\n");
+	}
+
+	expa &= ~0x01;
+
+	if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */
+		expa |= 0x01;
+	}
+
+	if ((err = write_gpio_expa(expa, 0x20)) != 0) {
+		printk(KERN_ERR "Error writing to I/O expander\n");
+	}
+}
+
+static int h4_transceiver_mode(struct device *dev, int mode)
+{
+	struct omap_irda_config *irda_config = dev->platform_data;
+
+	cancel_delayed_work(&irda_config->gpio_expa);
+	PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+	schedule_work(&irda_config->gpio_expa);
+
+	return 0;
+}
+
+static struct omap_irda_config h4_irda_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+	.transceiver_mode	= h4_transceiver_mode,
+	.select_irda	 	= h4_select_irda,
+	.rx_channel		= OMAP24XX_DMA_UART3_RX,
+	.tx_channel		= OMAP24XX_DMA_UART3_TX,
+	.dest_start		= OMAP_UART3_BASE,
+	.src_start		= OMAP_UART3_BASE,
+	.tx_trigger		= OMAP24XX_DMA_UART3_TX,
+	.rx_trigger		= OMAP24XX_DMA_UART3_RX,
+};
+
+static struct resource h4_irda_resources[] = {
+	[0] = {
+		.start	= INT_24XX_UART3_IRQ,
+		.end	= INT_24XX_UART3_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device h4_irda_device = {
+	.name		= "omapirda",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &h4_irda_data,
+	},
+	.num_resources	= 1,
+	.resource	= h4_irda_resources,
+};
+
+static struct omap_kp_platform_data h4_kp_data = {
+	.rows		= 6,
+	.cols		= 7,
+	.keymap 	= h4_keymap,
+	.rep		= 1,
+	.row_gpios 	= row_gpios,
+	.col_gpios 	= col_gpios,
+};
+
+static struct platform_device h4_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &h4_kp_data,
+	},
+};
+
+static struct platform_device h4_lcd_device = {
+	.name		= "lcd_h4",
+	.id		= -1,
+};
+
 static struct platform_device *h4_devices[] __initdata = {
 	&h4_smc91x_device,
 	&h4_flash_device,
+	&h4_irda_device,
+	&h4_kp_device,
+	&h4_lcd_device,
 };
 
 static inline void __init h4_init_smc91x(void)
@@ -157,7 +315,6 @@
 };
 
 static struct omap_lcd_config h4_lcd_config __initdata = {
-	.panel_name	= "h4",
 	.ctrl_name	= "internal",
 };
 
@@ -174,6 +331,19 @@
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+	omap_cfg_reg(K15_24XX_UART3_TX);
+	omap_cfg_reg(K14_24XX_UART3_RX);
+#endif
+
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+	if (omap_has_menelaus()) {
+		row_gpios[5] = 0;
+		col_gpios[2] = 15;
+		col_gpios[6] = 18;
+	}
+#endif
+
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap_board_config = h4_config;
 	omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180f675..72eb4bf 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -28,14 +28,14 @@
 
 #include <asm/arch/clock.h>
 #include <asm/arch/sram.h>
-#include <asm/arch/prcm.h>
 
+#include "prcm-regs.h"
+#include "memory.h"
 #include "clock.h"
 
 //#define DOWN_VARIABLE_DPLL 1			/* Experimental */
 
 static struct prcm_config *curr_prcm_set;
-static struct memory_timings mem_timings;
 static u32 curr_perf_level = PRCM_FULL_SPEED;
 
 /*-------------------------------------------------------------------------
@@ -54,11 +54,13 @@
 
 static u32 omap2_get_dpll_rate(struct clk * tclk)
 {
-	int dpll_clk, dpll_mult, dpll_div, amult;
+	long long dpll_clk;
+	int dpll_mult, dpll_div, amult;
 
 	dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff;	/* 10 bits */
 	dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f;	/* 4 bits */
-	dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
+	dpll_clk = (long long)tclk->parent->rate * dpll_mult;
+	do_div(dpll_clk, dpll_div + 1);
 	amult = CM_CLKSEL2_PLL & 0x3;
 	dpll_clk *= amult;
 
@@ -385,75 +387,23 @@
 		return 0;
 }
 
-static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
-{
-	unsigned long dll_cnt;
-	u32 fast_dll = 0;
-
-	mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
-
-	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
-	 * In the case of 2422, its ok to use CS1 instead of CS0.
-	 */
-
-#if 0	/* FIXME: Enable after 24xx cpu detection works */
-	ctype = get_cpu_type();
-	if (cpu_is_omap2422())
-		mem_timings.base_cs = 1;
-	else
-#endif
-		mem_timings.base_cs = 0;
-
-	if (mem_timings.m_type != M_DDR)
-		return;
-
-	/* With DDR we need to determine the low frequency DLL value */
-	if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
-		mem_timings.dll_mode = M_UNLOCK;
-	else
-		mem_timings.dll_mode = M_LOCK;
-
-	if (mem_timings.base_cs == 0) {
-		fast_dll = SDRC_DLLA_CTRL;
-		dll_cnt = SDRC_DLLA_STATUS & 0xff00;
-	} else {
-		fast_dll = SDRC_DLLB_CTRL;
-		dll_cnt = SDRC_DLLB_STATUS & 0xff00;
-	}
-	if (force_lock_to_unlock_mode) {
-		fast_dll &= ~0xff00;
-		fast_dll |= dll_cnt;		/* Current lock mode */
-	}
-	mem_timings.fast_dll_ctrl = fast_dll;
-
-	/* No disruptions, DDR will be offline & C-ABI not followed */
-	omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
-			    mem_timings.fast_dll_ctrl,
-			    mem_timings.base_cs,
-			    force_lock_to_unlock_mode);
-	mem_timings.slow_dll_ctrl &= 0xff00;	/* Keep lock value */
-
-	/* Turn status into unlock ctrl */
-	mem_timings.slow_dll_ctrl |=
-		((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
-
-	/* 90 degree phase for anything below 133Mhz */
-	mem_timings.slow_dll_ctrl |= (1 << 1);
-}
-
 static u32 omap2_reprogram_sdrc(u32 level, u32 force)
 {
+	u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
 	u32 prev = curr_perf_level, flags;
 
 	if ((curr_perf_level == level) && !force)
 		return prev;
 
+	m_type = omap2_memory_get_type();
+	slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+	fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+
 	if (level == PRCM_HALF_SPEED) {
 		local_irq_save(flags);
 		PRCM_VOLTSETUP = 0xffff;
 		omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
-					  mem_timings.slow_dll_ctrl,
-					  mem_timings.m_type);
+					  slow_dll_ctrl, m_type);
 		curr_perf_level = PRCM_HALF_SPEED;
 		local_irq_restore(flags);
 	}
@@ -461,8 +411,7 @@
 		local_irq_save(flags);
 		PRCM_VOLTSETUP = 0xffff;
 		omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
-					  mem_timings.fast_dll_ctrl,
-					  mem_timings.m_type);
+					  fast_dll_ctrl, m_type);
 		curr_perf_level = PRCM_FULL_SPEED;
 		local_irq_restore(flags);
 	}
@@ -650,7 +599,7 @@
 		case 13:				/* dss2 */
 			mask = 0x1; break;
 		case 25:				/* usb */
-			mask = 0xf; break;
+			mask = 0x7; break;
 		}
 	}
 
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 6cab20b..6c78d47 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -33,20 +33,6 @@
 #define RATE_IN_242X	(1 << 0)
 #define RATE_IN_243X	(1 << 1)
 
-/* Memory timings */
-#define M_DDR		1
-#define M_LOCK_CTRL	(1 << 2)
-#define M_UNLOCK	0
-#define M_LOCK		1
-
-struct memory_timings {
-	u32 m_type;		/* ddr = 1, sdr = 0 */
-	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
-	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
-	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
-	u32 base_cs;		/* base chip select to use for calculations */
-};
-
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
  * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
@@ -731,6 +717,16 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static struct clk emul_ck = {
+	.name		= "emul_ck",
+	.parent		= &func_54m_ck,
+	.flags		= CLOCK_IN_OMAP242X,
+	.enable_reg	= (void __iomem *)&PRCM_CLKEMUL_CTRL,
+	.enable_bit	= 0,
+	.recalc		= &omap2_propagate_rate,
+
+};
+
 /*
  * MPU clock domain
  *	Clocks:
@@ -1702,7 +1698,8 @@
 };
 
 static struct clk i2c2_ick = {
-	.name		= "i2c2_ick",
+	.name		= "i2c_ick",
+	.id		= 2,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1711,7 +1708,8 @@
 };
 
 static struct clk i2c2_fck = {
-	.name		= "i2c2_fck",
+	.name		= "i2c_fck",
+	.id		= 2,
 	.parent		= &func_12m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1729,7 +1727,8 @@
 };
 
 static struct clk i2c1_ick = {
-	.name		= "i2c1_ick",
+	.name		= "i2c_ick",
+	.id		= 1,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1738,7 +1737,8 @@
 };
 
 static struct clk i2c1_fck = {
-	.name		= "i2c1_fck",
+	.name		= "i2c_fck",
+	.id		= 1,
 	.parent		= &func_12m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1971,6 +1971,7 @@
 	&wdt1_osc_ck,
 	&sys_clkout,
 	&sys_clkout2,
+	&emul_ck,
 	/* mpu domain clocks */
 	&mpu_ck,
 	/* dsp domain clocks */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 7181edb..def9e53 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -74,6 +74,47 @@
 
 #endif
 
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP2_STI_BASE		IO_ADDRESS(0x48068000)
+#define OMAP2_STI_CHANNEL_BASE	0x54000000
+#define OMAP2_STI_IRQ		4
+
+static struct resource sti_resources[] = {
+	{
+		.start		= OMAP2_STI_BASE,
+		.end		= OMAP2_STI_BASE + 0x7ff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP2_STI_CHANNEL_BASE,
+		.end		= OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP2_STI_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device sti_device = {
+	.name		= "sti",
+	.id		= -1,
+	.dev = {
+		.release	= omap_nop_release,
+	},
+	.num_resources	= ARRAY_SIZE(sti_resources),
+	.resource	= sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+	platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -82,6 +123,7 @@
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_i2c();
+	omap_init_sti();
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 8ea67bf..7d57116 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -16,9 +16,13 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/mach/map.h>
+#include <asm/tlb.h>
 #include <asm/io.h>
+
+#include <asm/mach/map.h>
+
 #include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
 
 extern void omap_sram_init(void);
 extern int omap2_clk_init(void);
@@ -43,11 +47,24 @@
 	}
 };
 
-void __init omap_map_common_io(void)
+void __init omap2_map_common_io(void)
 {
 	iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+
+	/* Normally devicemaps_init() would flush caches and tlb after
+	 * mdesc->map_io(), but we must also do it here because of the CPU
+	 * revision check below.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+
 	omap2_check_revision();
 	omap_sram_init();
+	omapfb_reserve_mem();
+}
+
+void __init omap2_init_common_hw(void)
+{
 	omap2_mux_init();
 	omap2_clk_init();
 }
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
new file mode 100644
index 0000000..1d925d6
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.c
+ *
+ * Memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+
+#include "prcm-regs.h"
+#include "memory.h"
+
+static struct memory_timings mem_timings;
+
+u32 omap2_memory_get_slow_dll_ctrl(void)
+{
+	return mem_timings.slow_dll_ctrl;
+}
+
+u32 omap2_memory_get_fast_dll_ctrl(void)
+{
+	return mem_timings.fast_dll_ctrl;
+}
+
+u32 omap2_memory_get_type(void)
+{
+	return mem_timings.m_type;
+}
+
+void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+	unsigned long dll_cnt;
+	u32 fast_dll = 0;
+
+	mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+	 * In the case of 2422, its ok to use CS1 instead of CS0.
+	 */
+	if (cpu_is_omap2422())
+		mem_timings.base_cs = 1;
+	else
+		mem_timings.base_cs = 0;
+
+	if (mem_timings.m_type != M_DDR)
+		return;
+
+	/* With DDR we need to determine the low frequency DLL value */
+	if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+		mem_timings.dll_mode = M_UNLOCK;
+	else
+		mem_timings.dll_mode = M_LOCK;
+
+	if (mem_timings.base_cs == 0) {
+		fast_dll = SDRC_DLLA_CTRL;
+		dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+	} else {
+		fast_dll = SDRC_DLLB_CTRL;
+		dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+	}
+	if (force_lock_to_unlock_mode) {
+		fast_dll &= ~0xff00;
+		fast_dll |= dll_cnt;		/* Current lock mode */
+	}
+	/* set fast timings with DLL filter disabled */
+	mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8));
+
+	/* No disruptions, DDR will be offline & C-ABI not followed */
+	omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+			    mem_timings.fast_dll_ctrl,
+			    mem_timings.base_cs,
+			    force_lock_to_unlock_mode);
+	mem_timings.slow_dll_ctrl &= 0xff00;	/* Keep lock value */
+
+	/* Turn status into unlock ctrl */
+	mem_timings.slow_dll_ctrl |=
+		((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+	/* 90 degree phase for anything below 133Mhz + disable DLL filter */
+	mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
+}
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
new file mode 100644
index 0000000..d212eea
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.h
+ *
+ * Interface for memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * 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.
+ */
+
+/* Memory timings */
+#define M_DDR		1
+#define M_LOCK_CTRL	(1 << 2)
+#define M_UNLOCK	0
+#define M_LOCK		1
+
+struct memory_timings {
+	u32 m_type;		/* ddr = 1, sdr = 0 */
+	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
+	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
+	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
+	u32 base_cs;		/* base chip select to use for calculations */
+};
+
+extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+extern u32 omap2_memory_get_slow_dll_ctrl(void);
+extern u32 omap2_memory_get_fast_dll_ctrl(void);
+extern u32 omap2_memory_get_type(void);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index ea46548..1197dc3 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -50,9 +50,54 @@
 /* Menelaus interrupt */
 MUX_CFG_24XX("W19_24XX_SYS_NIRQ",	0x12c,	0,	1,	1,	1)
 
+/* 24xx clocks */
+MUX_CFG_24XX("W14_24XX_SYS_CLKOUT",	0x137,	0,	1,	1,	1)
+
+/* 24xx McBSP */
+MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX",	0x124,	1,	1,	0,	1)
+MUX_CFG_24XX("R14_24XX_MCBSP2_FSX",	0x125,	1,	1,	0,	1)
+MUX_CFG_24XX("W15_24XX_MCBSP2_DR",	0x126,	1,	1,	0,	1)
+MUX_CFG_24XX("V15_24XX_MCBSP2_DX",	0x127,	1,	1,	0,	1)
+
 /* 24xx GPIO */
+MUX_CFG_24XX("M21_242X_GPIO11",	 0x0c9,  3,      1,      1,      1)
+MUX_CFG_24XX("AA10_242X_GPIO13",	0x0e5,  3,      0,      0,      1)
+MUX_CFG_24XX("AA6_242X_GPIO14",	 0x0e6,  3,      0,      0,      1)
+MUX_CFG_24XX("AA4_242X_GPIO15",	 0x0e7,  3,      0,      0,      1)
+MUX_CFG_24XX("Y11_242X_GPIO16",	 0x0e8,  3,      0,      0,      1)
+MUX_CFG_24XX("AA12_242X_GPIO17",	0x0e9,  3,      0,      0,      1)
+MUX_CFG_24XX("AA8_242X_GPIO58",	 0x0ea,  3,      0,      0,      1)
 MUX_CFG_24XX("Y20_24XX_GPIO60",		0x12c,	3,	0,	0,	1)
+MUX_CFG_24XX("W4__24XX_GPIO74",	 0x0f2,  3,      0,      0,      1)
 MUX_CFG_24XX("M15_24XX_GPIO92",		0x10a,	3,	0,	0,	1)
+MUX_CFG_24XX("V14_24XX_GPIO117",	0x128,	3,	1,	0,	1)
+
+/* TSC IRQ */
+MUX_CFG_24XX("P20_24XX_TSC_IRQ",	0x108,	0,	0,	0,	1)
+
+/* UART3  */
+MUX_CFG_24XX("K15_24XX_UART3_TX",	0x118,	0,	0,	0,	1)
+MUX_CFG_24XX("K14_24XX_UART3_RX",	0x119,	0,	0,	0,	1)
+
+/* Keypad GPIO*/
+MUX_CFG_24XX("T19_24XX_KBR0",		0x106,	3,	1,	1,	1)
+MUX_CFG_24XX("R19_24XX_KBR1",		0x107,	3,	1,	1,	1)
+MUX_CFG_24XX("V18_24XX_KBR2",		0x139,	3,	1,	1,	1)
+MUX_CFG_24XX("M21_24XX_KBR3",		0xc9,	3,	1,	1,	1)
+MUX_CFG_24XX("E5__24XX_KBR4",		0x138,	3,	1,	1,	1)
+MUX_CFG_24XX("M18_24XX_KBR5",		0x10e,	3,	1,	1,	1)
+MUX_CFG_24XX("R20_24XX_KBC0",		0x108,	3,	0,	0,	1)
+MUX_CFG_24XX("M14_24XX_KBC1",		0x109,	3,	0,	0,	1)
+MUX_CFG_24XX("H19_24XX_KBC2",		0x114,	3,	0,	0,	1)
+MUX_CFG_24XX("V17_24XX_KBC3",		0x135,	3,	0,	0,	1)
+MUX_CFG_24XX("P21_24XX_KBC4",		0xca,	3,	0,	0,	1)
+MUX_CFG_24XX("L14_24XX_KBC5",		0x10f,	3,	0,	0,	1)
+MUX_CFG_24XX("N19_24XX_KBC6",		0x110,	3,	0,	0,	1)
+
+/* 24xx Menelaus Keypad GPIO */
+MUX_CFG_24XX("B3__24XX_KBR5",		0x30,	3,	1,	1,	1)
+MUX_CFG_24XX("AA4_24XX_KBC2",		0xe7,	3,	0,	0,	1)
+MUX_CFG_24XX("B13_24XX_KBC6",		0x110,	3,	0,	0,	1)
 
 };
 
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644
index 0000000..562168f
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap2/pm.c
+ *
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * 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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/pm.h>
+
+static struct clk *vclk;
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+static void (*saved_idle)(void);
+
+void omap2_pm_idle(void)
+{
+	local_irq_disable();
+	local_fiq_disable();
+	if (need_resched()) {
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+
+	/*
+	 * Since an interrupt may set up a timer, we don't want to
+	 * reprogram the hardware timer with interrupts enabled.
+	 * Re-enable interrupts only after returning from idle.
+	 */
+	timer_dyn_reprogram();
+
+	omap2_sram_idle();
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int omap2_pm_prepare(suspend_state_t state)
+{
+	int error = 0;
+
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return error;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		/* FIXME: Add suspend */
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int omap2_pm_finish(suspend_state_t state)
+{
+	pm_idle = saved_idle;
+	return 0;
+}
+
+static struct pm_ops omap_pm_ops = {
+	.pm_disk_mode	= 0,
+	.prepare	= omap2_pm_prepare,
+	.enter		= omap2_pm_enter,
+	.finish		= omap2_pm_finish,
+};
+
+int __init omap2_pm_init(void)
+{
+	printk("Power Management for TI OMAP.\n");
+
+	vclk = clk_get(NULL, "virt_prcm_set");
+	if (IS_ERR(vclk)) {
+		printk(KERN_ERR "Could not get PM vclk\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * We copy the assembler sleep/wakeup routines to SRAM.
+	 * These routines need to be in SRAM as that's the only
+	 * memory the MPU can see when it wakes up.
+	 */
+	omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+					 omap24xx_idle_loop_suspend_sz);
+
+	omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+					    omap24xx_cpu_suspend_sz);
+
+	pm_set_ops(&omap_pm_ops);
+	pm_idle = omap2_pm_idle;
+
+	return 0;
+}
+
+__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm-regs.h
similarity index 69%
rename from arch/arm/mach-omap2/prcm.h
rename to arch/arm/mach-omap2/prcm-regs.h
index 2eb89b9..22ac7be 100644
--- a/arch/arm/mach-omap2/prcm.h
+++ b/arch/arm/mach-omap2/prcm-regs.h
@@ -1,5 +1,7 @@
 /*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/arch/arm/mach-omap2/prcm-reg.h
+ *
+ * OMAP24XX Power Reset and Clock Management (PRCM) registers
  *
  * Copyright (C) 2005 Texas Instruments, Inc.
  *
@@ -18,8 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
-#define __ASM_ARM_ARCH_DPM_PRCM_H
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_H
 
 /* SET_PERFORMANCE_LEVEL PARAMETERS */
 #define PRCM_HALF_SPEED 1
@@ -159,54 +161,63 @@
 #define CM_FCLKEN_MDM		PRCM_REG32(0xC00)
 #define CM_ICLKEN_MDM		PRCM_REG32(0xC10)
 #define CM_IDLEST_MDM		PRCM_REG32(0xC20)
+#define CM_AUTOIDLE_MDM		PRCM_REG32(0xC30)
 #define CM_CLKSEL_MDM		PRCM_REG32(0xC40)
+#define CM_CLKSTCTRL_MDM	PRCM_REG32(0xC48)
+#define RM_RSTCTRL_MDM		PRCM_REG32(0xC50)
+#define RM_RSTST_MDM		PRCM_REG32(0xC58)
+#define PM_WKEN_MDM		PRCM_REG32(0xCA0)
+#define PM_WKST_MDM		PRCM_REG32(0xCB0)
+#define PM_WKDEP_MDM		PRCM_REG32(0xCC8)
+#define PM_PWSTCTRL_MDM		PRCM_REG32(0xCE0)
+#define PM_PWSTST_MDM		PRCM_REG32(0xCE4)
 
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE		(OMAP24XX_L4_IO_BASE+0x50000)
+#define OMAP24XX_L4_IO_BASE	0x48000000
+
+#define DISP_BASE		(OMAP24XX_L4_IO_BASE + 0x50000)
 #define DISP_REG32(offset)	__REG32(DISP_BASE + (offset))
 
-#define GPMC_BASE		(OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset)	__REG32(GPMC_BASE + (offset))
+#define OMAP24XX_GPMC_BASE	(L3_24XX_BASE + 0xa000)
+#define GPMC_REG32(offset)	__REG32(OMAP24XX_GPMC_BASE + (offset))
 
-#define GPT1_BASE		(OMAP24XX_GPT1)
+/* FIXME: Move these to timer code */
+#define GPT1_BASE		(0x48028000)
 #define GPT1_REG32(offset)	__REG32(GPT1_BASE + (offset))
 
 /* Misc sysconfig */
 #define DISPC_SYSCONFIG		DISP_REG32(0x410)
-#define SPI_BASE		(OMAP24XX_L4_IO_BASE+0x98000)
+#define SPI_BASE		(OMAP24XX_L4_IO_BASE + 0x98000)
 #define MCSPI1_SYSCONFIG	__REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG	__REG32(SPI_BASE+0x2000 + 0x10)
+#define MCSPI2_SYSCONFIG	__REG32(SPI_BASE + 0x2000 + 0x10)
+#define MCSPI3_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
 
-//#define DSP_MMU_SYSCONFIG	0x5A000010
-#define CAMERA_MMU_SYSCONFIG	__REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG	0x5D000010
-//#define DSP_DMA_SYSCONFIG	0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG	__REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG	__REG32(DISP_BASE+0x602C)
+#define CAMERA_MMU_SYSCONFIG	__REG32(DISP_BASE + 0x2C10)
+#define CAMERA_DMA_SYSCONFIG	__REG32(DISP_BASE + 0x282C)
+#define SYSTEM_DMA_SYSCONFIG	__REG32(DISP_BASE + 0x602C)
 #define GPMC_SYSCONFIG		GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG		0x5C060010
-#define SDRC_SYSCONFIG		__REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG		__REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG		__REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG	0x67FFFE10
+#define MAILBOXES_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+#define UART1_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+#define UART2_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+#define UART3_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+#define SDRC_SYSCONFIG		__REG32(OMAP24XX_SDRC_BASE + 0x10)
+#define OMAP24XX_SMS_BASE	(L3_24XX_BASE + 0x8000)
+#define SMS_SYSCONFIG		__REG32(OMAP24XX_SMS_BASE + 0x10)
+#define SSI_SYSCONFIG		__REG32(DISP_BASE + 0x8010)
 
 /* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2		(OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3		(OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4		(OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5		(OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6		(OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7		(OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8		(OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9		(OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10		(OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11		(OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12		(OMAP24XX_L4_IO_BASE+0x8A000)
+#define OMAP24XX_GPT2		(OMAP24XX_L4_IO_BASE + 0x2A000)
+#define OMAP24XX_GPT3		(OMAP24XX_L4_IO_BASE + 0x78000)
+#define OMAP24XX_GPT4		(OMAP24XX_L4_IO_BASE + 0x7A000)
+#define OMAP24XX_GPT5		(OMAP24XX_L4_IO_BASE + 0x7C000)
+#define OMAP24XX_GPT6		(OMAP24XX_L4_IO_BASE + 0x7E000)
+#define OMAP24XX_GPT7		(OMAP24XX_L4_IO_BASE + 0x80000)
+#define OMAP24XX_GPT8		(OMAP24XX_L4_IO_BASE + 0x82000)
+#define OMAP24XX_GPT9		(OMAP24XX_L4_IO_BASE + 0x84000)
+#define OMAP24XX_GPT10		(OMAP24XX_L4_IO_BASE + 0x86000)
+#define OMAP24XX_GPT11		(OMAP24XX_L4_IO_BASE + 0x88000)
+#define OMAP24XX_GPT12		(OMAP24XX_L4_IO_BASE + 0x8A000)
 
+/* FIXME: Move these to timer code */
 #define GPTIMER1_SYSCONFIG	GPT1_REG32(0x010)
 #define GPTIMER2_SYSCONFIG	__REG32(OMAP24XX_GPT2 + 0x10)
 #define GPTIMER3_SYSCONFIG	__REG32(OMAP24XX_GPT3 + 0x10)
@@ -220,12 +231,18 @@
 #define GPTIMER11_SYSCONFIG	__REG32(OMAP24XX_GPT11 + 0x10)
 #define GPTIMER12_SYSCONFIG	__REG32(OMAP24XX_GPT12 + 0x10)
 
-#define GPIOX_BASE(X)		(OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+/* FIXME: Move these to gpio code */
+#define OMAP24XX_GPIO_BASE	0x48018000
+#define GPIOX_BASE(X)		(OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
 
-#define GPIO1_SYSCONFIG		__REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG		__REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG		__REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG		__REG32((GPIOX_BASE(4)+0x10))
+#define GPIO1_SYSCONFIG		__REG32((GPIOX_BASE(1) + 0x10))
+#define GPIO2_SYSCONFIG		__REG32((GPIOX_BASE(2) + 0x10))
+#define GPIO3_SYSCONFIG		__REG32((GPIOX_BASE(3) + 0x10))
+#define GPIO4_SYSCONFIG		__REG32((GPIOX_BASE(4) + 0x10))
+
+#if defined(CONFIG_ARCH_OMAP243X)
+#define GPIO5_SYSCONFIG		__REG32((OMAP24XX_GPIO5_BASE + 0x10))
+#endif
 
 /* GP TIMER 1 */
 #define GPTIMER1_TISTAT		GPT1_REG32(0x014)
@@ -243,15 +260,15 @@
 #define GPTIMER1_TCAR2		GPT1_REG32(0x044)
 
 /* rkw -- base fix up please... */
-#define GPTIMER3_TISR		__REG32(OMAP24XX_L4_IO_BASE+0x78018)
+#define GPTIMER3_TISR		__REG32(OMAP24XX_L4_IO_BASE + 0x78018)
 
 /* SDRC */
-#define SDRC_DLLA_CTRL		__REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS	__REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL		__REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS	__REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER		__REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0		__REG32(OMAP24XX_SDRC_BASE+0x084)
+#define SDRC_DLLA_CTRL		__REG32(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_DLLA_STATUS	__REG32(OMAP24XX_SDRC_BASE + 0x064)
+#define SDRC_DLLB_CTRL		__REG32(OMAP24XX_SDRC_BASE + 0x068)
+#define SDRC_DLLB_STATUS	__REG32(OMAP24XX_SDRC_BASE + 0x06C)
+#define SDRC_POWER		__REG32(OMAP24XX_SDRC_BASE + 0x070)
+#define SDRC_MR_0		__REG32(OMAP24XX_SDRC_BASE + 0x084)
 
 /* GPIO 1 */
 #define GPIO1_BASE		GPIOX_BASE(1)
@@ -278,6 +295,8 @@
 #define GPIO2_DATAIN		GPIO2_REG32(0x038)
 #define GPIO2_OE		GPIO2_REG32(0x034)
 #define GPIO2_DATAOUT		GPIO2_REG32(0x03C)
+#define GPIO2_DEBOUNCENABLE	GPIO2_REG32(0x050)
+#define GPIO2_DEBOUNCINGTIME	GPIO2_REG32(0x054)
 
 /* GPIO 3 */
 #define GPIO3_BASE		GPIOX_BASE(3)
@@ -294,6 +313,8 @@
 #define GPIO3_DATAOUT		GPIO3_REG32(0x03C)
 #define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
 #define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
+#define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
 
 /* GPIO 4 */
 #define GPIO4_BASE		GPIOX_BASE(4)
@@ -311,10 +332,26 @@
 #define GPIO4_DEBOUNCENABLE	GPIO4_REG32(0x050)
 #define GPIO4_DEBOUNCINGTIME	GPIO4_REG32(0x054)
 
+#if defined(CONFIG_ARCH_OMAP243X)
+/* GPIO 5 */
+#define GPIO5_REG32(offset)	__REG32((OMAP24XX_GPIO5_BASE + (offset)))
+#define GPIO5_IRQENABLE1	GPIO5_REG32(0x01C)
+#define GPIO5_IRQSTATUS1	GPIO5_REG32(0x018)
+#define GPIO5_IRQENABLE2	GPIO5_REG32(0x02C)
+#define GPIO5_IRQSTATUS2	GPIO5_REG32(0x028)
+#define GPIO5_WAKEUPENABLE	GPIO5_REG32(0x020)
+#define GPIO5_RISINGDETECT	GPIO5_REG32(0x048)
+#define GPIO5_FALLINGDETECT	GPIO5_REG32(0x04C)
+#define GPIO5_DATAIN		GPIO5_REG32(0x038)
+#define GPIO5_OE		GPIO5_REG32(0x034)
+#define GPIO5_DATAOUT		GPIO5_REG32(0x03C)
+#define GPIO5_DEBOUNCENABLE	GPIO5_REG32(0x050)
+#define GPIO5_DEBOUNCINGTIME	GPIO5_REG32(0x054)
+#endif
 
 /* IO CONFIG */
-#define CONTROL_BASE		(OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset)	__REG32(CONTROL_BASE + (offset))
+#define OMAP24XX_CTRL_BASE		(L4_24XX_BASE)
+#define CONTROL_REG32(offset)		__REG32(OMAP24XX_CTRL_BASE + (offset))
 
 #define CONTROL_PADCONF_SPI1_NCS2	CONTROL_REG32(0x104)
 #define CONTROL_PADCONF_SYS_XTALOUT	CONTROL_REG32(0x134)
@@ -322,15 +359,18 @@
 #define CONTROL_PADCONF_MCBSP1_DX	CONTROL_REG32(0x10C)
 #define CONTROL_PADCONF_GPMC_NCS4	CONTROL_REG32(0x090)
 #define CONTROL_PADCONF_DSS_D5		CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9		CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D9		CONTROL_REG32(0x0BC)	/* 2420 */
 #define CONTROL_PADCONF_DSS_D13		CONTROL_REG32(0x0C0)
 #define CONTROL_PADCONF_DSS_VSYNC	CONTROL_REG32(0x0CC)
+#define CONTROL_PADCONF_SYS_NIRQW0	CONTROL_REG32(0x0BC)	/* 2430 */
+#define CONTROL_PADCONF_SSI1_FLAG_TX	CONTROL_REG32(0x108)	/* 2430 */
 
 /* CONTROL */
 #define CONTROL_DEVCONF		CONTROL_REG32(0x274)
+#define CONTROL_DEVCONF1	CONTROL_REG32(0x2E8)
 
 /* INTERRUPT CONTROLLER */
-#define INTC_BASE		(OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_BASE		((L4_24XX_BASE) + 0xfe000)
 #define INTC_REG32(offset)	__REG32(INTC_BASE + (offset))
 
 #define INTC1_U_BASE		INTC_REG32(0x000)
@@ -348,10 +388,12 @@
 #define INTC_ISR_CLEAR2		INTC_REG32(0x0D4)
 #define INTC_SIR_IRQ		INTC_REG32(0x040)
 #define INTC_CONTROL		INTC_REG32(0x048)
-#define INTC_ILR11		INTC_REG32(0x12C)
+#define INTC_ILR11		INTC_REG32(0x12C)	/* PRCM on MPU PIC */
+#define INTC_ILR30		INTC_REG32(0x178)
+#define INTC_ILR31		INTC_REG32(0x17C)
 #define INTC_ILR32		INTC_REG32(0x180)
-#define INTC_ILR37		INTC_REG32(0x194)
-#define INTC_SYSCONFIG		INTC_REG32(0x010)
+#define INTC_ILR37		INTC_REG32(0x194)	/* GPIO4 on MPU PIC */
+#define INTC_SYSCONFIG		INTC_REG32(0x010)	/* GPT1 on MPU PIC */
 
 /* RAM FIREWALL */
 #define RAMFW_BASE		(0x68005000)
@@ -373,6 +415,24 @@
 #define GPMC_CONFIG6_0		GPMC_REG32(0x074)
 #define GPMC_CONFIG7_0		GPMC_REG32(0x078)
 
+/* GPMC CS1 */
+#define GPMC_CONFIG1_1		GPMC_REG32(0x090)
+#define GPMC_CONFIG2_1		GPMC_REG32(0x094)
+#define GPMC_CONFIG3_1		GPMC_REG32(0x098)
+#define GPMC_CONFIG4_1		GPMC_REG32(0x09C)
+#define GPMC_CONFIG5_1		GPMC_REG32(0x0a0)
+#define GPMC_CONFIG6_1		GPMC_REG32(0x0a4)
+#define GPMC_CONFIG7_1		GPMC_REG32(0x0a8)
+
+/* GPMC CS3 */
+#define GPMC_CONFIG1_3		GPMC_REG32(0x0F0)
+#define GPMC_CONFIG2_3		GPMC_REG32(0x0F4)
+#define GPMC_CONFIG3_3		GPMC_REG32(0x0F8)
+#define GPMC_CONFIG4_3		GPMC_REG32(0x0FC)
+#define GPMC_CONFIG5_3		GPMC_REG32(0x100)
+#define GPMC_CONFIG6_3		GPMC_REG32(0x104)
+#define GPMC_CONFIG7_3		GPMC_REG32(0x108)
+
 /* DSS */
 #define DSS_CONTROL		DISP_REG32(0x040)
 #define DISPC_CONTROL		DISP_REG32(0x440)
@@ -405,11 +465,15 @@
 #define DISPC_DATA_CYCLE2	DISP_REG32(0x5D8)
 #define DISPC_DATA_CYCLE3	DISP_REG32(0x5DC)
 
-/* Wake up define for board */
-#define GPIO97			(1 << 1)
-#define GPIO88			(1 << 24)
+/* HSUSB Suspend */
+#define HSUSB_CTRL		__REG8(0x480AC001)
+#define USBOTG_POWER		__REG32(0x480AC000)
 
-#endif /* __ASSEMBLER__ */
+/* HS MMC */
+#define MMCHS1_SYSCONFIG	__REG32(0x4809C010)
+#define MMCHS2_SYSCONFIG	__REG32(0x480b4010)
+
+#endif	/* __ASSEMBLER__ */
 
 #endif
 
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
new file mode 100644
index 0000000..8893479
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm.c
@@ -0,0 +1,40 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm.c
+ *
+ * OMAP 24xx Power Reset and Clock Management (PRCM) functions
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include "prcm-regs.h"
+
+u32 omap_prcm_get_reset_sources(void)
+{
+	return RM_RSTST_WKUP & 0x7f;
+}
+EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+
+/* Resets clock rates and reboots the system. Only called from system.h */
+void omap_prcm_arch_reset(char mode)
+{
+	u32 rate;
+	struct clk *vclk, *sclk;
+
+	vclk = clk_get(NULL, "virt_prcm_set");
+	sclk = clk_get(NULL, "sys_ck");
+	rate = clk_get_rate(sclk);
+	clk_set_rate(vclk, rate);	/* go to bypass for OMAP limitation */
+	RM_RSTCTRL_WKUP |= 2;
+}
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644
index 0000000..00299cb
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep.S
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+#define A_32KSYNC_CR_V		IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+#define A_PRCM_VOLTCTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+#define A_PRCM_CLKCFG_CTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+#define A_CM_CLKEN_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+#define A_CM_IDLEST_CKGEN_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+#define A_CM_CLKSEL1_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+#define A_CM_CLKSEL2_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
+
+#define A_SDRC_DLLA_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+#define	A_SDRC_POWER_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+#define A_SDRC_RFR_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
+#define A_SDRC0_V		(0xC0000000)
+#define A_SDRC_MANUAL_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+	.text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap24xx_idle_loop_suspend)
+	stmfd	sp!, {r0, lr}		@ save registers on stack
+	mov	r0, #0			@ clear for mcr setup
+	mcr	p15, 0, r0, c7, c0, 4	@ wait for interrupt
+	ldmfd	sp!, {r0, pc}		@ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+	.word	. - omap24xx_idle_loop_suspend
+
+/*
+ * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 :	DLL ctrl value pre-Sleep
+ * R1 : Processor+Revision
+ *	2420: 0x21 = 242xES1, 0x26 = 242xES2.2
+ *	2430: 0x31 = 2430ES1, 0x32 = 2430ES2
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't.  We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL.  Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF.	It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
+	mov	r3, #0x0		@ clear for mrc call
+	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier, hope SDR/DDR finished
+	nop
+	nop
+	ldr	r3, A_SDRC_POWER	@ addr of sdrc power
+	ldr	r4, [r3]		@ value of sdrc power
+	orr	r4, r4, #0x40		@ enable self refresh on idle req
+	mov	r5, #0x2000		@ set delay (DPLL relock + DLL relock)
+	str	r4, [r3]		@ make it so
+	mov	r2, #0
+	nop
+	mcr	p15, 0, r2, c7, c0, 4	@ wait for interrupt
+	nop
+loop:
+	subs	r5, r5, #0x1		@ awake, wait just a bit
+	bne	loop
+
+	/* The DPLL has on before we take the DDR out of self refresh */
+	bic	r4, r4, #0x40		@ now clear self refresh bit.
+	str	r4, [r3]		@ put vlaue back.
+	ldr	r4, A_SDRC0		@ make a clock happen
+	ldr	r4, [r4]
+	nop				@ start auto refresh only after clk ok
+	movs	r0, r0			@ see if DDR or SDR
+	ldrne	r1, A_SDRC_DLLA_CTRL_S	@ get addr of DLL ctrl
+	strne	r0, [r1]		@ rewrite DLLA to force DLL reload
+	addne	r1, r1, #0x8		@ move to DLLB
+	strne	r0, [r1]		@ rewrite DLLB to force DLL reload
+
+	mov	r5, #0x1000
+loop2:
+	subs	r5, r5, #0x1
+	bne	loop2
+	/* resume*/
+	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return
+
+A_SDRC_POWER:
+	.word A_SDRC_POWER_V
+A_SDRC0:
+	.word A_SDRC0_V
+A_CM_CLKSEL2_PLL_S:
+	.word A_CM_CLKSEL2_PLL_V
+A_CM_CLKEN_PLL:
+	.word A_CM_CLKEN_PLL_V
+A_SDRC_DLLA_CTRL_S:
+	.word A_SDRC_DLLA_CTRL_V
+A_SDRC_MANUAL_S:
+	.word A_SDRC_MANUAL_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+	.word	. - omap24xx_cpu_suspend
+
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
index 2a869e2..d261e4f 100644
--- a/arch/arm/mach-omap2/sram-fn.S
+++ b/arch/arm/mach-omap2/sram-fn.S
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-omap1/sram.S
+ * linux/arch/arm/mach-omap2/sram.S
  *
  * Omap2 specific functions that need to be run in internal SRAM
  *
@@ -28,7 +28,7 @@
 #include <asm/arch/io.h>
 #include <asm/hardware.h>
 
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
 
 #define TIMER_32KSYNCT_CR_V	IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index b45560a..a042473 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -307,6 +307,10 @@
 		struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	sharpsl_save_param();
+	mi->nr_banks=1;
+	mi->bank[0].start = 0xa0000000;
+	mi->bank[0].node = 0;
+	mi->bank[0].size = (32*1024*1024);
 }
 
 MACHINE_START(POODLE, "SHARP Poodle")
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index ed07c41..ce7d810 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -50,9 +50,15 @@
 
 	  <http://zoo.weinigel.se/n30>.
 
+config MACH_SMDK
+	bool
+	help
+	  Common machine code for SMDK2410 and SMDK2440
+
 config ARCH_SMDK2410
 	bool "SMDK2410/A9M2410"
 	select CPU_S3C2410
+	select MACH_SMDK
 	help
 	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
            <http://www.fsforth.de>
@@ -60,6 +66,7 @@
 config ARCH_S3C2440
 	bool "SMDK2440"
 	select CPU_S3C2440
+	select MACH_SMDK
 	help
 	  Say Y here if you are using the SMDK2440.
 
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 1b3b476..3e5712d 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -48,3 +48,5 @@
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
 obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+
+obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
\ No newline at end of file
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index fec02c9..b7f85e6 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -249,7 +249,7 @@
 
 	/* if we started the UPLL, then allow to settle */
 
-	if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF))
+	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
 		udelay(200);
 
 	return 0;
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
new file mode 100644
index 0000000..36b8291
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -0,0 +1,134 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/arch/nand.h>
+
+#include "devs.h"
+#include "pm.h"
+
+/* NAND parititon from 2.4.18-swl5 */
+
+static struct mtd_partition smdk_default_nand_part[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_16K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "S3C2410 flash parition 1",
+		.offset = 0,
+		.size	= SZ_2M,
+	},
+	[2] = {
+		.name	= "S3C2410 flash partition 2",
+		.offset = SZ_4M,
+		.size	= SZ_4M,
+	},
+	[3] = {
+		.name	= "S3C2410 flash partition 3",
+		.offset	= SZ_8M,
+		.size	= SZ_2M,
+	},
+	[4] = {
+		.name	= "S3C2410 flash partition 4",
+		.offset = SZ_1M * 10,
+		.size	= SZ_4M,
+	},
+	[5] = {
+		.name	= "S3C2410 flash partition 5",
+		.offset	= SZ_1M * 14,
+		.size	= SZ_1M * 10,
+	},
+	[6] = {
+		.name	= "S3C2410 flash partition 6",
+		.offset	= SZ_1M * 24,
+		.size	= SZ_1M * 24,
+	},
+	[7] = {
+		.name	= "S3C2410 flash partition 7",
+		.offset = SZ_1M * 48,
+		.size	= SZ_16M,
+	}
+};
+
+static struct s3c2410_nand_set smdk_nand_sets[] = {
+	[0] = {
+		.name		= "NAND",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(smdk_default_nand_part),
+		.partitions	= smdk_default_nand_part,
+	},
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand smdk_nand_info = {
+	.tacls		= 20,
+	.twrph0		= 60,
+	.twrph1		= 20,
+	.nr_sets	= ARRAY_SIZE(smdk_nand_sets),
+	.sets		= smdk_nand_sets,
+};
+
+/* devices we initialise */
+
+static struct platform_device __initdata *smdk_devs[] = {
+	&s3c_device_nand,
+};
+
+void __init smdk_machine_init(void)
+{
+	/* Configure the LEDs (even if we have no LED support)*/
+
+	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+	s3c2410_gpio_setpin(S3C2410_GPF4, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF5, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF6, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF7, 1);
+
+	s3c_device_nand.dev.platform_data = &smdk_nand_info;
+
+	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
+
+	s3c2410_pm_init();
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h
new file mode 100644
index 0000000..0e3a3be
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 3e327b8..cc97fbf 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -232,8 +232,8 @@
 
 static struct s3c2410_platform_nand anubis_nand_info = {
 	.tacls		= 25,
-	.twrph0		= 80,
-	.twrph1		= 80,
+	.twrph0		= 55,
+	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
 	.sets		= anubis_nand_sets,
 	.select_chip	= anubis_nand_select,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 0260ed5..306afc1 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -32,6 +32,11 @@
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -46,6 +51,7 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-lcd.h>
 
+#include <asm/arch/nand.h>
 #include <asm/arch/fb.h>
 
 #include "clock.h"
@@ -170,12 +176,39 @@
 	},
 };
 
+static struct mtd_partition rx3715_nand_part[] = {
+	[0] = {
+		.name		= "Whole Flash",
+		.offset		= 0,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= MTD_WRITEABLE,
+	}
+};
+
+static struct s3c2410_nand_set rx3715_nand_sets[] = {
+	[0] = {
+		.name		= "Internal",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(rx3715_nand_part),
+		.partitions	= rx3715_nand_part,
+	},
+};
+
+static struct s3c2410_platform_nand rx3715_nand_info = {
+	.tacls		= 25,
+	.twrph0		= 50,
+	.twrph1		= 15,
+	.nr_sets	= ARRAY_SIZE(rx3715_nand_sets),
+	.sets		= rx3715_nand_sets,
+};
+
 static struct platform_device *rx3715_devices[] __initdata = {
 	&s3c_device_usb,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c,
 	&s3c_device_iis,
+	&s3c_device_nand,
 };
 
 static struct s3c24xx_board rx3715_board __initdata = {
@@ -185,6 +218,8 @@
 
 static void __init rx3715_map_io(void)
 {
+	s3c_device_nand.dev.platform_data = &rx3715_nand_info;
+
 	s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
 	s3c24xx_init_clocks(16934000);
 	s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 1e76e1f..2db932d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -28,7 +28,8 @@
  * Ben Dooks <ben@simtec.co.uk>
  *
  * 10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
- * 20-Sep-2005 BJD  Added static to non-exported items
+ * 20-Sep-2005 BJD   Added static to non-exported items
+ * 01-Apr-2006 BJD   Moved init code to common smdk
  *
  ***********************************************************************/
 
@@ -54,6 +55,8 @@
 #include "devs.h"
 #include "cpu.h"
 
+#include "common-smdk.h"
+
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
 };
@@ -107,11 +110,6 @@
 	s3c24xx_set_board(&smdk2410_board);
 }
 
-static void __init smdk2410_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
 	/* Maintainer: Jonas Dietsche */
@@ -119,7 +117,8 @@
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= smdk2410_map_io,
-	.init_irq	= smdk2410_init_irq,
+	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= smdk_machine_init,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index f431572..5fffd1d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -53,7 +53,8 @@
 #include "clock.h"
 #include "devs.h"
 #include "cpu.h"
-#include "pm.h"
+
+#include "common-smdk.h"
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
 	/* ISA IO Space map (memory space selected by A24) */
@@ -197,21 +198,9 @@
 
 static void __init smdk2440_machine_init(void)
 {
-	/* Configure the LEDs (even if we have no LED support)*/
-
-	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
-
-	s3c2410_gpio_setpin(S3C2410_GPF4, 0);
-	s3c2410_gpio_setpin(S3C2410_GPF5, 0);
-	s3c2410_gpio_setpin(S3C2410_GPF6, 0);
-	s3c2410_gpio_setpin(S3C2410_GPF7, 0);
-
 	s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
 
-	s3c2410_pm_init();
+	smdk_machine_init();
 }
 
 MACHINE_START(S3C2440, "SMDK2440")
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 1024540..676b5c5 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -11,7 +11,8 @@
  * published by the Free Software Foundation.
  *
  * ChangeLog:
- *  03-06-2004 John Lenz <jelenz@wisc.edu>
+ *  2006 Pavel Machek <pavel@suse.cz>
+ *  03-06-2004 John Lenz <lenz@cs.wisc.edu>
  *  06-04-2002 Chris Larson <kergoth@digitalnemesis.net>
  *  04-16-2001 Lineo Japan,Inc. ...
  */
@@ -87,12 +88,75 @@
 	.sclk_rate      = 11981000,
 };
 
+#ifdef CONFIG_SHARP_LOCOMO
+/*
+ * low-level UART features.
+ */
+static struct locomo_dev *uart_dev = NULL;
+
+static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ 	if (!uart_dev) return;
+
+ 	if (mctrl & TIOCM_RTS)
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+ 	else
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+
+ 	if (mctrl & TIOCM_DTR)
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+ 	else
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+}
+
+static u_int collie_uart_get_mctrl(struct uart_port *port)
+{
+	int ret = TIOCM_CD;
+	unsigned int r;
+	if (!uart_dev) return ret;
+
+	r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+	if (r & LOCOMO_GPIO_CTS)
+		ret |= TIOCM_CTS;
+	if (r & LOCOMO_GPIO_DSR)
+		ret |= TIOCM_DSR;
+
+	return ret;
+}
 
 static struct sa1100_port_fns collie_port_fns __initdata = {
 	.set_mctrl	= collie_uart_set_mctrl,
 	.get_mctrl	= collie_uart_get_mctrl,
 };
 
+static int collie_uart_probe(struct locomo_dev *dev)
+{
+	uart_dev = dev;
+	return 0;
+}
+
+static int collie_uart_remove(struct locomo_dev *dev)
+{
+	uart_dev = NULL;
+	return 0;
+}
+
+static struct locomo_driver collie_uart_driver = {
+	.drv = {
+		.name = "collie_uart",
+	},
+	.devid	= LOCOMO_DEVID_UART,
+	.probe	= collie_uart_probe,
+	.remove	= collie_uart_remove,
+};
+
+static int __init collie_uart_init(void) {
+	return locomo_driver_register(&collie_uart_driver);
+}
+device_initcall(collie_uart_init);
+
+#endif
+
 
 static struct resource locomo_resources[] = {
 	[0] = {
@@ -218,6 +282,12 @@
 {
 	sa1100_map_io();
 	iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc));
+
+#ifdef CONFIG_SHARP_LOCOMO
+	sa1100_register_uart_fns(&collie_port_fns);
+#endif
+	sa1100_register_uart(0, 3);
+	sa1100_register_uart(1, 1);
 }
 
 MACHINE_START(COLLIE, "Sharp-Collie")
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 8a1bfcd..50e6b6b 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 
+#include <asm/memory.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
@@ -272,6 +273,17 @@
 void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
+	if (arch_is_coherent()) {
+		void *virt;
+
+		virt = kmalloc(size, gfp);
+		if (!virt)
+			return NULL;
+		*handle =  virt_to_dma(dev, virt);
+
+		return virt;
+	}
+
 	return __dma_alloc(dev, size, handle, gfp,
 			   pgprot_noncached(pgprot_kernel));
 }
@@ -350,6 +362,11 @@
 
 	WARN_ON(irqs_disabled());
 
+	if (arch_is_coherent()) {
+		kfree(cpu_addr);
+		return;
+	}
+
 	size = PAGE_ALIGN(size);
 
 	spin_lock_irqsave(&consistent_lock, flags);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 5e5d05b..f14b2d0 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -389,6 +389,17 @@
 	kern_pgprot = user_pgprot = cp->pte;
 
 	/*
+	 * Enable CPU-specific coherency if supported.
+	 * (Only available on XSC3 at the moment.)
+	 */
+	if (arch_is_coherent()) {
+		if (cpu_is_xsc3()) {
+			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+			mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+		}
+	}
+
+	/*
 	 * ARMv6 and above have extended page tables.
 	 */
 	if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index b9dfce5..80873b3 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -371,7 +371,7 @@
 ENTRY(cpu_xsc3_set_pte)
 	str	r1, [r0], #-2048		@ linux version
 
-	bic	r2, r1, #0xff0
+	bic	r2, r1, #0xdf0			@ Keep C, B, coherency bits
 	orr	r2, r2, #PTE_TYPE_EXT		@ extended page
 
 	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 0887bb2..ec49495 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -70,13 +70,13 @@
 
 config OMAP_32K_TIMER
 	bool "Use 32KHz timer"
-	depends on ARCH_OMAP16XX
+	depends on ARCH_OMAP16XX || ARCH_OMAP24XX
 	help
 	  Select this option if you want to enable the OMAP 32KHz timer.
 	  This timer saves power compared to the OMAP_MPU_TIMER, and has
 	  support for no tick during idle. The 32KHz timer provides less
 	  intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
-	  currently only available for OMAP-16xx.
+	  currently only available for OMAP16XX and 24XX.
 
 endchoice
 
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9ccf194..2896b45 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,16 +3,16 @@
 #
 
 # Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
 obj-m :=
 obj-n :=
 obj-  :=
 
+obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
+
 # OCPI interconnect support for 1710, 1610 and 5912
 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
-# Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 3c2bfc0..06485c1 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>
@@ -37,17 +38,37 @@
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
 struct clk * clk_get(struct device *dev, const char *id)
 {
 	struct clk *p, *clk = ERR_PTR(-ENOENT);
+	int idno;
+
+	if (dev == NULL || dev->bus != &platform_bus_type)
+		idno = -1;
+	else
+		idno = to_platform_device(dev)->id;
 
 	mutex_lock(&clocks_mutex);
+
+	list_for_each_entry(p, &clocks, node) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
 	list_for_each_entry(p, &clocks, node) {
 		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
 			clk = p;
 			break;
 		}
 	}
+
 	mutex_unlock(&clocks_mutex);
 
 	return clk;
@@ -59,6 +80,9 @@
 	unsigned long flags;
 	int ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_enable)
 		ret = arch_clock->clk_enable(clk);
@@ -72,6 +96,9 @@
 {
 	unsigned long flags;
 
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_disable)
 		arch_clock->clk_disable(clk);
@@ -84,6 +111,9 @@
 	unsigned long flags;
 	int ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return 0;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	ret = clk->usecount;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -97,6 +127,9 @@
 	unsigned long flags;
 	unsigned long ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return 0;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	ret = clk->rate;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -121,6 +154,9 @@
 	unsigned long flags;
 	long ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_round_rate)
 		ret = arch_clock->clk_round_rate(clk, rate);
@@ -133,7 +169,10 @@
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret = -EINVAL;
+
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_rate)
@@ -147,7 +186,10 @@
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret = -EINVAL;
+
+	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
+		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_parent)
@@ -163,6 +205,9 @@
 	unsigned long flags;
 	struct clk * ret = NULL;
 
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_get_parent)
 		ret = arch_clock->clk_get_parent(clk);
@@ -199,6 +244,9 @@
 /* Used for clocks that always have same value as the parent clock */
 void followparent_recalc(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	clk->rate = clk->parent->rate;
 }
 
@@ -207,6 +255,9 @@
 {
 	struct clk *clkp;
 
+	if (tclk == NULL || IS_ERR(tclk))
+		return;
+
 	list_for_each_entry(clkp, &clocks, node) {
 		if (likely(clkp->parent != tclk))
 			continue;
@@ -217,6 +268,9 @@
 
 int clk_register(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
 	mutex_lock(&clocks_mutex);
 	list_add(&clk->node, &clocks);
 	if (clk->init)
@@ -229,6 +283,9 @@
 
 void clk_unregister(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	mutex_lock(&clocks_mutex);
 	list_del(&clk->node);
 	mutex_unlock(&clocks_mutex);
@@ -239,6 +296,9 @@
 {
 	unsigned long flags;
 
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_deny_idle)
 		arch_clock->clk_deny_idle(clk);
@@ -250,6 +310,9 @@
 {
 	unsigned long flags;
 
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_allow_idle)
 		arch_clock->clk_allow_idle(clk);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 9dcce90..079b67d 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -24,6 +24,7 @@
 #include <asm/arch/board.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/menelaus.h>
 
 
 void omap_nop_release(struct device *dev)
@@ -98,6 +99,62 @@
 #endif
 
 /*-------------------------------------------------------------------------*/
+#if	defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+static void omap_init_kp(void)
+{
+	if (machine_is_omap_h2() || machine_is_omap_h3()) {
+		omap_cfg_reg(F18_1610_KBC0);
+		omap_cfg_reg(D20_1610_KBC1);
+		omap_cfg_reg(D19_1610_KBC2);
+		omap_cfg_reg(E18_1610_KBC3);
+		omap_cfg_reg(C21_1610_KBC4);
+
+		omap_cfg_reg(G18_1610_KBR0);
+		omap_cfg_reg(F19_1610_KBR1);
+		omap_cfg_reg(H14_1610_KBR2);
+		omap_cfg_reg(E20_1610_KBR3);
+		omap_cfg_reg(E19_1610_KBR4);
+		omap_cfg_reg(N19_1610_KBR5);
+	} else if (machine_is_omap_perseus2()) {
+		omap_cfg_reg(E2_730_KBR0);
+		omap_cfg_reg(J7_730_KBR1);
+		omap_cfg_reg(E1_730_KBR2);
+		omap_cfg_reg(F3_730_KBR3);
+		omap_cfg_reg(D2_730_KBR4);
+
+		omap_cfg_reg(C2_730_KBC0);
+		omap_cfg_reg(D3_730_KBC1);
+		omap_cfg_reg(E4_730_KBC2);
+		omap_cfg_reg(F4_730_KBC3);
+		omap_cfg_reg(E3_730_KBC4);
+	} else if (machine_is_omap_h4()) {
+		omap_cfg_reg(T19_24XX_KBR0);
+		omap_cfg_reg(R19_24XX_KBR1);
+		omap_cfg_reg(V18_24XX_KBR2);
+		omap_cfg_reg(M21_24XX_KBR3);
+		omap_cfg_reg(E5__24XX_KBR4);
+		if (omap_has_menelaus()) {
+			omap_cfg_reg(B3__24XX_KBR5);
+			omap_cfg_reg(AA4_24XX_KBC2);
+			omap_cfg_reg(B13_24XX_KBC6);
+		} else {
+			omap_cfg_reg(M18_24XX_KBR5);
+			omap_cfg_reg(H19_24XX_KBC2);
+			omap_cfg_reg(N19_24XX_KBC6);
+		}
+		omap_cfg_reg(R20_24XX_KBC0);
+		omap_cfg_reg(M14_24XX_KBC1);
+		omap_cfg_reg(V17_24XX_KBC3);
+		omap_cfg_reg(P21_24XX_KBC4);
+		omap_cfg_reg(L14_24XX_KBC5);
+	}
+}
+#else
+static inline void omap_init_kp(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
 
 #if	defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
@@ -240,6 +297,55 @@
 static inline void omap_init_mmc(void) {}
 #endif
 
+/*-------------------------------------------------------------------------*/
+
+/* Numbering for the SPI-capable controllers when used for SPI:
+ * spi		= 1
+ * uwire	= 2
+ * mmc1..2	= 3..4
+ * mcbsp1..3	= 5..7
+ */
+
+#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE)
+
+#define	OMAP_UWIRE_BASE		0xfffb3000
+
+static struct resource uwire_resources[] = {
+	{
+		.start		= OMAP_UWIRE_BASE,
+		.end		= OMAP_UWIRE_BASE + 0x20,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device omap_uwire_device = {
+	.name	   = "omap_uwire",
+	.id	     = -1,
+	.dev = {
+		.release	= omap_nop_release,
+	},
+	.num_resources	= ARRAY_SIZE(uwire_resources),
+	.resource	= uwire_resources,
+};
+
+static void omap_init_uwire(void)
+{
+	/* FIXME define and use a boot tag; not all boards will be hooking
+	 * up devices to the microwire controller, and multi-board configs
+	 * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
+	 */
+
+	/* board-specific code must configure chipselects (only a few
+	 * are normally used) and SCLK/SDI/SDO (each has two choices).
+	 */
+	(void) platform_device_register(&omap_uwire_device);
+}
+#else
+static inline void omap_init_uwire(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #if	defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
 
 #ifdef CONFIG_ARCH_OMAP24XX
@@ -310,40 +416,6 @@
 static inline void omap_init_rng(void) {}
 #endif
 
-#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
-
-static struct omap_lcd_config omap_fb_conf;
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-
-static struct platform_device omap_fb_device = {
-	.name		= "omapfb",
-	.id		= -1,
-	.dev = {
-		.release		= omap_nop_release,
-		.dma_mask		= &omap_fb_dma_mask,
-		.coherent_dma_mask	= ~(u32)0,
-		.platform_data		= &omap_fb_conf,
-	},
-	.num_resources = 0,
-};
-
-static inline void omap_init_fb(void)
-{
-	const struct omap_lcd_config *conf;
-
-	conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
-	if (conf != NULL)
-		omap_fb_conf = *conf;
-	platform_device_register(&omap_fb_device);
-}
-
-#else
-
-static inline void omap_init_fb(void) {}
-
-#endif
-
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -369,9 +441,10 @@
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	omap_init_fb();
 	omap_init_i2c();
+	omap_init_kp();
 	omap_init_mmc();
+	omap_init_uwire();
 	omap_init_wdt();
 	omap_init_rng();
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index a4e5ac7..5dac423 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1258,6 +1258,11 @@
 	omap_writew(w, OMAP1610_DMA_LCD_CTRL);
 }
 
+int omap_lcd_dma_ext_running(void)
+{
+	return lcd_dma.ext_ctrl && lcd_dma.active;
+}
+
 /*----------------------------------------------------------------------------*/
 
 static int __init omap_init_dma(void)
@@ -1389,6 +1394,7 @@
 EXPORT_SYMBOL(omap_enable_lcd_dma);
 EXPORT_SYMBOL(omap_setup_lcd_dma);
 EXPORT_SYMBOL(omap_stop_lcd_dma);
+EXPORT_SYMBOL(omap_lcd_dma_ext_running);
 EXPORT_SYMBOL(omap_set_lcd_dma_b1);
 EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
 EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 38d7ebf..eba3cb5 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -97,6 +97,32 @@
 }
 
 
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+	int n;
+
+	/* If ARMXOR cannot be idled this function call is unnecessary */
+	if (!(inputmask & (1 << 1)))
+		return inputmask;
+
+	/* If any active timer is using ARMXOR return modified mask */
+	for (n = 0; dm_timers[n].base; ++n)
+		if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)&
+		    OMAP_TIMER_CTRL_ST) {
+			if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0)
+				inputmask &= ~(1 << 1);
+			else
+				inputmask &= ~(1 << 2);
+		}
+
+	return inputmask;
+}
+
+
 void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
 	int n = (timer - dm_timers) << 1;
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
new file mode 100644
index 0000000..305e9b9
--- /dev/null
+++ b/arch/arm/plat-omap/fb.c
@@ -0,0 +1,80 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static struct omapfb_platform_data omapfb_config;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+	.name		= "omapfb",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &omap_fb_dma_mask,
+		.coherent_dma_mask	= ~(u32)0,
+		.platform_data		= &omapfb_config,
+	},
+	.num_resources = 0,
+};
+
+/* called from map_io */
+void omapfb_reserve_mem(void)
+{
+	const struct omap_fbmem_config *fbmem_conf;
+
+	omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
+	omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+
+	fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+
+	if (fbmem_conf != NULL) {
+		/* indicate that the bootloader already initialized the
+		 * fb device, so we'll skip that part in the fb driver
+		 */
+		omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
+		omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
+		if (fbmem_conf->fb_sdram_size) {
+			pr_info("Reserving %u bytes SDRAM for frame buffer\n",
+				fbmem_conf->fb_sdram_size);
+			reserve_bootmem(fbmem_conf->fb_sdram_start,
+					fbmem_conf->fb_sdram_size);
+		}
+	}
+}
+
+static inline int omap_init_fb(void)
+{
+	const struct omap_lcd_config *conf;
+
+	conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+	if (conf == NULL)
+		return 0;
+
+	omapfb_config.lcd = *conf;
+
+	return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#else
+
+void omapfb_reserve_mem(void) {}
+
+#endif
+
+
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b4d5b9e..d3c8ea7 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -174,7 +174,7 @@
 static inline struct gpio_bank *get_gpio_bank(int gpio)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		if (OMAP_GPIO_IS_MPUIO(gpio))
 			return &gpio_bank[0];
 		return &gpio_bank[1];
@@ -223,7 +223,7 @@
 		return 0;
 	}
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510() && gpio < 16)
+	if (cpu_is_omap15xx() && gpio < 16)
 		return 0;
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
@@ -402,13 +402,13 @@
 	u32 gpio_bit = 1 << gpio;
 
 	MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-		trigger & IRQT_LOW);
+		trigger & __IRQT_LOWLVL);
 	MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-		trigger & IRQT_HIGH);
+		trigger & __IRQT_HIGHLVL);
 	MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-		trigger & IRQT_RISING);
+		trigger & __IRQT_RISEDGE);
 	MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-		trigger & IRQT_FALLING);
+		trigger & __IRQT_FALEDGE);
 	/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
 	 * triggering requested. */
 }
@@ -422,9 +422,9 @@
 	case METHOD_MPUIO:
 		reg += OMAP_MPUIO_GPIO_INT_EDGE;
 		l = __raw_readl(reg);
-		if (trigger == IRQT_RISING)
+		if (trigger & __IRQT_RISEDGE)
 			l |= 1 << gpio;
-		else if (trigger == IRQT_FALLING)
+		else if (trigger & __IRQT_FALEDGE)
 			l &= ~(1 << gpio);
 		else
 			goto bad;
@@ -432,9 +432,9 @@
 	case METHOD_GPIO_1510:
 		reg += OMAP1510_GPIO_INT_CONTROL;
 		l = __raw_readl(reg);
-		if (trigger == IRQT_RISING)
+		if (trigger & __IRQT_RISEDGE)
 			l |= 1 << gpio;
-		else if (trigger == IRQT_FALLING)
+		else if (trigger & __IRQT_FALEDGE)
 			l &= ~(1 << gpio);
 		else
 			goto bad;
@@ -446,20 +446,21 @@
 			reg += OMAP1610_GPIO_EDGE_CTRL1;
 		gpio &= 0x07;
 		/* We allow only edge triggering, i.e. two lowest bits */
-		if (trigger & ~IRQT_BOTHEDGE)
+		if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
 			BUG();
-		/* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
-		trigger &= 0x03;
 		l = __raw_readl(reg);
 		l &= ~(3 << (gpio << 1));
-		l |= trigger << (gpio << 1);
+		if (trigger & __IRQT_RISEDGE)
+			l |= 2 << (gpio << 1);
+		if (trigger & __IRQT_FALEDGE)
+			l |= 1 << (gpio << 1);
 		break;
 	case METHOD_GPIO_730:
 		reg += OMAP730_GPIO_INT_CONTROL;
 		l = __raw_readl(reg);
-		if (trigger == IRQT_RISING)
+		if (trigger & __IRQT_RISEDGE)
 			l |= 1 << gpio;
-		else if (trigger == IRQT_FALLING)
+		else if (trigger & __IRQT_FALEDGE)
 			l &= ~(1 << gpio);
 		else
 			goto bad;
@@ -491,7 +492,9 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+	if (type & IRQT_PROBE)
+		return -EINVAL;
+	if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
 		return -EINVAL;
 
 	bank = get_gpio_bank(gpio);
@@ -755,13 +758,32 @@
 	if (bank->method == METHOD_GPIO_24XX)
 		isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
 #endif
-
 	while(1) {
-		isr = __raw_readl(isr_reg);
-		_enable_gpio_irqbank(bank, isr, 0);
-		_clear_gpio_irqbank(bank, isr);
-		_enable_gpio_irqbank(bank, isr, 1);
-		desc->chip->unmask(irq);
+		u32 isr_saved, level_mask = 0;
+
+		isr_saved = isr = __raw_readl(isr_reg);
+
+		if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
+			isr &= 0x0000ffff;
+
+		if (cpu_is_omap24xx())
+			level_mask =
+				__raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0) |
+				__raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+
+		/* clear edge sensitive interrupts before handler(s) are
+		called so that we don't miss any interrupt occurred while
+		executing them */
+		_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+		_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+		_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+
+		/* if there is only edge sensitive GPIO pin interrupts
+		configured, we could unmask GPIO bank interrupt immediately */
+		if (!level_mask)
+			desc->chip->unmask(irq);
 
 		if (!isr)
 			break;
@@ -774,6 +796,20 @@
 			d = irq_desc + gpio_irq;
 			desc_handle_irq(gpio_irq, d, regs);
 		}
+
+		if (cpu_is_omap24xx()) {
+			/* clear level sensitive interrupts after handler(s) */
+			_enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+			_clear_gpio_irqbank(bank, isr_saved & level_mask);
+			_enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+		}
+
+		/* if bank has any level sensitive GPIO pin interrupt
+		configured, we must unmask the bank interrupt only after
+		handler(s) are executed in order to avoid spurious bank
+		interrupt */
+		if (level_mask)
+			desc->chip->unmask(irq);
 	}
 }
 
@@ -848,7 +884,7 @@
 
 	initialized = 1;
 
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		gpio_ick = clk_get(NULL, "arm_gpio_ck");
 		if (IS_ERR(gpio_ick))
 			printk("Could not get arm_gpio_ck\n");
@@ -869,7 +905,7 @@
 	}
 
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		printk(KERN_INFO "OMAP1510 GPIO hardware\n");
 		gpio_bank_count = 2;
 		gpio_bank = gpio_bank_1510;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 1cd2cac..196aac3 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -34,7 +34,7 @@
 #ifdef CONFIG_MCBSP_DEBUG
 #define DBG(x...)	printk(x)
 #else
-#define DBG(x...)	do { } while (0)
+#define DBG(x...)			do { } while (0)
 #endif
 
 struct omap_mcbsp {
@@ -44,6 +44,7 @@
 	omap_mcbsp_word_length       rx_word_length;
 	omap_mcbsp_word_length       tx_word_length;
 
+	omap_mcbsp_io_type_t         io_type; /* IRQ or poll */
 	/* IRQ based TX/RX */
 	int                          rx_irq;
 	int                          tx_irq;
@@ -64,10 +65,19 @@
 };
 
 static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+#ifdef CONFIG_ARCH_OMAP1
 static struct clk *mcbsp_dsp_ck = 0;
 static struct clk *mcbsp_api_ck = 0;
 static struct clk *mcbsp_dspxor_ck = 0;
-
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+static struct clk *mcbsp1_ick = 0;
+static struct clk *mcbsp1_fck = 0;
+static struct clk *mcbsp2_ick = 0;
+static struct clk *mcbsp2_fck = 0;
+static struct clk *sys_ck = 0;
+static struct clk *sys_clkout = 0;
+#endif
 
 static void omap_mcbsp_dump_reg(u8 id)
 {
@@ -88,7 +98,6 @@
 	DBG("***********************\n");
 }
 
-
 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
@@ -109,7 +118,6 @@
 	return IRQ_HANDLED;
 }
 
-
 static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
 {
 	struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
@@ -176,7 +184,7 @@
 		return 0;
 	}
 
-	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+	if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
 		if (id > OMAP_MAX_MCBSP_COUNT) {
 			printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
 			return -1;
@@ -187,9 +195,10 @@
 	return -1;
 }
 
+#ifdef CONFIG_ARCH_OMAP1
 static void omap_mcbsp_dsp_request(void)
 {
-	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+	if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
 		clk_enable(mcbsp_dsp_ck);
 		clk_enable(mcbsp_api_ck);
 
@@ -207,12 +216,49 @@
 
 static void omap_mcbsp_dsp_free(void)
 {
-	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+	if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
 		clk_disable(mcbsp_dspxor_ck);
 		clk_disable(mcbsp_dsp_ck);
 		clk_disable(mcbsp_api_ck);
 	}
 }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static void omap2_mcbsp2_mux_setup(void)
+{
+	omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
+	omap_cfg_reg(R14_24XX_MCBSP2_FSX);
+	omap_cfg_reg(W15_24XX_MCBSP2_DR);
+	omap_cfg_reg(V15_24XX_MCBSP2_DX);
+	omap_cfg_reg(V14_24XX_GPIO117);
+	omap_cfg_reg(W14_24XX_SYS_CLKOUT);
+}
+#endif
+
+/*
+ * We can choose between IRQ based or polled IO.
+ * This needs to be called before omap_mcbsp_request().
+ */
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
+{
+	if (omap_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	spin_lock(&mcbsp[id].lock);
+
+	if (!mcbsp[id].free) {
+		printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+		spin_unlock(&mcbsp[id].lock);
+		return -EINVAL;
+	}
+
+	mcbsp[id].io_type = io_type;
+
+	spin_unlock(&mcbsp[id].lock);
+
+	return 0;
+}
 
 int omap_mcbsp_request(unsigned int id)
 {
@@ -221,12 +267,26 @@
 	if (omap_mcbsp_check(id) < 0)
 		return -EINVAL;
 
+#ifdef CONFIG_ARCH_OMAP1
 	/*
 	 * On 1510, 1610 and 1710, McBSP1 and McBSP3
 	 * are DSP public peripherals.
 	 */
 	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
 		omap_mcbsp_dsp_request();
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+	if (cpu_is_omap24xx()) {
+		if (id == OMAP_MCBSP1) {
+			clk_enable(mcbsp1_ick);
+			clk_enable(mcbsp1_fck);
+		} else {
+			clk_enable(mcbsp2_ick);
+			clk_enable(mcbsp2_fck);
+		}
+	}
+#endif
 
 	spin_lock(&mcbsp[id].lock);
 	if (!mcbsp[id].free) {
@@ -238,30 +298,33 @@
 	mcbsp[id].free = 0;
 	spin_unlock(&mcbsp[id].lock);
 
-	/* We need to get IRQs here */
-	err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
-			  "McBSP",
-			  (void *) (&mcbsp[id]));
-	if (err != 0) {
-		printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
-		       mcbsp[id].tx_irq, mcbsp[id].id);
-		return err;
+	if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+		/* We need to get IRQs here */
+		err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+				  "McBSP",
+				  (void *) (&mcbsp[id]));
+		if (err != 0) {
+			printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+			       mcbsp[id].tx_irq, mcbsp[id].id);
+			return err;
+		}
+
+		init_completion(&(mcbsp[id].tx_irq_completion));
+
+
+		err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+				  "McBSP",
+				  (void *) (&mcbsp[id]));
+		if (err != 0) {
+			printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+			       mcbsp[id].rx_irq, mcbsp[id].id);
+			free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+			return err;
+		}
+
+		init_completion(&(mcbsp[id].rx_irq_completion));
 	}
 
-	init_completion(&(mcbsp[id].tx_irq_completion));
-
-
-	err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
-			  "McBSP",
-			  (void *) (&mcbsp[id]));
-	if (err != 0) {
-		printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
-		       mcbsp[id].rx_irq, mcbsp[id].id);
-		free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
-		return err;
-	}
-
-	init_completion(&(mcbsp[id].rx_irq_completion));
 	return 0;
 
 }
@@ -271,8 +334,24 @@
 	if (omap_mcbsp_check(id) < 0)
 		return;
 
-	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
-		omap_mcbsp_dsp_free();
+#ifdef CONFIG_ARCH_OMAP1
+	if (cpu_class_is_omap1()) {
+		if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+			omap_mcbsp_dsp_free();
+	}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+	if (cpu_is_omap24xx()) {
+		if (id == OMAP_MCBSP1) {
+			clk_disable(mcbsp1_ick);
+			clk_disable(mcbsp1_fck);
+		} else {
+			clk_disable(mcbsp2_ick);
+			clk_disable(mcbsp2_fck);
+		}
+	}
+#endif
 
 	spin_lock(&mcbsp[id].lock);
 	if (mcbsp[id].free) {
@@ -284,9 +363,11 @@
 	mcbsp[id].free = 1;
 	spin_unlock(&mcbsp[id].lock);
 
-	/* Free IRQs */
-	free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
-	free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+	if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+		/* Free IRQs */
+		free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+		free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+	}
 }
 
 /*
@@ -461,6 +542,115 @@
 }
 
 
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
+{
+	u32 io_base = mcbsp[id].io_base;
+	omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+	omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+	u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+	if (tx_word_length != rx_word_length)
+		return -EINVAL;
+
+	/* First we wait for the transmitter to be ready */
+	spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+	while (!(spcr2 & XRDY)) {
+		spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+		if (attempts++ > 1000) {
+			/* We must reset the transmitter */
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+			udelay(10);
+			printk("McBSP transmitter not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* Now we can push the data */
+	if (tx_word_length > OMAP_MCBSP_WORD_16)
+		OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+	OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+
+	/* We wait for the receiver to be ready */
+	spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+	while (!(spcr1 & RRDY)) {
+		spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+		if (attempts++ > 1000) {
+			/* We must reset the receiver */
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+			udelay(10);
+			printk("McBSP receiver not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* Receiver is ready, let's read the dummy data */
+	if (rx_word_length > OMAP_MCBSP_WORD_16)
+		word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+	word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+	return 0;
+}
+
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word)
+{
+	u32 io_base = mcbsp[id].io_base, clock_word = 0;
+	omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+	omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+	u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+	if (tx_word_length != rx_word_length)
+		return -EINVAL;
+
+	/* First we wait for the transmitter to be ready */
+	spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+	while (!(spcr2 & XRDY)) {
+		spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+		if (attempts++ > 1000) {
+			/* We must reset the transmitter */
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+			udelay(10);
+			printk("McBSP transmitter not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* We first need to enable the bus clock */
+	if (tx_word_length > OMAP_MCBSP_WORD_16)
+		OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16);
+	OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff);
+
+	/* We wait for the receiver to be ready */
+	spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+	while (!(spcr1 & RRDY)) {
+		spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+		if (attempts++ > 1000) {
+			/* We must reset the receiver */
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+			udelay(10);
+			printk("McBSP receiver not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* Receiver is ready, there is something for us */
+	if (rx_word_length > OMAP_MCBSP_WORD_16)
+		word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+	word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+	word[0] = (word_lsb | (word_msb << 16));
+
+	return 0;
+}
+
+
 /*
  * Simple DMA based buffer rx/tx routines.
  * Nothing fancy, just a single buffer tx/rx through DMA.
@@ -471,6 +661,9 @@
 int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
 {
 	int dma_tx_ch;
+	int src_port = 0;
+	int dest_port = 0;
+	int sync_dev = 0;
 
 	if (omap_mcbsp_check(id) < 0)
 		return -EINVAL;
@@ -487,20 +680,27 @@
 
 	init_completion(&(mcbsp[id].tx_dma_completion));
 
+	if (cpu_class_is_omap1()) {
+		src_port = OMAP_DMA_PORT_TIPB;
+		dest_port = OMAP_DMA_PORT_EMIFF;
+	}
+	if (cpu_is_omap24xx())
+		sync_dev = mcbsp[id].dma_tx_sync;
+
 	omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
 				     OMAP_DMA_DATA_TYPE_S16,
 				     length >> 1, 1,
 				     OMAP_DMA_SYNC_ELEMENT,
-				     0, 0);
+	 sync_dev, 0);
 
 	omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
-				 OMAP_DMA_PORT_TIPB,
+				 src_port,
 				 OMAP_DMA_AMODE_CONSTANT,
 				 mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
 				 0, 0);
 
 	omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
-				OMAP_DMA_PORT_EMIFF,
+				dest_port,
 				OMAP_DMA_AMODE_POST_INC,
 				buffer,
 				0, 0);
@@ -514,6 +714,9 @@
 int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
 {
 	int dma_rx_ch;
+	int src_port = 0;
+	int dest_port = 0;
+	int sync_dev = 0;
 
 	if (omap_mcbsp_check(id) < 0)
 		return -EINVAL;
@@ -530,20 +733,27 @@
 
 	init_completion(&(mcbsp[id].rx_dma_completion));
 
+	if (cpu_class_is_omap1()) {
+		src_port = OMAP_DMA_PORT_TIPB;
+		dest_port = OMAP_DMA_PORT_EMIFF;
+	}
+	if (cpu_is_omap24xx())
+		sync_dev = mcbsp[id].dma_rx_sync;
+
 	omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
 				     OMAP_DMA_DATA_TYPE_S16,
 				     length >> 1, 1,
 				     OMAP_DMA_SYNC_ELEMENT,
-				     0, 0);
+	 sync_dev, 0);
 
 	omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
-				OMAP_DMA_PORT_TIPB,
+				src_port,
 				OMAP_DMA_AMODE_CONSTANT,
 				mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
 				0, 0);
 
 	omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
-				 OMAP_DMA_PORT_EMIFF,
+				 dest_port,
 				 OMAP_DMA_AMODE_POST_INC,
 				 buffer,
 				 0, 0);
@@ -688,6 +898,23 @@
 };
 #endif
 
+#if defined(CONFIG_ARCH_OMAP24XX)
+static const struct omap_mcbsp_info mcbsp_24xx[] = {
+	[0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
+		.dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
+		.dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
+		.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
+		.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
+		},
+	[1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
+		.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
+		.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
+		.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
+		.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
+		},
+};
+#endif
+
 static int __init omap_mcbsp_init(void)
 {
 	int mcbsp_count = 0, i;
@@ -695,6 +922,7 @@
 
 	printk("Initializing OMAP McBSP system\n");
 
+#ifdef CONFIG_ARCH_OMAP1
 	mcbsp_dsp_ck = clk_get(0, "dsp_ck");
 	if (IS_ERR(mcbsp_dsp_ck)) {
 		printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
@@ -710,6 +938,29 @@
 		printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
 		return PTR_ERR(mcbsp_dspxor_ck);
 	}
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+	mcbsp1_ick = clk_get(0, "mcbsp1_ick");
+	if (IS_ERR(mcbsp1_ick)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
+		return PTR_ERR(mcbsp1_ick);
+	}
+	mcbsp1_fck = clk_get(0, "mcbsp1_fck");
+	if (IS_ERR(mcbsp1_fck)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
+		return PTR_ERR(mcbsp1_fck);
+	}
+	mcbsp2_ick = clk_get(0, "mcbsp2_ick");
+	if (IS_ERR(mcbsp2_ick)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
+		return PTR_ERR(mcbsp2_ick);
+	}
+	mcbsp2_fck = clk_get(0, "mcbsp2_fck");
+	if (IS_ERR(mcbsp2_fck)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
+		return PTR_ERR(mcbsp2_fck);
+	}
+#endif
 
 #ifdef CONFIG_ARCH_OMAP730
 	if (cpu_is_omap730()) {
@@ -718,7 +969,7 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		mcbsp_info = mcbsp_1510;
 		mcbsp_count = ARRAY_SIZE(mcbsp_1510);
 	}
@@ -729,6 +980,19 @@
 		mcbsp_count = ARRAY_SIZE(mcbsp_1610);
 	}
 #endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+	if (cpu_is_omap24xx()) {
+		mcbsp_info = mcbsp_24xx;
+		mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
+
+		/* REVISIT: where's the right place? */
+		omap2_mcbsp2_mux_setup();
+		sys_ck = clk_get(0, "sys_ck");
+		sys_clkout = clk_get(0, "sys_clkout");
+		clk_set_parent(sys_clkout, sys_ck);
+		clk_enable(sys_clkout);
+	}
+#endif
 	for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
 		if (i >= mcbsp_count) {
 			mcbsp[i].io_base = 0;
@@ -741,6 +1005,7 @@
 		mcbsp[i].dma_rx_lch = -1;
 
 		mcbsp[i].io_base = mcbsp_info[i].virt_base;
+		mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */
 		mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
 		mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
 		mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
@@ -751,11 +1016,11 @@
 	return 0;
 }
 
-
 arch_initcall(omap_mcbsp_init);
 
 EXPORT_SYMBOL(omap_mcbsp_config);
 EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_set_io_type);
 EXPORT_SYMBOL(omap_mcbsp_free);
 EXPORT_SYMBOL(omap_mcbsp_start);
 EXPORT_SYMBOL(omap_mcbsp_stop);
@@ -763,4 +1028,6 @@
 EXPORT_SYMBOL(omap_mcbsp_recv_word);
 EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
 EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
 EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index 5cc6775..37792d4 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -62,9 +62,6 @@
 	if (!cpu_is_omap16xx())
 		return -ENODEV;
 
-	/* Make sure there's clock for OCPI */
-	clk_enable(ocpi_ck);
-
 	/* Enable access for OHCI in OCPI */
 	val = omap_readl(OCPI_PROT);
 	val &= ~0xff;
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
index 093efd7..1a24e2c 100644
--- a/arch/arm/plat-omap/pm.c
+++ b/arch/arm/plat-omap/pm.c
@@ -38,6 +38,7 @@
 #include <linux/pm.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/pm.h>
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index ee82763..b7bf09b 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -16,24 +16,94 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/mach/map.h>
 #include <asm/tlb.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
+#include <asm/mach/map.h>
+
 #include <asm/arch/sram.h>
+#include <asm/arch/board.h>
 
 #define OMAP1_SRAM_PA		0x20000000
 #define OMAP1_SRAM_VA		0xd0000000
 #define OMAP2_SRAM_PA		0x40200000
+#define OMAP2_SRAM_PUB_PA	0x4020f800
 #define OMAP2_SRAM_VA		0xd0000000
+#define OMAP2_SRAM_PUB_VA	0xd0000800
 
+#if defined(CONFIG_ARCH_OMAP24XX)
+#define SRAM_BOOTLOADER_SZ	0x00
+#else
 #define SRAM_BOOTLOADER_SZ	0x80
+#endif
+
+#define VA_REQINFOPERM0		IO_ADDRESS(0x68005048)
+#define VA_READPERM0		IO_ADDRESS(0x68005050)
+#define VA_WRITEPERM0		IO_ADDRESS(0x68005058)
+#define VA_CONTROL_STAT		IO_ADDRESS(0x480002F8)
+#define GP_DEVICE		0x300
+#define TYPE_MASK		0x700
+
+#define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
 
 static unsigned long omap_sram_base;
 static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
+unsigned long omap_fb_sram_start;
+unsigned long omap_fb_sram_size;
+
+/* Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies.  The default accessable size for all device types is 2k. A GP
+ * device allows ARM11 but not other initators for full size. This
+ * functionality seems ok until some nice security API happens.
+ */
+static int is_sram_locked(void)
+{
+	int type = 0;
+
+	if (cpu_is_omap242x())
+		type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK;
+
+	if (type == GP_DEVICE) {
+		/* RAMFW: R/W access to all initators for all qualifier sets */
+		if (cpu_is_omap242x()) {
+			__raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */
+			__raw_writel(0xCFDE, VA_READPERM0);  /* all i-read */
+			__raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */
+		}
+		return 0;
+	} else
+		return 1; /* assume locked with no PPA or security driver */
+}
+
+void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
+		      unsigned long *start, unsigned long *size)
+{
+	const struct omap_fbmem_config *fbmem_conf;
+
+	fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+	if (fbmem_conf != NULL) {
+		*start = fbmem_conf->fb_sram_start;
+		*size = fbmem_conf->fb_sram_size;
+	} else {
+		*size = 0;
+		*start = 0;
+	}
+
+	if (*size && (
+	    *start < start_avail ||
+	    *start + *size > start_avail + size_avail)) {
+		printk(KERN_ERR "invalid FB SRAM configuration\n");
+		*start = start_avail;
+		*size = size_avail;
+	}
+
+	if (*size)
+		pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
+}
+
 /*
  * The amount of SRAM depends on the core type.
  * Note that we cannot try to test for SRAM here because writes
@@ -42,26 +112,45 @@
  */
 void __init omap_detect_sram(void)
 {
-	if (!cpu_is_omap24xx())
+	unsigned long sram_start;
+
+	if (cpu_is_omap24xx()) {
+		if (is_sram_locked()) {
+			omap_sram_base = OMAP2_SRAM_PUB_VA;
+			sram_start = OMAP2_SRAM_PUB_PA;
+			omap_sram_size = 0x800; /* 2K */
+		} else {
+			omap_sram_base = OMAP2_SRAM_VA;
+			sram_start = OMAP2_SRAM_PA;
+			if (cpu_is_omap242x())
+				omap_sram_size = 0xa0000; /* 640K */
+			else if (cpu_is_omap243x())
+				omap_sram_size = 0x10000; /* 64K */
+		}
+	} else {
 		omap_sram_base = OMAP1_SRAM_VA;
-	else
-		omap_sram_base = OMAP2_SRAM_VA;
+		sram_start = OMAP1_SRAM_PA;
 
-	if (cpu_is_omap730())
-		omap_sram_size = 0x32000;	/* 200K */
-	else if (cpu_is_omap15xx())
-		omap_sram_size = 0x30000;	/* 192K */
-	else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
-		omap_sram_size = 0x4000;	/* 16K */
-	else if (cpu_is_omap1611())
-		omap_sram_size = 0x3e800;	/* 250K */
-	else if (cpu_is_omap2420())
-		omap_sram_size = 0xa0014;	/* 640K */
-	else {
-		printk(KERN_ERR "Could not detect SRAM size\n");
-		omap_sram_size = 0x4000;
+		if (cpu_is_omap730())
+			omap_sram_size = 0x32000;	/* 200K */
+		else if (cpu_is_omap15xx())
+			omap_sram_size = 0x30000;	/* 192K */
+		else if (cpu_is_omap1610() || cpu_is_omap1621() ||
+		     cpu_is_omap1710())
+			omap_sram_size = 0x4000;	/* 16K */
+		else if (cpu_is_omap1611())
+			omap_sram_size = 0x3e800;	/* 250K */
+		else {
+			printk(KERN_ERR "Could not detect SRAM size\n");
+			omap_sram_size = 0x4000;
+		}
 	}
-
+	get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
+			 omap_sram_size - SRAM_BOOTLOADER_SZ,
+			 &omap_fb_sram_start, &omap_fb_sram_size);
+	if (omap_fb_sram_size)
+		omap_sram_size -= sram_start + omap_sram_size -
+				  omap_fb_sram_start;
 	omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
@@ -80,12 +169,20 @@
  */
 void __init omap_map_sram(void)
 {
+	unsigned long base;
+
 	if (omap_sram_size == 0)
 		return;
 
 	if (cpu_is_omap24xx()) {
 		omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
-		omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
+
+		if (is_sram_locked())
+			base = OMAP2_SRAM_PUB_PA;
+		else
+			base = OMAP2_SRAM_PA;
+		base = ROUND_DOWN(base, PAGE_SIZE);
+		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
 	}
 
 	omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
@@ -93,7 +190,8 @@
 	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
 	printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
-	       omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
+	__pfn_to_phys(omap_sram_io_desc[0].pfn),
+	omap_sram_io_desc[0].virtual,
 	       omap_sram_io_desc[0].length);
 
 	/*
@@ -118,8 +216,9 @@
 		printk(KERN_ERR "Not enough space in SRAM\n");
 		return NULL;
 	}
+
 	omap_sram_ceil -= size;
-	omap_sram_ceil &= ~0x3;
+	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
 	memcpy((void *)omap_sram_ceil, start, size);
 
 	return (void *)omap_sram_ceil;
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
new file mode 100644
index 0000000..b2a943b
--- /dev/null
+++ b/arch/arm/plat-omap/timer32k.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/arm/plat-omap/timer32k.c
+ *
+ * OMAP 32K Timer
+ *
+ * Copyright (C) 2004 - 2005 Nokia Corporation
+ * Partial timer rewrite and additional dynamic tick timer support by
+ * Tony Lindgen <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * MPU timer code based on the older MPU timer code for OMAP
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+struct sys_timer omap_timer;
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED		0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED		0x48004010
+#else
+#error OMAP 32KHz timer does not currently work on 15XX!
+#endif
+
+/* 16xx specific defines */
+#define OMAP1_32K_TIMER_BASE		0xfffb9000
+#define OMAP1_32K_TIMER_CR		0x08
+#define OMAP1_32K_TIMER_TVR		0x00
+#define OMAP1_32K_TIMER_TCR		0x04
+
+/* 24xx specific defines */
+#define OMAP2_GP_TIMER_BASE		0x48028000
+#define CM_CLKSEL_WKUP			0x48008440
+#define GP_TIMER_TIDR			0x00
+#define GP_TIMER_TISR			0x18
+#define GP_TIMER_TIER			0x1c
+#define GP_TIMER_TCLR			0x24
+#define GP_TIMER_TCRR			0x28
+#define GP_TIMER_TLDR			0x2c
+#define GP_TIMER_TTGR			0x30
+#define GP_TIMER_TSICR			0x40
+
+#define OMAP_32K_TICKS_PER_HZ		(32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 128, TVR = 255.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
+				(((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+	if (cpu_class_is_omap1())
+		omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+
+	if (cpu_is_omap24xx())
+		omap_writel(val, OMAP2_GP_TIMER_BASE + reg);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+	if (cpu_class_is_omap1())
+		return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+
+	if (cpu_is_omap24xx())
+		return omap_readl(OMAP2_GP_TIMER_BASE + reg);
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+	return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+	if (cpu_class_is_omap1()) {
+		omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+		omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+	}
+
+	if (cpu_is_omap24xx()) {
+		omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR);
+		omap_32k_timer_write((1 << 1), GP_TIMER_TIER);
+		omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR);
+	}
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+	if (cpu_class_is_omap1())
+		omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+
+	if (cpu_is_omap24xx())
+		omap_32k_timer_write(0x0, GP_TIMER_TCLR);
+}
+
+/*
+ * Rounds down to nearest usec. Note that this will overflow for larger values.
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+	return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+/*
+ * Rounds down to nearest nsec.
+ */
+static inline unsigned long long
+omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+{
+	return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+	unsigned long now = omap_32k_sync_timer_read();
+	return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+	return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+					    struct pt_regs *regs)
+{
+	unsigned long flags;
+	unsigned long now;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	if (cpu_is_omap24xx()) {
+		u32 status = omap_32k_timer_read(GP_TIMER_TISR);
+		omap_32k_timer_write(status, GP_TIMER_TISR);
+	}
+
+	now = omap_32k_sync_timer_read();
+
+	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+		timer_tick(regs);
+	}
+
+	/* Restart timer so we don't drift off due to modulo or dynamic tick.
+	 * By default we program the next timer to be continuous to avoid
+	 * latencies during high system load. During dynamic tick operation the
+	 * continuous timer can be overridden from pm_idle to be longer.
+	 */
+	omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. Note that
+ * we can keep the timer continuous, and don't need to set it to run in
+ * one-shot mode. This is because the timer will get reprogrammed again
+ * after next interrupt.
+ */
+void omap_32k_timer_reprogram(unsigned long next_tick)
+{
+	omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+}
+
+static struct irqaction omap_32k_timer_irq;
+extern struct timer_update_handler timer_update;
+
+static int omap_32k_timer_enable_dyn_tick(void)
+{
+	/* No need to reprogram timer, just use the next interrupt */
+	return 0;
+}
+
+static int omap_32k_timer_disable_dyn_tick(void)
+{
+	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+	return 0;
+}
+
+static struct dyn_tick_timer omap_dyn_tick_timer = {
+	.enable		= omap_32k_timer_enable_dyn_tick,
+	.disable	= omap_32k_timer_disable_dyn_tick,
+	.reprogram	= omap_32k_timer_reprogram,
+	.handler	= omap_32k_timer_interrupt,
+};
+#endif	/* CONFIG_NO_IDLE_HZ */
+
+static struct irqaction omap_32k_timer_irq = {
+	.name		= "32KHz timer",
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= omap_32k_timer_interrupt,
+};
+
+static struct clk * gpt1_ick;
+static struct clk * gpt1_fck;
+
+static __init void omap_init_32k_timer(void)
+{
+#ifdef CONFIG_NO_IDLE_HZ
+	omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
+	if (cpu_class_is_omap1())
+		setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+	if (cpu_is_omap24xx())
+		setup_irq(37, &omap_32k_timer_irq);
+	omap_timer.offset  = omap_32k_timer_gettimeoffset;
+	omap_32k_last_tick = omap_32k_sync_timer_read();
+
+	/* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+	if (cpu_is_omap24xx()) {
+		omap_32k_timer_write(0, GP_TIMER_TCLR);
+		omap_writel(0, CM_CLKSEL_WKUP);		/* 32KHz clock source */
+
+		gpt1_ick = clk_get(NULL, "gpt1_ick");
+		if (IS_ERR(gpt1_ick))
+			printk(KERN_ERR "Could not get gpt1_ick\n");
+		else
+			clk_enable(gpt1_ick);
+
+		gpt1_fck = clk_get(NULL, "gpt1_fck");
+		if (IS_ERR(gpt1_fck))
+			printk(KERN_ERR "Could not get gpt1_fck\n");
+		else
+			clk_enable(gpt1_fck);
+
+		mdelay(100);		/* Wait for clocks to stabilize */
+
+		omap_32k_timer_write(0x7, GP_TIMER_TISR);
+	}
+
+	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+	omap_init_32k_timer();
+}
+
+struct sys_timer omap_timer = {
+	.init		= omap_timer_init,
+	.offset		= NULL,		/* Initialized later */
+};
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index e3c5fca0..2b0cfce 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -69,7 +69,7 @@
 	 * for the data I pass, and I need tags
 	 * on the data to indicate what information I have
 	 * squirrelled away.  ELF notes happen to provide
-	 * all of that that no need to invent something new.
+	 * all of that, so there is no need to invent something new.
 	 */
 	buf = (u32*)per_cpu_ptr(crash_notes, cpu);
 	if (!buf)
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 5b26af8..e112d1a 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1740,7 +1740,7 @@
 
 /**
  * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
- * @q:    the request queue to be released
+ * @kobj:    the kobj belonging of the request queue to be released
  *
  * Description:
  *     blk_cleanup_queue is the pair to blk_init_queue() or
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 16e99db..d53f664 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -60,6 +60,13 @@
 
 # ARM Architecture
 
+config AT91_WATCHDOG
+	tristate "AT91RM9200 watchdog"
+	depends on WATCHDOG && ARCH_AT91RM9200
+	help
+	  Watchdog timer embedded into AT91RM9200 chips. This will reboot your
+	  system when the timeout is reached.
+
 config 21285_WATCHDOG
 	tristate "DC21285 watchdog"
 	depends on WATCHDOG && FOOTBRIDGE
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index d6f27fd..6ab77b6 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 
 # ARM Architecture
+obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c
new file mode 100644
index 0000000..ac83bc4
--- /dev/null
+++ b/drivers/char/watchdog/at91_wdt.c
@@ -0,0 +1,228 @@
+/*
+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
+ *
+ *  Copyright (C) 2003 SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+
+#define WDT_DEFAULT_TIME	5	/* 5 seconds */
+#define WDT_MAX_TIME		256	/* 256 seconds */
+
+static int wdt_time = WDT_DEFAULT_TIME;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_time, int, 0);
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+
+static unsigned long at91wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline at91_wdt_stop(void)
+{
+	at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline at91_wdt_start(void)
+{
+	at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
+	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/*
+ * Reload the watchdog timer.  (ie, pat the watchdog)
+ */
+static void inline at91_wdt_reload(void)
+{
+	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at91_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &at91wdt_busy))
+		return -EBUSY;
+
+	at91_wdt_start();
+	return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
+ *  disabled.
+ */
+static int at91_wdt_close(struct inode *inode, struct file *file)
+{
+	if (!nowayout)
+		at91_wdt_stop();	/* Disable the watchdog when file is closed */
+
+	clear_bit(0, &at91wdt_busy);
+	return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at91_wdt_settimeout(int new_time)
+{
+	/*
+	 * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+	 *
+	 * Since WDV is a 16-bit counter, the maximum period is
+	 * 65536 / 0.256 = 256 seconds.
+	 */
+	if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
+		return -EINVAL;
+
+	/* Set new watchdog time. It will be used when at91_wdt_start() is called. */
+	wdt_time = new_time;
+	return 0;
+}
+
+static struct watchdog_info at91_wdt_info = {
+	.identity	= "at91 watchdog",
+	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at91_wdt_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int new_value;
+
+	switch(cmd) {
+		case WDIOC_KEEPALIVE:
+			at91_wdt_reload();	/* pat the watchdog */
+			return 0;
+
+		case WDIOC_GETSUPPORT:
+			return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0;
+
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_value, p))
+				return -EFAULT;
+				
+			if (at91_wdt_settimeout(new_value))
+				return -EINVAL;
+
+			/* Enable new time value */
+			at91_wdt_start();
+
+			/* Return current value */
+			return put_user(wdt_time, p);
+
+		case WDIOC_GETTIMEOUT:
+			return put_user(wdt_time, p);
+
+		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, p);
+
+		case WDIOC_SETOPTIONS:
+			if (get_user(new_value, p))
+				return -EFAULT;
+
+			if (new_value & WDIOS_DISABLECARD)
+				at91_wdt_stop();
+			if (new_value & WDIOS_ENABLECARD)
+				at91_wdt_start();
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+	at91_wdt_reload();		/* pat the watchdog */
+	return len;
+}
+
+/* ......................................................................... */
+
+static struct file_operations at91wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.ioctl		= at91_wdt_ioctl,
+	.open		= at91_wdt_open,
+	.release	= at91_wdt_close,
+	.write		= at91_wdt_write,
+};
+
+static struct miscdevice at91wdt_miscdev = {
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &at91wdt_fops,
+};
+
+static int __init at91_wdt_init(void)
+{
+	int res;
+
+	/* Check that the heartbeat value is within range; if not reset to the default */
+	if (at91_wdt_settimeout(wdt_time)) {
+		at91_wdt_settimeout(WDT_DEFAULT_TIME);
+		printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
+	}
+
+	res = misc_register(&at91wdt_miscdev);
+	if (res)
+		return res;
+
+	printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout);
+	return 0;
+}
+
+static void __exit at91_wdt_exit(void)
+{
+	misc_deregister(&at91wdt_miscdev);
+}
+
+module_init(at91_wdt_init);
+module_exit(at91_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 8d6b249..6d44ca6 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -66,15 +66,13 @@
 #include <linux/fs.h>		/* For file operations */
 #include <linux/ioport.h>	/* For io-port access */
 #include <linux/spinlock.h>	/* For spin_lock/spin_unlock/... */
-#include <linux/sched.h>	/* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <linux/slab.h>		/* For kmalloc */
 
 #include <asm/uaccess.h>	/* For copy_to_user/put_user/... */
 #include <asm/io.h>		/* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.16"
-#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_VERSION "1.17"
+#define WATCHDOG_DATE "12 Feb 2006"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
 #define PFX WATCHDOG_NAME ": "
@@ -96,15 +94,19 @@
  * PCI-PC Watchdog card.
 */
 /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
-#define WD_WDRST                0x01	/* Previously reset state */
-#define WD_T110                 0x02	/* Temperature overheat sense */
-#define WD_HRTBT                0x04	/* Heartbeat sense */
-#define WD_RLY2                 0x08	/* External relay triggered */
-#define WD_SRLY2                0x80	/* Software external relay triggered */
+#define WD_WDRST		0x01	/* Previously reset state */
+#define WD_T110			0x02	/* Temperature overheat sense */
+#define WD_HRTBT		0x04	/* Heartbeat sense */
+#define WD_RLY2			0x08	/* External relay triggered */
+#define WD_SRLY2		0x80	/* Software external relay triggered */
 /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
-#define WD_REVC_WTRP            0x01	/* Watchdog Trip status */
-#define WD_REVC_HRBT            0x02	/* Watchdog Heartbeat */
-#define WD_REVC_TTRP            0x04	/* Temperature Trip status */
+#define WD_REVC_WTRP		0x01	/* Watchdog Trip status */
+#define WD_REVC_HRBT		0x02	/* Watchdog Heartbeat */
+#define WD_REVC_TTRP		0x04	/* Temperature Trip status */
+#define WD_REVC_RL2A		0x08	/* Relay 2 activated by on-board processor */
+#define WD_REVC_RL1A		0x10	/* Relay 1 active */
+#define WD_REVC_R2DS		0x40	/* Relay 2 disable */
+#define WD_REVC_RLY2		0x80	/* Relay 2 activated? */
 /* Port 2 : Control Status #2 */
 #define WD_WDIS			0x10	/* Watchdog Disabled */
 #define WD_ENTP			0x20	/* Watchdog Enable Temperature Trip */
@@ -122,9 +124,14 @@
 #define CMD_ISA_VERSION_HUNDRETH	0x03
 #define CMD_ISA_VERSION_MINOR		0x04
 #define CMD_ISA_SWITCH_SETTINGS		0x05
+#define CMD_ISA_RESET_PC		0x06
+#define CMD_ISA_ARM_0			0x07
+#define CMD_ISA_ARM_30			0x08
+#define CMD_ISA_ARM_60			0x09
 #define CMD_ISA_DELAY_TIME_2SECS	0x0A
 #define CMD_ISA_DELAY_TIME_4SECS	0x0B
 #define CMD_ISA_DELAY_TIME_8SECS	0x0C
+#define CMD_ISA_RESET_RELAYS		0x0D
 
 /*
  * We are using an kernel timer to do the pinging of the watchdog
@@ -142,6 +149,7 @@
 static char expect_close;
 static int temp_panic;
 static struct {				/* this is private data for each ISA-PC watchdog card */
+	char fw_ver_str[6];		/* The cards firmware version */
 	int revision;			/* The card's revision */
 	int supports_temp;		/* Wether or not the card has a temperature device */
 	int command_mode;		/* Wether or not the card is in command mode */
@@ -153,6 +161,13 @@
 } pcwd_private;
 
 /* module parameters */
+#define QUIET	0	/* Default */
+#define VERBOSE	1	/* Verbose */
+#define DEBUG	2	/* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
 #define WATCHDOG_HEARTBEAT 60		/* 60 sec default heartbeat */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
@@ -172,6 +187,10 @@
 	int control_status;
 	int port0, last_port0;	/* Double read for stabilising */
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
+			cmd);
+
 	/* The WCMD bit must be 1 and the command is only 4 bits in size */
 	control_status = (cmd & 0x0F) | WD_WCMD;
 	outb_p(control_status, pcwd_private.io_addr + 2);
@@ -188,6 +207,10 @@
 		udelay (250);
 	}
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+			cmd, port0, last_port0);
+
 	return port0;
 }
 
@@ -214,6 +237,10 @@
 	spin_unlock(&pcwd_private.io_lock);
 	pcwd_private.command_mode = found;
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "command_mode=%d\n",
+				pcwd_private.command_mode);
+
 	return(found);
 }
 
@@ -226,6 +253,10 @@
 	spin_unlock(&pcwd_private.io_lock);
 
 	pcwd_private.command_mode = 0;
+
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "command_mode=%d\n",
+				pcwd_private.command_mode);
 }
 
 static inline void pcwd_check_temperature_support(void)
@@ -234,27 +265,22 @@
 		pcwd_private.supports_temp = 1;
 }
 
-static inline char *get_firmware(void)
+static inline void pcwd_get_firmware(void)
 {
 	int one, ten, hund, minor;
-	char *ret;
 
-	ret = kmalloc(6, GFP_KERNEL);
-	if(ret == NULL)
-		return NULL;
+	strcpy(pcwd_private.fw_ver_str, "ERROR");
 
 	if (set_command_mode()) {
 		one = send_isa_command(CMD_ISA_VERSION_INTEGER);
 		ten = send_isa_command(CMD_ISA_VERSION_TENTH);
 		hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
 		minor = send_isa_command(CMD_ISA_VERSION_MINOR);
-		sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+		sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor);
 	}
-	else
-		sprintf(ret, "ERROR");
-
 	unset_command_mode();
-	return(ret);
+
+	return;
 }
 
 static inline int pcwd_get_option_switches(void)
@@ -272,17 +298,15 @@
 
 static void pcwd_show_card_info(void)
 {
-	char *firmware;
 	int option_switches;
 
 	/* Get some extra info from the hardware (in command/debug/diag mode) */
 	if (pcwd_private.revision == PCWD_REVISION_A)
 		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
 	else if (pcwd_private.revision == PCWD_REVISION_C) {
-		firmware = get_firmware();
+		pcwd_get_firmware();
 		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
-			pcwd_private.io_addr, firmware);
-		kfree(firmware);
+			pcwd_private.io_addr, pcwd_private.fw_ver_str);
 		option_switches = pcwd_get_option_switches();
 		printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
 			option_switches,
@@ -362,6 +386,10 @@
 			return -EIO;
 		}
 	}
+
+	if (debug >= VERBOSE)
+		printk(KERN_DEBUG PFX "Watchdog started\n");
+
 	return 0;
 }
 
@@ -386,6 +414,10 @@
 			return -EIO;
 		}
 	}
+
+	if (debug >= VERBOSE)
+		printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
 	return 0;
 }
 
@@ -393,6 +425,10 @@
 {
 	/* user land ping */
 	pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
+
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
 	return 0;
 }
 
@@ -402,12 +438,17 @@
 		return -EINVAL;
 
 	heartbeat = t;
+
+	if (debug >= VERBOSE)
+		printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+		       heartbeat);
+
 	return 0;
 }
 
 static int pcwd_get_status(int *status)
 {
-	int card_status;
+	int control_status;
 
 	*status=0;
 	spin_lock(&pcwd_private.io_lock);
@@ -415,37 +456,39 @@
 		/* Rev A cards return status information from
 		 * the base register, which is used for the
 		 * temperature in other cards. */
-		card_status = inb(pcwd_private.io_addr);
+		control_status = inb(pcwd_private.io_addr);
 	else {
 		/* Rev C cards return card status in the base
 		 * address + 1 register. And use different bits
 		 * to indicate a card initiated reset, and an
 		 * over-temperature condition. And the reboot
 		 * status can be reset. */
-		card_status = inb(pcwd_private.io_addr + 1);
+		control_status = inb(pcwd_private.io_addr + 1);
 	}
 	spin_unlock(&pcwd_private.io_lock);
 
 	if (pcwd_private.revision == PCWD_REVISION_A) {
-		if (card_status & WD_WDRST)
+		if (control_status & WD_WDRST)
 			*status |= WDIOF_CARDRESET;
 
-		if (card_status & WD_T110) {
+		if (control_status & WD_T110) {
 			*status |= WDIOF_OVERHEAT;
 			if (temp_panic) {
 				printk (KERN_INFO PFX "Temperature overheat trip!\n");
 				kernel_power_off();
+				/* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
 			}
 		}
 	} else {
-		if (card_status & WD_REVC_WTRP)
+		if (control_status & WD_REVC_WTRP)
 			*status |= WDIOF_CARDRESET;
 
-		if (card_status & WD_REVC_TTRP) {
+		if (control_status & WD_REVC_TTRP) {
 			*status |= WDIOF_OVERHEAT;
 			if (temp_panic) {
 				printk (KERN_INFO PFX "Temperature overheat trip!\n");
 				kernel_power_off();
+				/* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
 			}
 		}
 	}
@@ -455,9 +498,25 @@
 
 static int pcwd_clear_status(void)
 {
+	int control_status;
+
 	if (pcwd_private.revision == PCWD_REVISION_C) {
 		spin_lock(&pcwd_private.io_lock);
-		outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+
+		if (debug >= VERBOSE)
+			printk(KERN_INFO PFX "clearing watchdog trip status\n");
+
+		control_status = inb_p(pcwd_private.io_addr + 1);
+
+		if (debug >= DEBUG) {
+			printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+			printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+				(control_status & WD_REVC_R2DS));
+		}
+
+		/* clear reset status & Keep Relay 2 disable state as it is */
+		outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1);
+
 		spin_unlock(&pcwd_private.io_lock);
 	}
 	return 0;
@@ -481,6 +540,11 @@
 	*temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
 	spin_unlock(&pcwd_private.io_lock);
 
+	if (debug >= DEBUG) {
+		printk(KERN_DEBUG PFX "temperature is: %d F\n",
+			*temperature);
+	}
+
 	return 0;
 }
 
@@ -599,6 +663,8 @@
 static int pcwd_open(struct inode *inode, struct file *file)
 {
 	if (!atomic_dec_and_test(&open_allowed) ) {
+		if (debug >= VERBOSE)
+			printk(KERN_ERR PFX "Attempt to open already opened device.\n");
 		atomic_inc( &open_allowed );
 		return -EBUSY;
 	}
@@ -922,7 +988,8 @@
 {
 	if (pcwd_private.io_addr)
 		pcwatchdog_exit();
-	return;
+
+	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(pcwd_init_module);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 2700c5c..3fdfda9 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -705,7 +705,8 @@
 err_out_unregister_reboot:
 	unregister_reboot_notifier(&usb_pcwd_notifier);
 error:
-	usb_pcwd_delete (usb_pcwd);
+	if (usb_pcwd)
+		usb_pcwd_delete(usb_pcwd);
 	usb_pcwd_device = NULL;
 	return retval;
 }
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 7636c1a..23a9e1e 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -33,7 +33,6 @@
 #include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/dmi.h>
-#include <linux/mutex.h>
 #include <asm/io.h>
 
 #define HDAPS_LOW_PORT		0x1600	/* first port used by hdaps */
@@ -71,10 +70,10 @@
 static int rest_x;
 static int rest_y;
 
-static DEFINE_MUTEX(hdaps_mutex);
+static DECLARE_MUTEX(hdaps_sem);
 
 /*
- * __get_latch - Get the value from a given port.  Callers must hold hdaps_mutex.
+ * __get_latch - Get the value from a given port.  Callers must hold hdaps_sem.
  */
 static inline u8 __get_latch(u16 port)
 {
@@ -83,7 +82,7 @@
 
 /*
  * __check_latch - Check a port latch for a given value.  Returns zero if the
- * port contains the given value.  Callers must hold hdaps_mutex.
+ * port contains the given value.  Callers must hold hdaps_sem.
  */
 static inline int __check_latch(u16 port, u8 val)
 {
@@ -94,7 +93,7 @@
 
 /*
  * __wait_latch - Wait up to 100us for a port latch to get a certain value,
- * returning zero if the value is obtained.  Callers must hold hdaps_mutex.
+ * returning zero if the value is obtained.  Callers must hold hdaps_sem.
  */
 static int __wait_latch(u16 port, u8 val)
 {
@@ -111,7 +110,7 @@
 
 /*
  * __device_refresh - request a refresh from the accelerometer.  Does not wait
- * for refresh to complete.  Callers must hold hdaps_mutex.
+ * for refresh to complete.  Callers must hold hdaps_sem.
  */
 static void __device_refresh(void)
 {
@@ -125,7 +124,7 @@
 /*
  * __device_refresh_sync - request a synchronous refresh from the
  * accelerometer.  We wait for the refresh to complete.  Returns zero if
- * successful and nonzero on error.  Callers must hold hdaps_mutex.
+ * successful and nonzero on error.  Callers must hold hdaps_sem.
  */
 static int __device_refresh_sync(void)
 {
@@ -135,7 +134,7 @@
 
 /*
  * __device_complete - indicate to the accelerometer that we are done reading
- * data, and then initiate an async refresh.  Callers must hold hdaps_mutex.
+ * data, and then initiate an async refresh.  Callers must hold hdaps_sem.
  */
 static inline void __device_complete(void)
 {
@@ -153,7 +152,7 @@
 {
 	int ret;
 
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 
 	/* do a sync refresh -- we need to be sure that we read fresh data */
 	ret = __device_refresh_sync();
@@ -164,7 +163,7 @@
 	__device_complete();
 
 out:
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 	return ret;
 }
 
@@ -199,9 +198,9 @@
 {
 	int ret;
 
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 	ret = __hdaps_read_pair(port1, port2, val1, val2);
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 
 	return ret;
 }
@@ -214,7 +213,7 @@
 {
 	int total, ret = -ENXIO;
 
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 
 	outb(0x13, 0x1610);
 	outb(0x01, 0x161f);
@@ -280,7 +279,7 @@
 	}
 
 out:
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 	return ret;
 }
 
@@ -314,7 +313,7 @@
 };
 
 /*
- * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_mutex.
+ * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_sem.
  */
 static void hdaps_calibrate(void)
 {
@@ -326,7 +325,7 @@
 	int x, y;
 
 	/* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
-	if (!mutex_trylock(&hdaps_mutex)) {
+	if (down_trylock(&hdaps_sem)) {
 		mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
 		return;
 	}
@@ -341,7 +340,7 @@
 	mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
 
 out:
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 }
 
 
@@ -421,9 +420,9 @@
 				     struct device_attribute *attr,
 				     const char *buf, size_t count)
 {
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 	hdaps_calibrate();
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 
 	return count;
 }
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 2c765ca..f420660 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -496,22 +496,17 @@
 /*
  * This function finds the sbp2_command for a given outstanding SCpnt.
  * Only looks at the inuse list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
+static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
+		struct scsi_id_instance_data *scsi_id, void *SCpnt)
 {
 	struct sbp2_command_info *command;
-	unsigned long flags;
 
-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
-			if (command->Current_SCpnt == SCpnt) {
-				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+	if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
+		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
+			if (command->Current_SCpnt == SCpnt)
 				return command;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return NULL;
 }
 
@@ -580,17 +575,15 @@
 
 /*
  * This function moves a command to the completed orb list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
-					    struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(
+		struct scsi_id_instance_data *scsi_id,
+		struct sbp2_command_info *command)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	list_del(&command->list);
 	sbp2util_free_command_dma(command);
 	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
 /*
@@ -2148,7 +2141,9 @@
 		 * Matched status with command, now grab scsi command pointers and check status
 		 */
 		SCpnt = command->Current_SCpnt;
+		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 		sbp2util_mark_command_completed(scsi_id, command);
+		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 		if (SCpnt) {
 
@@ -2484,6 +2479,7 @@
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	struct sbp2_command_info *command;
+	unsigned long flags;
 
 	SBP2_ERR("aborting sbp2 command");
 	scsi_print_command(SCpnt);
@@ -2494,6 +2490,7 @@
 		 * Right now, just return any matching command structures
 		 * to the free pool.
 		 */
+		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
 		if (command) {
 			SBP2_DEBUG("Found command to abort");
@@ -2511,6 +2508,7 @@
 				command->Current_done(command->Current_SCpnt);
 			}
 		}
+		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 		/*
 		 * Initiate a fetch agent reset.
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index aecd9e0..64fd8e7 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -78,8 +78,7 @@
 	if (--ti->use == 0)
 		module_put(ti->tt.module);
 
-	if (ti->use < 0)
-		BUG();
+	BUG_ON(ti->use < 0);
 	up_read(&_lock);
 
 	return;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 9b374c9..6081941 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1558,8 +1558,7 @@
 	int buffs;
 
 	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
-	if (conf->r1buf_pool)
-		BUG();
+	BUG_ON(conf->r1buf_pool);
 	conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free,
 					  conf->poolinfo);
 	if (!conf->r1buf_pool)
@@ -1732,8 +1731,7 @@
 			    !conf->fullsync &&
 			    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
 				break;
-			if (sync_blocks < (PAGE_SIZE>>9))
-				BUG();
+			BUG_ON(sync_blocks < (PAGE_SIZE>>9));
 			if (len > (sync_blocks<<9))
 				len = sync_blocks<<9;
 		}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ab90a6d..617012b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1117,8 +1117,7 @@
 	for (i=0; i<conf->copies; i++)
 		if (r10_bio->devs[i].bio == bio)
 			break;
-	if (i == conf->copies)
-		BUG();
+	BUG_ON(i == conf->copies);
 	update_head_pos(i, r10_bio);
 	d = r10_bio->devs[i].devnum;
 
@@ -1518,8 +1517,7 @@
 	int buffs;
 
 	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
-	if (conf->r10buf_pool)
-		BUG();
+	BUG_ON(conf->r10buf_pool);
 	conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
 	if (!conf->r10buf_pool)
 		return -ENOMEM;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index dae740a..3184360 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -73,10 +73,8 @@
 static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
-		if (!list_empty(&sh->lru))
-			BUG();
-		if (atomic_read(&conf->active_stripes)==0)
-			BUG();
+		BUG_ON(!list_empty(&sh->lru));
+		BUG_ON(atomic_read(&conf->active_stripes)==0);
 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
 			if (test_bit(STRIPE_DELAYED, &sh->state))
 				list_add_tail(&sh->lru, &conf->delayed_list);
@@ -184,10 +182,8 @@
 	raid5_conf_t *conf = sh->raid_conf;
 	int i;
 
-	if (atomic_read(&sh->count) != 0)
-		BUG();
-	if (test_bit(STRIPE_HANDLE, &sh->state))
-		BUG();
+	BUG_ON(atomic_read(&sh->count) != 0);
+	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 	
 	CHECK_DEVLOCK();
 	PRINTK("init_stripe called, stripe %llu\n", 
@@ -269,8 +265,7 @@
 				init_stripe(sh, sector, pd_idx, disks);
 		} else {
 			if (atomic_read(&sh->count)) {
-				if (!list_empty(&sh->lru))
-					BUG();
+			  BUG_ON(!list_empty(&sh->lru));
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
@@ -465,8 +460,7 @@
 	spin_unlock_irq(&conf->device_lock);
 	if (!sh)
 		return 0;
-	if (atomic_read(&sh->count))
-		BUG();
+	BUG_ON(atomic_read(&sh->count));
 	shrink_buffers(sh, conf->pool_size);
 	kmem_cache_free(conf->slab_cache, sh);
 	atomic_dec(&conf->active_stripes);
@@ -882,8 +876,7 @@
 	ptr[0] = page_address(sh->dev[pd_idx].page);
 	switch(method) {
 	case READ_MODIFY_WRITE:
-		if (!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags))
-			BUG();
+		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
 		for (i=disks ; i-- ;) {
 			if (i==pd_idx)
 				continue;
@@ -896,7 +889,7 @@
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 					wake_up(&conf->wait_for_overlap);
 
-				if (sh->dev[i].written) BUG();
+				BUG_ON(sh->dev[i].written);
 				sh->dev[i].written = chosen;
 				check_xor();
 			}
@@ -912,7 +905,7 @@
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 					wake_up(&conf->wait_for_overlap);
 
-				if (sh->dev[i].written) BUG();
+				BUG_ON(sh->dev[i].written);
 				sh->dev[i].written = chosen;
 			}
 		break;
@@ -995,8 +988,7 @@
 	if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
 		goto overlap;
 
-	if (*bip && bi->bi_next && (*bip) != bi->bi_next)
-		BUG();
+	BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
 	if (*bip)
 		bi->bi_next = *bip;
 	*bip = bi;
@@ -1430,8 +1422,7 @@
 		set_bit(STRIPE_HANDLE, &sh->state);
 		if (failed == 0) {
 			char *pagea;
-			if (uptodate != disks)
-				BUG();
+			BUG_ON(uptodate != disks);
 			compute_parity(sh, CHECK_PARITY);
 			uptodate--;
 			pagea = page_address(sh->dev[sh->pd_idx].page);
@@ -2096,8 +2087,7 @@
 
 		list_del_init(first);
 		atomic_inc(&sh->count);
-		if (atomic_read(&sh->count)!= 1)
-			BUG();
+		BUG_ON(atomic_read(&sh->count)!= 1);
 		spin_unlock_irq(&conf->device_lock);
 		
 		handled++;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index ab64b37..bc69355 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -91,10 +91,8 @@
 static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
-		if (!list_empty(&sh->lru))
-			BUG();
-		if (atomic_read(&conf->active_stripes)==0)
-			BUG();
+		BUG_ON(!list_empty(&sh->lru));
+		BUG_ON(atomic_read(&conf->active_stripes)==0);
 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
 			if (test_bit(STRIPE_DELAYED, &sh->state))
 				list_add_tail(&sh->lru, &conf->delayed_list);
@@ -202,10 +200,8 @@
 	raid6_conf_t *conf = sh->raid_conf;
 	int disks = conf->raid_disks, i;
 
-	if (atomic_read(&sh->count) != 0)
-		BUG();
-	if (test_bit(STRIPE_HANDLE, &sh->state))
-		BUG();
+	BUG_ON(atomic_read(&sh->count) != 0);
+	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 
 	CHECK_DEVLOCK();
 	PRINTK("init_stripe called, stripe %llu\n",
@@ -284,13 +280,11 @@
 				init_stripe(sh, sector, pd_idx);
 		} else {
 			if (atomic_read(&sh->count)) {
-				if (!list_empty(&sh->lru))
-					BUG();
+				BUG_ON(!list_empty(&sh->lru));
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
-				if (list_empty(&sh->lru))
-					BUG();
+				BUG_ON(list_empty(&sh->lru));
 				list_del_init(&sh->lru);
 			}
 		}
@@ -353,8 +347,7 @@
 	spin_unlock_irq(&conf->device_lock);
 	if (!sh)
 		return 0;
-	if (atomic_read(&sh->count))
-		BUG();
+	BUG_ON(atomic_read(&sh->count));
 	shrink_buffers(sh, conf->raid_disks);
 	kmem_cache_free(conf->slab_cache, sh);
 	atomic_dec(&conf->active_stripes);
@@ -780,7 +773,7 @@
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 					wake_up(&conf->wait_for_overlap);
 
-				if (sh->dev[i].written) BUG();
+				BUG_ON(sh->dev[i].written);
 				sh->dev[i].written = chosen;
 			}
 		break;
@@ -970,8 +963,7 @@
 	if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
 		goto overlap;
 
-	if (*bip && bi->bi_next && (*bip) != bi->bi_next)
-		BUG();
+	BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
 	if (*bip)
 		bi->bi_next = *bip;
 	*bip = bi;
@@ -1906,8 +1898,7 @@
 
 		list_del_init(first);
 		atomic_inc(&sh->count);
-		if (atomic_read(&sh->count)!= 1)
-			BUG();
+		BUG_ON(atomic_read(&sh->count)!= 1);
 		spin_unlock_irq(&conf->device_lock);
 
 		handled++;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 7cc162e..003b077 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -91,4 +91,22 @@
 
 	  If unsure, say N.
 
+config MMC_AT91RM9200
+	tristate "AT91RM9200 SD/MMC Card Interface support"
+	depends on ARCH_AT91RM9200 && MMC
+	help
+	  This selects the AT91RM9200 MCI controller.
+
+	  If unsure, say N.
+
+config MMC_IMX
+	tristate "Motorola i.MX Multimedia Card Interface support"
+	depends on ARCH_IMX && MMC
+	help
+	  This selects the Motorola i.MX Multimedia card Interface.
+	  If you have a i.MX platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c7c34aa..d2957e3 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -17,10 +17,12 @@
 #
 obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
+obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_AT91RM9200)	+= at91_mci.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
 
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
new file mode 100644
index 0000000..6061c2d
--- /dev/null
+++ b/drivers/mmc/at91_mci.c
@@ -0,0 +1,988 @@
+/*
+ *  linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ *
+ *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
+ *
+ *  Copyright (C) 2006 Malcolm Noyes
+ *
+ * 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.
+ */
+
+/*
+   This is the AT91RM9200 MCI driver that has been tested with both MMC cards
+   and SD-cards.  Boards that support write protect are now supported.
+   The CCAT91SBC001 board does not support SD cards.
+
+   The three entry points are at91_mci_request, at91_mci_set_ios
+   and at91_mci_get_ro.
+
+   SET IOS
+     This configures the device to put it into the correct mode and clock speed
+     required.
+
+   MCI REQUEST
+     MCI request processes the commands sent in the mmc_request structure. This
+     can consist of a processing command and a stop command in the case of
+     multiple block transfers.
+
+     There are three main types of request, commands, reads and writes.
+
+     Commands are straight forward. The command is submitted to the controller and
+     the request function returns. When the controller generates an interrupt to indicate
+     the command is finished, the response to the command are read and the mmc_request_done
+     function called to end the request.
+
+     Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
+     controller to manage the transfers.
+
+     A read is done from the controller directly to the scatterlist passed in from the request.
+     Due to a bug in the controller, when a read is completed, all the words are byte
+     swapped in the scatterlist buffers.
+
+     The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
+
+     A write is slightly different in that the bytes to write are read from the scatterlist
+     into a dma memory buffer (this is in case the source buffer should be read only). The
+     entire write buffer is then done from this single dma memory buffer.
+
+     The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
+
+   GET RO
+     Gets the status of the write protect pin, if available.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/mmc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mci.h>
+#include <asm/arch/at91rm9200_pdc.h>
+
+#define DRIVER_NAME "at91_mci"
+
+#undef	SUPPORT_4WIRE
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(fmt...)	\
+	printk(fmt)
+#else
+#define DBG(fmt...)	do { } while (0)
+#endif
+
+static struct clk *mci_clk;
+
+#define FL_SENT_COMMAND (1 << 0)
+#define FL_SENT_STOP (1 << 1)
+
+
+
+/*
+ * Read from a MCI register.
+ */
+static inline unsigned long at91_mci_read(unsigned int reg)
+{
+	void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+	return __raw_readl(mci_base + reg);
+}
+
+/*
+ * Write to a MCI register.
+ */
+static inline void at91_mci_write(unsigned int reg, unsigned long value)
+{
+        void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+        __raw_writel(value, mci_base + reg);
+}
+
+/*
+ * Low level type for this driver
+ */
+struct at91mci_host
+{
+	struct mmc_host *mmc;
+	struct mmc_command *cmd;
+	struct mmc_request *request;
+
+	struct at91_mmc_data *board;
+	int present;
+
+	/*
+	 * Flag indicating when the command has been sent. This is used to
+	 * work out whether or not to send the stop
+	 */
+	unsigned int flags;
+	/* flag for current bus settings */
+	u32 bus_mode;
+
+	/* DMA buffer used for transmitting */
+	unsigned int* buffer;
+	dma_addr_t physical_address;
+	unsigned int total_length;
+
+	/* Latest in the scatterlist that has been enabled for transfer, but not freed */
+	int in_use_index;
+
+	/* Latest in the scatterlist that has been enabled for transfer */
+	int transfer_index;
+};
+
+/*
+ * Copy from sg to a dma block - used for transfers
+ */
+static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+{
+	unsigned int len, i, size;
+	unsigned *dmabuf = host->buffer;
+
+	size = host->total_length;
+	len = data->sg_len;
+
+	/*
+	 * Just loop through all entries. Size might not
+	 * be the entire list though so make sure that
+	 * we do not transfer too much.
+	 */
+	for (i = 0; i < len; i++) {
+		struct scatterlist *sg;
+		int amount;
+		int index;
+		unsigned int *sgbuffer;
+
+		sg = &data->sg[i];
+
+		sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+		amount = min(size, sg->length);
+		size -= amount;
+		amount /= 4;
+
+		for (index = 0; index < amount; index++)
+			*dmabuf++ = swab32(sgbuffer[index]);
+
+		kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+
+		if (size == 0)
+			break;
+	}
+
+	/*
+	 * Check that we didn't get a request to transfer
+	 * more data than can fit into the SG list.
+	 */
+	BUG_ON(size != 0);
+}
+
+/*
+ * Prepare a dma read
+ */
+static void at91mci_pre_dma_read(struct at91mci_host *host)
+{
+	int i;
+	struct scatterlist *sg;
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	DBG("pre dma read\n");
+
+	cmd = host->cmd;
+	if (!cmd) {
+		DBG("no command\n");
+		return;
+	}
+
+	data = cmd->data;
+	if (!data) {
+		DBG("no data\n");
+		return;
+	}
+
+	for (i = 0; i < 2; i++) {
+		/* nothing left to transfer */
+		if (host->transfer_index >= data->sg_len) {
+			DBG("Nothing left to transfer (index = %d)\n", host->transfer_index);
+			break;
+		}
+
+		/* Check to see if this needs filling */
+		if (i == 0) {
+			if (at91_mci_read(AT91_PDC_RCR) != 0) {
+				DBG("Transfer active in current\n");
+				continue;
+			}
+		}
+		else {
+			if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+				DBG("Transfer active in next\n");
+				continue;
+			}
+		}
+
+		/* Setup the next transfer */
+		DBG("Using transfer index %d\n", host->transfer_index);
+
+		sg = &data->sg[host->transfer_index++];
+		DBG("sg = %p\n", sg);
+
+		sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
+
+		DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
+
+		if (i == 0) {
+			at91_mci_write(AT91_PDC_RPR, sg->dma_address);
+			at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+		}
+		else {
+			at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
+			at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+		}
+	}
+
+	DBG("pre dma read done\n");
+}
+
+/*
+ * Handle after a dma read
+ */
+static void at91mci_post_dma_read(struct at91mci_host *host)
+{
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	DBG("post dma read\n");
+
+	cmd = host->cmd;
+	if (!cmd) {
+		DBG("no command\n");
+		return;
+	}
+
+	data = cmd->data;
+	if (!data) {
+		DBG("no data\n");
+		return;
+	}
+
+	while (host->in_use_index < host->transfer_index) {
+		unsigned int *buffer;
+		int index;
+		int len;
+
+		struct scatterlist *sg;
+
+		DBG("finishing index %d\n", host->in_use_index);
+
+		sg = &data->sg[host->in_use_index++];
+
+		DBG("Unmapping page %08X\n", sg->dma_address);
+
+		dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
+
+		/* Swap the contents of the buffer */
+		buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+		DBG("buffer = %p, length = %d\n", buffer, sg->length);
+
+		data->bytes_xfered += sg->length;
+
+		len = sg->length / 4;
+
+		for (index = 0; index < len; index++) {
+			buffer[index] = swab32(buffer[index]);
+		}
+		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+		flush_dcache_page(sg->page);
+	}
+
+	/* Is there another transfer to trigger? */
+	if (host->transfer_index < data->sg_len)
+		at91mci_pre_dma_read(host);
+	else {
+		at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
+		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+	}
+
+	DBG("post dma read done\n");
+}
+
+/*
+ * Handle transmitted data
+ */
+static void at91_mci_handle_transmitted(struct at91mci_host *host)
+{
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	DBG("Handling the transmit\n");
+
+	/* Disable the transfer */
+	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+	/* Now wait for cmd ready */
+	at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
+	at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
+	cmd = host->cmd;
+	if (!cmd) return;
+
+	data = cmd->data;
+	if (!data) return;
+
+	data->bytes_xfered = host->total_length;
+}
+
+/*
+ * Enable the controller
+ */
+static void at91_mci_enable(void)
+{
+	at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+	at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
+	at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+	at91_mci_write(AT91_MCI_MR, 0x834A);
+	at91_mci_write(AT91_MCI_SDCR, 0x0);
+}
+
+/*
+ * Disable the controller
+ */
+static void at91_mci_disable(void)
+{
+	at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+}
+
+/*
+ * Send a command
+ * return the interrupts to enable
+ */
+static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+	unsigned int cmdr, mr;
+	unsigned int block_length;
+	struct mmc_data *data = cmd->data;
+
+	unsigned int blocks;
+	unsigned int ier = 0;
+
+	host->cmd = cmd;
+
+	/* Not sure if this is needed */
+#if 0
+	if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+		DBG("Clearing timeout\n");
+		at91_mci_write(AT91_MCI_ARGR, 0);
+		at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+		while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+			/* spin */
+			DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+		}
+	}
+#endif
+	cmdr = cmd->opcode;
+
+	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
+		cmdr |= AT91_MCI_RSPTYP_NONE;
+	else {
+		/* if a response is expected then allow maximum response latancy */
+		cmdr |= AT91_MCI_MAXLAT;
+		/* set 136 bit response for R2, 48 bit response otherwise */
+		if (mmc_resp_type(cmd) == MMC_RSP_R2)
+			cmdr |= AT91_MCI_RSPTYP_136;
+		else
+			cmdr |= AT91_MCI_RSPTYP_48;
+	}
+
+	if (data) {
+		block_length = 1 << data->blksz_bits;
+		blocks = data->blocks;
+
+		/* always set data start - also set direction flag for read */
+		if (data->flags & MMC_DATA_READ)
+			cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
+		else if (data->flags & MMC_DATA_WRITE)
+			cmdr |= AT91_MCI_TRCMD_START;
+
+		if (data->flags & MMC_DATA_STREAM)
+			cmdr |= AT91_MCI_TRTYP_STREAM;
+		if (data->flags & MMC_DATA_MULTI)
+			cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+	}
+	else {
+		block_length = 0;
+		blocks = 0;
+	}
+
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		cmdr |= AT91_MCI_TRCMD_STOP;
+
+	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+		cmdr |= AT91_MCI_OPDCMD;
+
+	/*
+	 * Set the arguments and send the command
+	 */
+	DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
+		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+
+	if (!data) {
+		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
+		at91_mci_write(AT91_PDC_RPR, 0);
+		at91_mci_write(AT91_PDC_RCR, 0);
+		at91_mci_write(AT91_PDC_RNPR, 0);
+		at91_mci_write(AT91_PDC_RNCR, 0);
+		at91_mci_write(AT91_PDC_TPR, 0);
+		at91_mci_write(AT91_PDC_TCR, 0);
+		at91_mci_write(AT91_PDC_TNPR, 0);
+		at91_mci_write(AT91_PDC_TNCR, 0);
+
+		at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+		at91_mci_write(AT91_MCI_CMDR, cmdr);
+		return AT91_MCI_CMDRDY;
+	}
+
+	mr = at91_mci_read(AT91_MCI_MR) & 0x7fff;	/* zero block length and PDC mode */
+	at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+
+	/*
+	 * Disable the PDC controller
+	 */
+	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+	if (cmdr & AT91_MCI_TRCMD_START) {
+		data->bytes_xfered = 0;
+		host->transfer_index = 0;
+		host->in_use_index = 0;
+		if (cmdr & AT91_MCI_TRDIR) {
+			/*
+			 * Handle a read
+			 */
+			host->buffer = NULL;
+			host->total_length = 0;
+
+			at91mci_pre_dma_read(host);
+			ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+		}
+		else {
+			/*
+			 * Handle a write
+			 */
+			host->total_length = block_length * blocks;
+			host->buffer = dma_alloc_coherent(NULL,
+						  host->total_length,
+						  &host->physical_address, GFP_KERNEL);
+
+			at91mci_sg_to_dma(host, data);
+
+			DBG("Transmitting %d bytes\n", host->total_length);
+
+			at91_mci_write(AT91_PDC_TPR, host->physical_address);
+			at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+			ier = AT91_MCI_TXBUFE;
+		}
+	}
+
+	/*
+	 * Send the command and then enable the PDC - not the other way round as
+	 * the data sheet says
+	 */
+
+	at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+	at91_mci_write(AT91_MCI_CMDR, cmdr);
+
+	if (cmdr & AT91_MCI_TRCMD_START) {
+		if (cmdr & AT91_MCI_TRDIR)
+			at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+		else
+			at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN);
+	}
+	return ier;
+}
+
+/*
+ * Wait for a command to complete
+ */
+static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+	unsigned int ier;
+
+	ier = at91_mci_send_command(host, cmd);
+
+	DBG("setting ier to %08X\n", ier);
+
+	/* Stop on errors or the required value */
+	at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+}
+
+/*
+ * Process the next step in the request
+ */
+static void at91mci_process_next(struct at91mci_host *host)
+{
+	if (!(host->flags & FL_SENT_COMMAND)) {
+		host->flags |= FL_SENT_COMMAND;
+		at91mci_process_command(host, host->request->cmd);
+	}
+	else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
+		host->flags |= FL_SENT_STOP;
+		at91mci_process_command(host, host->request->stop);
+	}
+	else
+		mmc_request_done(host->mmc, host->request);
+}
+
+/*
+ * Handle a command that has been completed
+ */
+static void at91mci_completed_command(struct at91mci_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	unsigned int status;
+
+	at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+
+	cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
+	cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
+	cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
+	cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+
+	if (host->buffer) {
+		dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+		host->buffer = NULL;
+	}
+
+	status = at91_mci_read(AT91_MCI_SR);
+
+	DBG("Status = %08X [%08X %08X %08X %08X]\n",
+		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+	if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
+			AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
+			AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
+		if ((status & AT91_MCI_RCRCE) &&
+			((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+			cmd->error = MMC_ERR_NONE;
+		}
+		else {
+			if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
+				cmd->error = MMC_ERR_TIMEOUT;
+			else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
+				cmd->error = MMC_ERR_BADCRC;
+			else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
+				cmd->error = MMC_ERR_FIFO;
+			else
+				cmd->error = MMC_ERR_FAILED;
+
+			DBG("Error detected and set to %d (cmd = %d, retries = %d)\n",
+				 cmd->error, cmd->opcode, cmd->retries);
+		}
+	}
+	else
+		cmd->error = MMC_ERR_NONE;
+
+	at91mci_process_next(host);
+}
+
+/*
+ * Handle an MMC request
+ */
+static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct at91mci_host *host = mmc_priv(mmc);
+	host->request = mrq;
+	host->flags = 0;
+
+	at91mci_process_next(host);
+}
+
+/*
+ * Set the IOS
+ */
+static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	int clkdiv;
+	struct at91mci_host *host = mmc_priv(mmc);
+	unsigned long at91_master_clock = clk_get_rate(mci_clk);
+
+	DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n",
+		ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+	if (host)
+		host->bus_mode = ios->bus_mode;
+	else
+		printk("MMC: No host for bus_mode\n");
+
+	if (ios->clock == 0) {
+		/* Disable the MCI controller */
+		at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+		clkdiv = 0;
+	}
+	else {
+		/* Enable the MCI controller */
+		at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+
+		if ((at91_master_clock % (ios->clock * 2)) == 0)
+			clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
+		else
+			clkdiv = (at91_master_clock / ios->clock) / 2;
+
+		DBG("clkdiv = %d. mcck = %ld\n", clkdiv,
+			at91_master_clock / (2 * (clkdiv + 1)));
+	}
+	if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
+		DBG("MMC: Setting controller bus width to 4\n");
+		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+	}
+	else {
+		DBG("MMC: Setting controller bus width to 1\n");
+		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+	}
+
+	/* Set the clock divider */
+	at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+
+	/* maybe switch power to the card */
+	if (host && host->board->vcc_pin) {
+		switch (ios->power_mode) {
+			case MMC_POWER_OFF:
+				at91_set_gpio_output(host->board->vcc_pin, 0);
+				break;
+			case MMC_POWER_UP:
+			case MMC_POWER_ON:
+				at91_set_gpio_output(host->board->vcc_pin, 1);
+				break;
+		}
+	}
+}
+
+/*
+ * Handle an interrupt
+ */
+static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct at91mci_host *host = devid;
+	int completed = 0;
+
+	unsigned int int_status;
+
+	if (host == NULL)
+		return IRQ_HANDLED;
+
+	int_status = at91_mci_read(AT91_MCI_SR);
+	DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
+		int_status & at91_mci_read(AT91_MCI_IMR));
+
+	if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+		completed = 1;
+
+	int_status &= at91_mci_read(AT91_MCI_IMR);
+
+	if (int_status & AT91_MCI_UNRE)
+		DBG("MMC: Underrun error\n");
+	if (int_status & AT91_MCI_OVRE)
+		DBG("MMC: Overrun error\n");
+	if (int_status & AT91_MCI_DTOE)
+		DBG("MMC: Data timeout\n");
+	if (int_status & AT91_MCI_DCRCE)
+		DBG("MMC: CRC error in data\n");
+	if (int_status & AT91_MCI_RTOE)
+		DBG("MMC: Response timeout\n");
+	if (int_status & AT91_MCI_RENDE)
+		DBG("MMC: Response end bit error\n");
+	if (int_status & AT91_MCI_RCRCE)
+		DBG("MMC: Response CRC error\n");
+	if (int_status & AT91_MCI_RDIRE)
+		DBG("MMC: Response direction error\n");
+	if (int_status & AT91_MCI_RINDE)
+		DBG("MMC: Response index error\n");
+
+	/* Only continue processing if no errors */
+	if (!completed) {
+		if (int_status & AT91_MCI_TXBUFE) {
+			DBG("TX buffer empty\n");
+			at91_mci_handle_transmitted(host);
+		}
+
+		if (int_status & AT91_MCI_RXBUFF) {
+			DBG("RX buffer full\n");
+			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+		}
+
+		if (int_status & AT91_MCI_ENDTX) {
+			DBG("Transmit has ended\n");
+		}
+
+		if (int_status & AT91_MCI_ENDRX) {
+			DBG("Receive has ended\n");
+			at91mci_post_dma_read(host);
+		}
+
+		if (int_status & AT91_MCI_NOTBUSY) {
+			DBG("Card is ready\n");
+			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+		}
+
+		if (int_status & AT91_MCI_DTIP) {
+			DBG("Data transfer in progress\n");
+		}
+
+		if (int_status & AT91_MCI_BLKE) {
+			DBG("Block transfer has ended\n");
+		}
+
+		if (int_status & AT91_MCI_TXRDY) {
+			DBG("Ready to transmit\n");
+		}
+
+		if (int_status & AT91_MCI_RXRDY) {
+			DBG("Ready to receive\n");
+		}
+
+		if (int_status & AT91_MCI_CMDRDY) {
+			DBG("Command ready\n");
+			completed = 1;
+		}
+	}
+	at91_mci_write(AT91_MCI_IDR, int_status);
+
+	if (completed) {
+		DBG("Completed command\n");
+		at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+		at91mci_completed_command(host);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs)
+{
+	struct at91mci_host *host = _host;
+	int present = !at91_get_gpio_value(irq);
+
+	/*
+	 * we expect this irq on both insert and remove,
+	 * and use a short delay to debounce.
+	 */
+	if (present != host->present) {
+		host->present = present;
+		DBG("%s: card %s\n", mmc_hostname(host->mmc),
+			present ? "insert" : "remove");
+		if (!present) {
+			DBG("****** Resetting SD-card bus width ******\n");
+			at91_mci_write(AT91_MCI_SDCR, 0);
+		}
+		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+	}
+	return IRQ_HANDLED;
+}
+
+int at91_mci_get_ro(struct mmc_host *mmc)
+{
+	int read_only = 0;
+	struct at91mci_host *host = mmc_priv(mmc);
+
+	if (host->board->wp_pin) {
+		read_only = at91_get_gpio_value(host->board->wp_pin);
+		printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
+				(read_only ? "read-only" : "read-write") );
+	}
+	else {
+		printk(KERN_WARNING "%s: host does not support reading read-only "
+				"switch.  Assuming write-enable.\n", mmc_hostname(mmc));
+	}
+	return read_only;
+}
+
+static struct mmc_host_ops at91_mci_ops = {
+	.request	= at91_mci_request,
+	.set_ios	= at91_mci_set_ios,
+	.get_ro		= at91_mci_get_ro,
+};
+
+/*
+ * Probe for the device
+ */
+static int at91_mci_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct at91mci_host *host;
+	int ret;
+
+	DBG("Probe MCI devices\n");
+	at91_mci_disable();
+	at91_mci_enable();
+
+	mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
+	if (!mmc) {
+		DBG("Failed to allocate mmc host\n");
+		return -ENOMEM;
+	}
+
+	mmc->ops = &at91_mci_ops;
+	mmc->f_min = 375000;
+	mmc->f_max = 25000000;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->buffer = NULL;
+	host->bus_mode = 0;
+	host->board = pdev->dev.platform_data;
+	if (host->board->wire4) {
+#ifdef SUPPORT_4WIRE
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
+#else
+		printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+#endif
+	}
+
+	/*
+	 * Get Clock
+	 */
+	mci_clk = clk_get(&pdev->dev, "mci_clk");
+	if (!mci_clk) {
+		printk(KERN_ERR "AT91 MMC: no clock defined.\n");
+		return -ENODEV;
+	}
+	clk_enable(mci_clk);			/* Enable the peripheral clock */
+
+	/*
+	 * Allocate the MCI interrupt
+	 */
+	ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host);
+	if (ret) {
+		DBG("Failed to request MCI interrupt\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, mmc);
+
+	/*
+	 * Add host to MMC layer
+	 */
+	if (host->board->det_pin)
+		host->present = !at91_get_gpio_value(host->board->det_pin);
+	else
+		host->present = -1;
+
+	mmc_add_host(mmc);
+
+	/*
+	 * monitor card insertion/removal if we can
+	 */
+	if (host->board->det_pin) {
+		ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
+				SA_SAMPLE_RANDOM, DRIVER_NAME, host);
+		if (ret)
+			DBG("couldn't allocate MMC detect irq\n");
+	}
+
+	DBG(KERN_INFO "Added MCI driver\n");
+
+	return 0;
+}
+
+/*
+ * Remove a device
+ */
+static int at91_mci_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct at91mci_host *host;
+
+	if (!mmc)
+		return -1;
+
+	host = mmc_priv(mmc);
+
+	if (host->present != -1) {
+		free_irq(host->board->det_pin, host);
+		cancel_delayed_work(&host->mmc->detect);
+	}
+
+	mmc_remove_host(mmc);
+	at91_mci_disable();
+	free_irq(AT91_ID_MCI, host);
+	mmc_free_host(mmc);
+
+	clk_disable(mci_clk);				/* Disable the peripheral clock */
+	clk_put(mci_clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	DBG("Removed\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (mmc)
+		ret = mmc_suspend_host(mmc, state);
+
+	return ret;
+}
+
+static int at91_mci_resume(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (mmc)
+		ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+#else
+#define at91_mci_suspend	NULL
+#define at91_mci_resume		NULL
+#endif
+
+static struct platform_driver at91_mci_driver = {
+	.probe		= at91_mci_probe,
+	.remove		= at91_mci_remove,
+	.suspend	= at91_mci_suspend,
+	.resume		= at91_mci_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_mci_init(void)
+{
+	return platform_driver_register(&at91_mci_driver);
+}
+
+static void __exit at91_mci_exit(void)
+{
+	platform_driver_unregister(&at91_mci_driver);
+}
+
+module_init(at91_mci_init);
+module_exit(at91_mci_exit);
+
+MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
+MODULE_AUTHOR("Nick Randell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
new file mode 100644
index 0000000..ffb7f55
--- /dev/null
+++ b/drivers/mmc/imxmmc.c
@@ -0,0 +1,1096 @@
+/*
+ *  linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
+ *
+ *  Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
+ *  Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ *  derived from pxamci.c by Russell King
+ *
+ * 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.
+ *
+ *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Changed to conform redesigned i.MX scatter gather DMA interface
+ *
+ *  2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Updated for 2.6.14 kernel
+ *
+ *  2005-12-13 Jay Monkman <jtm@smoothsmoothie.com>
+ *             Found and corrected problems in the write path
+ *
+ *  2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             The event handling rewritten right way in softirq.
+ *             Added many ugly hacks and delays to overcome SDHC
+ *             deficiencies
+ *
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG
+#else
+#undef  DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/protocol.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/imx-dma.h>
+
+#include "imxmmc.h"
+
+#define DRIVER_NAME "imx-mmc"
+
+#define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \
+	              INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \
+		      INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO)
+
+struct imxmci_host {
+	struct mmc_host		*mmc;
+	spinlock_t		lock;
+	struct resource		*res;
+	int			irq;
+	imx_dmach_t		dma;
+	unsigned int		clkrt;
+	unsigned int		cmdat;
+	volatile unsigned int	imask;
+	unsigned int		power_mode;
+	unsigned int		present;
+	struct imxmmc_platform_data *pdata;
+
+	struct mmc_request	*req;
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+
+	struct timer_list	timer;
+	struct tasklet_struct	tasklet;
+	unsigned int		status_reg;
+	unsigned long		pending_events;
+	/* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */
+	u16			*data_ptr;
+	unsigned int		data_cnt;
+	atomic_t		stuck_timeout;
+
+	unsigned int		dma_nents;
+	unsigned int		dma_size;
+	unsigned int		dma_dir;
+	int			dma_allocated;
+
+	unsigned char		actual_bus_width;
+};
+
+#define IMXMCI_PEND_IRQ_b	0
+#define IMXMCI_PEND_DMA_END_b	1
+#define IMXMCI_PEND_DMA_ERR_b	2
+#define IMXMCI_PEND_WAIT_RESP_b	3
+#define IMXMCI_PEND_DMA_DATA_b	4
+#define IMXMCI_PEND_CPU_DATA_b	5
+#define IMXMCI_PEND_CARD_XCHG_b	6
+#define IMXMCI_PEND_SET_INIT_b	7
+
+#define IMXMCI_PEND_IRQ_m	(1 << IMXMCI_PEND_IRQ_b)
+#define IMXMCI_PEND_DMA_END_m	(1 << IMXMCI_PEND_DMA_END_b)
+#define IMXMCI_PEND_DMA_ERR_m	(1 << IMXMCI_PEND_DMA_ERR_b)
+#define IMXMCI_PEND_WAIT_RESP_m	(1 << IMXMCI_PEND_WAIT_RESP_b)
+#define IMXMCI_PEND_DMA_DATA_m	(1 << IMXMCI_PEND_DMA_DATA_b)
+#define IMXMCI_PEND_CPU_DATA_m	(1 << IMXMCI_PEND_CPU_DATA_b)
+#define IMXMCI_PEND_CARD_XCHG_m	(1 << IMXMCI_PEND_CARD_XCHG_b)
+#define IMXMCI_PEND_SET_INIT_m	(1 << IMXMCI_PEND_SET_INIT_b)
+
+static void imxmci_stop_clock(struct imxmci_host *host)
+{
+	int i = 0;
+	MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK;
+	while(i < 0x1000) {
+	        if(!(i & 0x7f))
+			MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK;
+
+		if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) {
+			/* Check twice before cut */
+			if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN))
+				return;
+		}
+
+		i++;
+	}
+	dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
+}
+
+static void imxmci_start_clock(struct imxmci_host *host)
+{
+	int i = 0;
+	MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
+	while(i < 0x1000) {
+	        if(!(i & 0x7f))
+			MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+		if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) {
+			/* Check twice before cut */
+			if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+				return;
+		}
+
+		i++;
+	}
+	dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+}
+
+static void imxmci_softreset(void)
+{
+	/* reset sequence */
+	MMC_STR_STP_CLK = 0x8;
+	MMC_STR_STP_CLK = 0xD;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+
+	MMC_RES_TO = 0xff;
+	MMC_BLK_LEN = 512;
+	MMC_NOB = 1;
+}
+
+static int imxmci_busy_wait_for_status(struct imxmci_host *host,
+			unsigned int *pstat, unsigned int stat_mask,
+			int timeout, const char *where)
+{
+	int loops=0;
+	while(!(*pstat & stat_mask)) {
+		loops+=2;
+		if(loops >= timeout) {
+			dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n",
+				where, *pstat, stat_mask);
+			return -1;
+		}
+		udelay(2);
+		*pstat |= MMC_STATUS;
+	}
+	if(!loops)
+		return 0;
+
+	dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
+		loops, where, *pstat, stat_mask);
+	return loops;
+}
+
+static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
+{
+	unsigned int nob = data->blocks;
+	unsigned int blksz = 1 << data->blksz_bits;
+	unsigned int datasz = nob * blksz;
+	int i;
+
+	if (data->flags & MMC_DATA_STREAM)
+		nob = 0xffff;
+
+	host->data = data;
+	data->bytes_xfered = 0;
+
+	MMC_NOB = nob;
+	MMC_BLK_LEN = blksz;
+
+	/*
+	 * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise.
+	 * We are in big troubles for non-512 byte transfers according to note in the paragraph
+	 * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least.
+	 * The situation is even more complex in reality. The SDHC in not able to handle wll
+	 * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
+	 * This is required for SCR read at least.
+	 */
+	if (datasz < 64) {
+		host->dma_size = datasz;
+		if (data->flags & MMC_DATA_READ) {
+			host->dma_dir = DMA_FROM_DEVICE;
+
+			/* Hack to enable read SCR */
+			if(datasz < 16) {
+				MMC_NOB = 1;
+				MMC_BLK_LEN = 16;
+			}
+		} else {
+			host->dma_dir = DMA_TO_DEVICE;
+		}
+
+		/* Convert back to virtual address */
+		host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
+		host->data_cnt = 0;
+
+		clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+		set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+		return;
+	}
+
+	if (data->flags & MMC_DATA_READ) {
+		host->dma_dir = DMA_FROM_DEVICE;
+		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+						data->sg_len,  host->dma_dir);
+
+		imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+			host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ);
+
+		/*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/
+		CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN;
+	} else {
+		host->dma_dir = DMA_TO_DEVICE;
+
+		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+						data->sg_len,  host->dma_dir);
+
+		imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+			host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE);
+
+		/*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/
+		CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN;
+	}
+
+#if 1	/* This code is there only for consistency checking and can be disabled in future */
+	host->dma_size = 0;
+	for(i=0; i<host->dma_nents; i++)
+		host->dma_size+=data->sg[i].length;
+
+	if (datasz > host->dma_size) {
+		dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n",
+		       datasz, host->dma_size);
+	}
+#endif
+
+	host->dma_size = datasz;
+
+	wmb();
+
+	if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+		BLR(host->dma) = 0;	/* burst 64 byte read / 64 bytes write */
+	else
+		BLR(host->dma) = 16;	/* burst 16 byte read / 16 bytes write */
+
+	RSSR(host->dma) = DMA_REQ_SDHC;
+
+	set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+	clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+	/* start DMA engine for read, write is delayed after initial response */
+	if (host->dma_dir == DMA_FROM_DEVICE) {
+		imx_dma_enable(host->dma);
+	}
+}
+
+static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+	unsigned long flags;
+	u32 imask;
+
+	WARN_ON(host->cmd != NULL);
+	host->cmd = cmd;
+
+	if (cmd->flags & MMC_RSP_BUSY)
+		cmdat |= CMD_DAT_CONT_BUSY;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_R1: /* short CRC, OPCODE */
+	case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
+		break;
+	case MMC_RSP_R2: /* long 136 bit + CRC */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
+		break;
+	case MMC_RSP_R3: /* short */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
+		break;
+	case MMC_RSP_R6: /* short CRC */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6;
+		break;
+	default:
+		break;
+	}
+
+	if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
+		cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */
+
+	if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
+		cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+
+	MMC_CMD = cmd->opcode;
+	MMC_ARGH = cmd->arg >> 16;
+	MMC_ARGL = cmd->arg & 0xffff;
+	MMC_CMD_DAT_CONT = cmdat;
+
+	atomic_set(&host->stuck_timeout, 0);
+	set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);
+
+
+	imask = IMXMCI_INT_MASK_DEFAULT;
+	imask &= ~INT_MASK_END_CMD_RES;
+	if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
+		/*imask &= ~INT_MASK_BUF_READY;*/
+		imask &= ~INT_MASK_DATA_TRAN;
+		if ( cmdat & CMD_DAT_CONT_WRITE )
+			imask &= ~INT_MASK_WRITE_OP_DONE;
+		if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+			imask &= ~INT_MASK_BUF_READY;
+	}
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->imask = imask;
+	MMC_INT_MASK = host->imask;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
+		cmd->opcode, cmd->opcode, imask);
+
+	imxmci_start_clock(host);
+}
+
+static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m |
+			IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m);
+
+	host->imask = IMXMCI_INT_MASK_DEFAULT;
+	MMC_INT_MASK = host->imask;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	host->req = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+	mmc_request_done(host->mmc, req);
+}
+
+static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat)
+{
+	struct mmc_data *data = host->data;
+	int data_error;
+
+	if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){
+		imx_dma_disable(host->dma);
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+			     host->dma_dir);
+	}
+
+	if ( stat & STATUS_ERR_MASK ) {
+		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat);
+		if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR))
+			data->error = MMC_ERR_BADCRC;
+		else if(stat & STATUS_TIME_OUT_READ)
+			data->error = MMC_ERR_TIMEOUT;
+		else
+			data->error = MMC_ERR_FAILED;
+	} else {
+		data->bytes_xfered = host->dma_size;
+	}
+
+	data_error = data->error;
+
+	host->data = NULL;
+
+	return data_error;
+}
+
+static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat)
+{
+	struct mmc_command *cmd = host->cmd;
+	int i;
+	u32 a,b,c;
+	struct mmc_data *data = host->data;
+
+	if (!cmd)
+		return 0;
+
+	host->cmd = NULL;
+
+	if (stat & STATUS_TIME_OUT_RESP) {
+		dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
+		cmd->error = MMC_ERR_TIMEOUT;
+	} else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+		dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
+		cmd->error = MMC_ERR_BADCRC;
+	}
+
+	if(cmd->flags & MMC_RSP_PRESENT) {
+		if(cmd->flags & MMC_RSP_136) {
+			for (i = 0; i < 4; i++) {
+				u32 a = MMC_RES_FIFO & 0xffff;
+				u32 b = MMC_RES_FIFO & 0xffff;
+				cmd->resp[i] = a<<16 | b;
+			}
+		} else {
+			a = MMC_RES_FIFO & 0xffff;
+			b = MMC_RES_FIFO & 0xffff;
+			c = MMC_RES_FIFO & 0xffff;
+			cmd->resp[0] = a<<24 | b<<8 | c>>8;
+		}
+	}
+
+	dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n",
+		cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
+
+	if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) {
+		if (host->req->data->flags & MMC_DATA_WRITE) {
+
+			/* Wait for FIFO to be empty before starting DMA write */
+
+			stat = MMC_STATUS;
+			if(imxmci_busy_wait_for_status(host, &stat,
+				STATUS_APPL_BUFF_FE,
+				40, "imxmci_cmd_done DMA WR") < 0) {
+				cmd->error = MMC_ERR_FIFO;
+				imxmci_finish_data(host, stat);
+				if(host->req)
+					imxmci_finish_request(host, host->req);
+				dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n",
+				       stat);
+				return 0;
+			}
+
+			if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+				imx_dma_enable(host->dma);
+			}
+		}
+	} else {
+		struct mmc_request *req;
+		imxmci_stop_clock(host);
+		req = host->req;
+
+		if(data)
+			imxmci_finish_data(host, stat);
+
+		if( req ) {
+			imxmci_finish_request(host, req);
+		} else {
+			dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n");
+		}
+	}
+
+	return 1;
+}
+
+static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
+{
+	struct mmc_data *data = host->data;
+	int data_error;
+
+	if (!data)
+		return 0;
+
+	data_error = imxmci_finish_data(host, stat);
+
+	if (host->req->stop && (data_error == MMC_ERR_NONE)) {
+		imxmci_stop_clock(host);
+		imxmci_start_cmd(host, host->req->stop, 0);
+	} else {
+		struct mmc_request *req;
+		req = host->req;
+		if( req ) {
+			imxmci_finish_request(host, req);
+		} else {
+			dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n");
+		}
+	}
+
+	return 1;
+}
+
+static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
+{
+	int i;
+	int burst_len;
+	int flush_len;
+	int trans_done = 0;
+	unsigned int stat = *pstat;
+
+	if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+		burst_len = 16;
+	else
+		burst_len = 64;
+
+	/* This is unfortunately required */
+	dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
+		stat);
+
+	if(host->dma_dir == DMA_FROM_DEVICE) {
+		imxmci_busy_wait_for_status(host, &stat,
+				STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
+				20, "imxmci_cpu_driven_data read");
+
+		while((stat & (STATUS_APPL_BUFF_FF |  STATUS_DATA_TRANS_DONE)) &&
+		      (host->data_cnt < host->dma_size)) {
+			if(burst_len >= host->dma_size - host->data_cnt) {
+				flush_len = burst_len;
+				burst_len = host->dma_size - host->data_cnt;
+				flush_len -= burst_len;
+				host->data_cnt = host->dma_size;
+				trans_done = 1;
+			} else {
+				flush_len = 0;
+				host->data_cnt += burst_len;
+			}
+
+			for(i = burst_len; i>=2 ; i-=2) {
+				*(host->data_ptr++) = MMC_BUFFER_ACCESS;
+				udelay(20);	/* required for clocks < 8MHz*/
+			}
+
+			if(i == 1)
+				*(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS;
+
+			stat = MMC_STATUS;
+
+			/* Flush extra bytes from FIFO */
+			while(flush_len >= 2){
+				flush_len -= 2;
+				i = MMC_BUFFER_ACCESS;
+				stat = MMC_STATUS;
+				stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
+			}
+
+			dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n",
+				burst_len, stat);
+		}
+	} else {
+		imxmci_busy_wait_for_status(host, &stat,
+				STATUS_APPL_BUFF_FE,
+				20, "imxmci_cpu_driven_data write");
+
+		while((stat & STATUS_APPL_BUFF_FE) &&
+		      (host->data_cnt < host->dma_size)) {
+			if(burst_len >= host->dma_size - host->data_cnt) {
+				burst_len = host->dma_size - host->data_cnt;
+				host->data_cnt = host->dma_size;
+				trans_done = 1;
+			} else {
+				host->data_cnt += burst_len;
+			}
+
+			for(i = burst_len; i>0 ; i-=2)
+				MMC_BUFFER_ACCESS = *(host->data_ptr++);
+
+			stat = MMC_STATUS;
+
+			dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n",
+				burst_len, stat);
+		}
+	}
+
+	*pstat = stat;
+
+	return trans_done;
+}
+
+static void imxmci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+{
+	struct imxmci_host *host = devid;
+	uint32_t stat = MMC_STATUS;
+
+	atomic_set(&host->stuck_timeout, 0);
+	host->status_reg = stat;
+	set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+	tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct imxmci_host *host = devid;
+	uint32_t stat = MMC_STATUS;
+	int handled = 1;
+
+	MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT;
+
+	atomic_set(&host->stuck_timeout, 0);
+	host->status_reg = stat;
+	set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+	tasklet_schedule(&host->tasklet);
+
+	return IRQ_RETVAL(handled);;
+}
+
+static void imxmci_tasklet_fnc(unsigned long data)
+{
+	struct imxmci_host *host = (struct imxmci_host *)data;
+	u32 stat;
+	unsigned int data_dir_mask = 0;	/* STATUS_WR_CRC_ERROR_CODE_MASK */
+	int timeout = 0;
+
+	if(atomic_read(&host->stuck_timeout) > 4) {
+		char *what;
+		timeout = 1;
+		stat = MMC_STATUS;
+		host->status_reg = stat;
+		if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+			if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+				what = "RESP+DMA";
+			else
+				what = "RESP";
+		else
+			if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+				if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
+					what = "DATA";
+				else
+					what = "DMA";
+			else
+				what = "???";
+
+		dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
+		       what, stat, MMC_INT_MASK);
+		dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
+		       MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
+		dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n",
+		       host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size);
+	}
+
+	if(!host->present || timeout)
+		host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
+				    STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;
+
+	if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
+		clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+
+		stat = MMC_STATUS;
+		/*
+		 * This is not required in theory, but there is chance to miss some flag
+		 * which clears automatically by mask write, FreeScale original code keeps
+		 * stat from IRQ time so do I
+		 */
+		stat |= host->status_reg;
+
+		if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+			imxmci_busy_wait_for_status(host, &stat,
+					STATUS_END_CMD_RESP | STATUS_ERR_MASK,
+					20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
+		}
+
+		if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
+			if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+				imxmci_cmd_done(host, stat);
+			if(host->data && (stat & STATUS_ERR_MASK))
+				imxmci_data_done(host, stat);
+		}
+
+		if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
+			stat |= MMC_STATUS;
+			if(imxmci_cpu_driven_data(host, &stat)){
+				if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+					imxmci_cmd_done(host, stat);
+				atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
+							&host->pending_events);
+				imxmci_data_done(host, stat);
+			}
+		}
+	}
+
+	if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
+	   !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+
+		stat = MMC_STATUS;
+		/* Same as above */
+		stat |= host->status_reg;
+
+		if(host->dma_dir == DMA_TO_DEVICE) {
+			data_dir_mask = STATUS_WRITE_OP_DONE;
+		} else {
+			data_dir_mask = STATUS_DATA_TRANS_DONE;
+		}
+
+		imxmci_busy_wait_for_status(host, &stat,
+				data_dir_mask,
+				50, "imxmci_tasklet_fnc data");
+
+		if(stat & data_dir_mask) {
+			clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+			imxmci_data_done(host, stat);
+		}
+	}
+
+	if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {
+
+		if(host->cmd)
+			imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);
+
+		if(host->data)
+			imxmci_data_done(host, STATUS_TIME_OUT_READ |
+					 STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);
+
+		if(host->req)
+			imxmci_finish_request(host, host->req);
+
+		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+
+	}
+}
+
+static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+	struct imxmci_host *host = mmc_priv(mmc);
+	unsigned int cmdat;
+
+	WARN_ON(host->req != NULL);
+
+	host->req = req;
+
+	cmdat = 0;
+
+	if (req->data) {
+		imxmci_setup_data(host, req->data);
+
+		cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+		if (req->data->flags & MMC_DATA_WRITE)
+			cmdat |= CMD_DAT_CONT_WRITE;
+
+		if (req->data->flags & MMC_DATA_STREAM) {
+			cmdat |= CMD_DAT_CONT_STREAM_BLOCK;
+		}
+	}
+
+	imxmci_start_cmd(host, req->cmd, cmdat);
+}
+
+#define CLK_RATE 19200000
+
+static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct imxmci_host *host = mmc_priv(mmc);
+	int prescaler;
+
+	dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n",
+		ios->clock, ios->power_mode, ios->vdd,
+		(ios->bus_width==MMC_BUS_WIDTH_4)?4:1);
+
+	if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
+		host->actual_bus_width = MMC_BUS_WIDTH_4;
+		imx_gpio_mode(PB11_PF_SD_DAT3);
+	}else{
+		host->actual_bus_width = MMC_BUS_WIDTH_1;
+		imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+	}
+
+	if ( host->power_mode != ios->power_mode ) {
+		switch (ios->power_mode) {
+		case MMC_POWER_OFF:
+        		break;
+		case MMC_POWER_UP:
+			set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+        		break;
+		case MMC_POWER_ON:
+        		break;
+		}
+		host->power_mode = ios->power_mode;
+	}
+
+	if ( ios->clock ) {
+		unsigned int clk;
+
+		/* The prescaler is 5 for PERCLK2 equal to 96MHz
+		 * then 96MHz / 5 = 19.2 MHz
+		 */
+		clk=imx_get_perclk2();
+		prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE;
+		switch(prescaler) {
+		case 0:
+		case 1:	prescaler = 0;
+			break;
+		case 2:	prescaler = 1;
+			break;
+		case 3:	prescaler = 2;
+			break;
+		case 4:	prescaler = 4;
+			break;
+		default:
+		case 5:	prescaler = 5;
+			break;
+		}
+
+		dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n",
+			clk, prescaler);
+
+		for(clk=0; clk<8; clk++) {
+			int x;
+			x = CLK_RATE / (1<<clk);
+			if( x <= ios->clock)
+				break;
+		}
+
+		MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */
+
+		imxmci_stop_clock(host);
+		MMC_CLK_RATE = (prescaler<<3) | clk;
+		imxmci_start_clock(host);
+
+		dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
+	} else {
+		imxmci_stop_clock(host);
+	}
+}
+
+static struct mmc_host_ops imxmci_ops = {
+	.request	= imxmci_request,
+	.set_ios	= imxmci_set_ios,
+};
+
+static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++)
+		if (dev->resource[i].flags == mask && nr-- == 0)
+			return &dev->resource[i];
+	return NULL;
+}
+
+static int platform_device_irq(struct platform_device *dev, int nr)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++)
+		if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
+			return dev->resource[i].start;
+	return NO_IRQ;
+}
+
+static void imxmci_check_status(unsigned long data)
+{
+	struct imxmci_host *host = (struct imxmci_host *)data;
+
+	if( host->pdata->card_present() != host->present ) {
+		host->present ^= 1;
+		dev_info(mmc_dev(host->mmc), "card %s\n",
+		      host->present ? "inserted" : "removed");
+
+		set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events);
+		tasklet_schedule(&host->tasklet);
+	}
+
+	if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) ||
+	   test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+		atomic_inc(&host->stuck_timeout);
+		if(atomic_read(&host->stuck_timeout) > 4)
+			tasklet_schedule(&host->tasklet);
+	} else {
+		atomic_set(&host->stuck_timeout, 0);
+
+	}
+
+	mod_timer(&host->timer, jiffies + (HZ>>1));
+}
+
+static int imxmci_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct imxmci_host *host = NULL;
+	struct resource *r;
+	int ret = 0, irq;
+
+	printk(KERN_INFO "i.MX mmc driver\n");
+
+	r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_device_irq(pdev, 0);
+	if (!r || irq == NO_IRQ)
+		return -ENXIO;
+
+	r = request_mem_region(r->start, 0x100, "IMXMCI");
+	if (!r)
+		return -EBUSY;
+
+	mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mmc->ops = &imxmci_ops;
+	mmc->f_min = 150000;
+	mmc->f_max = CLK_RATE/2;
+	mmc->ocr_avail = MMC_VDD_32_33;
+	mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+	/* MMC core transfer sizes tunable parameters */
+	mmc->max_hw_segs = 64;
+	mmc->max_phys_segs = 64;
+	mmc->max_sectors = 64;		/* default 1 << (PAGE_CACHE_SHIFT - 9) */
+	mmc->max_seg_size = 64*512;	/* default PAGE_CACHE_SIZE */
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->dma_allocated = 0;
+	host->pdata = pdev->dev.platform_data;
+
+	spin_lock_init(&host->lock);
+	host->res = r;
+	host->irq = irq;
+
+	imx_gpio_mode(PB8_PF_SD_DAT0);
+	imx_gpio_mode(PB9_PF_SD_DAT1);
+	imx_gpio_mode(PB10_PF_SD_DAT2);
+	/* Configured as GPIO with pull-up to ensure right MCC card mode */
+	/* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */
+	imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+	/* imx_gpio_mode(PB11_PF_SD_DAT3); */
+	imx_gpio_mode(PB12_PF_SD_CLK);
+	imx_gpio_mode(PB13_PF_SD_CMD);
+
+	imxmci_softreset();
+
+	if ( MMC_REV_NO != 0x390 ) {
+		dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
+		        MMC_REV_NO);
+		goto out;
+	}
+
+	MMC_READ_TO = 0x2db4; /* recommended in data sheet */
+
+	host->imask = IMXMCI_INT_MASK_DEFAULT;
+	MMC_INT_MASK = host->imask;
+
+
+	if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){
+		dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
+		ret = -EBUSY;
+		goto out;
+	}
+	host->dma_allocated=1;
+	imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
+
+	tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
+	host->status_reg=0;
+	host->pending_events=0;
+
+	ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host);
+	if (ret)
+		goto out;
+
+	host->present = host->pdata->card_present();
+	init_timer(&host->timer);
+	host->timer.data = (unsigned long)host;
+	host->timer.function = imxmci_check_status;
+	add_timer(&host->timer);
+	mod_timer(&host->timer, jiffies + (HZ>>1));
+
+	platform_set_drvdata(pdev, mmc);
+
+	mmc_add_host(mmc);
+
+	return 0;
+
+out:
+	if (host) {
+		if(host->dma_allocated){
+			imx_dma_free(host->dma);
+			host->dma_allocated=0;
+		}
+	}
+	if (mmc)
+		mmc_free_host(mmc);
+	release_resource(r);
+	return ret;
+}
+
+static int imxmci_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (mmc) {
+		struct imxmci_host *host = mmc_priv(mmc);
+
+		tasklet_disable(&host->tasklet);
+
+		del_timer_sync(&host->timer);
+		mmc_remove_host(mmc);
+
+		free_irq(host->irq, host);
+		if(host->dma_allocated){
+			imx_dma_free(host->dma);
+			host->dma_allocated=0;
+		}
+
+		tasklet_kill(&host->tasklet);
+
+		release_resource(host->res);
+
+		mmc_free_host(mmc);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc)
+		ret = mmc_suspend_host(mmc, state);
+
+	return ret;
+}
+
+static int imxmci_resume(struct platform_device *dev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+	struct imxmci_host *host;
+	int ret = 0;
+
+	if (mmc) {
+		host = mmc_priv(mmc);
+		if(host)
+			set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+		ret = mmc_resume_host(mmc);
+	}
+
+	return ret;
+}
+#else
+#define imxmci_suspend  NULL
+#define imxmci_resume   NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver imxmci_driver = {
+	.probe		= imxmci_probe,
+	.remove		= imxmci_remove,
+	.suspend	= imxmci_suspend,
+	.resume		= imxmci_resume,
+	.driver		= {
+		.name		= DRIVER_NAME,
+	}
+};
+
+static int __init imxmci_init(void)
+{
+	return platform_driver_register(&imxmci_driver);
+}
+
+static void __exit imxmci_exit(void)
+{
+	platform_driver_unregister(&imxmci_driver);
+}
+
+module_init(imxmci_init);
+module_exit(imxmci_exit);
+
+MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/imxmmc.h
new file mode 100644
index 0000000..e5339e3
--- /dev/null
+++ b/drivers/mmc/imxmmc.h
@@ -0,0 +1,67 @@
+
+# define __REG16(x)	(*((volatile u16 *)IO_ADDRESS(x)))
+
+#define MMC_STR_STP_CLK  __REG16(IMX_MMC_BASE + 0x00)
+#define MMC_STATUS       __REG16(IMX_MMC_BASE + 0x04)
+#define MMC_CLK_RATE     __REG16(IMX_MMC_BASE + 0x08)
+#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C)
+#define MMC_RES_TO       __REG16(IMX_MMC_BASE + 0x10)
+#define MMC_READ_TO      __REG16(IMX_MMC_BASE + 0x14)
+#define MMC_BLK_LEN      __REG16(IMX_MMC_BASE + 0x18)
+#define MMC_NOB          __REG16(IMX_MMC_BASE + 0x1C)
+#define MMC_REV_NO       __REG16(IMX_MMC_BASE + 0x20)
+#define MMC_INT_MASK     __REG16(IMX_MMC_BASE + 0x24)
+#define MMC_CMD          __REG16(IMX_MMC_BASE + 0x28)
+#define MMC_ARGH         __REG16(IMX_MMC_BASE + 0x2C)
+#define MMC_ARGL         __REG16(IMX_MMC_BASE + 0x30)
+#define MMC_RES_FIFO     __REG16(IMX_MMC_BASE + 0x34)
+#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38)
+#define MMC_BUFFER_ACCESS_OFS 0x38
+
+
+#define STR_STP_CLK_ENDIAN              (1<<5)
+#define STR_STP_CLK_RESET               (1<<3)
+#define STR_STP_CLK_ENABLE              (1<<2)
+#define STR_STP_CLK_START_CLK           (1<<1)
+#define STR_STP_CLK_STOP_CLK            (1<<0)
+#define STATUS_CARD_PRESENCE            (1<<15)
+#define STATUS_SDIO_INT_ACTIVE          (1<<14)
+#define STATUS_END_CMD_RESP             (1<<13)
+#define STATUS_WRITE_OP_DONE            (1<<12)
+#define STATUS_DATA_TRANS_DONE          (1<<11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK   (3<<10)
+#define STATUS_CARD_BUS_CLK_RUN         (1<<8)
+#define STATUS_APPL_BUFF_FF             (1<<7)
+#define STATUS_APPL_BUFF_FE             (1<<6)
+#define STATUS_RESP_CRC_ERR             (1<<5)
+#define STATUS_CRC_READ_ERR             (1<<3)
+#define STATUS_CRC_WRITE_ERR            (1<<2)
+#define STATUS_TIME_OUT_RESP            (1<<1)
+#define STATUS_TIME_OUT_READ            (1<<0)
+#define STATUS_ERR_MASK                 0x2f
+#define CLK_RATE_PRESCALER(x)           ((x) & 0x7)
+#define CLK_RATE_CLK_RATE(x)            (((x) & 0x7) << 3)
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF  (1<<12)
+#define CMD_DAT_CONT_STOP_READWAIT      (1<<11)
+#define CMD_DAT_CONT_START_READWAIT     (1<<10)
+#define CMD_DAT_CONT_BUS_WIDTH_1        (0<<8)
+#define CMD_DAT_CONT_BUS_WIDTH_4        (2<<8)
+#define CMD_DAT_CONT_INIT               (1<<7)
+#define CMD_DAT_CONT_BUSY               (1<<6)
+#define CMD_DAT_CONT_STREAM_BLOCK       (1<<5)
+#define CMD_DAT_CONT_WRITE              (1<<4)
+#define CMD_DAT_CONT_DATA_ENABLE        (1<<3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6)
+#define INT_MASK_AUTO_CARD_DETECT       (1<<6)
+#define INT_MASK_DAT0_EN                (1<<5)
+#define INT_MASK_SDIO                   (1<<4)
+#define INT_MASK_BUF_READY              (1<<3)
+#define INT_MASK_END_CMD_RES            (1<<2)
+#define INT_MASK_WRITE_OP_DONE          (1<<1)
+#define INT_MASK_DATA_TRAN              (1<<0)
+#define INT_ALL                         (0x7f)
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 0f6bb2e..a7ec595 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -200,27 +200,6 @@
 	  provides support for one of those command sets, used on chips
 	  including the AMD Am29LV320.
 
-config MTD_CFI_AMDSTD_RETRY
-	int "Retry failed commands (erase/program)"
-	depends on MTD_CFI_AMDSTD
-	default "0"
-	help
-	  Some chips, when attached to a shared bus, don't properly filter
-	  bus traffic that is destined to other devices.  This broken
-	  behavior causes erase and program sequences to be aborted when
-	  the sequences are mixed with traffic for other devices.
-
-	  SST49LF040 (and related) chips are know to be broken.
-
-config MTD_CFI_AMDSTD_RETRY_MAX
-	int "Max retries of failed commands (erase/program)"
-	depends on MTD_CFI_AMDSTD_RETRY
-	default "0"
-	help
-	  If you have an SST49LF040 (or related chip) then this value should
-	  be set to at least 1.  This can also be adjusted at driver load
-	  time with the retry_cmd_max module parameter.
-
 config MTD_CFI_STAA
 	tristate "Support for ST (Advanced Architecture) flash chips"
 	depends on MTD_GEN_PROBE
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ce99845..066e22b 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -539,8 +539,7 @@
 		unsigned buflen;
 
 		skb = cp->rx_skb[rx_tail].skb;
-		if (!skb)
-			BUG();
+		BUG_ON(!skb);
 
 		desc = &cp->rx_ring[rx_tail];
 		status = le32_to_cpu(desc->opts1);
@@ -723,8 +722,7 @@
 			break;
 
 		skb = cp->tx_skb[tx_tail].skb;
-		if (!skb)
-			BUG();
+		BUG_ON(!skb);
 
 		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
 				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
@@ -1550,8 +1548,7 @@
 	tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
 	tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
 	tmp_stats[i++] = cp->cp_stats.rx_frags;
-	if (i != CP_NUM_STATS)
-		BUG();
+	BUG_ON(i != CP_NUM_STATS);
 
 	pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
 }
@@ -1856,8 +1853,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct cp_private *cp = netdev_priv(dev);
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 	unregister_netdev(dev);
 	iounmap(cp->regs);
 	if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 64e2caf3..fabc060 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -765,8 +765,7 @@
 	BUGMSG(D_DURING, "in arcnet_interrupt\n");
 	
 	lp = dev->priv;
-	if (!lp)
-		BUG();
+	BUG_ON(!lp);
 		
 	spin_lock(&lp->lock);
 
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 15032f2..c4e12b5 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -608,8 +608,7 @@
 		struct ring_info *rp = &bp->tx_buffers[cons];
 		struct sk_buff *skb = rp->skb;
 
-		if (unlikely(skb == NULL))
-			BUG();
+		BUG_ON(skb == NULL);
 
 		pci_unmap_single(bp->pdev,
 				 pci_unmap_addr(rp, mapping),
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 30ff8ea..4391bf4 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1093,8 +1093,7 @@
 		if (likely(e->DataValid)) {
 			struct freelQ *fl = &sge->freelQ[e->FreelistQid];
 
-			if (unlikely(!e->Sop || !e->Eop))
-				BUG();
+			BUG_ON(!e->Sop || !e->Eop);
 			if (unlikely(e->Offload))
 				unexpected_offload(adapter, fl);
 			else
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 49cd096..add8dc4 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3308,8 +3308,7 @@
 
 	while (poll_dev != &adapter->polling_netdev[i]) {
 		i++;
-		if (unlikely(i == adapter->num_rx_queues))
-			BUG();
+		BUG_ON(i == adapter->num_rx_queues);
 	}
 
 	if (likely(adapter->num_tx_queues == 1)) {
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index aa15691..815436c 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -203,8 +203,7 @@
 	printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
 	       "your slave devices.\n", dev->name);
 
-	if (!list_empty(&eql->queue.all_slaves))
-		BUG();
+	BUG_ON(!list_empty(&eql->queue.all_slaves));
 
 	eql->min_slaves = 1;
 	eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 63d38fb..f530686 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -695,8 +695,7 @@
 		/*
 		 * We must not be transmitting...
 		 */
-		if (si->txskb)
-			BUG();
+		BUG_ON(si->txskb);
 
 		netif_stop_queue(dev);
 
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index d11821d..ced9fdb 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -645,9 +645,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	if (!dev)
-		BUG();
-
+	BUG_ON(!dev);
 	unregister_netdev(dev);
 	release_region(dev->base_addr, NE_IO_EXTENT);
 	free_netdev(dev);
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 8e9b1a5..706aed7 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -568,8 +568,7 @@
 #endif
 
 	sg = dev->rx_info.descs + (next_empty * DESC_SIZE);
-	if (unlikely(NULL != dev->rx_info.skbs[next_empty]))
-		BUG();
+	BUG_ON(NULL != dev->rx_info.skbs[next_empty]);
 	dev->rx_info.skbs[next_empty] = skb;
 
 	dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC;
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 35b1805..45ad036 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -2122,8 +2122,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct netdev_private *np = netdev_priv(dev);
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 
 	unregister_netdev(dev);
 
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 770e6b6..0b53580 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -2959,9 +2959,7 @@
 		struct sk_buff *skb = ri->skb;
 		int i;
 
-		if (unlikely(skb == NULL))
-			BUG();
-
+		BUG_ON(skb == NULL);
 		pci_unmap_single(tp->pdev,
 				 pci_unmap_addr(ri, mapping),
 				 skb_headlen(skb),
@@ -2972,12 +2970,10 @@
 		sw_idx = NEXT_TX(sw_idx);
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			if (unlikely(sw_idx == hw_idx))
-				BUG();
+			BUG_ON(sw_idx == hw_idx);
 
 			ri = &tp->tx_buffers[sw_idx];
-			if (unlikely(ri->skb != NULL))
-				BUG();
+			BUG_ON(ri->skb != NULL);
 
 			pci_unmap_page(tp->pdev,
 				       pci_unmap_addr(ri, mapping),
@@ -4928,9 +4924,8 @@
 {
 	int i;
 
-	if (offset == TX_CPU_BASE &&
-	    (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
-		BUG();
+	BUG_ON(offset == TX_CPU_BASE &&
+	    (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
 
 	if (offset == RX_CPU_BASE) {
 		for (i = 0; i < 10000; i++) {
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 9345e68..649d8ea 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -438,8 +438,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 	unregister_netdev(dev);
 	release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
 	free_irq(dev->irq, dev);
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 3a25d19..19e6f4d 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -735,8 +735,7 @@
 	struct net_local *tp;
         struct card_info *card;
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 
 	tp = dev->priv;
 	card = tp->tmspriv;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9dce522..bca89cf 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -5573,8 +5573,7 @@
 	case IEEE80211_52GHZ_BAND:
 		network->mode = IEEE_A;
 		i = ieee80211_channel_to_index(priv->ieee, priv->channel);
-		if (i == -1)
-			BUG();
+		BUG_ON(i == -1);
 		if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
 			IPW_WARNING("Overriding invalid channel\n");
 			priv->channel = geo->a[0].channel;
@@ -5587,8 +5586,7 @@
 		else
 			network->mode = IEEE_B;
 		i = ieee80211_channel_to_index(priv->ieee, priv->channel);
-		if (i == -1)
-			BUG();
+		BUG_ON(i == -1);
 		if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
 			IPW_WARNING("Overriding invalid channel\n");
 			priv->channel = geo->bg[0].channel;
@@ -6715,8 +6713,7 @@
 
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_ADHOC:
-		if (!(network->capability & WLAN_CAPABILITY_IBSS))
-			BUG();
+		BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS));
 
 		qos_data = &ibss_data;
 		break;
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 75d56bf..fd0f43b 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1441,8 +1441,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct yellowfin_private *np;
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 	np = netdev_priv(dev);
 
         pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, 
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 8fd71ab..b842377 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -32,9 +32,8 @@
 	int size;
 
 	/* Sanity checks */
-	if ( magic == NULL || datasize > PAGE_SIZE ||
-	     (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
-		BUG();
+	BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+	     (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
 
 	size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
 	if (cplength > 0)
@@ -125,8 +124,7 @@
 	struct dasd_device *device;
 	int success;
 
-	if (cqr->refers == NULL || cqr->function == NULL)
-		BUG();
+	BUG_ON(cqr->refers == NULL || cqr->function == NULL);
 
 	device = cqr->device;
 	success = cqr->status == DASD_CQR_DONE;
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index ac10dfb..91e93c7 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -24,7 +24,7 @@
 
 /*
  * The room for the SCCB (only for writing) is not equal to a pages size
- * (as it is specified as the maximum size in the the SCLP ducumentation)
+ * (as it is specified as the maximum size in the the SCLP documentation)
  * because of the additional data structure described above.
  */
 #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 5ced272..5c65cf3 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -198,9 +198,7 @@
 
 	device = (struct tape_device *) queue->queuedata;
 	DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device);
-	if (device == NULL)
-		BUG();
-
+	BUG_ON(device == NULL);
 	tapeblock_trigger_requeue(device);
 }
 
@@ -307,8 +305,7 @@
 	int			rc;
 
 	device = (struct tape_device *) disk->private_data;
-	if (!device)
-		BUG();
+	BUG_ON(!device);
 
 	if (!device->blk_data.medium_changed)
 		return 0;
@@ -440,11 +437,9 @@
 
 	rc     = 0;
 	disk   = inode->i_bdev->bd_disk;
-	if (!disk)
-		BUG();
+	BUG_ON(!disk);
 	device = disk->private_data;
-	if (!device)
-		BUG();
+	BUG_ON(!device);
 	minor  = iminor(inode);
 
 	DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index edcf05d..5d6b7a5 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -675,9 +675,8 @@
 	int index, rc;
 
 	LCS_DBF_TEXT(5, trace, "rdybuff");
-	if (buffer->state != BUF_STATE_LOCKED &&
-	    buffer->state != BUF_STATE_PROCESSED)
-		BUG();
+	BUG_ON(buffer->state != BUF_STATE_LOCKED &&
+		buffer->state != BUF_STATE_PROCESSED);
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	buffer->state = BUF_STATE_READY;
 	index = buffer - channel->iob;
@@ -701,8 +700,7 @@
 	int index, prev, next;
 
 	LCS_DBF_TEXT(5, trace, "prcsbuff");
-	if (buffer->state != BUF_STATE_READY)
-		BUG();
+	BUG_ON(buffer->state != BUF_STATE_READY);
 	buffer->state = BUF_STATE_PROCESSED;
 	index = buffer - channel->iob;
 	prev = (index - 1) & (LCS_NUM_BUFFS - 1);
@@ -734,9 +732,8 @@
 	unsigned long flags;
 
 	LCS_DBF_TEXT(5, trace, "relbuff");
-	if (buffer->state != BUF_STATE_LOCKED &&
-	    buffer->state != BUF_STATE_PROCESSED)
-		BUG();
+	BUG_ON(buffer->state != BUF_STATE_LOCKED &&
+		buffer->state != BUF_STATE_PROCESSED);
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	buffer->state = BUF_STATE_EMPTY;
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 6c2c395..5517da5 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -86,7 +86,7 @@
         default "0"
         help
 	Bit mask of debug options that is only valid if the
-	CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled.  The bits in this mask
+	CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled.  The bits in this mask
 	are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the
 	variable ahc_debug in that file to find them.
 
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index dfc1e86..043f50b 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -20,7 +20,7 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong   <wendyx@us.ibm.com>
  *
  ***********************************************************************/
 
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index b1b66e7..b3e1f71 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -20,7 +20,7 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong   <wendyx@us.ibm.com>
  *
  *
  ***********************************************************************/
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 87e4e2c..a5fc589 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -20,7 +20,7 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong   <wendyx@us.ibm.com>
  *
  ***********************************************************************/
 #include <linux/delay.h>	/* For udelay */
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 910a8ed..b05d1b2 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -929,8 +929,7 @@
 			block_in_page += this_chunk_blocks;
 			dio->blocks_available -= this_chunk_blocks;
 next_block:
-			if (dio->block_in_file > dio->final_block_in_request)
-				BUG();
+			BUG_ON(dio->block_in_file > dio->final_block_in_request);
 			if (dio->block_in_file == dio->final_block_in_request)
 				break;
 		}
diff --git a/fs/dquot.c b/fs/dquot.c
index 6b38869..81d87a4 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -590,8 +590,7 @@
 	atomic_dec(&dquot->dq_count);
 #ifdef __DQUOT_PARANOIA
 	/* sanity check */
-	if (!list_empty(&dquot->dq_free))
-		BUG();
+	BUG_ON(!list_empty(&dquot->dq_free));
 #endif
 	put_dquot_last(dquot);
 	spin_unlock(&dq_list_lock);
@@ -666,8 +665,7 @@
 		return NODQUOT;
 	}
 #ifdef __DQUOT_PARANOIA
-	if (!dquot->dq_sb)	/* Has somebody invalidated entry under us? */
-		BUG();
+	BUG_ON(!dquot->dq_sb);	/* Has somebody invalidated entry under us? */
 #endif
 
 	return dquot;
diff --git a/fs/exec.c b/fs/exec.c
index 950ebd4..0291a68 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -561,7 +561,7 @@
 	arch_pick_mmap_layout(mm);
 	if (old_mm) {
 		up_read(&old_mm->mmap_sem);
-		if (active_mm != old_mm) BUG();
+		BUG_ON(active_mm != old_mm);
 		mmput(old_mm);
 		return 0;
 	}
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 2a24791..d35cbc6 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -453,8 +453,7 @@
 			/* Make sure we are called with one of the POLL_*
 			   reasons, otherwise we could leak kernel stack into
 			   userspace.  */
-			if ((reason & __SI_MASK) != __SI_POLL)
-				BUG();
+			BUG_ON((reason & __SI_MASK) != __SI_POLL);
 			if (reason - POLL_IN >= NSIGPOLL)
 				si.si_band  = ~0L;
 			else
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 76a0708..049500847 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -42,24 +42,21 @@
 static inline void
 vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
 {
-	if (infp->vsi_fshino)
-		BUG();
+	BUG_ON(infp->vsi_fshino);
 	infp->vsi_fshino = fshp->olt_fsino[0];
 }
 
 static inline void
 vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
 {
-	if (infp->vsi_iext)
-		BUG();
+	BUG_ON(infp->vsi_iext);
 	infp->vsi_iext = ilistp->olt_iext[0]; 
 }
 
 static inline u_long
 vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
 {
-	if (sbp->s_blocksize % bsize)
-		BUG();
+	BUG_ON(sbp->s_blocksize % bsize);
 	return (block * (sbp->s_blocksize / bsize));
 }
 
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 8f07e8f..746abc9 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -466,8 +466,7 @@
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
-	if (!*p)
-		BUG();
+	BUG_ON(!*p);
 	*p = node->next_hash;
 	node->tree->node_hash_cnt--;
 }
@@ -622,8 +621,7 @@
 
 		dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
 		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
-		if (!atomic_read(&node->refcnt))
-			BUG();
+		BUG_ON(!atomic_read(&node->refcnt));
 		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index a67edfa..effa899 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -269,8 +269,7 @@
 	u8 *data, byte, m;
 
 	dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this);
-	if (!node->this)
-		BUG();
+	BUG_ON(!node->this);
 	tree = node->tree;
 	nidx = node->this;
 	node = hfs_bnode_find(tree, 0);
diff --git a/fs/inode.c b/fs/inode.c
index 32b7c33..3a2446a 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -172,8 +172,7 @@
 
 void destroy_inode(struct inode *inode) 
 {
-	if (inode_has_buffers(inode))
-		BUG();
+	BUG_ON(inode_has_buffers(inode));
 	security_inode_free(inode);
 	if (inode->i_sb->s_op->destroy_inode)
 		inode->i_sb->s_op->destroy_inode(inode);
@@ -249,12 +248,9 @@
 	might_sleep();
 	invalidate_inode_buffers(inode);
        
-	if (inode->i_data.nrpages)
-		BUG();
-	if (!(inode->i_state & I_FREEING))
-		BUG();
-	if (inode->i_state & I_CLEAR)
-		BUG();
+	BUG_ON(inode->i_data.nrpages);
+	BUG_ON(!(inode->i_state & I_FREEING));
+	BUG_ON(inode->i_state & I_CLEAR);
 	wait_on_inode(inode);
 	DQUOT_DROP(inode);
 	if (inode->i_sb && inode->i_sb->s_op->clear_inode)
@@ -1054,8 +1050,7 @@
 	hlist_del_init(&inode->i_hash);
 	spin_unlock(&inode_lock);
 	wake_up_inode(inode);
-	if (inode->i_state != I_CLEAR)
-		BUG();
+	BUG_ON(inode->i_state != I_CLEAR);
 	destroy_inode(inode);
 }
 
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 7b77a95..ff2a872 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -35,8 +35,7 @@
 	pid_t pid;
 	int ret = 0;
 
-	if (c->gc_task)
-		BUG();
+	BUG_ON(c->gc_task);
 
 	init_completion(&c->gc_thread_start);
 	init_completion(&c->gc_thread_exit);
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index c56bd99..ed9a24d 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -178,11 +178,9 @@
 	unsigned offset = PAGE_CACHE_SIZE;
 	int err;
 
-	if (!mapping)
-		BUG();
+	BUG_ON(!mapping);
 	inode = mapping->host;
-	if (!inode)
-		BUG();
+	BUG_ON(!inode);
 
 	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index f26880a..6cfdc9a 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -50,7 +50,7 @@
 	return sd;
 }
 
-/**
+/*
  *
  * Return -EEXIST if there is already a sysfs element with the same name for
  * the same parent.
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 830f76fa..f1cb1dd 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -183,7 +183,7 @@
 		return -ENOMEM;
 
 	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE;
+		count = PAGE_SIZE - 1;
 	error = copy_from_user(buffer->page,buf,count);
 	buffer->needs_read_fill = 1;
 	return error ? -EFAULT : count;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4c29ac4..f0b347b 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -175,8 +175,7 @@
 	struct bin_attribute * bin_attr;
 	struct sysfs_symlink  * sl;
 
-	if (!sd || !sd->s_element)
-		BUG();
+	BUG_ON(!sd || !sd->s_element);
 
 	switch (sd->s_type) {
 		case SYSFS_DIR:
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 8c66e92..d707434 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -253,8 +253,7 @@
 
 	lock_page(page);
 	err = mapping->a_ops->prepare_write(NULL, page, from, to);
-	if (err)
-		BUG();
+	BUG_ON(err);
 	de->inode = 0;
 	err = dir_commit_chunk(page, from, to);
 	dir_put_page(page);
@@ -353,8 +352,7 @@
 
 	lock_page(page);
 	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
-	if (err)
-		BUG();
+	BUG_ON(err);
 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
 	err = dir_commit_chunk(page, from, to);
 	dir_put_page(page);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 81e0e84..2983afd 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -312,12 +312,10 @@
 	err = 0;
 
 	bh = inode_getblk(inode, block, &err, &phys, &new);
-	if (bh)
-		BUG();
+	BUG_ON(bh);
 	if (err)
 		goto abort;
-	if (!phys)
-		BUG();
+	BUG_ON(!phys);
 
 	if (new)
 		set_buffer_new(bh_result);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 85997b1..ae4c475 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -69,7 +69,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_aio_read(
 	struct kiocb		*iocb,
@@ -90,7 +89,6 @@
 	return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_write(
 	struct kiocb	*iocb,
@@ -113,7 +111,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_aio_write(
 	struct kiocb		*iocb,
@@ -134,7 +131,6 @@
 	return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_readv(
 	struct file		*file,
@@ -179,7 +175,6 @@
 	return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_writev(
 	struct file		*file,
@@ -204,7 +199,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_writev(
 	struct file		*file,
@@ -228,7 +222,7 @@
 STATIC ssize_t
 xfs_file_sendfile(
 	struct file		*filp,
-	loff_t			*ppos,
+	loff_t			*pos,
 	size_t			count,
 	read_actor_t		actor,
 	void			*target)
@@ -236,10 +230,80 @@
 	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
 	ssize_t			rval;
 
-	VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
+	VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
 	return rval;
 }
 
+STATIC ssize_t
+xfs_file_sendfile_invis(
+	struct file		*filp,
+	loff_t			*pos,
+	size_t			count,
+	read_actor_t		actor,
+	void			*target)
+{
+	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read(
+	struct file		*infilp,
+	struct inode		*pipe,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read_invis(
+	struct file		*infilp,
+	struct inode		*pipe,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write(
+	struct inode		*pipe,
+	struct file		*outfilp,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write_invis(
+	struct inode		*pipe,
+	struct file		*outfilp,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval);
+	return rval;
+}
 
 STATIC int
 xfs_file_open(
@@ -251,13 +315,10 @@
 
 	if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EFBIG;
-
-	ASSERT(vp);
 	VOP_OPEN(vp, NULL, error);
 	return -error;
 }
 
-
 STATIC int
 xfs_file_release(
 	struct inode	*inode,
@@ -271,7 +332,6 @@
 	return -error;
 }
 
-
 STATIC int
 xfs_file_fsync(
 	struct file	*filp,
@@ -285,21 +345,11 @@
 
 	if (datasync)
 		flags |= FSYNC_DATA;
-
-	ASSERT(vp);
 	VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
 	return -error;
 }
 
-/*
- * xfs_file_readdir maps to VOP_READDIR().
- * We need to build a uio, cred, ...
- */
-
-#define nextdp(dp)      ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
-
 #ifdef CONFIG_XFS_DMAPI
-
 STATIC struct page *
 xfs_vm_nopage(
 	struct vm_area_struct	*area,
@@ -319,10 +369,8 @@
 
 	return filemap_nopage(area, address, type);
 }
-
 #endif /* CONFIG_XFS_DMAPI */
 
-
 STATIC int
 xfs_file_readdir(
 	struct file	*filp,
@@ -330,7 +378,7 @@
 	filldir_t	filldir)
 {
 	int		error = 0;
-	vnode_t		*vp;
+	vnode_t		*vp = vn_from_inode(filp->f_dentry->d_inode);
 	uio_t		uio;
 	iovec_t		iov;
 	int		eof = 0;
@@ -340,9 +388,6 @@
 	xfs_off_t	start_offset, curr_offset;
 	xfs_dirent_t	*dbp = NULL;
 
-	vp = vn_from_inode(filp->f_dentry->d_inode);
-	ASSERT(vp);
-
 	/* Try fairly hard to get memory */
 	do {
 		if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
@@ -387,7 +432,7 @@
 			}
 			size -= dbp->d_reclen;
 			curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
-			dbp = nextdp(dbp);
+			dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
 		}
 	}
 done:
@@ -402,7 +447,6 @@
 	return -error;
 }
 
-
 STATIC int
 xfs_file_mmap(
 	struct file	*filp,
@@ -457,11 +501,10 @@
 	unsigned int	cmd,
 	unsigned long	arg)
 {
-	int		error;
 	struct inode	*inode = filp->f_dentry->d_inode;
 	vnode_t		*vp = vn_from_inode(inode);
+	int		error;
 
-	ASSERT(vp);
 	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 
@@ -537,6 +580,8 @@
 	.aio_read	= xfs_file_aio_read,
 	.aio_write	= xfs_file_aio_write,
 	.sendfile	= xfs_file_sendfile,
+	.splice_read	= xfs_file_splice_read,
+	.splice_write	= xfs_file_splice_write,
 	.unlocked_ioctl	= xfs_file_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= xfs_file_compat_ioctl,
@@ -558,7 +603,9 @@
 	.writev		= xfs_file_writev_invis,
 	.aio_read	= xfs_file_aio_read_invis,
 	.aio_write	= xfs_file_aio_write_invis,
-	.sendfile	= xfs_file_sendfile,
+	.sendfile	= xfs_file_sendfile_invis,
+	.splice_read	= xfs_file_splice_read_invis,
+	.splice_write	= xfs_file_splice_write_invis,
 	.unlocked_ioctl	= xfs_file_ioctl_invis,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= xfs_file_compat_invis_ioctl,
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 1fe09f2..e9fe43d 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -103,6 +103,7 @@
  */
 #undef  HAVE_REFCACHE	/* reference cache not needed for NFS in 2.6 */
 #define HAVE_SENDFILE	/* sendfile(2) exists in 2.6, but not in 2.4 */
+#define HAVE_SPLICE	/* a splice(2) exists in 2.6, but not in 2.4 */
 #ifdef CONFIG_SMP
 #define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
 #else
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 84ddf18..90cd314 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -301,36 +301,23 @@
 	void			*target,
 	cred_t			*credp)
 {
+	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
+	xfs_mount_t		*mp = ip->i_mount;
 	ssize_t			ret;
-	xfs_fsize_t		n;
-	xfs_inode_t		*ip;
-	xfs_mount_t		*mp;
-	vnode_t			*vp;
-
-	ip = XFS_BHVTOI(bdp);
-	vp = BHV_TO_VNODE(bdp);
-	mp = ip->i_mount;
 
 	XFS_STATS_INC(xs_read_calls);
-
-	n = XFS_MAXIOFFSET(mp) - *offset;
-	if ((n <= 0) || (count == 0))
-		return 0;
-
-	if (n < count)
-		count = n;
-
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
-	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
+	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
 	    (!(ioflags & IO_INVIS))) {
 		vrwlock_t locktype = VRWLOCK_READ;
 		int error;
 
-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count,
+		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+				      *offset, count,
 				      FILP_DELAY_FLAG(filp), &locktype);
 		if (error) {
 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -340,12 +327,96 @@
 	xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
 		   (void *)(unsigned long)target, count, *offset, ioflags);
 	ret = generic_file_sendfile(filp, offset, count, actor, target);
-
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-
 	if (ret > 0)
 		XFS_STATS_ADD(xs_read_bytes, ret);
 
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+	return ret;
+}
+
+ssize_t
+xfs_splice_read(
+	bhv_desc_t		*bdp,
+	struct file		*infilp,
+	struct inode		*pipe,
+	size_t			count,
+	int			flags,
+	int			ioflags,
+	cred_t			*credp)
+{
+	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
+	xfs_mount_t		*mp = ip->i_mount;
+	ssize_t			ret;
+
+	XFS_STATS_INC(xs_read_calls);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
+	    (!(ioflags & IO_INVIS))) {
+		vrwlock_t locktype = VRWLOCK_READ;
+		int error;
+
+		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+					infilp->f_pos, count,
+					FILP_DELAY_FLAG(infilp), &locktype);
+		if (error) {
+			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+			return -error;
+		}
+	}
+	xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
+			   pipe, count, infilp->f_pos, ioflags);
+	ret = generic_file_splice_read(infilp, pipe, count, flags);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_read_bytes, ret);
+
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+	return ret;
+}
+
+ssize_t
+xfs_splice_write(
+	bhv_desc_t		*bdp,
+	struct inode		*pipe,
+	struct file		*outfilp,
+	size_t			count,
+	int			flags,
+	int			ioflags,
+	cred_t			*credp)
+{
+	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
+	xfs_mount_t		*mp = ip->i_mount;
+	ssize_t			ret;
+
+	XFS_STATS_INC(xs_write_calls);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
+	    (!(ioflags & IO_INVIS))) {
+		vrwlock_t locktype = VRWLOCK_WRITE;
+		int error;
+
+		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
+					outfilp->f_pos, count,
+					FILP_DELAY_FLAG(outfilp), &locktype);
+		if (error) {
+			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			return -error;
+		}
+	}
+	xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
+			   pipe, count, outfilp->f_pos, ioflags);
+	ret = generic_file_splice_write(pipe, outfilp, count, flags);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_write_bytes, ret);
+
+	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 	return ret;
 }
 
@@ -363,7 +434,7 @@
 	xfs_fsize_t	end_size)
 {
 	xfs_fileoff_t	last_fsb;
-	xfs_mount_t	*mp;
+	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		zero_offset;
 	int		zero_len;
@@ -373,8 +444,6 @@
 
 	ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
 
-	mp = io->io_mount;
-
 	zero_offset = XFS_B_FSB_OFFSET(mp, isize);
 	if (zero_offset == 0) {
 		/*
@@ -405,10 +474,9 @@
 	 * don't deadlock when the buffer cache calls back to us.
 	 */
 	XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
+
 	loff = XFS_FSB_TO_B(mp, last_fsb);
-
 	zero_len = mp->m_sb.sb_blocksize - zero_offset;
-
 	error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
 
 	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
@@ -441,7 +509,7 @@
 	xfs_fileoff_t	zero_count_fsb;
 	xfs_fileoff_t	last_fsb;
 	xfs_extlen_t	buf_len_fsb;
-	xfs_mount_t	*mp;
+	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		error = 0;
 	xfs_bmbt_irec_t	imap;
@@ -450,8 +518,6 @@
 	ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
 	ASSERT(offset > isize);
 
-	mp = io->io_mount;
-
 	/*
 	 * First handle zeroing the block on which isize resides.
 	 * We only zero a part of that block so it is handled specially.
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 38864a8..eaa5659 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -60,6 +60,8 @@
 #define	XFS_IOMAP_ALLOC_ENTER	25
 #define	XFS_IOMAP_ALLOC_MAP	26
 #define	XFS_IOMAP_UNWRITTEN	27
+#define XFS_SPLICE_READ_ENTER	28
+#define XFS_SPLICE_WRITE_ENTER	29
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
 				void *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
@@ -78,6 +80,7 @@
 			struct xfs_iomap *, int *);
 extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
 extern int xfs_bdstrat_cb(struct xfs_buf *);
+extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
 
 extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
 				xfs_fsize_t, xfs_fsize_t);
@@ -90,7 +93,11 @@
 extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
 				loff_t *, int, size_t, read_actor_t,
 				void *, struct cred *);
-
-extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *,
+				struct inode *, size_t, int, int,
+				struct cred *);
+extern ssize_t xfs_splice_write(struct bhv_desc *, struct inode *,
+				struct file *, size_t, int, int,
+				struct cred *);
 
 #endif	/* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 1884300..68f4793 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -67,7 +67,8 @@
 
 STATIC struct xfs_mount_args *
 xfs_args_allocate(
-	struct super_block	*sb)
+	struct super_block	*sb,
+	int			silent)
 {
 	struct xfs_mount_args	*args;
 
@@ -80,8 +81,8 @@
 		args->flags |= XFSMNT_DIRSYNC;
 	if (sb->s_flags & MS_SYNCHRONOUS)
 		args->flags |= XFSMNT_WSYNC;
-
-	/* Default to 32 bit inodes on Linux all the time */
+	if (silent)
+		args->flags |= XFSMNT_QUIET;
 	args->flags |= XFSMNT_32BITINODES;
 
 	return args;
@@ -719,7 +720,7 @@
 	char			*options)
 {
 	vfs_t			*vfsp = vfs_from_sb(sb);
-	struct xfs_mount_args	*args = xfs_args_allocate(sb);
+	struct xfs_mount_args	*args = xfs_args_allocate(sb, 0);
 	int			error;
 
 	VFS_PARSEARGS(vfsp, options, args, 1, error);
@@ -825,7 +826,7 @@
 {
 	vnode_t			*rootvp;
 	struct vfs		*vfsp = vfs_allocate(sb);
-	struct xfs_mount_args	*args = xfs_args_allocate(sb);
+	struct xfs_mount_args	*args = xfs_args_allocate(sb, silent);
 	struct kstatfs		statvfs;
 	int			error, error2;
 
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 06f5845..6f1c79a 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -173,6 +173,12 @@
 typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
 				loff_t *, int, size_t, read_actor_t,
 				void *, struct cred *);
+typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *,
+				struct inode *, size_t, int, int,
+				struct cred *);
+typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct inode *,
+				struct file *, size_t, int, int,
+				struct cred *);
 typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
 				int, unsigned int, void __user *);
 typedef int	(*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -231,6 +237,8 @@
 	vop_read_t		vop_read;
 	vop_write_t		vop_write;
 	vop_sendfile_t		vop_sendfile;
+	vop_splice_read_t	vop_splice_read;
+	vop_splice_write_t	vop_splice_write;
 	vop_ioctl_t		vop_ioctl;
 	vop_getattr_t		vop_getattr;
 	vop_setattr_t		vop_setattr;
@@ -276,6 +284,10 @@
 	rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
 #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv)		\
 	rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
+#define VOP_SPLICE_READ(vp,f,pipe,cnt,fl,iofl,cr,rv)			\
+	rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr)
+#define VOP_SPLICE_WRITE(vp,f,pipe,cnt,fl,iofl,cr,rv)			\
+	rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr)
 #define VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
 	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
 #define VOP_OPEN(vp, cr, rv)						\
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 73c1e5e8..7fb5eca 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -2624,7 +2624,7 @@
 {
 	int		error;
 	xfs_mount_t	*mp;
-	uint		delblks, blkflags;
+	uint		delblks, blkflags, prjflags = 0;
 	xfs_dquot_t	*unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
 	ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2650,10 +2650,13 @@
 		}
 	}
 	if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
-		if ((XFS_IS_GQUOTA_ON(ip->i_mount) &&
-		     ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) ||
-		    (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-		     ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
+		if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
+		     ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+			prjflags = XFS_QMOPT_ENOSPC;
+
+		if (prjflags ||
+		    (XFS_IS_GQUOTA_ON(ip->i_mount) &&
+		     ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
 			delblksgdq = gdqp;
 			if (delblks) {
 				ASSERT(ip->i_gdquot);
@@ -2664,7 +2667,7 @@
 
 	if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
 				delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
-				flags | blkflags)))
+				flags | blkflags | prjflags)))
 		return (error);
 
 	/*
@@ -2681,7 +2684,7 @@
 		ASSERT(unresudq || unresgdq);
 		if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
 				delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
-				flags | blkflags)))
+				flags | blkflags | prjflags)))
 			return (error);
 		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
 				unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index d8e131e..9168918 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -595,12 +595,19 @@
 	}
 }
 
+STATIC int
+xfs_quota_error(uint flags)
+{
+	if (flags & XFS_QMOPT_ENOSPC)
+		return ENOSPC;
+	return EDQUOT;
+}
+
 /*
  * This reserves disk blocks and inodes against a dquot.
  * Flags indicate if the dquot is to be locked here and also
  * if the blk reservation is for RT or regular blocks.
  * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
- * Returns EDQUOT if quota is exceeded.
  */
 STATIC int
 xfs_trans_dqresv(
@@ -666,19 +673,15 @@
 			 */
 			if (hardlimit > 0ULL &&
 			     (hardlimit <= nblks + *resbcountp)) {
-				error = EDQUOT;
+				error = xfs_quota_error(flags);
 				goto error_return;
 			}
 
 			if (softlimit > 0ULL &&
 			     (softlimit <= nblks + *resbcountp)) {
-				/*
-				 * If timer or warnings has expired,
-				 * return EDQUOT
-				 */
 				if ((timer != 0 && get_seconds() > timer) ||
 				    (warns != 0 && warns >= warnlimit)) {
-					error = EDQUOT;
+					error = xfs_quota_error(flags);
 					goto error_return;
 				}
 			}
@@ -695,16 +698,12 @@
 			if (!softlimit)
 				softlimit = q->qi_isoftlimit;
 			if (hardlimit > 0ULL && count >= hardlimit) {
-				error = EDQUOT;
+				error = xfs_quota_error(flags);
 				goto error_return;
 			} else if (softlimit > 0ULL && count >= softlimit) {
-				/*
-				 * If timer or warnings has expired,
-				 * return EDQUOT
-				 */
 				if ((timer != 0 && get_seconds() > timer) ||
 				     (warns != 0 && warns >= warnlimit)) {
-					error = EDQUOT;
+					error = xfs_quota_error(flags);
 					goto error_return;
 				}
 			}
@@ -751,13 +750,14 @@
 
 
 /*
- * Given a dquot(s), make disk block and/or inode reservations against them.
+ * Given dquot(s), make disk block and/or inode reservations against them.
  * The fact that this does the reservation against both the usr and
- * grp quotas is important, because this follows a both-or-nothing
+ * grp/prj quotas is important, because this follows a both-or-nothing
  * approach.
  *
  * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
  *	   XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
+ *	   XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT.  Used by pquota.
  *	   XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
  *	   XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
  * dquots are unlocked on return, if they were not locked by caller.
@@ -772,25 +772,27 @@
 	long		ninos,
 	uint		flags)
 {
-	int		resvd;
+	int		resvd = 0, error;
 
-	if (! XFS_IS_QUOTA_ON(mp))
-		return (0);
+	if (!XFS_IS_QUOTA_ON(mp))
+		return 0;
 
 	if (tp && tp->t_dqinfo == NULL)
 		xfs_trans_alloc_dqinfo(tp);
 
 	ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
-	resvd = 0;
 
 	if (udqp) {
-		if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
-			return (EDQUOT);
+		error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
+					(flags & ~XFS_QMOPT_ENOSPC));
+		if (error)
+			return error;
 		resvd = 1;
 	}
 
 	if (gdqp) {
-		if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
+		error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
+		if (error) {
 			/*
 			 * can't do it, so backout previous reservation
 			 */
@@ -799,14 +801,14 @@
 				xfs_trans_dqresv(tp, mp, udqp,
 						 -nblks, -ninos, flags);
 			}
-			return (EDQUOT);
+			return error;
 		}
 	}
 
 	/*
 	 * Didn't change anything critical, so, no need to log
 	 */
-	return (0);
+	return 0;
 }
 
 
@@ -814,8 +816,6 @@
  * Lock the dquot and change the reservation if we can.
  * This doesn't change the actual usage, just the reservation.
  * The inode sent in is locked.
- *
- * Returns 0 on success, EDQUOT or other errors otherwise
  */
 STATIC int
 xfs_trans_reserve_quota_nblks(
@@ -824,20 +824,24 @@
 	xfs_inode_t	*ip,
 	long		nblks,
 	long		ninos,
-	uint		type)
+	uint		flags)
 {
 	int		error;
 
 	if (!XFS_IS_QUOTA_ON(mp))
-		return (0);
+		return 0;
+	if (XFS_IS_PQUOTA_ON(mp))
+		flags |= XFS_QMOPT_ENOSPC;
 
 	ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
 	ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
 
 	ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
 	ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
-	ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
-	       (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);
+	ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+				XFS_TRANS_DQ_RES_RTBLKS ||
+	       (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+				XFS_TRANS_DQ_RES_BLKS);
 
 	/*
 	 * Reserve nblks against these dquots, with trans as the mediator.
@@ -845,8 +849,8 @@
 	error = xfs_trans_reserve_quota_bydquots(tp, mp,
 						 ip->i_udquot, ip->i_gdquot,
 						 nblks, ninos,
-						 type);
-	return (error);
+						 flags);
+	return error;
 }
 
 /*
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index d384e48..26939d3 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4719,18 +4719,17 @@
 				/*
 				 * Make a transaction-less quota reservation for
 				 * delayed allocation blocks. This number gets
-				 * adjusted later.
-				 * We return EDQUOT if we haven't allocated
-				 * blks already inside this loop;
+				 * adjusted later.  We return if we haven't
+				 * allocated blocks already inside this loop.
 				 */
-				if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+				if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
 						mp, NULL, ip, (long)alen, 0,
 						rt ? XFS_QMOPT_RES_RTBLKS :
-						     XFS_QMOPT_RES_REGBLKS)) {
+						     XFS_QMOPT_RES_REGBLKS))) {
 					if (n == 0) {
 						*nmap = 0;
 						ASSERT(cur == NULL);
-						return XFS_ERROR(EDQUOT);
+						return error;
 					}
 					break;
 				}
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index f83399c..8e0d73d 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -353,10 +353,11 @@
 	xfs_extnum_t		num);
 
 /*
- * Call xfs_bmap_do_search_extents() to search for the extent
- * record containing block bno. If in multi-level in-core extent
- * allocation mode, find and extract the target extent buffer,
- * otherwise just use the direct extent list.
+ * Search the extent records for the entry containing block bno.
+ * If bno lies in a hole, point to the next entry.  If bno lies
+ * past eof, *eofp will be set, and *prevp will contain the last
+ * entry (null if none).  Else, *lastxp will be set to the index
+ * of the found entry; *gotp will contain the entry.
  */
 xfs_bmbt_rec_t *
 xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 022fff6..5b7eb81 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -68,6 +68,7 @@
 						 * enforcement */
 #define XFSMNT_PQUOTAENF	0x00000040	/* IRIX project quota limit
 						 * enforcement */
+#define XFSMNT_QUIET		0x00000080	/* don't report mount errors */
 #define XFSMNT_NOALIGN		0x00000200	/* don't allocate at
 						 * stripe boundaries*/
 #define XFSMNT_RETERR		0x00000400	/* return error to user */
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 26b8e70..bc43163 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -186,4 +186,7 @@
 #define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
 	xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args)
 
+#define xfs_fs_mount_cmn_err(f, fmt, args...) \
+	((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
+
 #endif	/* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 72e7e78..049fabb 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -213,7 +213,8 @@
 STATIC int
 xfs_mount_validate_sb(
 	xfs_mount_t	*mp,
-	xfs_sb_t	*sbp)
+	xfs_sb_t	*sbp,
+	int		flags)
 {
 	/*
 	 * If the log device and data device have the
@@ -223,33 +224,29 @@
 	 * a volume filesystem in a non-volume manner.
 	 */
 	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
-		cmn_err(CE_WARN, "XFS: bad magic number");
+		xfs_fs_mount_cmn_err(flags, "bad magic number");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (!XFS_SB_GOOD_VERSION(sbp)) {
-		cmn_err(CE_WARN, "XFS: bad version");
+		xfs_fs_mount_cmn_err(flags, "bad version");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
-		cmn_err(CE_WARN,
-	"XFS: filesystem is marked as having an external log; "
-	"specify logdev on the\nmount command line.");
-		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)",
-				     XFS_ERRLEVEL_HIGH, mp, sbp);
-		return XFS_ERROR(EFSCORRUPTED);
+		xfs_fs_mount_cmn_err(flags,
+			"filesystem is marked as having an external log; "
+			"specify logdev on the\nmount command line.");
+		return XFS_ERROR(EINVAL);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
-		cmn_err(CE_WARN,
-	"XFS: filesystem is marked as having an internal log; "
-	"don't specify logdev on\nthe mount command line.");
-		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)",
-				     XFS_ERRLEVEL_HIGH, mp, sbp);
-		return XFS_ERROR(EFSCORRUPTED);
+		xfs_fs_mount_cmn_err(flags,
+			"filesystem is marked as having an internal log; "
+			"do not specify logdev on\nthe mount command line.");
+		return XFS_ERROR(EINVAL);
 	}
 
 	/*
@@ -274,9 +271,7 @@
 	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
 	    (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) {
-		cmn_err(CE_WARN, "XFS: SB sanity check 1 failed");
-		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)",
-				     XFS_ERRLEVEL_LOW, mp, sbp);
+		xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -289,9 +284,7 @@
 	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
 	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
 			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
-		cmn_err(CE_WARN, "XFS: SB sanity check 2 failed");
-		XFS_ERROR_REPORT("xfs_mount_validate_sb(4)",
-				 XFS_ERRLEVEL_LOW, mp);
+		xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -307,15 +300,13 @@
 	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
 	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
 #endif
-		cmn_err(CE_WARN,
-	"XFS: File system is too large to be mounted on this system.");
+		xfs_fs_mount_cmn_err(flags,
+			"file system too large to be mounted on this system.");
 		return XFS_ERROR(E2BIG);
 	}
 
 	if (unlikely(sbp->sb_inprogress)) {
-		cmn_err(CE_WARN, "XFS: file system busy");
-		XFS_ERROR_REPORT("xfs_mount_validate_sb(5)",
-				 XFS_ERRLEVEL_LOW, mp);
+		xfs_fs_mount_cmn_err(flags, "file system busy");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -323,8 +314,8 @@
 	 * Version 1 directory format has never worked on Linux.
 	 */
 	if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
-		cmn_err(CE_WARN,
-	"XFS: Attempted to mount file system using version 1 directory format");
+		xfs_fs_mount_cmn_err(flags,
+			"file system using version 1 directory format");
 		return XFS_ERROR(ENOSYS);
 	}
 
@@ -332,11 +323,11 @@
 	 * Until this is fixed only page-sized or smaller data blocks work.
 	 */
 	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
-		cmn_err(CE_WARN,
-		"XFS: Attempted to mount file system with blocksize %d bytes",
+		xfs_fs_mount_cmn_err(flags,
+			"file system with blocksize %d bytes",
 			sbp->sb_blocksize);
-		cmn_err(CE_WARN,
-		"XFS: Only page-sized (%ld) or less blocksizes currently work.",
+		xfs_fs_mount_cmn_err(flags,
+			"only pagesize (%ld) or less will currently work.",
 			PAGE_SIZE);
 		return XFS_ERROR(ENOSYS);
 	}
@@ -484,7 +475,7 @@
  * Does the initial read of the superblock.
  */
 int
-xfs_readsb(xfs_mount_t *mp)
+xfs_readsb(xfs_mount_t *mp, int flags)
 {
 	unsigned int	sector_size;
 	unsigned int	extra_flags;
@@ -506,7 +497,7 @@
 	bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
 				BTOBB(sector_size), extra_flags);
 	if (!bp || XFS_BUF_ISERROR(bp)) {
-		cmn_err(CE_WARN, "XFS: SB read failed");
+		xfs_fs_mount_cmn_err(flags, "SB read failed");
 		error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
 		goto fail;
 	}
@@ -520,9 +511,9 @@
 	sbp = XFS_BUF_TO_SBP(bp);
 	xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
 
-	error = xfs_mount_validate_sb(mp, &(mp->m_sb));
+	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: SB validate failed");
+		xfs_fs_mount_cmn_err(flags, "SB validate failed");
 		goto fail;
 	}
 
@@ -530,8 +521,8 @@
 	 * We must be able to do sector-sized and sector-aligned IO.
 	 */
 	if (sector_size > mp->m_sb.sb_sectsize) {
-		cmn_err(CE_WARN,
-			"XFS: device supports only %u byte sectors (not %u)",
+		xfs_fs_mount_cmn_err(flags,
+			"device supports only %u byte sectors (not %u)",
 			sector_size, mp->m_sb.sb_sectsize);
 		error = ENOSYS;
 		goto fail;
@@ -548,7 +539,7 @@
 		bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
 					BTOBB(sector_size), extra_flags);
 		if (!bp || XFS_BUF_ISERROR(bp)) {
-			cmn_err(CE_WARN, "XFS: SB re-read failed");
+			xfs_fs_mount_cmn_err(flags, "SB re-read failed");
 			error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
 			goto fail;
 		}
@@ -678,7 +669,7 @@
 	int		error = 0;
 
 	if (mp->m_sb_bp == NULL) {
-		if ((error = xfs_readsb(mp))) {
+		if ((error = xfs_readsb(mp, mfsi_flags))) {
 			return error;
 		}
 	}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 66cbee7..668ad23 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -510,9 +510,12 @@
  */
 #define XFS_MFSI_SECOND		0x01	/* Secondary mount -- skip stuff */
 #define XFS_MFSI_CLIENT		0x02	/* Is a client -- skip lots of stuff */
+/*	XFS_MFSI_RRINODES	*/
 #define XFS_MFSI_NOUNLINK	0x08	/* Skip unlinked inode processing in */
 					/* log recovery */
 #define XFS_MFSI_NO_QUOTACHECK	0x10	/* Skip quotacheck processing */
+/*	XFS_MFSI_CONVERT_SUNIT	*/
+#define XFS_MFSI_QUIET		0x40	/* Be silent if mount errors found */
 
 /*
  * Macros for getting from mount to vfs and back.
@@ -581,7 +584,7 @@
 extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
 			uint, int);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
-extern int	xfs_readsb(xfs_mount_t *mp);
+extern int	xfs_readsb(xfs_mount_t *, int);
 extern void	xfs_freesb(xfs_mount_t *);
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 4f6a034..7fbef97 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -196,10 +196,11 @@
 #define XFS_QMOPT_QUOTAOFF	0x0000080 /* quotas are being turned off */
 #define XFS_QMOPT_UMOUNTING	0x0000100 /* filesys is being unmounted */
 #define XFS_QMOPT_DOLOG		0x0000200 /* log buf changes (in quotacheck) */
-#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if necessary */
+#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if needed */
 #define XFS_QMOPT_ILOCKED	0x0000800 /* inode is already locked (excl) */
-#define XFS_QMOPT_DQREPAIR	0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_DQREPAIR	0x0001000 /* repair dquot if damaged */
 #define XFS_QMOPT_GQUOTA	0x0002000 /* group dquot requested */
+#define XFS_QMOPT_ENOSPC	0x0004000 /* enospc instead of edquot (prj) */
 
 /*
  * flags to xfs_trans_mod_dquot to indicate which field needs to be
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 504d2a8..f0e09ca 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -442,6 +442,9 @@
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
 	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
 
+	if (args->flags & XFSMNT_QUIET)
+		flags |= XFS_MFSI_QUIET;
+
 	/*
 	 * Open real time and log devices - order is important.
 	 */
@@ -492,7 +495,7 @@
 	error = xfs_start_flags(vfsp, args, mp);
 	if (error)
 		goto error1;
-	error = xfs_readsb(mp);
+	error = xfs_readsb(mp, flags);
 	if (error)
 		goto error1;
 	error = xfs_finish_flags(vfsp, args, mp);
@@ -1697,8 +1700,9 @@
 	int			dsunit, dswidth, vol_dsunit, vol_dswidth;
 	int			iosize;
 
-	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
 	args->flags |= XFSMNT_IDELETE;
+	args->flags |= XFSMNT_BARRIER;
+	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
 
 	if (!options)
 		goto done;
@@ -1947,8 +1951,6 @@
 		seq_printf(m, "," MNTOPT_IKEEP);
 	if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
 		seq_printf(m, "," MNTOPT_LARGEIO);
-	if (mp->m_flags & XFS_MOUNT_BARRIER)
-		seq_printf(m, "," MNTOPT_BARRIER);
 
 	if (!(vfsp->vfs_flag & VFS_32BITINODES))
 		seq_printf(m, "," MNTOPT_64BITINODE);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de49601..fa71b30 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -4649,6 +4649,10 @@
 #ifdef HAVE_SENDFILE
 	.vop_sendfile		= xfs_sendfile,
 #endif
+#ifdef HAVE_SPLICE
+	.vop_splice_read	= xfs_splice_read,
+	.vop_splice_write	= xfs_splice_write,
+#endif
 	.vop_write		= xfs_write,
 	.vop_ioctl		= xfs_ioctl,
 	.vop_getattr		= xfs_getattr,
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
new file mode 100644
index 0000000..f28636d
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
@@ -0,0 +1,104 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * MultiMedia Card Interface (MCI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_MCI_H
+#define AT91RM9200_MCI_H
+
+#define AT91_MCI_CR		0x00		/* Control Register */
+#define		AT91_MCI_MCIEN		(1 <<  0)	/* Multi-Media Interface Enable */
+#define		AT91_MCI_MCIDIS		(1 <<  1)	/* Multi-Media Interface Disable */
+#define		AT91_MCI_PWSEN		(1 <<  2)	/* Power Save Mode Enable */
+#define		AT91_MCI_PWSDIS		(1 <<  3)	/* Power Save Mode Disable */
+#define		AT91_MCI_SWRST		(1 <<  7)	/* Software Reset */
+
+#define AT91_MCI_MR		0x04		/* Mode Register */
+#define		AT91_MCI_CLKDIV		(0xff  <<  0)	/* Clock Divider */
+#define		AT91_MCI_PWSDIV		(3     <<  8)	/* Power Saving Divider */
+#define		AT91_MCI_PDCPADV	(1     << 14)	/* PDC Padding Value */
+#define		AT91_MCI_PDCMODE	(1     << 15)	/* PDC-orientated Mode */
+#define		AT91_MCI_BLKLEN 	(0xfff << 18)	/* Data Block Length */
+
+#define AT91_MCI_DTOR		0x08		/* Data Timeout Register */
+#define		AT91_MCI_DTOCYC		(0xf << 0)	/* Data Timeout Cycle Number */
+#define		AT91_MCI_DTOMUL		(7   << 4)	/* Data Timeout Multiplier */
+#define		AT91_MCI_DTOMUL_1		(0 <<  4)
+#define		AT91_MCI_DTOMUL_16		(1 <<  4)
+#define		AT91_MCI_DTOMUL_128		(2 <<  4)
+#define		AT91_MCI_DTOMUL_256		(3 <<  4)
+#define		AT91_MCI_DTOMUL_1K		(4 <<  4)
+#define		AT91_MCI_DTOMUL_4K		(5 <<  4)
+#define		AT91_MCI_DTOMUL_64K		(6 <<  4)
+#define		AT91_MCI_DTOMUL_1M		(7 <<  4)
+
+#define AT91_MCI_SDCR		0x0c		/* SD Card Register */
+#define		AT91_MCI_SDCSEL		(0xf << 0)	/* SD Card Selector */
+#define		AT91_MCI_SDCBUS		(1   << 7)	/* 1-bit or 4-bit bus */
+
+#define AT91_MCI_ARGR		0x10		/* Argument Register */
+
+#define AT91_MCI_CMDR		0x14		/* Command Register */
+#define		AT91_MCI_CMDNB		(0x3f << 0)	/* Command Number */
+#define		AT91_MCI_RSPTYP		(3    << 6)	/* Response Type */
+#define			AT91_MCI_RSPTYP_NONE	(0 <<  6)
+#define			AT91_MCI_RSPTYP_48	(1 <<  6)
+#define			AT91_MCI_RSPTYP_136	(2 <<  6)
+#define		AT91_MCI_SPCMD		(7    << 8)	/* Special Command */
+#define			AT91_MCI_SPCMD_NONE	(0 <<  8)
+#define			AT91_MCI_SPCMD_INIT	(1 <<  8)
+#define			AT91_MCI_SPCMD_SYNC	(2 <<  8)
+#define			AT91_MCI_SPCMD_ICMD	(4 <<  8)
+#define			AT91_MCI_SPCMD_IRESP	(5 <<  8)
+#define		AT91_MCI_OPDCMD		(1 << 11)	/* Open Drain Command */
+#define		AT91_MCI_MAXLAT		(1 << 12)	/* Max Latency for Command to Response */
+#define		AT91_MCI_TRCMD		(3 << 16)	/* Transfer Command */
+#define			AT91_MCI_TRCMD_NONE	(0 << 16)
+#define			AT91_MCI_TRCMD_START	(1 << 16)
+#define			AT91_MCI_TRCMD_STOP	(2 << 16)
+#define		AT91_MCI_TRDIR		(1 << 18)	/* Transfer Direction */
+#define		AT91_MCI_TRTYP		(3 << 19)	/* Transfer Type */
+#define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
+#define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
+#define			AT91_MCI_TRTYP_STREAM	(2 << 19)
+
+#define AT91_MCI_RSPR(n)	(0x20 + ((n) * 4))	/* Response Registers 0-3 */
+#define AT91_MCR_RDR		0x30		/* Receive Data Register */
+#define AT91_MCR_TDR		0x34		/* Transmit Data Register */
+
+#define AT91_MCI_SR		0x40		/* Status Register */
+#define		AT91_MCI_CMDRDY		(1 <<  0)	/* Command Ready */
+#define		AT91_MCI_RXRDY		(1 <<  1) 	/* Receiver Ready */
+#define		AT91_MCI_TXRDY		(1 <<  2)	/* Transmit Ready */
+#define		AT91_MCI_BLKE		(1 <<  3)	/* Data Block Ended */
+#define		AT91_MCI_DTIP		(1 <<  4)	/* Data Transfer in Progress */
+#define		AT91_MCI_NOTBUSY	(1 <<  5)	/* Data Not Busy */
+#define		AT91_MCI_ENDRX		(1 <<  6)	/* End of RX Buffer */
+#define		AT91_MCI_ENDTX		(1 <<  7)	/* End fo TX Buffer */
+#define		AT91_MCI_RXBUFF		(1 << 14)	/* RX Buffer Full */
+#define		AT91_MCI_TXBUFE		(1 << 15)	/* TX Buffer Empty */
+#define		AT91_MCI_RINDE		(1 << 16)  	/* Response Index Error */
+#define		AT91_MCI_RDIRE		(1 << 17)	/* Response Direction Error */
+#define		AT91_MCI_RCRCE		(1 << 18)   	/* Response CRC Error */
+#define		AT91_MCI_RENDE		(1 << 19)	/* Response End Bit Error */
+#define		AT91_MCI_RTOE		(1 << 20)	/* Reponse Time-out Error */
+#define		AT91_MCI_DCRCE		(1 << 21)	/* Data CRC Error */
+#define		AT91_MCI_DTOE		(1 << 22)	/* Data Time-out Error */
+#define		AT91_MCI_OVRE		(1 << 30)	/* Overrun */
+#define		AT91_MCI_UNRE		(1 << 31)	/* Underrun */
+
+#define AT91_MCI_IER		0x44		/* Interrupt Enable Register */
+#define AT91_MCI_IDR		0x48		/* Interrupt Disable Register */
+#define AT91_MCI_IMR		0x4c		/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
index 2e7d113..4fdef13 100644
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ b/include/asm-arm/arch-at91rm9200/board.h
@@ -38,6 +38,8 @@
 extern int at91_serial_map[AT91_NR_UART];
 extern int at91_console_port;
 
+#include <linux/mtd/partitions.h>
+
  /* USB Device */
 struct at91_udc_data {
 	u8	vbus_pin;		/* high == host powering us */
@@ -77,4 +79,26 @@
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 
+ /* NAND / SmartMedia */
+struct at91_nand_data {
+	u8		enable_pin;	/* chip enable */
+	u8		det_pin;	/* card detect */
+	u8		rdy_pin;	/* ready/busy */
+	u8		ale;		/* address line number connected to ALE */
+	u8		cle;		/* address line number connected to CLE */
+        struct mtd_partition* (*partition_info)(int, int*);
+};
+extern void __init at91_add_device_nand(struct at91_nand_data *data);
+
+ /* I2C*/
+void __init at91_add_device_i2c(void);
+
+ /* RTC */
+void __init at91_add_device_rtc(void);
+
+ /* LEDs */
+extern u8 at91_leds_cpu;
+extern u8 at91_leds_timer;
+extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
+
 #endif
diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
index 412215e..a94f63f 100644
--- a/include/asm-arm/arch-ep93xx/ts72xx.h
+++ b/include/asm-arm/arch-ep93xx/ts72xx.h
@@ -12,6 +12,8 @@
  * febfc000	[67]0000000	4K	NAND data register
  * febfb000	[67]0400000	4K	NAND control register
  * febfa000	[67]0800000	4K	NAND busy register
+ * febf9000	10800000	4K	TS-5620 RTC index register
+ * febf8000	11700000	4K	TS-5620 RTC data register
  */
 
 #define TS72XX_MODEL_PHYS_BASE		0x22000000
@@ -58,6 +60,15 @@
 #define TS72XX_NAND_BUSY_SIZE		0x00001000
 
 
+#define TS72XX_RTC_INDEX_VIRT_BASE	0xfebf9000
+#define TS72XX_RTC_INDEX_PHYS_BASE	0x10800000
+#define TS72XX_RTC_INDEX_SIZE		0x00001000
+
+#define TS72XX_RTC_DATA_VIRT_BASE	0xfebf8000
+#define TS72XX_RTC_DATA_PHYS_BASE	0x11700000
+#define TS72XX_RTC_DATA_SIZE		0x00001000
+
+
 #ifndef __ASSEMBLY__
 #include <asm/io.h>
 
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
index b45fa36..621ff2c 100644
--- a/include/asm-arm/arch-imx/dma.h
+++ b/include/asm-arm/arch-imx/dma.h
@@ -17,27 +17,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/*
- * DMA registration
- */
-
 typedef enum {
 	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 3,
-	DMA_PRIO_LOW = 6
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
 } imx_dma_prio;
 
-int imx_request_dma(char *name, imx_dma_prio prio,
-		    void (*irq_handler) (int, void *, struct pt_regs *),
-		    void (*err_handler) (int, void *, struct pt_regs *),
-		    void *data);
-
-void imx_free_dma(int dma_ch);
-
-
 #define DMA_REQ_UART3_T        2
 #define DMA_REQ_UART3_R        3
 #define DMA_REQ_SSI2_T         4
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
new file mode 100644
index 0000000..f2063c1
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -0,0 +1,90 @@
+/*
+ *  linux/include/asm-arm/imxads/dma.h
+ *
+ *  Copyright (C) 1997,1998 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <asm/dma.h>
+
+#ifndef __ASM_ARCH_IMX_DMA_H
+#define __ASM_ARCH_IMX_DMA_H
+
+#define IMX_DMA_CHANNELS  11
+
+/*
+ * struct imx_dma_channel - i.MX specific DMA extension
+ * @name: name specified by DMA client
+ * @irq_handler: client callback for end of transfer
+ * @err_handler: client callback for error condition
+ * @data: clients context data for callbacks
+ * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE
+ * @sg: pointer to the actual read/written chunk for scatter-gather emulation
+ * @sgbc: counter of processed bytes in the actual read/written chunk
+ * @resbytes: total residual number of bytes to transfer
+ *            (it can be lower or same as sum of SG mapped chunk sizes)
+ * @sgcount: number of chunks to be read/written
+ *
+ * Structure is used for IMX DMA processing. It would be probably good
+ * @struct dma_struct in the future for external interfacing and use
+ * @struct imx_dma_channel only as extension to it.
+ */
+
+struct imx_dma_channel {
+	const char *name;
+	void (*irq_handler) (int, void *, struct pt_regs *);
+	void (*err_handler) (int, void *, struct pt_regs *);
+	void *data;
+	dmamode_t  dma_mode;
+	struct scatterlist *sg;
+	unsigned int sgbc;
+	unsigned int sgcount;
+	unsigned int resbytes;
+	int dma_num;
+};
+
+extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+
+/* The type to distinguish channel numbers parameter from ordinal int type */
+typedef int imx_dmach_t;
+
+int
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+		unsigned int dma_length, unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+		 struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+		 unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+		void (*irq_handler) (int, void *, struct pt_regs *),
+		void (*err_handler) (int, void *, struct pt_regs *), void *data);
+
+void imx_dma_enable(imx_dmach_t dma_ch);
+
+void imx_dma_disable(imx_dmach_t dma_ch);
+
+int imx_dma_request(imx_dmach_t dma_ch, const char *name);
+
+void imx_dma_free(imx_dmach_t dma_ch);
+
+int imx_dma_request_by_prio(imx_dmach_t *pdma_ch, const char *name, imx_dma_prio prio);
+
+
+#endif	/* _ASM_ARCH_IMX_DMA_H */
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h
new file mode 100644
index 0000000..1937151
--- /dev/null
+++ b/include/asm-arm/arch-imx/mmc.h
@@ -0,0 +1,12 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/protocol.h>
+
+struct imxmmc_platform_data {
+	int (*card_present)(void);
+};
+
+extern void imx_set_mmc_info(struct imxmmc_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
index bebcf0a..6e19f46 100644
--- a/include/asm-arm/arch-ixp23xx/memory.h
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -28,6 +28,7 @@
  *		to an address that the kernel can use.
  */
 #ifndef __ASSEMBLY__
+#include <asm/mach-types.h>
 
 #define __virt_to_bus(v)						\
 	({ unsigned int ret;						\
@@ -40,6 +41,22 @@
 	data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR);		\
 	 __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
 
+/*
+ * Coherency support.  Only supported on A2 CPUs or on A1
+ * systems that have the cache coherency workaround.
+ */
+static inline int __ixp23xx_arch_is_coherent(void)
+{
+	extern unsigned int processor_id;
+
+	if (((processor_id & 15) >= 2) || machine_is_roadrunner())
+		return 1;
+
+	return 0;
+}
+
+#define arch_is_coherent()	__ixp23xx_arch_is_coherent()
+
 #endif
 
 
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
index f85b468..e4d9906 100644
--- a/include/asm-arm/arch-ixp23xx/platform.h
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -22,6 +22,7 @@
 int ixp23xx_pci_setup(int, struct pci_sys_data *);
 void ixp23xx_pci_preinit(void);
 struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*);
+void ixp23xx_pci_slave_init(void);
 
 extern struct sys_timer ixp23xx_timer;
 
diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h
index 590bac2..6513065 100644
--- a/include/asm-arm/arch-omap/aic23.h
+++ b/include/asm-arm/arch-omap/aic23.h
@@ -57,6 +57,7 @@
 #define LHV_MIN				0x0000
 
 // Analog audio path control register
+#define STA_REG(x)			((x)<<6)
 #define STE_ENABLED			0x0020
 #define DAC_SELECTED			0x0010
 #define BYPASS_ON			0x0008
@@ -109,4 +110,7 @@
 #define TLV320AIC23ID1                  (0x1a)	// cs low
 #define TLV320AIC23ID2                  (0x1b)	// cs high
 
+void tlv320aic23_power_up(void);
+void tlv320aic23_power_down(void);
+
 #endif /* __ASM_ARCH_AIC23_H */
diff --git a/include/asm-arm/arch-omap/board-ams-delta.h b/include/asm-arm/arch-omap/board-ams-delta.h
new file mode 100644
index 0000000..0070f6d
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-ams-delta.h
@@ -0,0 +1,65 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-ams-delta.h
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __ASM_ARCH_OMAP_AMS_DELTA_H
+#define __ASM_ARCH_OMAP_AMS_DELTA_H
+
+#if defined (CONFIG_MACH_AMS_DELTA)
+
+#define AMS_DELTA_LATCH1_PHYS		0x01000000
+#define AMS_DELTA_LATCH1_VIRT		0xEA000000
+#define AMS_DELTA_MODEM_PHYS		0x04000000
+#define AMS_DELTA_MODEM_VIRT		0xEB000000
+#define AMS_DELTA_LATCH2_PHYS		0x08000000
+#define AMS_DELTA_LATCH2_VIRT		0xEC000000
+
+#define AMS_DELTA_LATCH1_LED_CAMERA	0x01
+#define AMS_DELTA_LATCH1_LED_ADVERT	0x02
+#define AMS_DELTA_LATCH1_LED_EMAIL	0x04
+#define AMS_DELTA_LATCH1_LED_HANDSFREE	0x08
+#define AMS_DELTA_LATCH1_LED_VOICEMAIL	0x10
+#define AMS_DELTA_LATCH1_LED_VOICE	0x20
+
+#define AMS_DELTA_LATCH2_LCD_VBLEN	0x0001
+#define AMS_DELTA_LATCH2_LCD_NDISP	0x0002
+#define AMS_DELTA_LATCH2_NAND_NCE	0x0004
+#define AMS_DELTA_LATCH2_NAND_NRE	0x0008
+#define AMS_DELTA_LATCH2_NAND_NWP	0x0010
+#define AMS_DELTA_LATCH2_NAND_NWE	0x0020
+#define AMS_DELTA_LATCH2_NAND_ALE	0x0040
+#define AMS_DELTA_LATCH2_NAND_CLE	0x0080
+#define AMS_DELTA_LATCH2_MODEM_NRESET	0x1000
+#define AMS_DELTA_LATCH2_MODEM_CODEC	0x2000
+
+#define AMS_DELTA_GPIO_PIN_NAND_RB	12
+
+#ifndef __ASSEMBLY__
+void ams_delta_latch1_write(u8 mask, u8 value);
+void ams_delta_latch2_write(u16 mask, u16 value);
+#endif
+
+#endif /* CONFIG_MACH_AMS_DELTA */
+
+#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
diff --git a/include/asm-arm/arch-omap/board-apollon.h b/include/asm-arm/arch-omap/board-apollon.h
new file mode 100644
index 0000000..de0c5b7
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-apollon.h
@@ -0,0 +1,45 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-apollon.h
+ *
+ * Hardware definitions for Samsung OMAP24XX Apollon board.
+ *
+ * Initial creation by Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_OMAP_APOLLON_H
+#define __ASM_ARCH_OMAP_APOLLON_H
+
+/* Placeholder for APOLLON specific defines */
+/* GPMC CS0 */
+#define APOLLON_CS0_BASE		0x00000000
+/* GPMC CS1 */
+#define APOLLON_CS1_BASE		0x08000000
+#define APOLLON_ETHR_START		(APOLLON_CS1_BASE + 0x300)
+#define APOLLON_ETHR_GPIO_IRQ		74
+/* GPMC CS2 - reserved for OneNAND */
+#define APOLLON_CS2_BASE		0x10000000
+/* GPMC CS3 - reserved for NOR or NAND */
+#define APOLLON_CS3_BASE		0x18000000
+
+#endif /*  __ASM_ARCH_OMAP_APOLLON_H */
+
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
index 39ca5a3..b2888ef 100644
--- a/include/asm-arm/arch-omap/board-h2.h
+++ b/include/asm-arm/arch-omap/board-h2.h
@@ -34,9 +34,5 @@
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define OMAP1610_ETHR_START		0x04000300
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
-
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index 1b12c1d..761ea0a 100644
--- a/include/asm-arm/arch-omap/board-h3.h
+++ b/include/asm-arm/arch-omap/board-h3.h
@@ -30,10 +30,6 @@
 /* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
 #define OMAP1710_ETHR_START		0x04000300
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
-
 #define MAXIRQNUM			(IH_BOARD_BASE)
 #define MAXFIQNUM			MAXIRQNUM
 #define MAXSWINUM			MAXIRQNUM
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h
index 33ea29a..7ef664b 100644
--- a/include/asm-arm/arch-omap/board-h4.h
+++ b/include/asm-arm/arch-omap/board-h4.h
@@ -33,12 +33,6 @@
 /* GPMC CS1 */
 #define OMAP24XX_ETHR_START             0x08000300
 #define OMAP24XX_ETHR_GPIO_IRQ		92
-
-#define H4_CS0_BASE		     0x04000000
-
-#define H4_CS0_BASE		     0x04000000
-
-#define H4_CS0_BASE		     0x04000000
-
+#define H4_CS0_BASE			0x04000000
 #endif /*  __ASM_ARCH_OMAP_H4_H */
 
diff --git a/include/asm-arm/arch-omap/board-netstar.h b/include/asm-arm/arch-omap/board-netstar.h
deleted file mode 100644
index 77cc0fb..0000000
--- a/include/asm-arm/arch-omap/board-netstar.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Hardware definitions for OMAP5910 based NetStar board.
- *
- * 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 __ASM_ARCH_NETSTAR_H
-#define __ASM_ARCH_NETSTAR_H
-
-#include <asm/arch/tc.h>
-
-#define OMAP_NAND_FLASH_START1		OMAP_CS1_PHYS + (1 << 23)
-#define OMAP_NAND_FLASH_START2		OMAP_CS1_PHYS + (2 << 23)
-
-#endif /*  __ASM_ARCH_NETSTAR_H */
diff --git a/include/asm-arm/arch-omap/board-nokia.h b/include/asm-arm/arch-omap/board-nokia.h
new file mode 100644
index 0000000..72deea2
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-nokia.h
@@ -0,0 +1,54 @@
+/*
+ *  linux/include/asm-arm/arch-omap/board-nokia.h
+ *
+ *  Information structures for Nokia-specific board config data
+ *
+ *  Copyright (C) 2005	Nokia Corporation
+ */
+
+#ifndef _OMAP_BOARD_NOKIA_H
+#define _OMAP_BOARD_NOKIA_H
+
+#include <linux/types.h>
+
+#define OMAP_TAG_NOKIA_BT	0x4e01
+#define OMAP_TAG_WLAN_CX3110X	0x4e02
+#define OMAP_TAG_CBUS		0x4e03
+#define OMAP_TAG_EM_ASIC_BB5	0x4e04
+
+
+#define BT_CHIP_CSR		1
+#define BT_CHIP_TI		2
+
+#define BT_SYSCLK_12		1
+#define BT_SYSCLK_38_4		2
+
+struct omap_bluetooth_config {
+	u8    chip_type;
+	u8    bt_wakeup_gpio;
+	u8    host_wakeup_gpio;
+	u8    reset_gpio;
+	u8    bt_uart;
+	u8    bd_addr[6];
+	u8    bt_sysclk;
+};
+
+struct omap_wlan_cx3110x_config {
+	u8  chip_type;
+	s16 power_gpio;
+	s16 irq_gpio;
+	s16 spi_cs_gpio;
+};
+
+struct omap_cbus_config {
+	s16 clk_gpio;
+	s16 dat_gpio;
+	s16 sel_gpio;
+};
+
+struct omap_em_asic_bb5_config {
+	s16 retu_irq_gpio;
+	s16 tahvo_irq_gpio;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
index 691e52a..eb74420 100644
--- a/include/asm-arm/arch-omap/board-perseus2.h
+++ b/include/asm-arm/arch-omap/board-perseus2.h
@@ -42,8 +42,4 @@
 
 #define NR_IRQS			(MAXIRQNUM + 1)
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1	   0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2	   0x0C000000 /* CS3 */
-
 #endif
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index a0040cd..6d6240a 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -21,9 +21,12 @@
 #define OMAP_TAG_LCD		0x4f05
 #define OMAP_TAG_GPIO_SWITCH	0x4f06
 #define OMAP_TAG_UART		0x4f07
+#define OMAP_TAG_FBMEM		0x4f08
+#define OMAP_TAG_STI_CONSOLE	0x4f09
 
 #define OMAP_TAG_BOOT_REASON    0x4f80
 #define OMAP_TAG_FLASH_PART	0x4f81
+#define OMAP_TAG_VERSION_STR	0x4f82
 
 struct omap_clock_config {
 	/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
@@ -54,6 +57,11 @@
 	u32 console_speed;
 };
 
+struct omap_sti_console_config {
+	unsigned enable:1;
+	u8 channel;
+};
+
 struct omap_usb_config {
 	/* Configure drivers according to the connectors on your board:
 	 *  - "A" connector (rectagular)
@@ -87,6 +95,13 @@
 	char ctrl_name[16];
 };
 
+struct omap_fbmem_config {
+	u32 fb_sram_start;
+	u32 fb_sram_size;
+	u32 fb_sdram_start;
+	u32 fb_sdram_size;
+};
+
 /* Cover:
  *      high -> closed
  *      low  -> open
@@ -106,6 +121,12 @@
 	int key_code:24; /* Linux key code */
 };
 
+struct omap_uart_config {
+	/* Bit field of UARTs present; bit 0 --> UART1 */
+	unsigned int enabled_uarts;
+};
+
+
 struct omap_flash_part_config {
 	char part_table[0];
 };
@@ -114,11 +135,14 @@
 	char reason_str[12];
 };
 
-struct omap_uart_config {
-	/* Bit field of UARTs present; bit 0 --> UART1 */
-	unsigned int enabled_uarts;
+struct omap_version_config {
+	char component[12];
+	char version[12];
 };
 
+
+#include <asm-arm/arch-omap/board-nokia.h>
+
 struct omap_board_config_entry {
 	u16 tag;
 	u16 len;
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 46a0402..3c4eb9f 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -19,6 +19,7 @@
 	struct list_head	node;
 	struct module		*owner;
 	const char		*name;
+	int			id;
 	struct clk		*parent;
 	unsigned long		rate;
 	__u32			flags;
@@ -57,6 +58,7 @@
 extern void followparent_recalc(struct clk * clk);
 extern void clk_allow_idle(struct clk *clk);
 extern void clk_deny_idle(struct clk *clk);
+extern int clk_get_usecount(struct clk *clk);
 
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
@@ -80,10 +82,11 @@
 #define CM_PLL_SEL1		(1 << 18)
 #define CM_PLL_SEL2		(1 << 19)
 #define CM_SYSCLKOUT_SEL1	(1 << 20)
-#define CLOCK_IN_OMAP730	(1 << 21)
-#define CLOCK_IN_OMAP1510	(1 << 22)
-#define CLOCK_IN_OMAP16XX	(1 << 23)
-#define CLOCK_IN_OMAP242X	(1 << 24)
-#define CLOCK_IN_OMAP243X	(1 << 25)
+#define CLOCK_IN_OMAP310	(1 << 21)
+#define CLOCK_IN_OMAP730	(1 << 22)
+#define CLOCK_IN_OMAP1510	(1 << 23)
+#define CLOCK_IN_OMAP16XX	(1 << 24)
+#define CLOCK_IN_OMAP242X	(1 << 25)
+#define CLOCK_IN_OMAP243X	(1 << 26)
 
 #endif
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index d4e73ef..ca12023 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -404,6 +404,7 @@
 extern void omap_setup_lcd_dma(void);
 extern void omap_enable_lcd_dma(void);
 extern void omap_stop_lcd_dma(void);
+extern int  omap_lcd_dma_ext_running(void);
 extern void omap_set_lcd_dma_ext_controller(int external);
 extern void omap_set_lcd_dma_single_transfer(int single);
 extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
index 11772c7..e6522e6 100644
--- a/include/asm-arm/arch-omap/dmtimer.h
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -88,5 +88,6 @@
 void omap_dm_timer_reset_counter(struct omap_dm_timer *timer);
 
 int omap_dm_timers_active(void);
+u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
 
 #endif /* __ASM_ARCH_TIMER_H */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
index 57bf4f3..06dad83 100644
--- a/include/asm-arm/arch-omap/dsp.h
+++ b/include/asm-arm/arch-omap/dsp.h
@@ -181,10 +181,16 @@
 #define OMAP_DSP_MBCMD_PM_ENABLE	0x01
 
 #define OMAP_DSP_MBCMD_KFUNC_FBCTL	0x00
+#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR	0x01
 
+#define OMAP_DSP_MBCMD_FBCTL_UPD	0x0000
 #define OMAP_DSP_MBCMD_FBCTL_ENABLE	0x0002
 #define OMAP_DSP_MBCMD_FBCTL_DISABLE	0x0003
 
+#define OMAP_DSP_MBCMD_AUDIO_PWR_UP	0x0000
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1	0x0001
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2	0x0002
+
 #define OMAP_DSP_MBCMD_TDEL_SAFE	0x0000
 #define OMAP_DSP_MBCMD_TDEL_KILL	0x0001
 
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
index 4fcce69..16a459d 100644
--- a/include/asm-arm/arch-omap/dsp_common.h
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -27,11 +27,12 @@
 #ifndef ASM_ARCH_DSP_COMMON_H
 #define ASM_ARCH_DSP_COMMON_H
 
-void omap_dsp_pm_suspend(void);
-void omap_dsp_pm_resume(void);
-void omap_dsp_request_mpui(void);
-void omap_dsp_release_mpui(void);
-int omap_dsp_request_mem(void);
-int omap_dsp_release_mem(void);
+extern void omap_dsp_request_mpui(void);
+extern void omap_dsp_release_mpui(void);
+extern int omap_dsp_request_mem(void);
+extern int omap_dsp_release_mem(void);
+
+extern void (*omap_dsp_audio_pwr_up_request)(int stage);
+extern void (*omap_dsp_audio_pwr_down_request)(int stage);
 
 #endif /* ASM_ARCH_DSP_COMMON_H */
diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h
new file mode 100644
index 0000000..7a43b0a
--- /dev/null
+++ b/include/asm-arm/arch-omap/gpioexpander.h
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpioexpander.h
+ *
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H
+#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
+
+/* Function Prototypes for GPIO Expander functions */
+
+int read_gpio_expa(u8 *, int);
+int write_gpio_expa(u8 , int);
+
+#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 5406b87..7909b72 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -306,6 +306,10 @@
 #include "board-h4.h"
 #endif
 
+#ifdef CONFIG_MACH_OMAP_APOLLON
+#include "board-apollon.h"
+#endif
+
 #ifdef CONFIG_MACH_OMAP_OSK
 #include "board-osk.h"
 #endif
@@ -314,10 +318,6 @@
 #include "board-voiceblue.h"
 #endif
 
-#ifdef CONFIG_MACH_NETSTAR
-#include "board-netstar.h"
-#endif
-
 #endif /* !__ASSEMBLER__ */
 
 #endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/include/asm-arm/arch-omap/irda.h b/include/asm-arm/arch-omap/irda.h
new file mode 100644
index 0000000..805ae35
--- /dev/null
+++ b/include/asm-arm/arch-omap/irda.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-omap/irda.h
+ *
+ *  Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.com>
+ *
+ * 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 ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_SEL		1	/* Selects IrDA */
+#define IR_SIRMODE	2
+#define IR_FIRMODE	4
+#define IR_MIRMODE	8
+
+struct omap_irda_config {
+	int transceiver_cap;
+	int (*transceiver_mode)(struct device *dev, int mode);
+	int (*select_irda)(struct device *dev, int state);
+	/* Very specific to the needs of some platforms (h3,h4)
+	 * having calls which can sleep in irda_set_speed.
+	 */
+	struct work_struct gpio_expa;
+	int rx_channel;
+	int tx_channel;
+	unsigned long dest_start;
+	unsigned long src_start;
+	int tx_trigger;
+	int rx_trigger;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 4ffce1d..42098d9 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -242,6 +242,11 @@
 #define INT_24XX_GPIO_BANK2	30
 #define INT_24XX_GPIO_BANK3	31
 #define INT_24XX_GPIO_BANK4	32
+#define INT_24XX_MCBSP1_IRQ_TX	59
+#define INT_24XX_MCBSP1_IRQ_RX	60
+#define INT_24XX_MCBSP2_IRQ_TX	62
+#define INT_24XX_MCBSP2_IRQ_RX	63
+#define INT_24XX_UART3_IRQ	74
 
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
  * 16 MPUIO lines */
diff --git a/include/asm-arm/arch-omap/keypad.h b/include/asm-arm/arch-omap/keypad.h
new file mode 100644
index 0000000..8a023a9
--- /dev/null
+++ b/include/asm-arm/arch-omap/keypad.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-omap/keypad.h
+ *
+ *  Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com>
+ *
+ * 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 ASMARM_ARCH_KEYPAD_H
+#define ASMARM_ARCH_KEYPAD_H
+
+struct omap_kp_platform_data {
+	int rows;
+	int cols;
+	int *keymap;
+	unsigned int rep:1;
+	/* specific to OMAP242x*/
+	unsigned int *row_gpios;
+	unsigned int *col_gpios;
+};
+
+/* Group (0..3) -- when multiple keys are pressed, only the
+ * keys pressed in the same group are considered as pressed. This is
+ * in order to workaround certain crappy HW designs that produce ghost
+ * keypresses. */
+#define GROUP_0		(0 << 16)
+#define GROUP_1		(1 << 16)
+#define GROUP_2		(2 << 16)
+#define GROUP_3		(3 << 16)
+#define GROUP_MASK	GROUP_3
+
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+
+#endif
+
diff --git a/include/asm-arm/arch-omap/lcd_lph8923.h b/include/asm-arm/arch-omap/lcd_lph8923.h
new file mode 100644
index 0000000..004e67e
--- /dev/null
+++ b/include/asm-arm/arch-omap/lcd_lph8923.h
@@ -0,0 +1,14 @@
+#ifndef __LCD_LPH8923_H
+#define __LCD_LPH8923_H
+
+enum lcd_lph8923_test_num {
+	LCD_LPH8923_TEST_RGB_LINES,
+};
+
+enum lcd_lph8923_test_result {
+	LCD_LPH8923_TEST_SUCCESS,
+	LCD_LPH8923_TEST_INVALID,
+	LCD_LPH8923_TEST_FAILED,
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
index e79d98a..ed0dde4 100644
--- a/include/asm-arm/arch-omap/mcbsp.h
+++ b/include/asm-arm/arch-omap/mcbsp.h
@@ -37,6 +37,11 @@
 #define OMAP1610_MCBSP2_BASE	0xfffb1000
 #define OMAP1610_MCBSP3_BASE	0xe1017000
 
+#define OMAP24XX_MCBSP1_BASE	0x48074000
+#define OMAP24XX_MCBSP2_BASE	0x48076000
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)
+
 #define OMAP_MCBSP_REG_DRR2	0x00
 #define OMAP_MCBSP_REG_DRR1	0x02
 #define OMAP_MCBSP_REG_DXR2	0x04
@@ -71,9 +76,62 @@
 
 #define OMAP_MAX_MCBSP_COUNT 3
 
+#define AUDIO_MCBSP_DATAWRITE	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP		OMAP_MCBSP1
+#define AUDIO_DMA_TX		OMAP_DMA_MCBSP1_TX
+#define AUDIO_DMA_RX		OMAP_DMA_MCBSP1_RX
+
+#elif defined(CONFIG_ARCH_OMAP24XX)
+
+#define OMAP_MCBSP_REG_DRR2	0x00
+#define OMAP_MCBSP_REG_DRR1	0x04
+#define OMAP_MCBSP_REG_DXR2	0x08
+#define OMAP_MCBSP_REG_DXR1	0x0C
+#define OMAP_MCBSP_REG_SPCR2	0x10
+#define OMAP_MCBSP_REG_SPCR1	0x14
+#define OMAP_MCBSP_REG_RCR2	0x18
+#define OMAP_MCBSP_REG_RCR1	0x1C
+#define OMAP_MCBSP_REG_XCR2	0x20
+#define OMAP_MCBSP_REG_XCR1	0x24
+#define OMAP_MCBSP_REG_SRGR2	0x28
+#define OMAP_MCBSP_REG_SRGR1	0x2C
+#define OMAP_MCBSP_REG_MCR2	0x30
+#define OMAP_MCBSP_REG_MCR1	0x34
+#define OMAP_MCBSP_REG_RCERA	0x38
+#define OMAP_MCBSP_REG_RCERB	0x3C
+#define OMAP_MCBSP_REG_XCERA	0x40
+#define OMAP_MCBSP_REG_XCERB	0x44
+#define OMAP_MCBSP_REG_PCR0	0x48