#
# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
#

--- linux-2.4.25/Documentation/Configure.help~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/Documentation/Configure.help	2004-03-31 17:15:11.000000000 +0200
@@ -4526,6 +4526,24 @@
   building a kernel for install/rescue disks or your system is very
   limited in memory.
 
+Kernel Execute-In-Place from ROM
+CONFIG_XIP_KERNEL
+  Execute-In-Place allows the kernel to run directly from 
+  non-volatile storage, such as flash. This saves RAM space since
+  the text section of the kernel is not loaded from flash to
+  RAM.  Read-write sections, such as the data section and stack,
+  are still copied to RAM.  The XIP kernel is not compressed since it
+  has to run directly from flash, so it will take more space to store 
+  it.  The flash address where the kernel is linked to run from and 
+  is stored is board dependent. Therefore, if you say Y, you must 
+  know the proper physical address where to store the kernel image.
+
+  Also note that the make target becomes "make xipImage" rather than
+  "make zImage" or "make Image".  The final kernel binary to put in
+  ROM memory will be arch/arm/boot/xipImage.
+
+  If unsure, say N.
+
 # Choice: kcore
 Kernel core (/proc/kcore) format
 CONFIG_KCORE_ELF
@@ -13386,6 +13404,30 @@
 
   If you don't know what this all is, saying Y is a safe choice.
 
+Workaround for XScale cache errata
+CONFIG_XSCALE_CACHE_ERRATA
+  There are couple errata that say that the cache may get confused
+  whether some cache lines are dirty or not, resulting in some memory
+  corruptions. The workaround (using the cache only in write through
+  mode) is performance impairing, and the bug _might_ just not be
+  that visible or critical to you depending on many esoteric
+  hardware factors.
+  
+  Not using the workaround makes Linux unreliable. If you're used
+  to some other OSes which requires to be rebooted once in a while
+  then this won't look so bad to you. On the other hand you may
+  stress test the system for hours without seeing any effect of this
+  bug.
+  
+  So this is configurable. Let's hope a future core revision will tell
+  this was just a bad dream. But in the mean time the risk and
+  trade-off is yours to decide.
+  
+  This should apply to all PXA250 up to rev B2 (erratum #120) and
+  possibly other current XScale cores as well.
+  
+  If you don't know what to answer, say Y.
+
 Support CD-ROM drives that are not SCSI or IDE/ATAPI
 CONFIG_CD_NO_IDESCSI
   If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
@@ -16568,6 +16610,40 @@
 
   If unsure, say N.
 
+Use linear addressing for cramfs
+CONFIG_CRAMFS_LINEAR
+  This option tells the cramfs driver to load data directly from a linear
+  adressed memory range (usually non volatile memory like flash) instead
+  of going through the block device layer.  This saves some memory since
+  no intermediate buffering is necessary.
+
+  This is also a prerequisite for XIP of binaries stored on the filesystem.
+
+  The location of the cramfs image in memory is board dependent. Therefore,
+  if you say Y, you must know the proper physical address where to store
+  the cramfs image and specify it using the physaddr=0x******** mount
+  option (for example: "mount -t cramfs -o physaddr=0x100000 none /mnt").
+
+  If unsure, say N.
+
+Support XIP on linear cramfs
+CONFIG_CRAMFS_LINEAR_XIP
+  You must say Y to this option if you want to be able to run applications
+  directly from non-volatile memory.  XIP applications are marked by
+  setting the sticky bit (ie, "chmod +t <app name>").  A cramfs file system
+  then needs to be created using mkcramfs (with XIP cramfs support
+  in it). Applications marked for XIP execution will not be compressed
+  since they have to run directly from flash.
+
+Root file system on linear cramfs
+CONFIG_ROOT_CRAMFS_LINEAR
+  Say Y if you have enabled linear cramfs, and you want to be able to use
+  the linear cramfs image as a root file system.  To actually have the
+  kernel mount this cramfs image as a root file system, you must also pass
+  the command line parameter "root=/dev/null rootflags=physaddr=0x********"
+  to the kernel (replace 0x******** with the physical address location
+  of the linear cramfs image to boot with).
+
 CMS file system support
 CONFIG_CMS_FS
   Read only support for CMS minidisk file systems found on IBM
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/Documentation/arm/XScale/PXA/USB-client	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,38 @@
+Date: Wed, 05 Jun 2002 13:38:53 -0700
+From: Frank Becker <fbecker@intrinsyc.com>
+To: Nicolas Pitre <nico@cam.org>
+Subject: [PATCH] PXA-USB
+
+Hi Nicolas,
+
+one more patch...
+
+This patch adds minimal USB client (UDC) support.
+
+Some notes:
+It adds just enough to get usb-eth working. I.e.
+endpoints 0-2, no dma. Performance isn't stellar
+partially due to UDC bug workarounds...
+(~350K @ 100Mhz, ~550K @ 200Mhz).
+
+Endpoint 1&2 have changed direction compared to
+the SA, so the host side requires a change to
+usbnet.c to flip endpoints (in:2/out:1 -> in:1/out:2).
+
+usb-eth and usb-char for PXA are almost identical
+to the SA versions, so they could probably be merged at
+one point. I made some minor changes to the eth driver
+to grab the usb resources at open, rather than at init
+and allow eth&char to be loaded at the same time.
+
+Stuart Lynne was working on his own USB client driver
+(and he was getting higher throughput than my driver).
+Assuming you guys have something in the oven for USB
+as well, there should be good selection for best of
+breed :)
+
+Cheers,
+Frank.
+-- 
+Frank Becker - Intrinsyc Software, Inc. - http://www.intrinsyc.com/
+Need a break? http://criticalmass.sf.net/
--- linux-2.4.25/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -1,11 +1,13 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 25
-EXTRAVERSION =-vrs2
+EXTRAVERSION =-vrs2-pxa1
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
-ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+ARCH := arm
+
 KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
 
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@@ -19,7 +21,7 @@
 HOSTCC  	= gcc
 HOSTCFLAGS	= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
 
-CROSS_COMPILE 	=
+CROSS_COMPILE 	= arm-linux-
 
 #
 # Include the make variables (CC, etc...)
@@ -168,6 +170,7 @@
 DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
 DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
 DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
+DRIVERS-$(CONFIG_MMC) += drivers/mmc/mmcdrivers.o
 DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o
 DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o
 DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o
--- linux-2.4.25/arch/arm/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/arch/arm/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -13,10 +13,11 @@
 CFLAGS		+=-Uarm -fno-common -pipe
 
 ifeq ($(CONFIG_FRAME_POINTER),y)
-CFLAGS		:=$(CFLAGS:-fomit-frame-pointer=-mapcs -mno-sched-prolog)
+CFLAGS		:=$(CFLAGS:-fomit-frame-pointer=)
+CFLAGS		+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
 endif
 
-CFLAGS		:=$(CFLAGS:-O2=-Os)
+#CFLAGS		:=$(CFLAGS:-O2=-Os)
 
 ifeq ($(CONFIG_DEBUG_INFO),y)
 CFLAGS		+=-g
@@ -38,6 +39,8 @@
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 -march=armv5
+#arch-$(CONFIG_CPU_XSCALE)	:=-D__LINUX_ARM_ARCH__=5 -mcpu=xscale
+arch-$(CONFIG_CPU_XSCALE)	:=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mcpu=xscale
 
 # This selects how we optimise for the processor.
 tune-y				:=
@@ -49,6 +52,8 @@
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
+tune-$(CONFIG_CPU_XSCALE)	:=-mtune=xscale
+#tune-$(CONFIG_CPU_XSCALE)	:=-mtune=strongarm
 
 CFLAGS_BOOT	:=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
 CFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
@@ -127,6 +132,10 @@
 MACHINE		 = sa1100
 endif
 
+ifeq ($(CONFIG_ARCH_PXA),y)
+MACHINE		 = pxa
+endif
+
 ifeq ($(CONFIG_ARCH_L7200),y)
 MACHINE		 = l7200
 endif
@@ -164,6 +173,17 @@
 MACHINE                = omaha
 endif
 
+ifeq ($(CONFIG_XIP_KERNEL),y) 
+  DATAADDR   := $(TEXTADDR)
+  # Replace phys addr with virt addr while keeping offset from base.
+  # Virt base addr also defined in include/asm-arm/arch-*/hardware.h
+  TEXTADDR    = $(shell echo 0x`echo $(CONFIG_XIP_PHYS_ADDR)|sed -e's/^0x//'` |\
+			awk --non-decimal-data '/[:xdigit:]/ \
+			  {printf("0x%x\n",and($$0,0x001fffff)+0xe8000000)}' )
+  LDSCRIPT    = arch/arm/vmlinux-armv-xip.lds.in
+  export DATAADDR
+endif
+
 export	MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT OBJCOPYFLAGS
 
 # Only set INCDIR if its not already defined above
@@ -269,7 +289,7 @@
 arch/arm/kernel arch/arm/mm arch/arm/lib: dummy
 	$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
 
-bzImage zImage zinstall Image bootpImage install: vmlinux
+bzImage zImage zinstall Image xipImage bootpImage install: vmlinux
 	@$(MAKEBOOT) $@
 
 CLEAN_FILES	+= \
--- linux-2.4.25/arch/arm/boot/Makefile~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/boot/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -113,6 +113,10 @@
 endif
 endif
 
+ifeq ($(CONFIG_ARCH_PXA),y)
+ZRELADDR	 = 0xa0008000
+endif
+
 ifeq ($(CONFIG_ARCH_ANAKIN),y)
 ZRELADDR	 = 0x20008000
 endif
@@ -140,6 +144,14 @@
 zImage:	compressed/vmlinux
 	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
 
+ifeq ($(CONFIG_XIP_KERNEL),y)
+xipImage: $(CONFIGURE) $(SYSTEM)
+	$(OBJCOPY) -S -O binary -R .data $(SYSTEM) vmlinux-text.bin
+	$(OBJCOPY) -S -O binary -R .init -R .text -R __ex_table -R __ksymtab $(SYSTEM) vmlinux-data.bin
+	cat vmlinux-text.bin vmlinux-data.bin > $@
+	$(RM) -f vmlinux-text.bin vmlinux-data.bin
+endif
+
 bootpImage: bootp/bootp
 	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
 
@@ -160,7 +172,7 @@
 	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
 clean:
-	$(RM) Image zImage bootpImage
+	$(RM) Image xipImage zImage bootpImage
 	@$(MAKE) -C compressed clean
 	@$(MAKE) -C bootp clean
 
--- linux-2.4.25/arch/arm/boot/compressed/Makefile~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/boot/compressed/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -71,6 +71,10 @@
 OBJS		+= head-sa1100.o
 endif
 
+ifeq ($(CONFIG_CPU_XSCALE),y)
+OBJS		+= head-xscale.o
+endif
+
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
 
 LIBGCC		:= $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/boot/compressed/head-xscale.S	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,50 @@
+/* 
+ * linux/arch/arm/boot/compressed/head-xscale.S
+ * 
+ * XScale specific tweaks.  This is merged into head.S by the linker.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+		.section        ".start", #alloc, #execinstr
+
+__XScale_start:
+
+		@ Preserve r8/r7 i.e. kernel entry values
+
+		@ Data cache might be active.
+		@ Be sure to flush kernel binary out of the cache,
+		@ whatever state it is, before it is turned off.
+		@ This is done by fetching through currently executed
+		@ memory to be sure we hit the same cache.
+		bic	r2, pc, #0x1f
+		add	r3, r2, #0x10000	@ 64 kb is quite enough...
+1:		ldr	r0, [r2], #32
+		teq	r2, r3
+		bne	1b
+		mcr	p15, 0, r0, c7, c10, 4	@ drain WB
+		mcr	p15, 0, r0, c7, c7, 0	@ flush I & D caches
+
+		@ disabling MMU and caches
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		bic	r0, r0, #0x05		@ clear DC, MMU
+		bic	r0, r0, #0x1000		@ clear Icache
+		mcr	p15, 0, r0, c1, c0, 0
+
+#ifdef CONFIG_ARCH_LUBBOCK
+		mov	r7, #MACH_TYPE_LUBBOCK
+#endif
+
+#ifdef CONFIG_ARCH_PXA_IDP
+		mov	r7, #MACH_TYPE_PXA_IDP
+#endif
+
+#ifdef CONFIG_ARCH_TRIZEPS2
+		mov	r7, #(MACH_TYPE_TRIZEPS2 & 0xFF00)
+		add	r7, r7, #(MACH_TYPE_TRIZEPS2 & 0xFF)
+#endif
+
+
--- linux-2.4.25/arch/arm/boot/compressed/head.S~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/arch/arm/boot/compressed/head.S	2004-03-31 17:15:11.000000000 +0200
@@ -351,7 +351,11 @@
 		orr	r1, r1, #3 << 10
 		add	r2, r3, #16384
 1:		cmp	r1, r8			@ if virt > start of RAM
+#ifdef CONFIG_XSCALE_CACHE_ERRATA
+		orrhs	r1, r1, #0x08           @ set cacheable, not bufferable
+#else
 		orrhs	r1, r1, #0x0c		@ set cacheable, bufferable
+#endif
 		cmp	r1, r9			@ if virt > end of RAM
 		bichs	r1, r1, #0x0c		@ clear cacheable, bufferable
 		str	r1, [r0], #4		@ 1:1 mapping
@@ -364,7 +368,11 @@
  * so there is no map overlap problem for up to 1 MB compressed kernel.
  * If the execution is in RAM then we would only be duplicating the above.
  */
+#ifdef CONFIG_XSCALE_CACHE_ERRATA
+		mov	r1, #0x1a
+#else
 		mov	r1, #0x1e
+#endif
 		orr	r1, r1, #3 << 10
 		mov	r2, pc, lsr #20
 		orr	r1, r1, r2, lsl #20
--- linux-2.4.25/arch/arm/config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/arch/arm/config.in	2004-03-31 17:15:11.000000000 +0200
@@ -38,6 +38,7 @@
 	 Cirrus-CL-PS7500FE     CONFIG_ARCH_CLPS7500 \
  	 CLPS711x/EP721x-based	CONFIG_ARCH_CLPS711X \
 	 Co-EBSA285		CONFIG_ARCH_CO285 \
+	 PXA250/210-based	CONFIG_ARCH_PXA \
 	 EBSA-110		CONFIG_ARCH_EBSA110 \
  	 Excalibur-ARM          CONFIG_ARCH_CAMELOT \
 	 FootBridge		CONFIG_ARCH_FOOTBRIDGE \
@@ -148,6 +149,47 @@
 endmenu
 
 mainmenu_option next_comment
+comment 'Intel PXA250/210 Implementations'
+dep_bool '  Intel DBPXA250 Development Platform' CONFIG_ARCH_LUBBOCK $CONFIG_ARCH_PXA
+dep_bool '  Accelent Xscale IDP' CONFIG_ARCH_PXA_IDP $CONFIG_ARCH_PXA
+dep_bool '  Intrinsyc CerfBoard' CONFIG_ARCH_PXA_CERF $CONFIG_ARCH_PXA
+dep_bool '  Trizeps-II MT6N' CONFIG_ARCH_TRIZEPS2 $CONFIG_ARCH_PXA
+
+if [ "$CONFIG_ARCH_PXA_CERF" = "y" ]; then
+   define_bool CONFIG_PXA_CERF y
+
+   choice 'CerfBoard Style' \
+      "PDA   CONFIG_PXA_CERF_PDA \
+       BOARD CONFIG_PXA_CERF_BOARD" PDA
+
+   choice 'CerfBoard RAM Available' \
+      "128MB  CONFIG_PXA_CERF_RAM_128MB \
+        64MB  CONFIG_PXA_CERF_RAM_64MB \
+        32MB  CONFIG_PXA_CERF_RAM_32MB \
+        16MB  CONFIG_PXA_CERF_RAM_16MB" 64MB
+
+   choice 'CerfBoard Flash Available' \
+      "64MB  CONFIG_PXA_CERF_FLASH_64MB \
+       32MB  CONFIG_PXA_CERF_FLASH_32MB \
+       16MB  CONFIG_PXA_CERF_FLASH_16MB \
+        8MB  CONFIG_PXA_CERF_FLASH_8MB" 32MB
+fi
+
+if [ "$CONFIG_ARCH_LUBBOCK" = "y" ]; then
+   define_bool CONFIG_SA1111 y
+fi
+
+if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then
+   define_bool CONFIG_TRIZEPS2 y
+fi
+
+dep_tristate 'PXA USB function support' CONFIG_PXA_USB $CONFIG_ARCH_PXA
+dep_tristate '  Support for PXA USB network link function' CONFIG_PXA_USB_NETLINK $CONFIG_PXA_USB
+dep_tristate '  Support for PXA USB character device emulation' CONFIG_PXA_USB_CHAR $CONFIG_PXA_USB
+
+endmenu
+
+mainmenu_option next_comment
 comment 'CLPS711X/EP721X Implementations'
 dep_bool '  AUTCPU12' CONFIG_ARCH_AUTCPU12 $CONFIG_ARCH_CLPS711X
 dep_bool '  CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X
@@ -385,6 +427,12 @@
    define_bool CONFIG_CPU_SA1100 n
 fi
 
+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
+   define_bool CONFIG_CPU_32v5 y
+   define_bool CONFIG_CPU_XSCALE y
+   bool 'Workaround for XScale cache errata (see help)' CONFIG_XSCALE_CACHE_ERRATA
+fi
+
 # Figure out what processor architecture version we should be using.
 # This defines the compiler instruction set which depends on the machine type.
 
@@ -493,6 +541,7 @@
 hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0
 
 if [ "$CONFIG_ARCH_SA1100" = "y" -o \
+     "$CONFIG_ARCH_PXA" = "y" -o \
      "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
    dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL
 fi
@@ -501,8 +550,10 @@
 bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
    source drivers/pcmcia/Config.in
+   source drivers/mmc/Config.in
 else
    define_bool CONFIG_PCMCIA n
+   define_bool CONFIG_MMC n
 fi
 if [ "$CONFIG_SA1100_ACCELENT" = "y" ]; then
    if [ "$CONFIG_PCMCIA" != "n" ]; then
@@ -513,6 +564,14 @@
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
+
+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
+    dep_bool 'Kernel Execute-In-Place from ROM (EXPERIMENTAL)' CONFIG_XIP_KERNEL $CONFIG_EXPERIMENTAL
+    if [ "$CONFIG_XIP_KERNEL" = "y" ]; then
+        hex '  Kernel .text physical address' CONFIG_XIP_PHYS_ADDR 0
+    fi    
+fi   
+
 comment 'At least one math emulation must be selected'
 tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE
 if [ "$CONFIG_FPE_NWFPE" != "n" ]; then
@@ -538,6 +597,9 @@
      "$CONFIG_ARCH_SHARK" = "y" -o      \
      "$CONFIG_ARCH_CO285" = "y" -o      \
      "$CONFIG_ARCH_SA1100" = "y" -o     \
+     "$CONFIG_ARCH_LUBBOCK" = "y" -o    \
+     "$CONFIG_ARCH_PXA_IDP" = "y" -o \
+     "$CONFIG_ARCH_PXA_CERF" = "y" -o \
      "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
      "$CONFIG_ARCH_CDB89712" = "y" -o   \
      "$CONFIG_ARCH_P720T" = "y" -o	\
@@ -549,8 +611,12 @@
 	   "$CONFIG_ARCH_SHARK" = "y" -o      \
 	   "$CONFIG_ARCH_CO285" = "y" -o      \
 	   "$CONFIG_ARCH_SA1100" = "y" -o     \
+           "$CONFIG_ARCH_LUBBOCK" = "y" -o    \
            "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
 	   "$CONFIG_ARCH_P720T" = "y" -o      \
+           "$CONFIG_ARCH_LUBBOCK" = "y" -o    \
+	   "$CONFIG_ARCH_PXA_CERF" = "y" -o   \
+	   "$CONFIG_ARCH_PXA_IDP" = "y" -o   \
 	   "$CONFIG_ARCH_OMAHA" = "y" ]; then
          bool '  Timer LED' CONFIG_LEDS_TIMER
          bool '  CPU usage LED' CONFIG_LEDS_CPU
@@ -684,6 +750,7 @@
    if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
         "$CONFIG_ARCH_SHARK" = "y" -o      \
         "$CONFIG_ARCH_SA1100" = "y" -o     \
+        "$CONFIG_ARCH_PXA" = "y" -o        \
         "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
         "$CONFIG_ARCH_TBOX" = "y" -o       \
         "$CONFIG_ARCH_CLPS7500" = "y" -o   \
@@ -705,6 +772,7 @@
      "$CONFIG_ARCH_TBOX" = "y" -o \
      "$CONFIG_ARCH_SHARK" = "y" -o \
      "$CONFIG_ARCH_SA1100" = "y" -o \
+     "$CONFIG_ARCH_PXA" = "y" -o \
      "$CONFIG_PCI" = "y" ]; then
    mainmenu_option next_comment
    comment 'Sound'
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/cerfboard_pxa	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,857 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_OMAHA is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_RISCSTATION is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ACCELENT is not set
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SIMPUTER is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_H3600_SLEEVE is not set
+
+#
+# Intel PXA250/210 Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_ARCH_PXA_CERF=y
+CONFIG_PXA_CERF=y
+# CONFIG_PXA_CERF_PDA is not set
+CONFIG_PXA_CERF_BOARD=y
+# CONFIG_PXA_CERF_RAM_128MB is not set
+CONFIG_PXA_CERF_RAM_64MB=y
+# CONFIG_PXA_CERF_RAM_32MB is not set
+# CONFIG_PXA_CERF_RAM_16MB is not set
+# CONFIG_PXA_CERF_FLASH_64MB is not set
+CONFIG_PXA_CERF_FLASH_32MB=y
+# CONFIG_PXA_CERF_FLASH_16MB is not set
+# CONFIG_PXA_CERF_FLASH_8MB is not set
+CONFIG_PXA_USB=y
+CONFIG_PXA_USB_NETLINK=y
+CONFIG_PXA_USB_CHAR=m
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_ARM1026 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+CONFIG_XSCALE_CACHE_ERRATA=y
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CPU_FREQ=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
+# CONFIG_PCMCIA_SA1100 is not set
+CONFIG_PCMCIA_PXA=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc"
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+# CONFIG_MTD_CFI_B2 is not set
+CONFIG_MTD_CFI_B4=y
+# CONFIG_MTD_CFI_B8 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_LUBBOCK is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_FORTUNET is not set
+CONFIG_MTD_PXA_CERF=y
+# CONFIG_MTD_EPXA10DB is not set
+# CONFIG_MTD_AUTCPU12 is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_ARM_CIRRUS is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+CONFIG_NET_PCMCIA_RADIO=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_PCMCIA_NETWAVE=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_AIRONET4500_CS=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_OMAHA is not set
+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_PXA_ALGO=y
+CONFIG_I2C_PXA_ADAP=y
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_PROC is not set
+# CONFIG_I2C_DS1307 is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_21285_WATCHDOG is not set
+# CONFIG_977_WATCHDOG is not set
+# CONFIG_SA1100_WATCHDOG is not set
+CONFIG_PXA_WATCHDOG=m
+# CONFIG_OMAHA_WATCHDOG is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_PXA_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_PCMCIA_SERIAL_CS=y
+CONFIG_PCMCIA_CHRDEV=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_UMSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+CONFIG_ROMFS_FS=y
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+CONFIG_NLS_CODEPAGE_863=m
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_MCP_UCB1400_TS is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/cerfpda_pxa	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,962 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_H3600_SLEEVE is not set
+
+#
+# Intel PXA250/210 Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_ARCH_PXA_CERF=y
+CONFIG_PXA_CERF=y
+CONFIG_PXA_CERF_PDA=y
+# CONFIG_PXA_CERF_BOARD is not set
+# CONFIG_PXA_CERF_RAM_128MB is not set
+CONFIG_PXA_CERF_RAM_64MB=y
+# CONFIG_PXA_CERF_RAM_32MB is not set
+# CONFIG_PXA_CERF_RAM_16MB is not set
+# CONFIG_PXA_CERF_FLASH_64MB is not set
+CONFIG_PXA_CERF_FLASH_32MB=y
+# CONFIG_PXA_CERF_FLASH_16MB is not set
+# CONFIG_PXA_CERF_FLASH_8MB is not set
+CONFIG_PXA_USB=y
+CONFIG_PXA_USB_NETLINK=y
+CONFIG_PXA_USB_CHAR=y
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+# CONFIG_XSCALE_CACHE_ERRATA is not set
+# CONFIG_ARM_THUMB is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
+# CONFIG_PCMCIA_SA1100 is not set
+CONFIG_PCMCIA_PXA=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc"
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+# CONFIG_MTD_CFI_B2 is not set
+CONFIG_MTD_CFI_B4=y
+# CONFIG_MTD_CFI_B8 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_LUBBOCK is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_FORTUNET is not set
+CONFIG_MTD_PXA_CERF=y
+# CONFIG_MTD_EPXA10DB is not set
+# CONFIG_MTD_AUTCPU12 is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=y
+CONFIG_IRLAN=y
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=y
+CONFIG_IRDA_ULTRA=y
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+CONFIG_IRTTY_SIR=y
+# CONFIG_IRPORT_SIR is not set
+# CONFIG_DONGLE is not set
+# CONFIG_USB_IRDA is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_PCMCIA_SERIAL_CS=y
+CONFIG_PCMCIA_CHRDEV=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_UMSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=m
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+CONFIG_ROMFS_FS=y
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+CONFIG_NLS_CODEPAGE_863=m
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_ANAKIN is not set
+# CONFIG_FB_CLPS711X is not set
+# CONFIG_FB_SA1100 is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_8BPP is not set
+CONFIG_FB_PXA_16BPP=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_WAVEARTIST is not set
+CONFIG_SOUND_PXA_AC97=y
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+CONFIG_MCP_UCB1400_TS=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+# CONFIG_USB_OHCI_SA1111 is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_HID is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_RIO500 is not set
+
+#
+# Bluetooth support
+#
+CONFIG_BLUEZ=y
+CONFIG_BLUEZ_L2CAP=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BLUEZ_HCIUSB is not set
+CONFIG_BLUEZ_HCIUART=y
+CONFIG_BLUEZ_HCIVHCI=y
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/csb226	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,615 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_OMAHA is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_RISCSTATION is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_AT91RM9200DK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ACCELENT is not set
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_HACKKIT is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SIMPUTER is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_H3600_SLEEVE is not set
+
+#
+# Intel PXA250/210 Board
+#
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_INNOKOM is not set
+CONFIG_ARCH_CSB226=y
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_ARCH_PXA_CERF is not set
+# CONFIG_PXA_USB is not set
+# CONFIG_PXA_USB_NETLINK is not set
+# CONFIG_PXA_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_ARM1026 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+CONFIG_XSCALE_CACHE_ERRATA=y
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+# CONFIG_CPU_FREQ is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+# CONFIG_MMC is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_XIP_KERNEL is not set
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,19200"
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_ARM_HWTIMER=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+CONFIG_ARM_CIRRUS=y
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_OMAHA is not set
+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_PXA_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_MCP_UCB1400_TS is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/innokom	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,699 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_OMAHA is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_RISCSTATION is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_AT91RM9200DK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ACCELENT is not set
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_HACKKIT is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SIMPUTER is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_H3600_SLEEVE is not set
+
+#
+# Intel PXA250/210 Board
+#
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_ARCH_INNOKOM=y
+# CONFIG_ARCH_CSB226 is not set
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_ARCH_PXA_CERF is not set
+# CONFIG_PXA_USB is not set
+# CONFIG_PXA_USB_NETLINK is not set
+# CONFIG_PXA_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_ARM1026 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+CONFIG_XSCALE_CACHE_ERRATA=y
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+# CONFIG_CPU_FREQ is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+# CONFIG_MMC is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_XIP_KERNEL is not set
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/nfs mem=32M ip=dhcp console=ttyS0,19200"
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_ARM_HWTIMER=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_LUBBOCK is not set
+# CONFIG_MTD_EPXA10DB is not set
+# CONFIG_MTD_FORTUNET is not set
+CONFIG_MTD_INNOKOM=y
+CONFIG_MTD_INNOKOM_16MB=y
+# CONFIG_MTD_INNOKOM_64MB is not set
+# CONFIG_MTD_AUTCPU12 is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_CEIVA is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PCMCIA is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_ARM_CIRRUS is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+CONFIG_SMC91X=y
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_OMAHA is not set
+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_PXA_ALGO=y
+CONFIG_I2C_PXA_ADAP=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PROC=y
+# CONFIG_I2C_DS1307 is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_PXA_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_MCP_UCB1400_TS is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/lubbock	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,971 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_OMAHA is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_RISCSTATION is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Archimedes/A5000 Implementations (select only ONE)
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ACCELENT is not set
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSAGC is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_ADSBITSYPLUS is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_H3600_SLEEVE is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_HACKKIT is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SIMPUTER is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_SA1100_SSP is not set
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+
+#
+# Intel PXA250/210 Implementations
+#
+CONFIG_ARCH_LUBBOCK=y
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_PXA_CERF is not set
+# CONFIG_ARCH_TRIZEPS2 is not set
+CONFIG_SA1111=y
+# CONFIG_PXA_USB is not set
+# CONFIG_PXA_USB_NETLINK is not set
+# CONFIG_PXA_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_GUIDEA07 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_ARM1026 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+# CONFIG_XSCALE_CACHE_ERRATA is not set
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+
+#
+# Processor Features
+#
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CPU_FREQ=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
+# CONFIG_PCMCIA_SA1100 is not set
+CONFIG_PCMCIA_PXA=y
+
+#
+# MMC device drivers
+#
+CONFIG_MMC=m
+CONFIG_MMC_PXA=m
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_PARTITIONS=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_XIP_KERNEL is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PM=y
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=32M"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+CONFIG_MTD_CFI_B2=y
+CONFIG_MTD_CFI_B4=y
+# CONFIG_MTD_CFI_B8 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_LUBBOCK=y
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_FORTUNET is not set
+# CONFIG_MTD_EPXA is not set
+# CONFIG_MTD_AUTCPU12 is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_CEIVA is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PCMCIA is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_ARM_CIRRUS is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+CONFIG_SMC91X=y
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=y
+# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_MX1TS is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_OMAHA is not set
+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
+# CONFIG_SERIAL_AT91 is not set
+# CONFIG_SERIAL_AT91_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+
+#
+# Other L3 adapters
+#
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_MK712_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_PXA_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_SYNCLINK_CS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+# CONFIG_CRAMFS_LINEAR is not set
+# CONFIG_CRAMFS_LINEAR_XIP is not set
+# CONFIG_ROOT_CRAMFS_LINEAR is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_ANAKIN is not set
+# CONFIG_FB_CLPS711X is not set
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_DBMX1 is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_8BPP is not set
+CONFIG_FB_PXA_16BPP=y
+# CONFIG_FB_PXA_QVGA is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_VIDC is not set
+# CONFIG_SOUND_WAVEARTIST is not set
+CONFIG_SOUND_PXA_AC97=y
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+CONFIG_MCP_UCB1400_TS=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
+
+#
+# Library routines
+#
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/pxa_idp	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,933 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_OMAHA is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_RISCSTATION is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ACCELENT is not set
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SIMPUTER is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_H3600_SLEEVE is not set
+
+#
+# Intel PXA250/210 Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+CONFIG_ARCH_PXA_IDP=y
+# CONFIG_ARCH_PXA_CERF is not set
+CONFIG_PXA_USB=m
+CONFIG_PXA_USB_NETLINK=m
+CONFIG_PXA_USB_CHAR=m
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_ARM1026 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+# CONFIG_XSCALE_CACHE_ERRATA is not set
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
+# CONFIG_PCMCIA_SA1100 is not set
+CONFIG_PCMCIA_PXA=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PM=y
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/mtdblock2 init=/linuxrc console=ttyS0,115200"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_B1 is not set
+# CONFIG_MTD_CFI_B2 is not set
+CONFIG_MTD_CFI_B4=y
+# CONFIG_MTD_CFI_B8 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_LUBBOCK=y
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_FORTUNET is not set
+# CONFIG_MTD_PXA_CERF is not set
+# CONFIG_MTD_EPXA10DB is not set
+# CONFIG_MTD_AUTCPU12 is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+CONFIG_ASI_MTD0_SIZE=40000
+CONFIG_ASI_MTD1_SIZE=100000
+CONFIG_ASI_MTD2_SIZE=1e00000
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_ARM_CIRRUS is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+CONFIG_SMC91111=m
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+CONFIG_NET_POCKET=y
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_STRIP is not set
+CONFIG_WAVELAN=m
+# CONFIG_ARLAN is not set
+CONFIG_AIRONET4500=y
+# CONFIG_AIRONET4500_NONCS is not set
+# CONFIG_AIRONET4500_PROC is not set
+CONFIG_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_AXNET is not set
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+CONFIG_NET_PCMCIA_RADIO=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_PCMCIA_NETWAVE=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_AIRONET4500_CS=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+CONFIG_IRTTY_SIR=m
+# CONFIG_IRPORT_SIR is not set
+# CONFIG_DONGLE is not set
+# CONFIG_USB_IRDA is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+CONFIG_PXA_FIR=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=m
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_OMAHA is not set
+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+# CONFIG_IDP_KEYB is not set
+CONFIG_MATRIX_KEYBOARD=y
+# CONFIG_SA1111_PS2_KEYB is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_MK712_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_PXA_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_PCMCIA_SERIAL_CS=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_CRAMFS=y
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+CONFIG_ZLIB_FS_INFLATE=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_ANAKIN is not set
+# CONFIG_FB_CLPS711X is not set
+# CONFIG_FB_SA1100 is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_WAVEARTIST is not set
+CONFIG_SOUND_PXA_AC97=y
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+CONFIG_MCP_UCB1400_TS=m
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SLAB=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/def-configs/trizeps2	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,873 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_OMAHA is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_MX1ADS is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_RISCSTATION is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ACCELENT is not set
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CEP is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_H3XXX is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_FRODO is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_PT_SYSTEM3 is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SIMPUTER is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+# CONFIG_H3600_SLEEVE is not set
+
+#
+# Intel PXA250/210 Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_PXA_CERF is not set
+CONFIG_ARCH_TRIZEPS2=y
+CONFIG_TRIZEPS2=y
+CONFIG_PXA_USB=y
+# CONFIG_PXA_USB_NETLINK is not set
+# CONFIG_PXA_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_PLD is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_ARM1026 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_XSCALE=y
+# CONFIG_XSCALE_CACHE_ERRATA is not set
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
+# CONFIG_PCMCIA_SA1100 is not set
+CONFIG_PCMCIA_PXA=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/mtdblock3 rw console=ttyS0,38400 mem=32M noinitrd init=/linuxrc"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_LUBBOCK is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_FORTUNET is not set
+# CONFIG_MTD_PXA_CERF is not set
+# CONFIG_MTD_EPXA10DB is not set
+# CONFIG_MTD_AUTCPU12 is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+CONFIG_MTD_TRIZEPS2=y
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_ARM_CIRRUS is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+CONFIG_SMC9194=y
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_ARLAN is not set
+# CONFIG_AIRONET4500 is not set
+# CONFIG_AIRONET4500_NONCS is not set
+# CONFIG_AIRONET4500_PROC is not set
+# CONFIG_HERMES is not set
+# CONFIG_PCMCIA_HERMES is not set
+CONFIG_AIRO_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+CONFIG_PCMCIA_3C574=m
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+CONFIG_NET_PCMCIA_RADIO=y
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_AIRONET4500_CS is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=m
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_OMAHA is not set
+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_PXA_ALGO=y
+CONFIG_I2C_PXA_ADAP=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PROC=y
+# CONFIG_I2C_DS1307 is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_PXA_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
+CONFIG_TRIZEPS2_TTLIO=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=m
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=m
+CONFIG_LOCKD=m
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_ANAKIN is not set
+# CONFIG_FB_CLPS711X is not set
+# CONFIG_FB_SA1100 is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
+# CONFIG_FBCON_CFB8 is not set
+CONFIG_FBCON_CFB16=y
+# CONFIG_FBCON_CFB24 is not set
+# CONFIG_FBCON_CFB32 is not set
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
+# CONFIG_FBCON_VGA is not set
+# CONFIG_FBCON_HGA is not set
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_WAVEARTIST is not set
+CONFIG_SOUND_PXA_AC97=y
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+CONFIG_MCP=y
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+CONFIG_MCP_UCB1400_TS=y
+CONFIG_MCP_UCB1X00_TS_COMPAT=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
--- linux-2.4.25/arch/arm/kernel/Makefile~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/kernel/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -10,7 +10,7 @@
 HEAD_OBJ  = head-$(PROCESSOR).o
 ENTRY_OBJ = entry-$(PROCESSOR).o
 
-AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR)
+AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR)
 
 # This is depreciated.
@@ -45,7 +45,7 @@
 		   $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
 		   $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \
 		   $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \
-		   $(CONFIG_ARCH_AT91RM9200)
+		   $(CONFIG_ARCH_AT91RM9200) $(CONFIG_ARCH_PXA)
 
 ifneq ($(findstring y,$(no-irq-arch)),y)
   obj-y		+= irq-arch.o
--- linux-2.4.25/arch/arm/kernel/debug-armv.S~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/kernel/debug-armv.S	2004-03-31 17:15:11.000000000 +0200
@@ -221,6 +221,31 @@
 		bne	1001b
 		.endm
 
+#elif defined(CONFIG_ARCH_PXA)
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x40000000		@ physical
+		movne	\rx, #io_p2v(0x40000000)	@ virtual
+		orr	\rx, \rx, #0x00100000		@ FFUART
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x14]
+		tst	\rd, #(1 << 6)
+		beq	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #0x14]
+		tst	\rd, #(1 << 5)
+		beq	1001b
+		.endm
 #elif defined(CONFIG_ARCH_CLPS7500)
 		.macro	addruart,rx
 		mov	\rx, #0xe0000000
--- linux-2.4.25/arch/arm/kernel/entry-armv.S~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/arch/arm/kernel/entry-armv.S	2004-03-31 17:15:11.000000000 +0200
@@ -615,6 +615,27 @@
 		.text
 		.endm
 
+#elif CONFIG_ARCH_PXA
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov	\base, #io_p2v(0x40000000)	@ IIR Ctl = 0x40d00000
+		add	\base, \base, #0x00d00000
+		ldr	\irqstat, [\base, #0]		@ ICIP
+		ldr	\irqnr, [\base, #4]		@ ICMR
+		ands	\irqstat, \irqstat, \irqnr
+		beq	1001f
+		rsb	\irqnr, \irqstat, #0
+		and	\irqstat, \irqstat, \irqnr
+		clz	\irqnr, \irqstat
+		rsb	\irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
+1001:
+		.endm
+
+		.macro	irq_prio_table
+		.endm
 #else
 #error Unknown architecture
 #endif
@@ -891,9 +912,17 @@
 		stmfd	sp!, {r4 - sl, fp, lr}		@ Store most regs on stack
 		mrs	ip, cpsr
 		str	ip, [sp, #-4]!			@ Save cpsr_SVC
+#ifdef CONFIG_CPU_XSCALE
+		mra	r4, r5, acc0
+		stmfd	sp!, {r4, r5}
+#endif
 		str	sp, [r0, #TSS_SAVE]		@ Save sp_SVC
 		ldr	sp, [r1, #TSS_SAVE]		@ Get saved sp_SVC
 		ldr	r2, [r1, #TSS_DOMAIN]
+#ifdef CONFIG_CPU_XSCALE
+		ldmfd	sp!, {r4, r5}
+		mar	acc0, r4, r5
+#endif
 		ldr	ip, [sp], #4
 		mcr	p15, 0, r2, c3, c0		@ Set domain register
 		msr	spsr, ip			@ Save tasks CPSR into SPSR for this return
--- linux-2.4.25/arch/arm/kernel/head-armv.S~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:08.000000000 +0200
+++ linux-2.4.25/arch/arm/kernel/head-armv.S	2004-03-31 17:15:11.000000000 +0200
@@ -30,6 +30,7 @@
  *
  * swapper_pg_dir, pgtbl and krnladr are all closely related.
  */
+#ifndef CONFIG_XIP_KERNEL
 #if (TEXTADDR & 0xffff) != 0x8000
 #error TEXTADDR must start at 0xXXXX8000
 #endif
@@ -41,6 +42,26 @@
 		adr	\reg, stext
 		sub	\reg, \reg, #0x4000
 		.endm
+#else
+#if (DATAADDR & 0xffff) != 0x8000
+#error DATAADDR must start at 0xXXXX8000
+#endif
+
+#define	PAGE_OFFSET	0xc0000000
+#ifdef CONFIG_ARCH_LUBBOCK
+#define	PHYS_OFFSET	0xa0000000
+#elif CONFIG_ARCH_OMAP
+#define	PHYS_OFFSET	0x10000000
+#endif
+
+		.globl	SYMBOL_NAME(swapper_pg_dir)
+		.equ	SYMBOL_NAME(swapper_pg_dir), DATAADDR - 0x4000
+
+		.macro	pgtbl, reg, rambase
+		ldr	\reg, PGTBL
+		add	\reg, \reg, #PHYS_OFFSET - PAGE_OFFSET
+		.endm
+#endif
 
 /*
  * Since the page table is closely related to the kernel start address, we
@@ -131,6 +152,32 @@
 		mov	r1, #MACH_TYPE_L7200
 #endif
 
+#ifdef CONFIG_XIP_KERNEL
+
+#if defined(CONFIG_ARCH_LUBBOCK)
+		mov	r1, #MACH_TYPE_LUBBOCK
+#endif
+
+		@ Data cache might be active.
+		@ Be sure to flush kernel binary out of the cache,
+		@ whatever state it is, before it is turned off.
+		@ This is done by fetching through currently executed
+		@ memory to be sure we hit the same cache.
+		bic	r2, pc, #0x1f
+		add	r3, r2, #0x10000	@ 64 kb is quite enough...
+1:		ldr	r0, [r2], #32
+		teq	r2, r3
+		bne	1b
+		mcr	p15, 0, r0, c7, c10, 4	@ drain WB
+		mcr	p15, 0, r0, c7, c7, 0	@ flush I & D caches
+
+		@ disabling MMU and caches
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		bic	r0, r0, #0x05		@ clear DC, MMU
+		bic	r0, r0, #0x1000		@ clear Icache
+		mcr	p15, 0, r0, c1, c0, 0
+#endif
+
 		mov	r0, #F_BIT | I_BIT | MODE_SVC	@ make sure svc mode
 		msr	cpsr_c, r0			@ and all irqs disabled
 		bl	__lookup_processor_type
@@ -179,6 +226,17 @@
  */
 		.align	5
 __mmap_switched:
+#ifdef CONFIG_XIP_KERNEL
+		ldr	r3, ETEXT			@ data section copy
+		ldr	r4, SDATA
+		ldr	r5, EDATA
+1:
+		ldr	r6, [r3], #4
+		str	r6, [r4], #4
+		cmp	r4, r5
+		blo	1b
+#endif
+
 		adr	r3, __switch_data + 4
 		ldmia	r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
 							@ sp = stack pointer
@@ -233,6 +291,8 @@
 		teq	r0, r2
 		bne	1b
 
+#ifndef CONFIG_XIP_KERNEL
+
 		/*
 		 * Create identity mapping for first MB of kernel to
 		 * cater for the MMU enable.  This identity mapping
@@ -271,6 +331,43 @@
 		add	r3, r8, r2			@ flags + rambase
 		str	r3, [r0]
 
+#else	/* CONFIG_XIP_KERNEL */
+
+		mov	r3, pc, lsr #20
+		mov	r3, r3, lsl #20		@ phys kernel start
+
+		add	r0, r4, r3, lsr #18
+		orr	r3, r3, r8
+		str	r3, [r0]
+
+		mov	r0, #TEXTADDR & 0xff000000
+		add	r0, r0, #TEXTADDR & 0x00f00000	@ virt kernel start
+		add	r0, r4, r0, lsr #18
+		add	r2, r3, #4 << 20		@ kernel + 4MB
+
+1:
+		str	r3, [r0], #4
+		add	r3, r3, #1 << 20
+		cmp	r3, r2
+		bne	1b
+
+		bic	r3, r4, #0x000ff000		@ ram start
+		add	r0, r4, r3, lsr #18
+		orr	r3, r3, r8
+		str	r3, [r0], #4
+
+		add	r0, r3, #PAGE_OFFSET - PHYS_OFFSET
+		add	r0, r4, r0, lsr #18
+		add	r2, r3, #4 << 20		@ ram + 4MB
+
+1:
+		str	r3, [r0], #4
+		add	r3, r3, #1 << 20
+		cmp	r3, r2
+		bne	1b
+
+#endif	/* CONFIG_XIP_KERNEL */
+
 		bic	r8, r8, #0x0c			@ turn off cacheable
 							@ and bufferable bits
 #ifdef CONFIG_DEBUG_LL
@@ -433,3 +530,13 @@
 		mov	pc, lr
 2:		ldmib	r4, {r5, r6, r7}		@ found, get results
 		mov	pc, lr
+
+#ifdef CONFIG_XIP_KERNEL
+
+PGTBL:		.long	SYMBOL_NAME(swapper_pg_dir)
+
+ETEXT:		.long	SYMBOL_NAME(_endtext)
+SDATA:		.long	SYMBOL_NAME(_sdata)
+EDATA:		.long	SYMBOL_NAME(__bss_start)
+
+#endif
--- linux-2.4.25/arch/arm/kernel/setup.c~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/kernel/setup.c	2004-03-31 17:15:11.000000000 +0200
@@ -55,6 +55,10 @@
 extern void reboot_setup(char *str);
 extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
+#ifdef CONFIG_XIP_KERNEL
+extern int _endtext, _sdata;
+#endif
+
 
 unsigned int processor_id;
 unsigned int __machine_arch_type;
@@ -105,6 +109,109 @@
 #define lp1 io_res[1]
 #define lp2 io_res[2]
 
+#ifdef CONFIG_CPU_32
+static const char *cache_types[16] = {
+	"write-through",
+	"write-back",
+	"write-back",
+	"undefined 3",
+	"undefined 4",
+	"undefined 5",
+	"write-back",
+	"write-back",
+	"undefined 8",
+	"undefined 9",
+	"undefined 10",
+	"undefined 11",
+	"undefined 12",
+	"undefined 13",
+	"undefined 14",
+	"undefined 15",
+};
+
+static const char *cache_clean[16] = {
+	"not required",
+	"read-block",
+	"cp15 c7 ops",
+	"undefined 3",
+	"undefined 4",
+	"undefined 5",
+	"cp15 c7 ops",
+	"cp15 c7 ops",
+	"undefined 8",
+	"undefined 9",
+	"undefined 10",
+	"undefined 11",
+	"undefined 12",
+	"undefined 13",
+	"undefined 14",
+	"undefined 15",
+};
+
+static const char *cache_lockdown[16] = {
+	"not supported",
+	"not supported",
+	"not supported",
+	"undefined 3",
+	"undefined 4",
+	"undefined 5",
+	"format A",
+	"format B",
+	"undefined 8",
+	"undefined 9",
+	"undefined 10",
+	"undefined 11",
+	"undefined 12",
+	"undefined 13",
+	"undefined 14",
+	"undefined 15",
+};
+
+#define CACHE_TYPE(x)	(((x) >> 25) & 15)
+#define CACHE_S(x)	((x) & (1 << 24))
+#define CACHE_DSIZE(x)	(((x) >> 12) & 4095)	/* only if S=1 */
+#define CACHE_ISIZE(x)	((x) & 4095)
+
+#define CACHE_SIZE(y)	(((y) >> 6) & 7)
+#define CACHE_ASSOC(y)	(((y) >> 3) & 7)
+#define CACHE_M(y)	((y) & (1 << 2))
+#define CACHE_LINE(y)	((y) & 3)
+
+static inline void dump_cache(const char *prefix, unsigned int cache)
+{
+	unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
+
+	printk("%s size %dK associativity %d line length %d sets %d\n",
+		prefix,
+		mult << (8 + CACHE_SIZE(cache)),
+		(mult << CACHE_ASSOC(cache)) >> 1,
+		8 << CACHE_LINE(cache),
+		1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
+			CACHE_LINE(cache)));
+}
+
+static inline void dump_cpu_cache_id(void)
+{
+	unsigned int cache_info;
+
+	asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
+
+	if (cache_info == processor_id)
+		return;
+
+	printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]);
+	if (CACHE_S(cache_info)) {
+		dump_cache("CPU: I cache", CACHE_ISIZE(cache_info));
+		dump_cache("CPU: D cache", CACHE_DSIZE(cache_info));
+	} else {
+		dump_cache("CPU: cache", CACHE_ISIZE(cache_info));
+	}
+}
+
+#else
+#define dump_cpu_cache_id() do { } while (0)
+#endif
+
 static void __init setup_processor(void)
 {
 	extern struct proc_info_list __proc_info_begin, __proc_info_end;
@@ -272,7 +379,11 @@
 
 	kernel_code.start  = __virt_to_phys(init_mm.start_code);
 	kernel_code.end    = __virt_to_phys(init_mm.end_code - 1);
+#ifndef CONFIG_XIP_KERNEL
 	kernel_data.start  = __virt_to_phys(init_mm.end_code);
+#else
+	kernel_data.start  = __virt_to_phys(init_mm.start_data);
+#endif
 	kernel_data.end    = __virt_to_phys(init_mm.brk - 1);
 
 	for (i = 0; i < mi->nr_banks; i++) {
@@ -531,7 +642,12 @@
 	}
 
 	init_mm.start_code = (unsigned long) &_text;
+#ifndef CONFIG_XIP_KERNEL
 	init_mm.end_code   = (unsigned long) &_etext;
+#else
+	init_mm.end_code   = (unsigned long) &_endtext;
+	init_mm.start_data   = (unsigned long) &_sdata;
+#endif
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
@@ -568,6 +684,41 @@
 	NULL
 };
 
+static const char *proc_arch[16] = {
+	"undefined 0",
+	"4",
+	"4T",
+	"5",
+	"5T",
+	"5TE",
+	"undefined 6",
+	"undefined 7",
+	"undefined 8",
+	"undefined 9",
+	"undefined 10",
+	"undefined 11",
+	"undefined 12",
+	"undefined 13",
+	"undefined 14",
+	"undefined 15"
+};
+
+static void
+c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
+{
+	unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
+
+	seq_printf(m, "%s size\t\t: %d\n"
+		      "%s assoc\t\t: %d\n"
+		      "%s line length\t: %d\n"
+		      "%s sets\t\t: %d\n",
+		type, mult << (8 + CACHE_SIZE(cache)),
+		type, (mult << CACHE_ASSOC(cache)) >> 1,
+		type, 8 << CACHE_LINE(cache),
+		type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
+			    CACHE_LINE(cache)));
+}
+
 static int c_show(struct seq_file *m, void *v)
 {
 	int i;
@@ -586,7 +737,60 @@
 		if (elf_hwcap & (1 << i))
 			seq_printf(m, "%s ", hwcap_str[i]);
 
-	seq_puts(m, "\n\n");
+	seq_puts(m, "\n");
+
+	if ((processor_id & 0x0000f000) == 0x00000000) {
+		/* pre-ARM7 */
+		seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
+	} else if ((processor_id & 0x0000f000) == 0x00007000) {
+		/* ARM7 */
+		seq_printf(m, "CPU implementor\t: 0x%02x\n"
+			      "CPU architecture: %s\n"
+			      "CPU variant\t: 0x%02x\n"
+			      "CPU part\t: 0x%03x\n",
+			   processor_id >> 24,
+			   processor_id & (1 << 23) ? "4T" : "3",
+			   (processor_id >> 16) & 127,
+			   (processor_id >> 4) & 0xfff);
+	} else {
+		/* post-ARM7 */
+		seq_printf(m, "CPU implementor\t: 0x%02x\n"
+			      "CPU architecture: %s\n"
+			      "CPU variant\t: 0x%x\n"
+			      "CPU part\t: 0x%03x\n",
+			   processor_id >> 24,
+			   proc_arch[(processor_id >> 16) & 15],
+			   (processor_id >> 20) & 15,
+			   (processor_id >> 4) & 0xfff);
+	}
+	seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
+
+#ifdef CONFIG_CPU_32
+	{
+		unsigned int cache_info;
+
+		asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
+		if (cache_info != processor_id) {
+			seq_printf(m, "Cache type\t: %s\n"
+				      "Cache clean\t: %s\n"
+				      "Cache lockdown\t: %s\n"
+				      "Cache unified\t: %s\n",
+				   cache_types[CACHE_TYPE(cache_info)],
+				   cache_clean[CACHE_TYPE(cache_info)],
+				   cache_lockdown[CACHE_TYPE(cache_info)],
+				   CACHE_S(cache_info) ? "harvard" : "unified");
+
+			if (CACHE_S(cache_info)) {
+				c_show_cache(m, "I", CACHE_ISIZE(cache_info));
+				c_show_cache(m, "D", CACHE_DSIZE(cache_info));
+			} else {
+				c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
+			}
+		}
+	}
+#endif
+
+	seq_puts(m, "\n");
 
 	seq_printf(m, "Hardware\t: %s\n", machine_name);
 	seq_printf(m, "Revision\t: %04x\n", system_rev);
--- linux-2.4.25/arch/arm/lib/copy_page.S~2.4.25-vrs2-pxa1.patch	2001-03-07 04:44:35.000000000 +0100
+++ linux-2.4.25/arch/arm/lib/copy_page.S	2004-03-31 17:15:11.000000000 +0200
@@ -13,6 +13,8 @@
 #include <asm/assembler.h>
 #include <asm/constants.h>
 
+#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
+
 		.text
 		.align	5
 /*
@@ -23,9 +25,13 @@
  */
 ENTRY(copy_page)
 		stmfd	sp!, {r4, lr}			@	2
-		mov	r2, #PAGE_SZ/64			@	1
+	PLD(	pld	[r1, #0]		)
+	PLD(	pld	[r1, #32]		)
+		mov	r2, #COPY_COUNT			@	1
 		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
-1:		stmia	r0!, {r3, r4, ip, lr}		@	4
+1:	PLD(	pld	[r1, #64]		)
+	PLD(	pld	[r1, #96]		)
+2:		stmia	r0!, {r3, r4, ip, lr}		@	4
 		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
 		stmia	r0!, {r3, r4, ip, lr}		@	4
 		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
@@ -33,6 +39,8 @@
 		ldmia	r1!, {r3, r4, ip, lr}		@	4
 		subs	r2, r2, #1			@	1
 		stmia	r0!, {r3, r4, ip, lr}		@	4
-		ldmneia	r1!, {r3, r4, ip, lr}		@	4
-		bne	1b				@	1
+		ldmgtia	r1!, {r3, r4, ip, lr}		@	4
+		bgt	1b				@	1
+	PLD(	ldmeqia r1!, {r3, r4, ip, lr}	)
+	PLD(	beq	2b			)
 		LOADREGS(fd, sp!, {r4, pc})		@	3
--- linux-2.4.25/arch/arm/lib/findbit.S~2.4.25-vrs2-pxa1.patch	2000-09-19 00:15:25.000000000 +0200
+++ linux-2.4.25/arch/arm/lib/findbit.S	2004-03-31 17:15:11.000000000 +0200
@@ -43,7 +43,15 @@
 /*
  * One or more bits in the LSB of r3 are assumed to be set.
  */
-.found:		tst	r3, #0x0f
+.found:
+#if __LINUX_ARM_ARCH__ >= 5
+		rsb	r1, r3, #0
+		and	r3, r3, r1
+		clz	r3, r3
+		rsb	r3, r3, #31
+		add	r0, r2, r3
+#else
+		tst	r3, #0x0f
 		addeq	r2, r2, #4
 		movne	r3, r3, lsl #4
 		tst	r3, #0x30
@@ -52,5 +60,6 @@
 		tst	r3, #0x40
 		addeq	r2, r2, #1
 		mov	r0, r2
+#endif
 		RETINSTR(mov,pc,lr)
 
--- linux-2.4.25/arch/arm/lib/getuser.S~2.4.25-vrs2-pxa1.patch	2002-08-03 02:39:42.000000000 +0200
+++ linux-2.4.25/arch/arm/lib/getuser.S	2004-03-31 17:15:11.000000000 +0200
@@ -18,7 +18,7 @@
  * Inputs:	r0 contains the address
  * Outputs:	r0 is the error code
  *		r1, r2 contains the zero-extended value
- *		lr corrupted
+ *		ip, lr corrupted
  *
  * No other registers must be altered.  (see include/asm-arm/uaccess.h
  * for specific ASM register usage).
@@ -42,14 +42,14 @@
 
 	.global	__get_user_2
 __get_user_2:
-	bic	r2, sp, #0x1f00
-	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TSK_ADDR_LIMIT]
-	sub	r2, r2, #2
-	cmp	r0, r2
+	bic	ip, sp, #0x1f00
+	bic	ip, ip, #0x00ff
+	ldr	ip, [ip, #TSK_ADDR_LIMIT]
+	sub	ip, ip, #2
+	cmp	r0, ip
 2:	ldrlsbt	r1, [r0], #1
-3:	ldrlsbt	r2, [r0]
-	orrls	r1, r1, r2, lsl #8
+3:	ldrlsbt	ip, [r0]
+	orrls	r1, r1, ip, lsl #8
 	movls	r0, #0
 	movls	pc, lr
 	b	__get_user_bad
--- linux-2.4.25/arch/arm/lib/memcpy.S~2.4.25-vrs2-pxa1.patch	2001-03-07 04:44:35.000000000 +0100
+++ linux-2.4.25/arch/arm/lib/memcpy.S	2004-03-31 17:15:11.000000000 +0200
@@ -8,6 +8,9 @@
  * published by the Free Software Foundation.
  *
  *  ASM optimised string functions
+ *
+ *  Big Endian, prefetching and code factorization provided by Nicolas Pitre:
+ *    Copyright (C) 2002-2003 MontaVista Software, Inc.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -27,15 +30,16 @@
 
 /*
  * Prototype: void memcpy(void *to,const void *from,unsigned long n);
- * ARM3: cant use memcopy here!!!
  */
 ENTRY(memcpy)
 ENTRY(memmove)
 		ENTER
-		cmp	r1, r0
-		bcc	19f
+		subs	ip, r0, r1
+		cmphi	r2, ip
+		bhi	18f
 		subs	r2, r2, #4
 		blt	6f
+	PLD(	pld	[r1, #0]		)
 		ands	ip, r0, #3
 		bne	7f
 		ands	ip, r1, #3
@@ -43,29 +47,59 @@
 
 1:		subs	r2, r2, #8
 		blt	5f
-		subs	r2, r2, #0x14
-		blt	3f
-2:		ldmia	r1!,{r3 - r9, ip}
-		stmia	r0!,{r3 - r9, ip}
+		subs	r2, r2, #20
+		blt	4f
+
+	PLD(	subs	r2, r2, #65		)
+	PLD(	blt	3f			)
+	PLD(	pld	[r1, #32]		)
+
+	PLD(	@ cache alignment		)
+	PLD(	ands	ip, r1, #31		)
+	PLD(	pld	[r1, #64]		)
+	PLD(	beq	2f			)
+	PLD(	rsb	ip, ip, #32		)
+	PLD(	cmp	r2, ip			)
+	PLD(	pld	[r1, #96]		)
+	PLD(	blt	2f			)
+	PLD(	cmp	ip, #16			)
+	PLD(	sub	r2, r2, ip		)
+	PLD(	ldmgeia	r1!, {r3 - r6}		)
+	PLD(	stmgeia	r0!, {r3 - r6}		)
+	PLD(	beq	2f			)
+	PLD(	and	ip, ip, #15		)
+	PLD(	cmp	ip, #8			)
+	PLD(	ldr	r3, [r1], #4		)
+	PLD(	ldrge	r4, [r1], #4		)
+	PLD(	ldrgt	r5, [r1], #4		)
+	PLD(	str	r3, [r0], #4		)
+	PLD(	strge	r4, [r0], #4		)
+	PLD(	strgt	r5, [r0], #4		)
+
+2:	PLD(	pld	[r1, #96]		)
+3:		ldmia	r1!, {r3 - r9, ip}
 		subs	r2, r2, #32
+		stmia	r0!, {r3 - r9, ip}
 		bge	2b
-		cmn	r2, #16
+	PLD(	cmn	r2, #65			)
+	PLD(	bge	3b			)
+	PLD(	add	r2, r2, #65		)
+4:		cmn	r2, #16
 		ldmgeia	r1!, {r3 - r6}
+		subge	r2, r2, #16
 		stmgeia	r0!, {r3 - r6}
-		subge	r2, r2, #0x10
-3:		adds	r2, r2, #0x14
-4:		ldmgeia	r1!, {r3 - r5}
+		adds	r2, r2, #20
+		ldmgeia	r1!, {r3 - r5}
+		subge	r2, r2, #12
 		stmgeia	r0!, {r3 - r5}
-		subges	r2, r2, #12
-		bge	4b
 5:		adds	r2, r2, #8
 		blt	6f
 		subs	r2, r2, #4
 		ldrlt	r3, [r1], #4
 		ldmgeia	r1!, {r4, r5}
+		subge	r2, r2, #4
 		strlt	r3, [r0], #4
 		stmgeia	r0!, {r4, r5}
-		subge	r2, r2, #4
 
 6:		adds	r2, r2, #4
 		EXITEQ
@@ -92,122 +126,175 @@
 		beq	1b
 
 8:		bic	r1, r1, #3
-		ldr	r7, [r1], #4
 		cmp	ip, #2
-		bgt	15f
-		beq	11f
+		ldr	lr, [r1], #4
+		bgt	17f
+		beq	16f
+
+
+		.macro	forward_copy_shift pull push
+
 		cmp	r2, #12
-		blt	10f
-		sub	r2, r2, #12
-9:		mov	r3, r7, lsr #8
-		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
+	PLD(	pld	[r1, #0]		)
+		blt	14f
+		subs	r2, r2, #28
+		blt	12f
+
+	PLD(	subs	r2, r2, #97		)
+	PLD(	blt	11f			)
+	PLD(	pld	[r1, #32]		)
+
+	PLD(	@ cache alignment		)
+	PLD(	rsb	ip, r1, #36		)
+	PLD(	pld	[r1, #64]		)
+	PLD(	ands	ip, ip, #31		)
+	PLD(	pld	[r1, #96]		)
+	PLD(	beq	10f			)
+	PLD(	cmp	r2, ip			)
+	PLD(	pld	[r1, #128]		)
+	PLD(	blt	10f			)
+	PLD(	sub	r2, r2, ip		)
+9:	PLD(	mov	r3, lr, pull #\pull	)
+	PLD(	ldr	lr, [r1], #4		)
+	PLD(	subs	ip, ip, #4		)
+	PLD(	orr	r3, r3, lr, push #\push	)
+	PLD(	str	r3, [r0], #4		)
+	PLD(	bgt	9b			)
+
+10:	PLD(	pld	[r1, #128]		)
+11:		mov	r3, lr, pull #\pull
+		ldmia	r1!, {r4 - r9, ip, lr}
+		subs	r2, r2, #32
+		orr	r3, r3, r4, push #\push
+		mov	r4, r4, pull #\pull
+		orr	r4, r4, r5, push #\push
+		mov	r5, r5, pull #\pull
+		orr	r5, r5, r6, push #\push
+		mov	r6, r6, pull #\pull
+		orr	r6, r6, r7, push #\push
+		mov	r7, r7, pull #\pull
+		orr	r7, r7, r8, push #\push
+		mov	r8, r8, pull #\pull
+		orr	r8, r8, r9, push #\push
+		mov	r9, r9, pull #\pull
+		orr	r9, r9, ip, push #\push
+		mov	ip, ip, pull #\pull
+		orr	ip, ip, lr, push #\push
+		stmia	r0!, {r3 - r9, ip}
+		bge	10b
+	PLD(	cmn	r2, #97			)
+	PLD(	bge	11b			)
+	PLD(	add	r2, r2, #97		)
+		cmn	r2, #16
+		blt	13f
+12:		mov	r3, lr, pull #\pull
+		ldmia	r1!, {r4 - r6, lr}
+		sub	r2, r2, #16
+		orr	r3, r3, r4, push #\push
+		mov	r4, r4, pull #\pull
+		orr	r4, r4, r5, push #\push
+		mov	r5, r5, pull #\pull
+		orr	r5, r5, r6, push #\push
+		mov	r6, r6, pull #\pull
+		orr	r6, r6, lr, push #\push
 		stmia	r0!, {r3 - r6}
-		subs	r2, r2, #16
-		bge	9b
-		adds	r2, r2, #12
-		blt	100f
-10:		mov	r3, r7, lsr #8
-		ldr	r7, [r1], #4
+13:		adds	r2, r2, #28
+		blt	15f
+14:		mov	r3, lr, pull #\pull
+		ldr	lr, [r1], #4
 		subs	r2, r2, #4
-		orr	r3, r3, r7, lsl #24
+		orr	r3, r3, lr, push #\push
 		str	r3, [r0], #4
-		bge	10b
-100:		sub	r1, r1, #3
+		bge	14b
+15:
+		.endm
+
+
+		forward_copy_shift	pull=8	push=24
+		sub	r1, r1, #3
 		b	6b
 
-11:		cmp	r2, #12
-		blt	13f		/* */
-		sub	r2, r2, #12
-12:		mov	r3, r7, lsr #16
-		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #16
-		mov	r4, r4, lsr #16
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7,LSL#16
-		stmia	r0!, {r3 - r6}
-		subs	r2, r2, #16
-		bge	12b
-		adds	r2, r2, #12
-		blt	14f
-13:		mov	r3, r7, lsr #16
-		ldr	r7, [r1], #4
-		subs	r2, r2, #4
-		orr	r3, r3, r7, lsl #16
-		str	r3, [r0], #4
-		bge	13b
-14:		sub	r1, r1, #2
+16:		forward_copy_shift	pull=16	push=16
+		sub	r1, r1, #2
 		b	6b
 
-15:		cmp	r2, #12
-		blt	17f
-		sub	r2, r2, #12
-16:		mov	r3, r7, lsr #24
-		ldmia	r1!,{r4 - r7}
-		orr	r3, r3, r4, lsl #8
-		mov	r4, r4, lsr #24
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		stmia	r0!, {r3 - r6}
-		subs	r2, r2, #16
-		bge	16b
-		adds	r2, r2, #12
-		blt	18f
-17:		mov	r3, r7, lsr #24
-		ldr	r7, [r1], #4
-		subs	r2, r2, #4
-		orr	r3, r3, r7, lsl#8
-		str	r3, [r0], #4
-		bge	17b
-18:		sub	r1, r1, #1
+17:		forward_copy_shift	pull=24	push=8
+		sub	r1, r1, #1
 		b	6b
 
 
-19:		add	r1, r1, r2
+18:		add	r1, r1, r2
 		add	r0, r0, r2
 		subs	r2, r2, #4
 		blt	24f
+	PLD(	pld	[r1, #-4]		)
 		ands	ip, r0, #3
 		bne	25f
 		ands	ip, r1, #3
 		bne	26f
 
-20:		subs	r2, r2, #8
+19:		subs	r2, r2, #8
 		blt	23f
-		subs	r2, r2, #0x14
+		subs	r2, r2, #20
 		blt	22f
-21:		ldmdb	r1!, {r3 - r9, ip}
-		stmdb	r0!, {r3 - r9, ip}
+
+	PLD(	subs	r2, r2, #96		)
+	PLD(	pld	[r1, #-32]		)
+	PLD(	blt	21f			)
+
+	PLD(	@ cache alignment		)
+	PLD(	ands	ip, r1, #31		)
+	PLD(	pld	[r1, #-64]		)
+	PLD(	beq	20f			)
+	PLD(	cmp	r2, ip			)
+	PLD(	pld	[r1, #-96]		)
+	PLD(	blt	20f			)
+	PLD(	cmp	ip, #16			)
+	PLD(	sub	r2, r2, ip		)
+	PLD(	ldmgedb	r1!, {r3 - r6}		)
+	PLD(	stmgedb	r0!, {r3 - r6}		)
+	PLD(	beq	20f			)
+	PLD(	and	ip, ip, #15		)
+	PLD(	cmp	ip, #8			)
+	PLD(	ldr	r3, [r1, #-4]!		)
+	PLD(	ldrge	r4, [r1, #-4]!		)
+	PLD(	ldrgt	r5, [r1, #-4]!		)
+	PLD(	str	r3, [r0, #-4]!		)
+	PLD(	strge	r4, [r0, #-4]!		)
+	PLD(	strgt	r5, [r0, #-4]!		)
+
+20:	PLD(	pld	[r1, #-96]		)
+	PLD(	pld	[r1, #-128]		)
+21:		ldmdb	r1!, {r3 - r6}
 		subs	r2, r2, #32
-		bge	21b
-22:		cmn	r2, #16
+		stmdb	r0!, {r3 - r6}
+		ldmdb	r1!, {r3 - r6}
+		stmgedb	r0!, {r3 - r6}
 		ldmgedb	r1!, {r3 - r6}
 		stmgedb	r0!, {r3 - r6}
+		ldmgedb	r1!, {r3 - r6}
+		subges	r2, r2, #32
+		stmdb	r0!, {r3 - r6}
+		bge	20b
+	PLD(	cmn	r2, #96			)
+	PLD(	bge	21b			)
+	PLD(	add	r2, r2, #96		)
+22:		cmn	r2, #16
+		ldmgedb	r1!, {r3 - r6}
 		subge	r2, r2, #16
+		stmgedb	r0!, {r3 - r6}
 		adds	r2, r2, #20
 		ldmgedb	r1!, {r3 - r5}
-		stmgedb	r0!, {r3 - r5}
 		subge	r2, r2, #12
+		stmgedb	r0!, {r3 - r5}
 23:		adds	r2, r2, #8
 		blt	24f
 		subs	r2, r2, #4
 		ldrlt	r3, [r1, #-4]!
 		ldmgedb	r1!, {r4, r5}
+		subge	r2, r2, #4
 		strlt	r3, [r0, #-4]!
 		stmgedb	r0!, {r4, r5}
-		subge	r2, r2, #4
 
 24:		adds	r2, r2, #4
 		EXITEQ
@@ -230,89 +317,101 @@
 		subs	r2, r2, ip
 		blt	24b
 		ands	ip, r1, #3
-		beq	20b
+		beq	19b
 
 26:		bic	r1, r1, #3
-		ldr	r3, [r1], #0
 		cmp	ip, #2
-		blt	34f
-		beq	30f
-		cmp	r2, #12
-		blt	28f
-		sub	r2, r2, #12
-27:		mov	r7, r3, lsl #8
-		ldmdb	r1!, {r3, r4, r5, r6}
-		orr	r7, r7, r6, lsr #24
-		mov	r6, r6, lsl #8
-		orr	r6, r6, r5, lsr #24
-		mov	r5, r5, lsl #8
-		orr	r5, r5, r4, lsr #24
-		mov	r4, r4, lsl #8
-		orr	r4, r4, r3, lsr #24
-		stmdb	r0!, {r4, r5, r6, r7}
-		subs	r2, r2, #16
-		bge	27b
-		adds	r2, r2, #12
-		blt	29f
-28:		mov	ip, r3, lsl #8
-		ldr	r3, [r1, #-4]!
-		subs	r2, r2, #4
-		orr	ip, ip, r3, lsr #24
-		str	ip, [r0, #-4]!
-		bge	28b
-29:		add	r1, r1, #3
-		b	24b
+		ldr	r3, [r1], #0
+		blt	35f
+		beq	34f
 
-30:		cmp	r2, #12
+
+		.macro	backward_copy_shift push pull
+
+		cmp	r2, #12
+	PLD(	pld	[r1, #-4]		)
 		blt	32f
-		sub	r2, r2, #12
-31:		mov	r7, r3, lsl #16
-		ldmdb	r1!, {r3, r4, r5, r6}
-		orr	r7, r7, r6, lsr #16
-		mov	r6, r6, lsl #16
-		orr	r6, r6, r5, lsr #16
-		mov	r5, r5, lsl #16
-		orr	r5, r5, r4, lsr #16
-		mov	r4, r4, lsl #16
-		orr	r4, r4, r3, lsr #16
-		stmdb	r0!, {r4, r5, r6, r7}
-		subs	r2, r2, #16
-		bge	31b
-		adds	r2, r2, #12
+		subs	r2, r2, #28
+		blt	30f
+
+	PLD(	subs	r2, r2, #96		)
+	PLD(	pld	[r1, #-32]		)
+	PLD(	blt	29f			)
+	PLD(	pld	[r1, #-64]		)
+
+	PLD(	@ cache alignment		)
+	PLD(	ands	ip, r1, #31		)
+	PLD(	pld	[r1, #-96]		)
+	PLD(	beq	28f			)
+	PLD(	cmp	r2, ip			)
+	PLD(	pld	[r1, #-128]		)
+	PLD(	blt	28f			)
+	PLD(	sub	r2, r2, ip		)
+27:	PLD(	mov	r4, r3, push #\push	)
+	PLD(	ldr	r3, [r1, #-4]!		)
+	PLD(	subs	ip, ip, #4		)
+	PLD(	orr	r4, r4, r3, pull #\pull	)
+	PLD(	str	r4, [r0, #-4]!		)
+	PLD(	bgt	27b			)
+
+28:	PLD(	pld	[r1, #-128]		)
+29:		mov	lr, r3, push #\push
+		ldmdb	r1!, {r3 - r9, ip}
+		subs	r2, r2, #32
+		orr	lr, lr, ip, pull #\pull
+		mov	ip, ip, push #\push
+		orr	ip, ip, r9, pull #\pull
+		mov	r9, r9, push #\push
+		orr	r9, r9, r8, pull #\pull
+		mov	r8, r8, push #\push
+		orr	r8, r8, r7, pull #\pull
+		mov	r7, r7, push #\push
+		orr	r7, r7, r6, pull #\pull
+		mov	r6, r6, push #\push
+		orr	r6, r6, r5, pull #\pull
+		mov	r5, r5, push #\push
+		orr	r5, r5, r4, pull #\pull
+		mov	r4, r4, push #\push
+		orr	r4, r4, r3, pull #\pull
+		stmdb	r0!, {r4 - r9, ip, lr}
+		bge	28b
+	PLD(	cmn	r2, #96			)
+	PLD(	bge	29b			)
+	PLD(	add	r2, r2, #96		)
+		cmn	r2, #16
+		blt	31f
+30:		mov	r7, r3, push #\push
+		ldmdb	r1!, {r3 - r6}
+		sub	r2, r2, #16
+		orr	r7, r7, r6, pull #\pull
+		mov	r6, r6, push #\push
+		orr	r6, r6, r5, pull #\pull
+		mov	r5, r5, push #\push
+		orr	r5, r5, r4, pull #\pull
+		mov	r4, r4, push #\push
+		orr	r4, r4, r3, pull #\pull
+		stmdb	r0!, {r4 - r7}
+31:		adds	r2, r2, #28
 		blt	33f
-32:		mov	ip, r3, lsl #16
+32:		mov	r4, r3, push #\push
 		ldr	r3, [r1, #-4]!
 		subs	r2, r2, #4
-		orr	ip, ip, r3, lsr #16
-		str	ip, [r0, #-4]!
+		orr	r4, r4, r3, pull #\pull
+		str	r4, [r0, #-4]!
 		bge	32b
-33:		add	r1, r1, #2
+33:
+		.endm
+
+
+		backward_copy_shift	push=8	pull=24
+		add	r1, r1, #3
 		b	24b
 
-34:		cmp	r2, #12
-		blt	36f
-		sub	r2, r2, #12
-35:		mov	r7, r3, lsl #24
-		ldmdb	r1!, {r3, r4, r5, r6}
-		orr	r7, r7, r6, lsr #8
-		mov	r6, r6, lsl #24
-		orr	r6, r6, r5, lsr #8
-		mov	r5, r5, lsl #24
-		orr	r5, r5, r4, lsr #8
-		mov	r4, r4, lsl #24
-		orr	r4, r4, r3, lsr #8
-		stmdb	r0!, {r4, r5, r6, r7}
-		subs	r2, r2, #16
-		bge	35b
-		adds	r2, r2, #12
-		blt	37f
-36:		mov	ip, r3, lsl #24
-		ldr	r3, [r1, #-4]!
-		subs	r2, r2, #4
-		orr	ip, ip, r3, lsr #8
-		str	ip, [r0, #-4]!
-		bge	36b
-37:		add	r1, r1, #1
+34:		backward_copy_shift	push=16	pull=16
+		add	r1, r1, #2
+		b	24b
+
+35:		backward_copy_shift	push=24	pull=8
+		add	r1, r1, #1
 		b	24b
 
-		.align
--- linux-2.4.25/arch/arm/lib/uaccess.S~2.4.25-vrs2-pxa1.patch	2000-09-19 00:15:25.000000000 +0200
+++ linux-2.4.25/arch/arm/lib/uaccess.S	2004-03-31 17:15:11.000000000 +0200
@@ -43,6 +43,8 @@
 		stmfd	sp!, {r2, r4 - r7, lr}
 		cmp	r2, #4
 		blt	.c2u_not_enough
+	PLD(	pld	[r1, #0]		)
+	PLD(	pld	[r0, #0]		)
 		ands	ip, r0, #3
 		bne	.c2u_dest_not_aligned
 .c2u_dest_aligned:
@@ -71,13 +73,26 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #32
 		blt	.c2u_0rem8lp
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
+	PLD(	subs	ip, ip, #64			)
+	PLD(	blt	.c2u_0cpynopld		)
+	PLD(	pld	[r1, #60]		)
+	PLD(	pld	[r0, #60]		)
 
-.c2u_0cpy8lp:	ldmia	r1!, {r3 - r6}
+.c2u_0cpy8lp:
+	PLD(	pld	[r1, #92]		)
+	PLD(	pld	[r0, #92]		)
+.c2u_0cpynopld:	ldmia	r1!, {r3 - r6}
 		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		ldmia	r1!, {r3 - r6}
-		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		subs	ip, ip, #32
+		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.c2u_0cpy8lp
+	PLD(	cmn	ip, #64			)
+	PLD(	bge	.c2u_0cpynopld		)
+	PLD(	add	ip, ip, #64		)
+
 .c2u_0rem8lp:	cmn	ip, #16
 		ldmgeia	r1!, {r3 - r6}
 		stmgeia	r0!, {r3 - r6}			@ Shouldnt fault
@@ -115,9 +130,9 @@
 .c2u_1fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.c2u_1nowords
-		mov	r3, r7, lsr #8
+		mov	r3, r7, pull #8
 		ldr	r7, [r1], #4
-		orr	r3, r3, r7, lsl #24
+		orr	r3, r3, r7, push #24
 USER(		strt	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -128,50 +143,63 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #16
 		blt	.c2u_1rem8lp
+	PLD(	pld	[r1, #12]		)
+	PLD(	pld	[r0, #12]		)
+	PLD(	subs	ip, ip, #32		)
+	PLD(	blt	.c2u_1cpynopld		)
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
 
-.c2u_1cpy8lp:	mov	r3, r7, lsr #8
+.c2u_1cpy8lp:
+	PLD(	pld	[r1, #44]		)
+	PLD(	pld	[r0, #44]		)
+.c2u_1cpynopld:	mov	r3, r7, pull #8
 		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		subs	ip, ip, #16
+		orr	r3, r3, r4, push #24
+		mov	r4, r4, pull #8
+		orr	r4, r4, r5, push #24
+		mov	r5, r5, pull #8
+		orr	r5, r5, r6, push #24
+		mov	r6, r6, pull #8
+		orr	r6, r6, r7, push #24
+		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.c2u_1cpy8lp
+	PLD(	cmn	ip, #32			)
+	PLD(	bge	.c2u_1cpynopld		)
+	PLD(	add	ip, ip, #32		)
+
 .c2u_1rem8lp:	tst	ip, #8
-		movne	r3, r7, lsr #8
+		movne	r3, r7, pull #8
 		ldmneia	r1!, {r4, r7}
-		orrne	r3, r3, r4, lsl #24
-		movne	r4, r4, lsr #8
-		orrne	r4, r4, r7, lsl #24
+		orrne	r3, r3, r4, push #24
+		movne	r4, r4, pull #8
+		orrne	r4, r4, r7, push #24
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
-		movne	r3, r7, lsr #8
+		movne	r3, r7, pull #8
 		ldrne	r7, [r1], #4
-		orrne	r3, r3, r7, lsl #24
+		orrne	r3, r3, r7, push #24
 		strnet	r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.c2u_1fupi
-.c2u_1nowords:	mov	r3, r7, lsr #8
+.c2u_1nowords:	mov	r3, r7, lsr #byte(1)
 		teq	ip, #0
 		beq	.c2u_finished
 		cmp	ip, #2
 USER(		strbt	r3, [r0], #1)			@ May fault
-		movge	r3, r3, lsr #8
+		movge	r3, r7, lsr #byte(2)
 USER(		strgebt	r3, [r0], #1)			@ May fault
-		movgt	r3, r3, lsr #8
+		movgt	r3, r7, lsr #byte(3)
 USER(		strgtbt	r3, [r0], #1)			@ May fault
 		b	.c2u_finished
 
 .c2u_2fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.c2u_2nowords
-		mov	r3, r7, lsr #16
+		mov	r3, r7, pull #16
 		ldr	r7, [r1], #4
-		orr	r3, r3, r7, lsl #16
+		orr	r3, r3, r7, push #16
 USER(		strt	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -182,39 +210,52 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #16
 		blt	.c2u_2rem8lp
+	PLD(	pld	[r1, #12]		)
+	PLD(	pld	[r0, #12]		)
+	PLD(	subs	ip, ip, #32		)
+	PLD(	blt	.c2u_2cpynopld		)
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
 
-.c2u_2cpy8lp:	mov	r3, r7, lsr #16
+.c2u_2cpy8lp:
+	PLD(	pld	[r1, #44]		)
+	PLD(	pld	[r0, #44]		)
+.c2u_2cpynopld:	mov	r3, r7, pull #16
 		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #16
-		mov	r4, r4, lsr #16
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		subs	ip, ip, #16
+		orr	r3, r3, r4, push #16
+		mov	r4, r4, pull #16
+		orr	r4, r4, r5, push #16
+		mov	r5, r5, pull #16
+		orr	r5, r5, r6, push #16
+		mov	r6, r6, pull #16
+		orr	r6, r6, r7, push #16
+		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.c2u_2cpy8lp
+	PLD(	cmn	ip, #32			)
+	PLD(	bge	.c2u_2cpynopld		)
+	PLD(	add	ip, ip, #32		)
+
 .c2u_2rem8lp:	tst	ip, #8
-		movne	r3, r7, lsr #16
+		movne	r3, r7, pull #16
 		ldmneia	r1!, {r4, r7}
-		orrne	r3, r3, r4, lsl #16
-		movne	r4, r4, lsr #16
-		orrne	r4, r4, r7, lsl #16
+		orrne	r3, r3, r4, push #16
+		movne	r4, r4, pull #16
+		orrne	r4, r4, r7, push #16
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
-		movne	r3, r7, lsr #16
+		movne	r3, r7, pull #16
 		ldrne	r7, [r1], #4
-		orrne	r3, r3, r7, lsl #16
+		orrne	r3, r3, r7, push #16
 		strnet	r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.c2u_2fupi
-.c2u_2nowords:	mov	r3, r7, lsr #16
+.c2u_2nowords:	mov	r3, r7, lsr #byte(2)
 		teq	ip, #0
 		beq	.c2u_finished
 		cmp	ip, #2
 USER(		strbt	r3, [r0], #1)			@ May fault
-		movge	r3, r3, lsr #8
+		movge	r3, r7, lsr #byte(3)
 USER(		strgebt	r3, [r0], #1)			@ May fault
 		ldrgtb	r3, [r1], #0
 USER(		strgtbt	r3, [r0], #1)			@ May fault
@@ -223,9 +264,9 @@
 .c2u_3fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.c2u_3nowords
-		mov	r3, r7, lsr #24
+		mov	r3, r7, pull #24
 		ldr	r7, [r1], #4
-		orr	r3, r3, r7, lsl #8
+		orr	r3, r3, r7, push #8
 USER(		strt	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -236,41 +277,54 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #16
 		blt	.c2u_3rem8lp
+	PLD(	pld	[r1, #12]		)
+	PLD(	pld	[r0, #12]		)
+	PLD(	subs	ip, ip, #32		)
+	PLD(	blt	.c2u_3cpynopld		)
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
 
-.c2u_3cpy8lp:	mov	r3, r7, lsr #24
+.c2u_3cpy8lp:
+	PLD(	pld	[r1, #44]		)
+	PLD(	pld	[r0, #44]		)
+.c2u_3cpynopld:	mov	r3, r7, pull #24
 		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #8
-		mov	r4, r4, lsr #24
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		subs	ip, ip, #16
+		orr	r3, r3, r4, push #8
+		mov	r4, r4, pull #24
+		orr	r4, r4, r5, push #8
+		mov	r5, r5, pull #24
+		orr	r5, r5, r6, push #8
+		mov	r6, r6, pull #24
+		orr	r6, r6, r7, push #8
+		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.c2u_3cpy8lp
+	PLD(	cmn	ip, #32			)
+	PLD(	bge	.c2u_3cpynopld		)
+	PLD(	add	ip, ip, #32		)
+
 .c2u_3rem8lp:	tst	ip, #8
-		movne	r3, r7, lsr #24
+		movne	r3, r7, pull #24
 		ldmneia	r1!, {r4, r7}
-		orrne	r3, r3, r4, lsl #8
-		movne	r4, r4, lsr #24
-		orrne	r4, r4, r7, lsl #8
+		orrne	r3, r3, r4, push #8
+		movne	r4, r4, pull #24
+		orrne	r4, r4, r7, push #8
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
-		movne	r3, r7, lsr #24
+		movne	r3, r7, pull #24
 		ldrne	r7, [r1], #4
-		orrne	r3, r3, r7, lsl #8
+		orrne	r3, r3, r7, push #8
 		strnet	r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.c2u_3fupi
-.c2u_3nowords:	mov	r3, r7, lsr #24
+.c2u_3nowords:	mov	r3, r7, lsr #byte(3)
 		teq	ip, #0
 		beq	.c2u_finished
 		cmp	ip, #2
 USER(		strbt	r3, [r0], #1)			@ May fault
-		ldrge	r3, [r1], #0
+		ldrgeb	r3, [r1], #1
 USER(		strgebt	r3, [r0], #1)			@ May fault
-		movgt	r3, r3, lsr #8
+		ldrgtb	r3, [r1], #0
 USER(		strgtbt	r3, [r0], #1)			@ May fault
 		b	.c2u_finished
 
@@ -302,6 +356,8 @@
 		stmfd	sp!, {r0, r2, r4 - r7, lr}
 		cmp	r2, #4
 		blt	.cfu_not_enough
+	PLD(	pld	[r1, #0]		)
+	PLD(	pld	[r0, #0]		)
 		ands	ip, r0, #3
 		bne	.cfu_dest_not_aligned
 .cfu_dest_aligned:
@@ -329,13 +385,26 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #32
 		blt	.cfu_0rem8lp
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
+	PLD(	subs	ip, ip, #64			)
+	PLD(	blt	.cfu_0cpynopld		)
+	PLD(	pld	[r1, #60]		)
+	PLD(	pld	[r0, #60]		)
 
-.cfu_0cpy8lp:	ldmia	r1!, {r3 - r6}			@ Shouldnt fault
+.cfu_0cpy8lp:
+	PLD(	pld	[r1, #92]		)
+	PLD(	pld	[r0, #92]		)
+.cfu_0cpynopld:	ldmia	r1!, {r3 - r6}			@ Shouldnt fault
 		stmia	r0!, {r3 - r6}
 		ldmia	r1!, {r3 - r6}			@ Shouldnt fault
-		stmia	r0!, {r3 - r6}
 		subs	ip, ip, #32
+		stmia	r0!, {r3 - r6}
 		bpl	.cfu_0cpy8lp
+	PLD(	cmn	ip, #64			)
+	PLD(	bge	.cfu_0cpynopld		)
+	PLD(	add	ip, ip, #64		)
+
 .cfu_0rem8lp:	cmn	ip, #16
 		ldmgeia	r1!, {r3 - r6}			@ Shouldnt fault
 		stmgeia	r0!, {r3 - r6}
@@ -374,9 +443,9 @@
 .cfu_1fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.cfu_1nowords
-		mov	r3, r7, lsr #8
+		mov	r3, r7, pull #8
 USER(		ldrt	r7, [r1], #4)			@ May fault
-		orr	r3, r3, r7, lsl #24
+		orr	r3, r3, r7, push #24
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -387,50 +456,63 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #16
 		blt	.cfu_1rem8lp
+	PLD(	pld	[r1, #12]		)
+	PLD(	pld	[r0, #12]		)
+	PLD(	subs	ip, ip, #32		)
+	PLD(	blt	.cfu_1cpynopld		)
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
 
-.cfu_1cpy8lp:	mov	r3, r7, lsr #8
+.cfu_1cpy8lp:
+	PLD(	pld	[r1, #44]		)
+	PLD(	pld	[r0, #44]		)
+.cfu_1cpynopld:	mov	r3, r7, pull #8
 		ldmia	r1!, {r4 - r7}			@ Shouldnt fault
-		orr	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		stmia	r0!, {r3 - r6}
 		subs	ip, ip, #16
+		orr	r3, r3, r4, push #24
+		mov	r4, r4, pull #8
+		orr	r4, r4, r5, push #24
+		mov	r5, r5, pull #8
+		orr	r5, r5, r6, push #24
+		mov	r6, r6, pull #8
+		orr	r6, r6, r7, push #24
+		stmia	r0!, {r3 - r6}
 		bpl	.cfu_1cpy8lp
+	PLD(	cmn	ip, #32			)
+	PLD(	bge	.cfu_1cpynopld		)
+	PLD(	add	ip, ip, #32		)
+
 .cfu_1rem8lp:	tst	ip, #8
-		movne	r3, r7, lsr #8
+		movne	r3, r7, pull #8
 		ldmneia	r1!, {r4, r7}			@ Shouldnt fault
-		orrne	r3, r3, r4, lsl #24
-		movne	r4, r4, lsr #8
-		orrne	r4, r4, r7, lsl #24
+		orrne	r3, r3, r4, push #24
+		movne	r4, r4, pull #8
+		orrne	r4, r4, r7, push #24
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		movne	r3, r7, lsr #8
+		movne	r3, r7, pull #8
 USER(		ldrnet	r7, [r1], #4)			@ May fault
-		orrne	r3, r3, r7, lsl #24
+		orrne	r3, r3, r7, push #24
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.cfu_1fupi
-.cfu_1nowords:	mov	r3, r7, lsr #8
+.cfu_1nowords:	mov	r3, r7, lsr #byte(1)
 		teq	ip, #0
 		beq	.cfu_finished
 		cmp	ip, #2
 		strb	r3, [r0], #1
-		movge	r3, r3, lsr #8
+		movge	r3, r7, lsr #byte(2)
 		strgeb	r3, [r0], #1
-		movgt	r3, r3, lsr #8
+		movgt	r3, r7, lsr #byte(3)
 		strgtb	r3, [r0], #1
 		b	.cfu_finished
 
 .cfu_2fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.cfu_2nowords
-		mov	r3, r7, lsr #16
+		mov	r3, r7, pull #16
 USER(		ldrt	r7, [r1], #4)			@ May fault
-		orr	r3, r3, r7, lsl #16
+		orr	r3, r3, r7, push #16
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -441,39 +523,52 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #16
 		blt	.cfu_2rem8lp
+	PLD(	pld	[r1, #12]		)
+	PLD(	pld	[r0, #12]		)
+	PLD(	subs	ip, ip, #32		)
+	PLD(	blt	.cfu_2cpynopld		)
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
 
-.cfu_2cpy8lp:	mov	r3, r7, lsr #16
+.cfu_2cpy8lp:
+	PLD(	pld	[r1, #44]		)
+	PLD(	pld	[r0, #44]		)
+.cfu_2cpynopld:	mov	r3, r7, pull #16
 		ldmia	r1!, {r4 - r7}			@ Shouldnt fault
-		orr	r3, r3, r4, lsl #16
-		mov	r4, r4, lsr #16
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		stmia	r0!, {r3 - r6}
 		subs	ip, ip, #16
+		orr	r3, r3, r4, push #16
+		mov	r4, r4, pull #16
+		orr	r4, r4, r5, push #16
+		mov	r5, r5, pull #16
+		orr	r5, r5, r6, push #16
+		mov	r6, r6, pull #16
+		orr	r6, r6, r7, push #16
+		stmia	r0!, {r3 - r6}
 		bpl	.cfu_2cpy8lp
+	PLD(	cmn	ip, #32			)
+	PLD(	bge	.cfu_2cpynopld		)
+	PLD(	add	ip, ip, #32		)
+
 .cfu_2rem8lp:	tst	ip, #8
-		movne	r3, r7, lsr #16
+		movne	r3, r7, pull #16
 		ldmneia	r1!, {r4, r7}			@ Shouldnt fault
-		orrne	r3, r3, r4, lsl #16
-		movne	r4, r4, lsr #16
-		orrne	r4, r4, r7, lsl #16
+		orrne	r3, r3, r4, push #16
+		movne	r4, r4, pull #16
+		orrne	r4, r4, r7, push #16
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		movne	r3, r7, lsr #16
+		movne	r3, r7, pull #16
 USER(		ldrnet	r7, [r1], #4)			@ May fault
-		orrne	r3, r3, r7, lsl #16
+		orrne	r3, r3, r7, push #16
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.cfu_2fupi
-.cfu_2nowords:	mov	r3, r7, lsr #16
+.cfu_2nowords:	mov	r3, r7, lsr #byte(2)
 		teq	ip, #0
 		beq	.cfu_finished
 		cmp	ip, #2
 		strb	r3, [r0], #1
-		movge	r3, r3, lsr #8
+		movge	r3, r7, lsr #byte(3)
 		strgeb	r3, [r0], #1
 USER(		ldrgtbt	r3, [r1], #0)			@ May fault
 		strgtb	r3, [r0], #1
@@ -482,9 +577,9 @@
 .cfu_3fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.cfu_3nowords
-		mov	r3, r7, lsr #24
+		mov	r3, r7, pull #24
 USER(		ldrt	r7, [r1], #4)			@ May fault
-		orr	r3, r3, r7, lsl #8
+		orr	r3, r3, r7, push #8
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -495,41 +590,54 @@
 		sub	r2, r2, ip
 		subs	ip, ip, #16
 		blt	.cfu_3rem8lp
+	PLD(	pld	[r1, #12]		)
+	PLD(	pld	[r0, #12]		)
+	PLD(	subs	ip, ip, #32		)
+	PLD(	blt	.cfu_3cpynopld		)
+	PLD(	pld	[r1, #28]		)
+	PLD(	pld	[r0, #28]		)
 
-.cfu_3cpy8lp:	mov	r3, r7, lsr #24
+.cfu_3cpy8lp:
+	PLD(	pld	[r1, #44]		)
+	PLD(	pld	[r0, #44]		)
+.cfu_3cpynopld:	mov	r3, r7, pull #24
 		ldmia	r1!, {r4 - r7}			@ Shouldnt fault
-		orr	r3, r3, r4, lsl #8
-		mov	r4, r4, lsr #24
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
+		orr	r3, r3, r4, push #8
+		mov	r4, r4, pull #24
+		orr	r4, r4, r5, push #8
+		mov	r5, r5, pull #24
+		orr	r5, r5, r6, push #8
+		mov	r6, r6, pull #24
+		orr	r6, r6, r7, push #8
 		stmia	r0!, {r3 - r6}
 		subs	ip, ip, #16
 		bpl	.cfu_3cpy8lp
+	PLD(	cmn	ip, #32			)
+	PLD(	bge	.cfu_3cpynopld		)
+	PLD(	add	ip, ip, #32		)
+
 .cfu_3rem8lp:	tst	ip, #8
-		movne	r3, r7, lsr #24
+		movne	r3, r7, pull #24
 		ldmneia	r1!, {r4, r7}			@ Shouldnt fault
-		orrne	r3, r3, r4, lsl #8
-		movne	r4, r4, lsr #24
-		orrne	r4, r4, r7, lsl #8
+		orrne	r3, r3, r4, push #8
+		movne	r4, r4, pull #24
+		orrne	r4, r4, r7, push #8
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		movne	r3, r7, lsr #24
+		movne	r3, r7, pull #24
 USER(		ldrnet	r7, [r1], #4)			@ May fault
-		orrne	r3, r3, r7, lsl #8
+		orrne	r3, r3, r7, push #8
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.cfu_3fupi
-.cfu_3nowords:	mov	r3, r7, lsr #24
+.cfu_3nowords:	mov	r3, r7, lsr #byte(3)
 		teq	ip, #0
 		beq	.cfu_finished
 		cmp	ip, #2
 		strb	r3, [r0], #1
-USER(		ldrget	r3, [r1], #0)			@ May fault
+USER(		ldrgebt	r3, [r1], #1)			@ May fault
 		strgeb	r3, [r0], #1
-		movgt	r3, r3, lsr #8
+USER(		ldrgtbt	r3, [r1], #1)			@ May fault
 		strgtb	r3, [r0], #1
 		b	.cfu_finished
 
@@ -544,7 +652,7 @@
 		ldr	r1, [sp], #4			@ unsigned long count
 		subs	r4, r1, r2			@ bytes left to copy
 		movne	r1, r4
-		blne	SYMBOL_NAME(__memzero)
+		blne	__memzero
 		mov	r0, r4
 		LOADREGS(fd,sp!, {r4 - r7, pc})
 		.previous
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,56 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET		:= pxa.o
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj-  :=
+
+export-objs := generic.o irq.o dma.o sa1111.o \
+               usb_ctl.o usb_recv.o usb_send.o
+
+# Common support (must be linked before board specific support)
+obj-y += generic.o irq.o dma.o
+obj-$(CONFIG_SA1111) += sa1111.o
+
+# Specific board support
+obj-$(CONFIG_ARCH_CSB226) += csb226.o
+obj-$(CONFIG_ARCH_INNOKOM) += innokom.o
+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+obj-$(CONFIG_ARCH_PXA_CERF) += cerf.o
+obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
+obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o
+
+# Support for blinky lights
+leds-y := leds.o
+leds-$(CONFIG_ARCH_CSB226) += leds-csb226.o
+leds-$(CONFIG_ARCH_INNOKOM) += leds-innokom.o
+leds-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
+leds-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
+leds-$(CONFIG_ARCH_PXA_CERF) += leds-cerf.o
+
+obj-$(CONFIG_LEDS) += $(leds-y)
+
+# PXA USB client support
+list-multi += pxausb_core.o
+pxausb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o
+obj-$(CONFIG_PXA_USB) += pxausb_core.o
+obj-$(CONFIG_PXA_USB_NETLINK) += usb-eth.o
+obj-$(CONFIG_PXA_USB_CHAR) += usb-char.o
+
+# Misc features
+obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
+
+include $(TOPDIR)/Rules.make
+
+pxausb_core.o: $(pxausb_core-objs)
+	$(LD) -r -o $@ $(pxausb_core-objs)
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/cerf.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,266 @@
+/*
+ *  linux/arch/arm/mach-pxa/cerf.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/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/io.h>
+#include <asm/arch/irq.h>
+
+#include "generic.h"
+
+/*
+ * Set this to zero to remove all the debug statements via
+ * dead code elimination.
+ */
+#define DEBUGGING       1
+
+#if DEBUGGING
+static unsigned int cerf_debug = DEBUGGING;
+#else
+#define cerf_debug       0
+#endif
+
+static void __init cerf_init_irq(void)
+{
+	pxa_init_irq();
+
+	if( cerf_debug > 1)
+	{
+#if 0
+		GPDR0 = 0xc05b9130;
+		GPDR1 = 0xfcffab82;
+		GPDR2 = 0x0001ffff;
+#endif
+
+		printk(KERN_INFO "Pin directions:\n");
+		printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0);
+		printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1);
+		printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2);
+
+		printk(KERN_INFO "Pin State:\n");
+		printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0);
+		printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1);
+		printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2);
+
+		printk(KERN_INFO "Rising Edge:\n");
+		printk(KERN_INFO "GRER0 0x%08x\n", GRER0);
+		printk(KERN_INFO "GRER1 0x%08x\n", GRER1);
+		printk(KERN_INFO "GRER2 0x%08x\n", GRER2);
+
+		printk(KERN_INFO "Falling Edge:\n");
+		printk(KERN_INFO "GFER0 0x%08x\n", GFER0);
+		printk(KERN_INFO "GFER1 0x%08x\n", GFER1);
+		printk(KERN_INFO "GFER2 0x%08x\n", GFER2);
+	}
+
+	/* set_GPIO_IRQ_edge has to be called before an irq can be requested */
+	set_GPIO_IRQ_edge(  0, GPIO_FALLING_EDGE); /* CPLD               */
+#ifdef CONFIG_PXA_CERF_PDA
+	set_GPIO_IRQ_edge(  2, GPIO_RISING_EDGE);  /* UART B Interrupt   */
+	set_GPIO_IRQ_edge(  3, GPIO_RISING_EDGE);  /* UART A Interrupt   */
+	set_GPIO_IRQ_edge( 32, GPIO_RISING_EDGE);  /* UCB1400 Interrupt  */
+#endif
+	set_GPIO_IRQ_edge( 14, GPIO_FALLING_EDGE); /* PCMCIA Card Detect */
+	set_GPIO_IRQ_edge( 21, GPIO_RISING_EDGE);  /* Ethernet Interrupt */
+}
+
+static int __init cerf_init(void)
+{
+	/*
+	 * All of the code that was here was SA1111 init code
+	 * which we do not have.
+	 */
+	return 0;
+}
+
+__initcall(cerf_init);
+
+static void __init
+fixup_cerf(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+	SET_BANK (0, CERF_RAM_BASE, CERF_RAM_SIZE);
+	mi->nr_banks      = 1;
+
+#if 0 // Enable this stuff if you plan on not using jffs2
+	setup_ramdisk (1, 0, 0, 8192);
+	setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+}
+
+/*
+ * IO map for the devices.
+ */
+static struct map_desc cerf_io_desc[] __initdata = {
+ /* virtual           physical          length            domain     r  w  c  b */
+  { CERF_FLASH_BASE , CERF_FLASH_PHYS , CERF_FLASH_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
+  { CERF_ETH_BASE   , CERF_ETH_PHYS   , CERF_ETH_SIZE   , DOMAIN_IO, 0, 1, 0, 0 },
+#ifdef CONFIG_PXA_CERF_PDA
+  { CERF_BT_BASE    , CERF_BT_PHYS    , CERF_BT_SIZE    , DOMAIN_IO, 0, 1, 0, 0 },
+  { CERF_SERIAL_BASE, CERF_SERIAL_PHYS, CERF_SERIAL_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+  { CERF_CPLD_BASE  , CERF_CPLD_PHYS  , CERF_CPLD_SIZE  , DOMAIN_IO, 0, 1, 0, 0 },
+#endif
+
+  LAST_DESC
+};
+
+static void __init cerf_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(cerf_io_desc);
+
+	if( cerf_debug > 1)
+	{
+		printk(KERN_INFO "origMCS0 = 0x%08x\n", MSC0);
+		printk(KERN_INFO "origMCS1 = 0x%08x\n", MSC1);
+		printk(KERN_INFO "origMCS2 = 0x%08x\n", MSC2);
+	}
+
+	/* setup memory timing for CS0/1 */
+	MSC0 = MSC_CS(0, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(3) |
+			 MSC_RDN(15) |
+			 MSC_RDF(13) |
+			 MSC_RBW(0) |
+			 MSC_RT(0)) |
+#ifdef CONFIG_PXA_CERF_PDA
+               MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(7) |
+			 MSC_RDN(15) |
+			 MSC_RDF(15) |
+			 MSC_RBW(1) |
+			 MSC_RT(0));
+#elif defined(CONFIG_PXA_CERF_BOARD)
+               MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(1) |
+			 MSC_RDN(2) |
+			 MSC_RDF(4) |
+			 MSC_RBW(0) |
+			 MSC_RT(4));
+#endif
+	printk(KERN_INFO "MCS0 = 0x%08x\n", MSC0);
+
+	/* setup memory timing for CS2/3 */
+	MSC1 = MSC_CS(2, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(5) |
+			 MSC_RDN(10) |
+			 MSC_RDF(10) |
+			 MSC_RBW(1) |
+			 MSC_RT(0)) |
+               MSC_CS(3, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(5) |
+			 MSC_RDN(10) |
+			 MSC_RDF(10) |
+			 MSC_RBW(1) |
+			 MSC_RT(0));
+	printk(KERN_INFO "MCS1 = 0x%08x\n", MSC1);
+
+	/* setup memory timing for CS4/5 */
+	MSC2 = MSC_CS(4, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(2) |
+			 MSC_RDN(4) |
+			 MSC_RDF(4) |
+			 MSC_RBW(1) |
+			 MSC_RT(0)) |
+               MSC_CS(5, MSC_RBUFF(MSC_RBUFF_SLOW) | 
+			 MSC_RRR(2) |
+			 MSC_RDN(4) |
+			 MSC_RDF(4) |
+			 MSC_RBW(1) |
+			 MSC_RT(0));
+	printk(KERN_INFO "MCS2 = 0x%08x\n", MSC2);
+
+#ifdef CONFIG_SOUND_PXA_AC97
+	printk(KERN_INFO "Enabling sound amp for pxa cerf pda.\n");
+	outw( CERF_PDA_SOUND_ENABLE, CERF_CPLD_BASE+CERF_PDA_CPLD_SOUND_ENA);
+#endif
+
+#ifdef CONFIG_FB_PXA
+	printk(KERN_INFO "Setting LCD to brightness to %d/15\n", CERF_PDA_DEFAULT_BRIGHTNESS);
+	outw( CERF_PDA_DEFAULT_BRIGHTNESS, CERF_CPLD_BASE+CERF_PDA_CPLD_BRIGHTNESS);
+#endif
+
+#ifdef CONFIG_IRDA
+	/* Enable IrDA UART (SIR)*/
+	CKEN |= CKEN5_STUART;
+
+	/* We want to get our goods from the STUART */
+	set_GPIO_mode(GPIO46_STRXD_MD);
+	set_GPIO_mode(GPIO47_STTXD_MD);
+
+	/* make sure FIR ICP is off */
+	ICCR0 = 0;
+
+	/* configure STUART to for SIR
+	 * NOTE: RCVEIR and XMITIR must not be set at the same time!
+	 * Start with receive in IR mode, and switch transmit to IR only
+	 * when we need to send something in serial driver.
+	 */
+	STISR = IrSR_IR_RECEIVE_ON;
+#endif
+
+#if 0
+	/* Connect FIR ICP to GPIO pins */
+	CKEN |= CKEN13_FICP;
+	set_GPIO_mode(GPIO46_ICPRXD_MD);
+	set_GPIO_mode(GPIO47_ICPTXD_MD);
+	ICCR0 = 0x1 | 0x18; //ICP unit enable
+#endif
+
+#if 0
+	/* Enable BT UART */
+	CKEN |= CKEN7_BTUART;
+	set_GPIO_mode(GPIO42_BTRXD_MD);
+	set_GPIO_mode(GPIO43_BTTXD_MD);
+	set_GPIO_mode(GPIO44_BTCTS_MD);
+	set_GPIO_mode(GPIO45_BTRTS_MD);
+#endif
+
+	if( cerf_debug > 1)
+	{
+		printk(KERN_INFO "GPDR0   0x%08x\n", GPDR0);
+		printk(KERN_INFO "GPDR1   0x%08x\n", GPDR1);
+		printk(KERN_INFO "GPDR2   0x%08x\n", GPDR2);
+		printk(KERN_INFO "GPLR0   0x%08x\n", GPLR0);
+		printk(KERN_INFO "GPLR1   0x%08x\n", GPLR1);
+		printk(KERN_INFO "GPLR2   0x%08x\n", GPLR2);
+		printk(KERN_INFO "GAFR0_L 0x%08x\n", GAFR0_L);
+		printk(KERN_INFO "GAFR0_U 0x%08x\n", GAFR0_U);
+		printk(KERN_INFO "GAFR1_L 0x%08x\n", GAFR1_L);
+		printk(KERN_INFO "GAFR1_U 0x%08x\n", GAFR1_U);
+		printk(KERN_INFO "GAFR2_L 0x%08x\n", GAFR2_L);
+		printk(KERN_INFO "GAFR2_U 0x%08x\n", GAFR2_U);
+		printk(KERN_INFO "CKEN  = 0x%08x\n", CKEN);
+		printk(KERN_INFO "ICCR0 = 0x%08x\n", ICCR0);
+		printk(KERN_INFO "STISR = 0x%08x\n", STISR);
+	}
+}
+
+MACHINE_START(PXA_CERF, "CerfBoard PXA Reference Board")
+	MAINTAINER("Intrinsyc Software Inc.")
+	BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
+	BOOT_PARAMS(0xa0000100)
+	FIXUP(fixup_cerf)
+	MAPIO(cerf_map_io)
+	INITIRQ(cerf_init_irq)
+MACHINE_END
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/cpu-pxa.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,240 @@
+/*
+ *  linux/arch/arm/mach-pxa/cpu-pxa.c
+ *
+ *  Copyright (C) 2002,2003 Intrinsyc Software
+ *
+ * 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.
+ *
+ * History:
+ *   31-Jul-2002 : Initial version [FB]
+ *   29-Jan-2003 : added PXA255 support [FB]
+ * 
+ * Note:
+ *
+ * Quote from erratum 134: 
+ * ""If the operation of these peripherals would be adversely affected,
+ *   then these peripherals would have to be disabled during a frequency
+ *   change. (MMC,FFUART,STUART,BTUART,IRDA,SSP,UDC,AC97)""
+ *
+ * This sounds like they are not sure what the bug is...
+ * If you run into problems with any of these peripherals, the effected
+ * driver should register with cpu freq notification and disable/enable 
+ * the peripheral on CPUFREQ_PRECHANGE and CPUFREQ_POSTCHANGE.
+ *  
+ * So far I've tested this code only under light load. It works for me.
+ *
+ * TODO: 
+ *   - determine min/max freq at runtime
+ *   - determine pxbus value at runtime
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+
+#include <asm/hardware.h>
+
+#define DEBUGGING	1
+
+#if DEBUGGING
+static unsigned int freq_debug = DEBUGGING;
+#else
+#define freq_debug	0
+#endif  
+
+typedef struct
+{
+	unsigned int khz;
+	unsigned int cccr;
+	unsigned int pxbus;
+} pxa_freqs_t;
+
+#define CCLKCFG_TURBO		0x1
+#define CCLKCFG_FCS		0x2
+
+#define PXA250_REV_A1		0x1
+#define PXA250_REV_B2		0x4
+#define PXA25x_MIN_FREQ		99000
+
+//#define PXA25x_ALLOW_OVERCLOCK
+
+#ifdef PXA25x_ALLOW_OVERCLOCK
+#warning *** Overclocking enabled - this may fry your hardware - you have been warned ***
+#define OC(x...)	x
+#define PXA25x_MAX_FREQ		471000
+#else
+#define OC(x...)
+#define PXA25x_MAX_FREQ		400000
+#endif
+
+/* If CONFIG_CPU_FREQ is turned on but we find (at runtime) 
+ * we can't support scaling, try to handle requests gracefully.
+ */
+static int supported;
+
+static pxa_freqs_t pxa250_valid_freqs[] =
+{
+	{199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
+	{298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
+	{398100, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
+	{0,0}
+};
+
+static pxa_freqs_t pxa255_valid_freqs[] =
+{
+	{ 99000, 0x121, 50}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */
+OC(	{118000, 0x122, 59},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */
+	{199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
+OC(	{236000, 0x142,118},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */
+	{298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
+OC(	{354000, 0x1c2,118},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */
+	{398099, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
+	{398100, 0x161,196}, /* mem= 99, run=398, turbo=398, PXbus=196 */
+OC(	{471000, 0x162,236},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */
+	{0,0}
+};
+
+static pxa_freqs_t *pxa_valid_freqs;
+
+/* This should be called with a valid freq point that was
+ * obtained via pxa_validate_speed
+ */
+static pxa_freqs_t * pxa_get_freq_info( unsigned int khz)
+{
+	int i=0;
+	while( pxa_valid_freqs[i].khz)
+	{
+		if( pxa_valid_freqs[i].khz == khz) 
+			return &pxa_valid_freqs[i]; 
+		i++;
+	}
+
+	/* shouldn't get here */
+	return 0;
+}
+
+/* find a valid frequency point */
+static unsigned int pxa_validate_speed(unsigned int khz)
+{
+	int i=0;
+	unsigned int vfreq = 0;
+	while( pxa_valid_freqs[i].khz && (khz >= pxa_valid_freqs[i].khz))
+	{
+		vfreq = pxa_valid_freqs[i].khz;
+		i++;
+	}
+	return vfreq;
+}
+
+/* This should be called with a valid freq point that was
+ * obtained via pxa_validate_speed
+ */
+static void pxa_setspeed(unsigned int khz)
+{
+	unsigned long flags;
+	unsigned int unused;
+	void *ramstart = phys_to_virt(0xa0000000);
+	pxa_freqs_t *freq_info;
+
+	if( ! supported) return;
+
+	freq_info = pxa_get_freq_info( khz);
+
+	if( ! freq_info) return;
+
+	CCCR = freq_info->cccr;
+	if( freq_debug)
+		printk(KERN_INFO "Changing CPU frequency to %d Mhz (PXbus=%dMhz).\n", 
+			khz/1000, freq_info->pxbus);
+
+	local_irq_save(flags);
+	__asm__ __volatile__("\
+		ldr	r4, [%1]			@load MDREFR	\n\
+		b	2f						\n\
+		.align  5						\n\
+1:									\n\
+		mcr	p14, 0, %2, c6, c0, 0		@ set CCLKCFG[FCS] \n\
+									\n\
+		@ restart sdcke 0 / 1					\n\
+		bic	r5,  r4,  #(0x00001000 | 0x00008000)	@ MDREFR_E0PIN | MDREFR_E1PIN \n\
+		str	r5,  [%1]			@clear		\n\
+		str	r4,  [%1]			@restore	\n\
+									\n\
+		@ Generate refresh cycles for all banks			\n\
+		ldr	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+		str	r4, [%3]					\n\
+									\n\
+		b	3f						\n\
+2:		b	1b						\n\
+3:		nop							\n\
+		"
+		: "=&r" (unused)
+		: "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart)
+		: "r4", "r5");
+	local_irq_restore(flags);
+}
+
+static int pxa_init_freqs( void)
+{
+	int cpu_ver; 
+	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver));
+
+	if( (cpu_ver & 0xf) <= PXA250_REV_A1)
+	{
+		return 0;
+	}
+
+	if( (cpu_ver & 0xf) <= PXA250_REV_B2)
+	{
+		if( freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n");
+		pxa_valid_freqs = pxa250_valid_freqs;
+	}	
+	else /* C0 and above */
+	{
+		if( freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n");
+		pxa_valid_freqs = pxa255_valid_freqs;
+	}
+	
+	return 1;
+}
+
+static int __init pxa_clk_init(void)
+{
+	if( pxa_init_freqs())
+	{
+		if( freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n");
+		supported = 1;
+
+		cpufreq_init( get_clk_frequency_khz(0), PXA25x_MIN_FREQ, PXA25x_MAX_FREQ);
+		cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
+	}
+	else
+	{
+		if( freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n");
+		/* Note that we have to initialize the generic code in order to 
+		 * release a lock (cpufreq_sem). Any registration for freq changes
+		 * (e.g. lcd driver) will get blocked otherwise.
+		 */
+		cpufreq_init( 0, 0, 0);
+		cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
+	}
+
+	return 0;
+}
+
+module_init(pxa_clk_init);
+
+MODULE_AUTHOR ("Intrinsyc Software Inc.");
+MODULE_LICENSE("GPL");
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/csb226.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,180 @@
+/*
+ *  linux/arch/arm/mach-pxa/csb226.c
+ *
+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ *
+ * 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/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/hardware/sa1111.h>
+
+#include "generic.h"
+
+static unsigned long csb226_irq_en_mask;
+
+static void csb226_mask_and_ack_irq(unsigned int irq)
+{
+	int csb226_irq = (irq - CSB226_IRQ(0));
+	csb226_irq_en_mask &= ~(1 << csb226_irq);
+	CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq);
+	CSB226_IRQ_SET_CLR &= ~(1 << csb226_irq);
+}
+
+static void csb226_mask_irq(unsigned int irq)
+{
+	int csb226_irq = (irq - CSB226_IRQ(0));
+	csb226_irq_en_mask &= ~(1 << csb226_irq);
+	CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq);
+}
+
+static void csb226_unmask_irq(unsigned int irq)
+{
+	int csb226_irq = (irq - CSB226_IRQ(0));
+	csb226_irq_en_mask |= (1 << csb226_irq);
+	CSB226_IRQ_MASK_EN |= (1 << csb226_irq);
+}
+
+void csb226_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long irq_status;
+	int i;
+
+	while ((irq_status = CSB226_IRQ_SET_CLR & csb226_irq_en_mask)) {
+		for (i = 0; i < 6; i++) {
+			if(irq_status & (1<<i)) 
+				do_IRQ(CSB226_IRQ(i), regs);
+		}
+	}
+}
+
+/* FIXME: this should not be necessary on csb226 */
+static struct irqaction csb226_irq = {
+	name:		"CSB226 FPGA",
+	handler:	csb226_irq_demux,
+	flags:		SA_INTERRUPT
+};
+
+static void __init csb226_init_irq(void)
+{
+	int irq;
+	
+	pxa_init_irq();
+
+	/* setup extra csb226 irqs */
+/* RS: ???
+	for(irq = CSB226_IRQ(0); irq <= CSB226_IRQ(5); irq++)
+	{
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= csb226_mask_and_ack_irq;
+		irq_desc[irq].mask	= csb226_mask_irq;
+		irq_desc[irq].unmask	= csb226_unmask_irq;
+	}
+
+	set_GPIO_IRQ_edge(GPIO_CSB226_IRQ, GPIO_FALLING_EDGE);
+	setup_arm_irq(IRQ_GPIO_CSB226_IRQ, &csb226_irq);
+*/
+}
+
+/* FIXME: not necessary on CSB226? */
+static int __init csb226_init(void)
+{
+	int ret;
+
+	return 0;
+}
+
+__initcall(csb226_init);
+
+static void __init
+fixup_csb226(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+	SET_BANK (0, 0xa0000000, 64*1024*1024);
+	mi->nr_banks      = 1;
+#if 0
+	setup_ramdisk (1, 0, 0, 8192);
+	setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+}
+
+/* FIXME: shouldn't this be moved to arch/arm/mach-pxa/mm.c? [RS] */
+static struct map_desc csb226_io_desc[] __initdata = {
+	/* virtual    physical    length      domain     r  w  c  b */
+//	{ 0xf4000000, 0x04000000, 0x00ffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* HT4562B PS/2 controller */
+	{ 0xf8000000, 0x08000000, 1024*1024,  DOMAIN_IO, 0, 1, 0, 0 }, /* CS8900 LAN controller   */
+//	{ 0xe0000000, 0x20000000, 0x0fffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* CompactFlash            */
+#if 0
+	{ 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD                    */
+	{ 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO             */
+	{ 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr           */
+	{ 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111                  */
+#endif
+  LAST_DESC
+};
+
+static void __init csb226_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(csb226_io_desc);
+
+	/* This enables the BTUART */
+	CKEN |= CKEN7_BTUART;
+	set_GPIO_mode(GPIO42_BTRXD_MD);
+	set_GPIO_mode(GPIO43_BTTXD_MD);
+	set_GPIO_mode(GPIO44_BTCTS_MD);
+	set_GPIO_mode(GPIO45_BTRTS_MD);
+
+	/* This is for the CS8900 chip select */
+	set_GPIO_mode(GPIO78_nCS_2_MD);
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(CSB226, "Cogent CSB226 Development Platform")
+	MAINTAINER("Robert Schwebel, Pengutronix")
+	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+	BOOT_PARAMS(0xa0000100)
+	FIXUP(fixup_csb226)
+	MAPIO(csb226_map_io)
+	INITIRQ(csb226_init_irq)
+MACHINE_END
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/dma.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,131 @@
+/*
+ *  linux/arch/arm/mach-pxa/dma.c
+ *
+ *  PXA DMA registration and IRQ dispatching
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 15, 2001
+ *  Copyright:	MontaVista Software 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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+
+
+static struct dma_channel {
+	char *name;
+	void (*irq_handler)(int, void *, struct pt_regs *);
+	void *data;
+} dma_channels[16];
+
+
+int pxa_request_dma (char *name, pxa_dma_prio prio,
+			 void (*irq_handler)(int, void *, struct pt_regs *),
+		 	 void *data)
+{
+	unsigned long flags;
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name || !irq_handler)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* 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 (!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 (found) {
+		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].data = data;
+	} else {
+		printk (KERN_WARNING "No more available DMA channels for %s\n", name);
+		i = -ENODEV;
+	}
+
+	local_irq_restore(flags);
+	return i;
+}
+
+void pxa_free_dma (int dma_ch)
+{
+	unsigned long flags;
+
+	if (!dma_channels[dma_ch].name) {
+		printk (KERN_CRIT __FUNCTION__
+			": trying to free channel %d which is already freed\n",
+			dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+	dma_channels[dma_ch].name = NULL;
+	local_irq_restore(flags);
+}
+
+static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int i, dint = DINT;
+
+	for (i = 0; i < 16; i++) {
+		if (dint & (1 << i)) {
+			struct dma_channel *channel = &dma_channels[i];
+			if (channel->name && channel->irq_handler) {
+				channel->irq_handler(i, channel->data, regs);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel:
+				 * let's clear the interrupts and disable it.
+				 */
+				printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
+				DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+			}
+		}
+	}
+}
+
+static int __init pxa_dma_init (void)
+{
+	int ret;
+
+	ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
+	if (ret)
+		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+	return ret;
+}
+
+__initcall(pxa_dma_init);
+
+EXPORT_SYMBOL(pxa_request_dma);
+EXPORT_SYMBOL(pxa_free_dma);
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/generic.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,142 @@
+/*
+ *  linux/arch/arm/mach-pxa/generic.c
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ * 
+ * Code common to all PXA machines.
+ *
+ * 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.
+ *
+ * Since this file should be linked before any other machine specific file,
+ * the __initcall() here will be executed first.  This serves as default
+ * initialization stuff for PXA machines which can be overriden later if
+ * need be.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/mach/map.h>
+
+#include "generic.h"
+
+/*
+ * Various clock factors driven by the CCCR register.
+ */
+
+/* Crystal Frequency to Memory Frequency Multiplier (L) */
+static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, };
+
+/* Memory Frequency to Run Mode Frequency Multiplier (M) */
+static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 };
+
+/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */
+/* Note: we store the value N * 2 here. */
+static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
+
+/* Crystal clock */
+#define BASE_CLK	3686400
+
+/*
+ * Get the clock frequency as reflected by CCCR and the turbo flag.
+ * We assume these values have been applied via a fcs.
+ * If info is not 0 we also display the current settings.
+ */
+unsigned int get_clk_frequency_khz( int info)
+{
+	unsigned long cccr, turbo;
+	unsigned int l, L, m, M, n2, N;
+
+	cccr = CCCR;
+	asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) );
+
+	l  =  L_clk_mult[(cccr >> 0) & 0x1f];
+	m  =  M_clk_mult[(cccr >> 5) & 0x03];
+	n2 = N2_clk_mult[(cccr >> 7) & 0x07];
+
+	L = l * BASE_CLK;
+	M = m * L;
+	N = n2 * M / 2;
+
+	if( info)
+	{
+		L += 5000;
+		printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n",
+			L / 1000000, (L % 1000000) / 10000, l );
+		M += 5000;
+		printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n",
+			M / 1000000, (M % 1000000) / 10000, m );
+		N += 5000;
+		printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n",
+			N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5,
+			(turbo & 1) ? "" : "in" );
+	}
+
+	return (turbo & 1) ? (N/1000) : (M/1000);
+}
+
+EXPORT_SYMBOL(get_clk_frequency_khz);
+
+/*
+ * Return the current lclk requency in units of 10kHz
+ */
+unsigned int get_lclk_frequency_10khz(void)
+{
+	return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
+}
+
+EXPORT_SYMBOL(get_lclk_frequency_10khz);
+
+/*
+ * Handy function to set GPIO alternate functions
+ */
+
+void set_GPIO_mode(int gpio_mode)
+{
+	long flags;
+	int gpio = gpio_mode & GPIO_MD_MASK_NR;
+	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+	int gafr;
+
+	local_irq_save(flags);
+	if (gpio_mode & GPIO_MD_MASK_DIR)
+		GPDR(gpio) |= GPIO_bit(gpio);
+	else
+		GPDR(gpio) &= ~GPIO_bit(gpio);
+	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(set_GPIO_mode);
+
+/* 
+ * Note that 0xfffe0000-0xffffffff is reserved for the vector table and
+ * cache flush area.
+ */
+static struct map_desc standard_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+  { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
+  { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
+  { 0xf8000000, 0x40000000, 0x01800000, DOMAIN_IO, 0, 1, 0, 0 }, /* Devs */
+  { 0xfa000000, 0x44000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
+  { 0xfc000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Mem Ctl */
+  { 0xff000000, 0x00000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* UNCACHED_PHYS_0 */
+  LAST_DESC
+};
+
+void __init pxa_map_io(void)
+{
+	iotable_init(standard_io_desc);
+	get_clk_frequency_khz( 1);
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/generic.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,19 @@
+/*
+ *  linux/arch/arm/mach-pxa/generic.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	MontaVista Software 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.
+ */
+
+extern void __init pxa_map_io(void);
+extern void __init pxa_init_irq(void);
+
+#define SET_BANK(__nr,__start,__size) \
+	mi->bank[__nr].start = (__start), \
+	mi->bank[__nr].size = (__size), \
+	mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/idp.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,142 @@
+/*
+ *  linux/arch/arm/mach-pxa/idp.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.
+ *
+ *  Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
+ * 
+ *  2001-09-13: Cliff Brake <cbrake@accelent.com>
+ *              Initial code
+ */
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>
+
+#include "generic.h"
+
+#define PXA_IDP_REV02
+
+#ifndef PXA_IDP_REV02
+/* shadow registers for write only registers */
+unsigned int idp_cpld_led_control_shadow = 0x1;
+unsigned int idp_cpld_periph_pwr_shadow = 0xd;
+unsigned int ipd_cpld_cir_shadow = 0;
+unsigned int idp_cpld_kb_col_high_shadow = 0;
+unsigned int idp_cpld_kb_col_low_shadow = 0;
+unsigned int idp_cpld_pccard_en_shadow = 0xC3;
+unsigned int idp_cpld_gpioh_dir_shadow = 0;
+unsigned int idp_cpld_gpioh_value_shadow = 0;
+unsigned int idp_cpld_gpiol_dir_shadow = 0;
+unsigned int idp_cpld_gpiol_value_shadow = 0;
+
+/*
+ * enable all LCD signals -- they should still be on
+ * write protect flash
+ * enable all serial port transceivers
+ */
+
+unsigned int idp_control_port_shadow = ((0x7 << 21) | 		/* LCD power */
+					(0x1 << 19) |		/* disable flash write enable */
+					(0x7 << 9));		/* enable serial port transeivers */
+
+#endif
+
+static int __init idp_init(void)
+{
+	printk("idp_init()\n");
+	return 0;
+}
+
+__initcall(idp_init);
+
+static void __init idp_init_irq(void)
+{
+	pxa_init_irq();
+}
+
+static void __init
+fixup_idp(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+#ifdef PXA_IDP_REV02
+	SET_BANK (0, 0xa0000000, 64*1024*1024);
+#else
+	SET_BANK (0, 0xa0000000, 32*1024*1024);
+#endif
+	mi->nr_banks      = 1;
+#if 0
+	setup_ramdisk (1, 0, 0, 8192);
+	setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+}
+
+static struct map_desc idp_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+
+
+#ifndef PXA_IDP_REV02
+  { IDP_CTRL_PORT_BASE,
+    IDP_CTRL_PORT_PHYS,
+    IDP_CTRL_PORT_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+#endif
+
+  { IDP_IDE_BASE,
+    IDP_IDE_PHYS,
+    IDP_IDE_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+  { IDP_ETH_BASE,
+    IDP_ETH_PHYS,
+    IDP_ETH_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+  { IDP_COREVOLT_BASE,
+    IDP_COREVOLT_PHYS,
+    IDP_COREVOLT_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+  { IDP_CPLD_BASE,
+    IDP_CPLD_PHYS,
+    IDP_CPLD_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+	
+  LAST_DESC
+};
+
+static void __init idp_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(idp_io_desc);
+
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO(SMC_IRQ), GPIO_RISING_EDGE);
+}
+
+MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
+	MAINTAINER("Accelent Systems Inc.")
+	BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
+	FIXUP(fixup_idp)
+	MAPIO(idp_map_io)
+	INITIRQ(idp_init_irq)
+MACHINE_END
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/innokom.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,129 @@
+/*
+ *  linux/arch/arm/mach-pxa/innokom.c
+ *
+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ *
+ * 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/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/hardware/sa1111.h>
+
+#include "generic.h"
+
+
+static void __init innokom_init_irq(void)
+{
+	pxa_init_irq();
+}
+
+
+void sw_update_handler( int irq, void* dev_id,struct pt_regs* regs)
+{
+}
+
+
+void reset_handler( int irq, void* dev_id,struct pt_regs* regs)
+{
+}
+
+
+static int __init innokom_init(void)
+{
+	int sw_irq = GPIO_2_80_TO_IRQ(11);	/* software update button */
+	int reset_irq = GPIO_2_80_TO_IRQ(3);	/* reset button           */
+
+	set_GPIO_IRQ_edge(11,GPIO_FALLING_EDGE);
+	if (request_irq(sw_irq,sw_update_handler,SA_INTERRUPT,"software update button",NULL))
+		printk(KERN_INFO "innokom: can't get assigned irq %i\n",sw_irq);
+
+	set_GPIO_IRQ_edge(3,GPIO_FALLING_EDGE);
+	if (request_irq(reset_irq,reset_handler,SA_INTERRUPT,"reset button",NULL))
+		printk(KERN_INFO "innokom: can't get assigned irq %i\n",reset_irq);
+
+	return 0;
+}
+
+
+__initcall(innokom_init);
+
+
+static void __init
+fixup_innokom(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+	/* we probably want to get this information from the bootloader later */
+	SET_BANK (0, 0xa0000000, 64*1024*1024); 
+	mi->nr_banks      = 1;
+}
+
+
+/* memory mapping */
+static struct map_desc innokom_io_desc[] __initdata = {
+/*  virtual           physical          length            domain     r  w  c  b                      */
+  { INNOKOM_ETH_BASE, INNOKOM_ETH_PHYS, INNOKOM_ETH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* ETH SMSC 91111 */
+  LAST_DESC
+};
+
+static void __init innokom_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(innokom_io_desc);
+
+	/* Enable the BTUART */
+	CKEN |= CKEN7_BTUART;
+	set_GPIO_mode(GPIO42_BTRXD_MD);
+	set_GPIO_mode(GPIO43_BTTXD_MD);
+	set_GPIO_mode(GPIO44_BTCTS_MD);
+	set_GPIO_mode(GPIO45_BTRTS_MD);
+
+	set_GPIO_mode(GPIO33_nCS_5_MD);	/* SMSC network chip */
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(INNOKOM, "Auerswald Innokom")
+	MAINTAINER("Robert Schwebel, Pengutronix")
+	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+	BOOT_PARAMS(0xa0000100)
+	FIXUP(fixup_innokom)
+	MAPIO(innokom_map_io)
+	INITIRQ(innokom_init_irq)
+MACHINE_END
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/irq.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,282 @@
+/*
+ *  linux/arch/arm/mach-pxa/irq.c
+ *  
+ *  Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software 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/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/irq.h>
+
+#include "generic.h"
+
+
+/*
+ * PXA GPIO edge detection for IRQs:
+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+ * This must be called *before* the appropriate IRQ is registered.
+ * Use this instead of directly setting GRER/GFER.
+ */
+
+static int GPIO_IRQ_rising_edge[3];
+static int GPIO_IRQ_falling_edge[3];
+
+void set_GPIO_IRQ_edge (int gpio_nr, int edge)
+{
+	long flags;
+	local_irq_save(flags);
+	set_GPIO_mode(gpio_nr | GPIO_IN);
+	if (edge & GPIO_FALLING_EDGE)
+		set_bit (gpio_nr, GPIO_IRQ_falling_edge);
+	else
+		clear_bit (gpio_nr, GPIO_IRQ_falling_edge);
+	if (edge & GPIO_RISING_EDGE)
+		set_bit (gpio_nr, GPIO_IRQ_rising_edge);
+	else
+		clear_bit (gpio_nr, GPIO_IRQ_rising_edge);
+	irq_desc[IRQ_GPIO(gpio_nr)].valid = 1;
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(set_GPIO_IRQ_edge);
+
+
+/*
+ * We don't need to ACK IRQs on the PXA unless they're GPIOs
+ * this is for IRQs known as PXA_IRQ([10...31]).
+ */
+
+static void pxa_mask_irq(unsigned int irq)
+{
+	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+}
+
+static void pxa_unmask_irq(unsigned int irq)
+{
+	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+}
+
+/*
+ * GPIO IRQs must be acknoledged.  This is for GPIO 0 and 1.
+ */
+
+static void pxa_mask_and_ack_GPIO_0_1_irq(unsigned int irq)
+{
+	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+	GEDR0 = (1 << (irq - IRQ_GPIO0));
+}
+
+static void pxa_mask_GPIO_0_1_irq(unsigned int irq)
+{
+	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+}
+
+static void pxa_unmask_GPIO_0_1_irq(unsigned int irq)
+{
+	int gpio = irq - IRQ_GPIO0;
+	GRER0 = (GRER0 & ~(1 << gpio))|(GPIO_IRQ_rising_edge[0] & (1 << gpio));
+	GFER0 = (GFER0 & ~(1 << gpio))|(GPIO_IRQ_falling_edge[0] & (1 << gpio));
+	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+}
+
+/*
+ * Demux handler for GPIO 2-80 edge detect interrupts
+ */
+
+static int GPIO_2_80_enabled[3];	/* enabled i.e. unmasked GPIO IRQs */
+static int GPIO_2_80_spurious[3];	/* GPIOs that triggered when masked */
+
+static void pxa_GPIO_2_80_demux(int irq, void *dev_id,
+				    struct pt_regs *regs)
+{
+	int i, gedr, spurious;
+
+	while ((gedr = (GEDR0 & ~3))) {
+		/*
+		 * We don't want to clear GRER/GFER when the corresponding
+		 * IRQ is masked because we could miss a level transition
+		 * i.e. an IRQ which need servicing as soon as it is
+		 * unmasked.  However, such situation should happen only
+		 * during the loop below.  Thus all IRQs which aren't
+		 * enabled at this point are considered spurious.  Those
+		 * are cleared but only de-activated if they happen twice.
+		 */
+		spurious = gedr & ~GPIO_2_80_enabled[0];
+		if (spurious) {
+			GEDR0 = spurious;
+			GRER0 &= ~(spurious & GPIO_2_80_spurious[0]);
+			GFER0 &= ~(spurious & GPIO_2_80_spurious[0]);
+			GPIO_2_80_spurious[0] |= spurious;
+			gedr ^= spurious;
+			if (!gedr) continue;
+		}
+
+		for (i = 2; i < 32; ++i) {
+			if (gedr & (1<<i)) {
+				do_IRQ (IRQ_GPIO(2) + i - 2, regs);
+			}
+		}
+	}
+	while ((gedr = GEDR1)) {
+		spurious = gedr & ~GPIO_2_80_enabled[1];
+		if (spurious) {
+			GEDR1 = spurious;
+			GRER1 &= ~(spurious & GPIO_2_80_spurious[1]);
+			GFER1 &= ~(spurious & GPIO_2_80_spurious[1]);
+			GPIO_2_80_spurious[1] |= spurious;
+			gedr ^= spurious;
+			if (!gedr) continue;
+		}
+
+		for (i = 0; i < 32; ++i) {
+			if (gedr & (1<<i)) {
+				do_IRQ (IRQ_GPIO(32) + i, regs);
+			}
+		}
+	}
+	while ((gedr = (GEDR2 & 0x0001ffff))) {
+		spurious = gedr & ~GPIO_2_80_enabled[2];
+		if (spurious) {
+			GEDR2 = spurious;
+			GRER2 &= ~(spurious & GPIO_2_80_spurious[2]);
+			GFER2 &= ~(spurious & GPIO_2_80_spurious[2]);
+			GPIO_2_80_spurious[2] |= spurious;
+			gedr ^= spurious;
+			if (!gedr) continue;
+		}
+
+		for (i = 0; i < 17; ++i) {
+			if (gedr & (1<<i)) {
+				do_IRQ (IRQ_GPIO(64) + i, regs);
+			}
+		}
+	}
+}
+
+static struct irqaction GPIO_2_80_irqaction = {
+	name:		"GPIO 2-80",
+	handler:	pxa_GPIO_2_80_demux,
+	flags:		SA_INTERRUPT
+};
+
+#define GRER_x(i)	(*(&GRER0 + (i)))
+#define GFER_x(i)	(*(&GFER0 + (i)))
+#define GEDR_x(i)	(*(&GEDR0 + (i)))
+#define GPLR_x(i)	(*(&GPLR0 + (i)))
+
+static void pxa_mask_and_ack_GPIO_2_80_irq(unsigned int irq)
+{
+	int gpio_nr = IRQ_TO_GPIO_2_80(irq);
+	int mask = 1 << (gpio_nr & 0x1f);
+	int index = gpio_nr >> 5;
+	GPIO_2_80_spurious[index] &= ~mask;
+	GPIO_2_80_enabled[index] &= ~mask;
+	GEDR_x(index) = mask;
+}
+
+static void pxa_mask_GPIO_2_80_irq(unsigned int irq)
+{
+	int gpio_nr = IRQ_TO_GPIO_2_80(irq);
+	int mask = 1 << (gpio_nr & 0x1f);
+	int index = gpio_nr >> 5;
+	GPIO_2_80_spurious[index] &= ~mask;
+	GPIO_2_80_enabled[index] &= ~mask;
+}
+
+static void pxa_unmask_GPIO_2_80_irq(unsigned int irq)
+{
+	int gpio_nr = IRQ_TO_GPIO_2_80(irq);
+	int mask = 1 << (gpio_nr & 0x1f);
+	int index = gpio_nr >> 5;
+	if (GPIO_2_80_spurious[index] & mask) {
+		/*
+		 * We don't want to miss an interrupt that would have occurred
+		 * while it was masked.  Simulate it if it is the case.
+		 */
+		int state = GPLR_x(index);
+		if (((state & GPIO_IRQ_rising_edge[index]) |
+		     (~state & GPIO_IRQ_falling_edge[index])) & mask)
+		{
+			/* just in case it gets referenced: */
+			struct pt_regs dummy;
+
+			memzero(&dummy, sizeof(dummy));
+			do_IRQ(irq, &dummy);
+
+			/* we are being called recursively from do_IRQ() */
+			return;
+		}
+	}
+	GPIO_2_80_enabled[index] |= mask;
+	GRER_x(index) =
+		(GRER_x(index) & ~mask) | (GPIO_IRQ_rising_edge[index] & mask);
+	GFER_x(index) =
+		(GFER_x(index) & ~mask) | (GPIO_IRQ_falling_edge[index] & mask);
+}
+
+
+void __init pxa_init_irq(void)
+{
+	int irq;
+
+	/* disable all IRQs */
+	ICMR = 0;
+
+	/* all IRQs are IRQ, not FIQ */
+	ICLR = 0;
+
+	/* clear all GPIO edge detects */
+	GFER0 = GFER1 = GFER2 = 0;
+	GRER0 = GRER1 = GRER2 = 0;
+	GEDR0 = GEDR0;
+	GEDR1 = GEDR1;
+	GEDR2 = GEDR2;
+
+	/* only unmasked interrupts kick us out of idle */
+	ICCR = 1;
+
+	for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 0;
+		irq_desc[irq].mask_ack	= pxa_mask_irq;
+		irq_desc[irq].mask	= pxa_mask_irq;
+		irq_desc[irq].unmask	= pxa_unmask_irq;
+	}
+
+	/*
+	 * Note: GPIO IRQs are initially invalid until set_GPIO_IRQ_edge()
+	 * is called at least once.
+	 */
+
+	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
+		irq_desc[irq].valid	= 0;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= pxa_mask_and_ack_GPIO_0_1_irq;
+		irq_desc[irq].mask	= pxa_mask_GPIO_0_1_irq;
+		irq_desc[irq].unmask	= pxa_unmask_GPIO_0_1_irq;
+	}
+
+	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
+		irq_desc[irq].valid	= 0;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= pxa_mask_and_ack_GPIO_2_80_irq;
+		irq_desc[irq].mask	= pxa_mask_GPIO_2_80_irq;
+		irq_desc[irq].unmask	= pxa_unmask_GPIO_2_80_irq;
+	}
+	setup_arm_irq( IRQ_GPIO_2_80, &GPIO_2_80_irqaction );
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/leds-cerf.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,135 @@
+/*
+ *  linux/arch/arm/mach-pxa/leds-cerf.c
+ *
+ *  Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
+ *
+ *  Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
+ *
+ *  Original (leds-footbridge.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.
+ */
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void pxa_cerf_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state = CERF_HEARTBEAT_LED;
+		led_state = LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = CERF_HEARTBEAT_LED;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = CERF_HEARTBEAT_LED;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= CERF_HEARTBEAT_LED;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= CERF_SYS_BUSY_LED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~CERF_SYS_BUSY_LED;
+		break;
+#endif
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~CERF_HEARTBEAT_LED;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= CERF_HEARTBEAT_LED;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+#ifndef CONFIG_PXA_CERF_PDA
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~CERF_SYS_BUSY_LED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= CERF_SYS_BUSY_LED;
+		break;
+#endif
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+	{
+		switch (hw_led_state) {
+		case 0: // all on
+			CERF_HEARTBEAT_LED_ON;
+			CERF_SYS_BUSY_LED_ON;
+			break;
+		case 1: // turn off heartbeat, status on:
+			CERF_HEARTBEAT_LED_OFF;
+			CERF_SYS_BUSY_LED_ON;
+			break;
+		case 2: // status off, heartbeat on:
+			CERF_HEARTBEAT_LED_ON;
+			CERF_SYS_BUSY_LED_OFF;
+			break;
+		case 3: // turn them both off...
+			CERF_HEARTBEAT_LED_OFF;
+			CERF_SYS_BUSY_LED_OFF;
+			break;
+		default:
+			break;
+		}
+	}
+	local_irq_restore(flags);
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/leds-idp.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * linux/arch/arm/mach-pxa/leds-idp.c
+ *
+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
+ *
+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
+ *
+ * Original (leds-footbridge.c) by Russell King
+ * 
+ * Macros for actual LED manipulation should be in machine specific
+ * files in this 'mach' directory.
+ */
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void idp_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
+		led_state = LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= IDP_HB_LED;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= IDP_BUSY_LED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~IDP_BUSY_LED;
+		break;
+#endif
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~IDP_HB_LED;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= IDP_HB_LED;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~IDP_BUSY_LED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= IDP_BUSY_LED;
+		break;
+
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+		IDP_WRITE_LEDS(hw_led_state);
+
+	local_irq_restore(flags);
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/leds-lubbock.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/arm/mach-pxa/leds-lubbock.c
+ *
+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
+ *
+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
+ *
+ * Original (leds-footbridge.c) by Russell King
+ *
+ * See leds.h for bit definitions.  The first version defines D28 on the
+ * Lubbock dev board as the heartbeat, and D27 as the Sys_busy led.
+ * There's plenty more if you're interested in adding them :)
+ */
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void lubbock_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
+		led_state = LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= HEARTBEAT_LED;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= SYS_BUSY_LED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~SYS_BUSY_LED;
+		break;
+#endif
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~HEARTBEAT_LED;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= HEARTBEAT_LED;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~SYS_BUSY_LED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= SYS_BUSY_LED;
+		break;
+
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+	{
+		switch (hw_led_state) {
+		case 0: // all on
+			HEARTBEAT_LED_ON;
+			SYS_BUSY_LED_ON;
+			break;
+		case 1: // turn off heartbeat, status on:
+			HEARTBEAT_LED_OFF;
+			SYS_BUSY_LED_ON;
+			break;
+		case 2: // status off, heartbeat on:
+			HEARTBEAT_LED_ON;
+			SYS_BUSY_LED_OFF;
+			break;
+		case 3: // turn them both off...
+			HEARTBEAT_LED_OFF;
+			SYS_BUSY_LED_OFF;
+			break;
+		default:
+			break;
+		}
+	}
+	local_irq_restore(flags);
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/leds.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,32 @@
+/*
+ * linux/arch/arm/mach-pxa/leds.c
+ *
+ * xscale LEDs dispatcher
+ * 
+ * Copyright (C) 2001 Nicolas Pitre
+ * 
+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include "leds.h"
+
+static int __init
+pxa_leds_init(void)
+{
+	if (machine_is_lubbock())
+		leds_event = lubbock_leds_event;
+	if (machine_is_pxa_idp())
+		leds_event = idp_leds_event;
+	if (machine_is_pxa_cerf())
+		leds_event = pxa_cerf_leds_event;
+
+	leds_event(led_start);
+	return 0;
+}
+
+__initcall(pxa_leds_init);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/leds.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,12 @@
+/*
+ * include/asm-arm/arch-pxa/leds.h
+ *
+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
+ *
+ * blinky lights for various PXA-based systems:
+ *
+ */
+
+extern void lubbock_leds_event(led_event_t evt);
+extern void idp_leds_event(led_event_t evt);
+extern void pxa_cerf_leds_event(led_event_t evt);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/lubbock.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,157 @@
+/*
+ *  linux/arch/arm/mach-pxa/lubbock.c
+ *
+ *  Support for the Intel DBPXA250 Development Platform.
+ *  
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software 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/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>
+#include <asm/hardware/sa1111.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_SA1111
+ #include "sa1111.h"
+#endif
+
+
+static unsigned long lubbock_irq_enabled;
+
+static void lubbock_mask_irq(unsigned int irq)
+{
+	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
+}
+
+static void lubbock_unmask_irq(unsigned int irq)
+{
+	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	/* the irq can be acknowledged only if deasserted, so it's done here */
+	LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
+	LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
+}
+
+void lubbock_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
+	do {
+		GEDR(0) = GPIO_bit(0);  /* clear useless edge notification */
+		if (likely(pending))
+			do_IRQ( LUBBOCK_IRQ(0) + __ffs(pending), regs );
+		pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
+	} while (pending);
+}
+
+static struct irqaction lubbock_irq = {
+	name:		"Lubbock FPGA",
+	handler:	lubbock_irq_demux,
+	flags:		SA_INTERRUPT
+};
+
+static void __init lubbock_init_irq(void)
+{
+	int irq;
+	
+	pxa_init_irq();
+
+	/* setup extra lubbock irqs */
+	for(irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= lubbock_mask_irq;
+		irq_desc[irq].mask	= lubbock_mask_irq;
+		irq_desc[irq].unmask	= lubbock_unmask_irq;
+	}
+
+	set_GPIO_IRQ_edge(GPIO_LUBBOCK_IRQ, GPIO_FALLING_EDGE);
+	setup_arm_irq(IRQ_GPIO_LUBBOCK_IRQ, &lubbock_irq);
+}
+
+static int __init lubbock_init(void)
+{
+	int ret;
+
+	ret = sa1111_probe(LUBBOCK_SA1111_BASE);
+	if (ret)
+		return ret;
+	sa1111_wake();
+	sa1111_init_irq(LUBBOCK_SA1111_IRQ);
+	return 0;
+}
+
+__initcall(lubbock_init);
+
+static void __init
+fixup_lubbock(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+	/* Some boards have 32MB some 64MB.  Let's use a safe default */
+	SET_BANK (0, 0xa0000000, 32*1024*1024);
+	mi->nr_banks      = 1;
+}
+
+static struct map_desc lubbock_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+  { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+  { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
+  { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
+  { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
+  LAST_DESC
+};
+
+static void __init lubbock_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(lubbock_io_desc);
+
+	/* This enables the BTUART */
+	CKEN |= CKEN7_BTUART;
+	set_GPIO_mode(GPIO42_BTRXD_MD);
+	set_GPIO_mode(GPIO43_BTTXD_MD);
+	set_GPIO_mode(GPIO44_BTCTS_MD);
+	set_GPIO_mode(GPIO45_BTRTS_MD);
+
+	/* This is for the SMC chip select */
+	set_GPIO_mode(GPIO79_nCS_3_MD);
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform")
+	MAINTAINER("MontaVista Software Inc.")
+	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+	FIXUP(fixup_lubbock)
+	MAPIO(lubbock_map_io)
+	INITIRQ(lubbock_init_irq)
+MACHINE_END
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/pm.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,265 @@
+/*
+ * PXA250/210 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.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/errno.h>
+
+#include <asm/hardware.h>
+#include <asm/memory.h>
+#include <asm/system.h>
+#include <asm/leds.h>
+
+
+/*
+ * Debug macros
+ */
+#undef DEBUG
+
+extern void pxa_cpu_suspend(void);
+extern void pxa_cpu_resume(void);
+
+#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
+#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
+
+/*
+ * List of global PXA peripheral registers to preserve.
+ * More ones like CP and general purpose register values are preserved
+ * with the stack pointer in sleep.S.
+ */
+enum {	SLEEP_SAVE_START = 0,
+
+	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
+	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
+
+	SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
+	SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
+	SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
+	SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L,
+	SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U,
+
+	SLEEP_SAVE_FFIER, SLEEP_SAVE_FFLCR, SLEEP_SAVE_FFMCR,
+	SLEEP_SAVE_FFSPR, SLEEP_SAVE_FFISR,
+	SLEEP_SAVE_FFDLL, SLEEP_SAVE_FFDLH,
+
+	SLEEP_SAVE_ICMR,
+	SLEEP_SAVE_CKEN,
+
+	SLEEP_SAVE_CKSUM,
+
+	SLEEP_SAVE_SIZE
+};
+
+
+int pm_do_suspend(void)
+{
+	unsigned long sleep_save[SLEEP_SAVE_SIZE];
+	unsigned long checksum = 0;
+	int i;
+
+	cli();
+	clf();
+
+	leds_event(led_stop);
+
+	/* preserve current time */
+	RCNR = xtime.tv_sec;
+
+	/* 
+	 * Temporary solution.  This won't be necessary once
+	 * we move pxa support into the serial/* driver
+	 * Save the FF UART 
+	 */
+	SAVE(FFIER);
+	SAVE(FFLCR);
+	SAVE(FFMCR);
+	SAVE(FFSPR);
+	SAVE(FFISR);
+	FFLCR |= 0x80;
+	SAVE(FFDLL);
+	SAVE(FFDLH);
+	FFLCR &= 0xef;
+
+	/* save vital registers */
+	SAVE(OSCR);
+	SAVE(OSMR0);
+	SAVE(OSMR1);
+	SAVE(OSMR2);
+	SAVE(OSMR3);
+	SAVE(OIER);
+
+	SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
+	SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
+	SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
+	SAVE(GAFR0_L); SAVE(GAFR0_U);
+	SAVE(GAFR1_L); SAVE(GAFR1_U);
+	SAVE(GAFR2_L); SAVE(GAFR2_U);
+
+	SAVE(ICMR);
+	ICMR = 0;
+
+	SAVE(CKEN);
+	CKEN = 0;
+
+	/* Note: wake up source are set up in each machine specific files */
+
+	/* clear GPIO transition detect  bits */
+	GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
+
+	/* Clear sleep reset status */
+	RCSR = RCSR_SMR;
+
+	/* set resume return address */
+	PSPR = virt_to_phys(pxa_cpu_resume);
+
+	/* before sleeping, calculate and save a checksum */
+	for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
+		checksum += sleep_save[i];
+	sleep_save[SLEEP_SAVE_CKSUM] = checksum;
+
+	/* *** go zzz *** */
+	pxa_cpu_suspend();
+
+	/* after sleeping, validate the checksum */
+	checksum = 0;
+	for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
+		checksum += sleep_save[i];
+
+	/* if invalid, display message and wait for a hardware reset */
+	if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) {
+#ifdef CONFIG_ARCH_LUBBOCK
+		LUB_HEXLED = 0xbadbadc5;
+#endif
+		while (1);
+	}
+
+	/* ensure not to come back here if it wasn't intended */
+	PSPR = 0;
+
+	/* restore registers */
+	RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
+	RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
+	RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
+	RESTORE(GAFR0_L); RESTORE(GAFR0_U);
+	RESTORE(GAFR1_L); RESTORE(GAFR1_U);
+	RESTORE(GAFR2_L); RESTORE(GAFR2_U);
+
+	PSSR = PSSR_PH;
+
+	RESTORE(OSMR0);
+	RESTORE(OSMR1);
+	RESTORE(OSMR2);
+	RESTORE(OSMR3);
+	RESTORE(OSCR);
+	RESTORE(OIER);
+
+	RESTORE(CKEN);
+
+	ICLR = 0;
+	ICCR = 1;
+	RESTORE(ICMR);
+
+	/* 
+	 * Temporary solution.  This won't be necessary once
+	 * we move pxa support into the serial/* driver.
+	 * Restore the FF UART.
+	 */
+	RESTORE(FFMCR);
+	RESTORE(FFSPR);
+	RESTORE(FFLCR);
+	FFLCR |= 0x80;
+	RESTORE(FFDLH);
+	RESTORE(FFDLL);
+	RESTORE(FFLCR);
+	RESTORE(FFISR);
+	FFFCR = 0x07;
+	RESTORE(FFIER);
+
+	/* restore current time */
+	xtime.tv_sec = RCNR;
+
+#ifdef DEBUG
+	printk(KERN_DEBUG "*** made it back from resume\n");
+#endif
+
+	leds_event(led_start);
+
+	sti();
+
+	return 0;
+}
+
+unsigned long sleep_phys_sp(void *sp)
+{
+	return virt_to_phys(sp);
+}
+
+#ifdef CONFIG_SYSCTL
+/*
+ * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
+ * linux/sysctl.h.
+ *
+ * This means our interface here won't survive long - it needs a new
+ * interface.  Quick hack to get this working - use sysctl id 9999.
+ */
+#warning ACPI broke the kernel, this interface needs to be fixed up.
+#define CTL_ACPI 9999
+#define ACPI_S1_SLP_TYP 19
+
+/*
+ * Send us to sleep.
+ */
+static int sysctl_pm_do_suspend(void)
+{
+	int retval;
+
+	retval = pm_send_all(PM_SUSPEND, (void *)3);
+
+	if (retval == 0) {
+		retval = pm_do_suspend();
+
+		pm_send_all(PM_RESUME, (void *)0);
+	}
+
+	return retval;
+}
+
+static struct ctl_table pm_table[] =
+{
+	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
+	{0}
+};
+
+static struct ctl_table pm_dir_table[] =
+{
+	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
+	{0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init pm_init(void)
+{
+	register_sysctl_table(pm_dir_table, 1);
+	return 0;
+}
+
+__initcall(pm_init);
+
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/pxa_usb.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,230 @@
+/*
+ * pxa_usb.h
+ *
+ * Public interface to the pxa USB core. For use by client modules
+ * like usb-eth and usb-char.
+ *
+ * 02-May-2002
+ *   Frank Becker (Intrinsyc) - derived from sa1100_usb.h
+ *
+ */
+
+#ifndef _PXA_USB_H
+#define _PXA_USB_H
+#include <asm/byteorder.h>
+
+typedef void (*usb_callback_t)(int flag, int size);
+
+/* in usb_ctl.c (see also descriptor methods at bottom of file) */
+
+// Open the USB client for client and initialize data structures
+// to default values, but _do not_ start UDC.
+int pxa_usb_open( const char * client_name );
+
+// Start UDC running
+int pxa_usb_start( void );
+
+// Immediately stop udc, fire off completion routines w/-EINTR
+int pxa_usb_stop( void ) ;
+
+// Disconnect client from usb core
+int pxa_usb_close( void ) ;
+
+// set notify callback for when core reaches configured state
+// return previous pointer (if any)
+typedef void (*usb_notify_t)(void);
+usb_notify_t pxa_set_configured_callback( usb_notify_t callback );
+
+/* in usb_send.c */
+int pxa_usb_xmitter_avail( void );
+int pxa_usb_send(char *buf, int len, usb_callback_t callback);
+void sa110a_usb_send_reset(void);
+
+/* in usb_recev.c */
+int pxa_usb_recv(char *buf, int len, usb_callback_t callback);
+void pxa_usb_recv_reset(void);
+
+//////////////////////////////////////////////////////////////////////////////
+// Descriptor Management
+//////////////////////////////////////////////////////////////////////////////
+
+#define DescriptorHeader \
+	__u8 bLength;        \
+	__u8 bDescriptorType
+
+
+// --- Device Descriptor -------------------
+
+typedef struct {
+	 DescriptorHeader;
+	 __u16 bcdUSB;		   	/* USB specification revision number in BCD */
+	 __u8  bDeviceClass;	/* USB class for entire device */
+	 __u8  bDeviceSubClass; /* USB subclass information for entire device */
+	 __u8  bDeviceProtocol; /* USB protocol information for entire device */
+	 __u8  bMaxPacketSize0; /* Max packet size for endpoint zero */
+	 __u16 idVendor;        /* USB vendor ID */
+	 __u16 idProduct;       /* USB product ID */
+	 __u16 bcdDevice;       /* vendor assigned device release number */
+	 __u8  iManufacturer;	/* index of manufacturer string */
+	 __u8  iProduct;        /* index of string that describes product */
+	 __u8  iSerialNumber;	/* index of string containing device serial number */
+	 __u8  bNumConfigurations; /* number fo configurations */
+} __attribute__ ((packed)) device_desc_t;
+
+// --- Configuration Descriptor ------------
+
+typedef struct {
+	 DescriptorHeader;
+	 __u16 wTotalLength;	    /* total # of bytes returned in the cfg buf 4 this cfg */
+	 __u8  bNumInterfaces;      /* number of interfaces in this cfg */
+	 __u8  bConfigurationValue; /* used to uniquely ID this cfg */
+	 __u8  iConfiguration;      /* index of string describing configuration */
+	 __u8  bmAttributes;        /* bitmap of attributes for ths cfg */
+	 __u8  MaxPower;		    /* power draw in 2ma units */
+} __attribute__ ((packed)) config_desc_t;
+
+// bmAttributes:
+enum { 
+	USB_CONFIG_REMOTEWAKE=0x20, 
+	USB_CONFIG_SELFPOWERED=0x40,
+	USB_CONFIG_BUSPOWERED=0x80 
+};
+
+// MaxPower:
+#define USB_POWER( x)  ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
+
+// --- Interface Descriptor ---------------
+
+typedef struct {
+	 DescriptorHeader;
+	 __u8  bInterfaceNumber;   /* Index uniquely identfying this interface */
+	 __u8  bAlternateSetting;  /* ids an alternate setting for this interface */
+	 __u8  bNumEndpoints;      /* number of endpoints in this interface */
+	 __u8  bInterfaceClass;    /* USB class info applying to this interface */
+	 __u8  bInterfaceSubClass; /* USB subclass info applying to this interface */
+	 __u8  bInterfaceProtocol; /* USB protocol info applying to this interface */
+	 __u8  iInterface;         /* index of string describing interface */
+} __attribute__ ((packed)) intf_desc_t;
+
+// --- Endpoint  Descriptor ---------------
+
+typedef struct {
+	 DescriptorHeader;
+	 __u8  bEndpointAddress;  /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
+	 __u8  bmAttributes;      /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
+	 __u16 wMaxPacketSize;    /* data payload size for this ep in this cfg */
+	 __u8  bInterval;         /* polling interval for this ep in this cfg */
+} __attribute__ ((packed)) ep_desc_t;
+
+// bEndpointAddress:
+enum { 
+	USB_OUT	=0, 
+	USB_IN	=1 
+};
+
+#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
+// bmAttributes:
+enum { 
+	USB_EP_CNTRL	=0, 
+	USB_EP_BULK	=2, 
+	USB_EP_INT	=3, 
+	USB_EP_ISO	=4 
+};
+
+// --- String Descriptor -------------------
+
+typedef struct {
+	 DescriptorHeader;
+	 __u16 bString[1];		  /* unicode string .. actaully 'n' __u16s */
+} __attribute__ ((packed)) string_desc_t;
+
+/*=======================================================
+ * Handy helpers when working with above
+ *
+ */
+// these are x86-style 16 bit "words" ...
+#define make_word_c( w ) __constant_cpu_to_le16(w)
+#define make_word( w )   __cpu_to_le16(w)
+
+// descriptor types
+enum { 
+    USB_DESC_DEVICE	= 1,
+    USB_DESC_CONFIG	= 2,
+    USB_DESC_STRING	= 3,
+    USB_DESC_INTERFACE	= 4,
+    USB_DESC_ENDPOINT	= 5
+};
+
+
+/*=======================================================
+ * Default descriptor layout for SA-1100 and SA-1110 UDC
+ */
+
+enum {
+  UNUSED = 0,
+
+  BULK_IN1  =  1,
+  BULK_OUT1 =  2,
+  ISO_IN1   =  3,
+  ISO_OUT1  =  4,
+  INT_IN1   =  5,
+
+  BULK_IN2  =  6,
+  BULK_OUT2 =  7,
+  ISO_IN2   =  8,
+  ISO_OUT2  =  9,
+  INT_IN2   = 10,
+
+  BULK_IN3  = 11,
+  BULK_OUT3 = 12,
+  ISO_IN3   = 13,
+  ISO_OUT3  = 14,
+  INT_IN3   = 15
+} /*endpoint_type*/;
+
+/* "config descriptor buffer" - that is, one config,
+   ..one interface and 2 endpoints */
+struct cdb {
+	 config_desc_t cfg;
+	 intf_desc_t   intf;
+	 ep_desc_t     ep1;
+	 ep_desc_t     ep2;
+} __attribute__ ((packed));
+
+/* all SA device descriptors */
+typedef struct {
+	 device_desc_t dev;   /* device descriptor */
+	 struct cdb b;        /* bundle of descriptors for this cfg */
+} __attribute__ ((packed)) desc_t;
+
+
+/*=======================================================
+ * Descriptor API
+ */
+
+/* Get the address of the statically allocated desc_t structure
+   in the usb core driver. Clients can modify this between
+   the time they call pxa_usb_open() and pxa_usb_start()
+*/
+desc_t *
+pxa_usb_get_descriptor_ptr( void );
+
+
+/* Set a pointer to the string descriptor at "index". The driver
+ ..has room for 8 string indicies internally. Index zero holds
+ ..a LANGID code and is set to US English by default. Inidices
+ ..1-7 are available for use in the config descriptors as client's
+ ..see fit. This pointer is assumed to be good as long as the
+ ..SA usb core is open (so statically allocate them). Returnes -EINVAL
+ ..if index out of range */
+int pxa_usb_set_string_descriptor( int index, string_desc_t * p );
+
+/* reverse of above */
+string_desc_t *
+pxa_usb_get_string_descriptor( int index );
+
+/* kmalloc() a string descriptor and convert "p" to unicode in it */
+string_desc_t *
+pxa_usb_kmalloc_string_descriptor( const char * p );
+
+#endif /* _PXA_USB_H */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/sa1111.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,3 @@
+#include "../mach-sa1100/sa1111.c"
+
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/sa1111.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,2 @@
+#include "../mach-sa1100/sa1111.h"
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/sleep.S	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,150 @@
+/*
+ * Low-level PXA250/210 sleep/wakeUp support
+ *
+ * Initial SA1110 code:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Adapted for PXA by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+		.text
+
+/*
+ * pxa_cpu_suspend()
+ *
+ * Forces CPU into sleep state
+ */
+
+ENTRY(pxa_cpu_suspend)
+
+	mra	r2, r3, acc0
+	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
+
+	@ get coprocessor registers
+	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
+	mrc	p15, 0, r5, c13, c0, 0		@ PID
+	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
+	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
+	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
+
+	@ store them plus current virtual stack ptr on stack
+	mov	r10, sp
+	stmfd	sp!, {r4 - r10}
+
+	@ preserve phys address of stack
+	mov	r0, sp
+	bl	sleep_phys_sp
+	ldr	r1, =sleep_save_sp
+	str	r0, [r1]
+
+	@ clean data cache 
+	bl	cpu_xscale_cache_clean_invalidate_all
+
+	@ Put the processor to sleep
+	@ (also workaround for sighting 28071)
+
+	@ prepare value for sleep mode
+	mov	r1, #3				@ sleep mode
+
+	@ prepare to put SDRAM into self-refresh manually
+	ldr	r4, =MDREFR
+	ldr	r5, [r4]
+	orr	r5, r5, #MDREFR_SLFRSH
+
+	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
+	mov	r2, #UNCACHED_PHYS_0
+
+	@ align execution to a cache line
+	b	1f
+
+	.ltorg
+	.align	5
+1:
+
+	@ All needed values are now in registers. 
+	@ These last instructions should be in cache
+
+	@ put SDRAM into self-refresh	
+	str	r5, [r4]
+
+	@ force address lines low by reading at physical address 0
+	ldr	r3, [r2]
+
+	@ enter sleep mode
+	mcr	p14, 0, r1, c7, c0, 0
+
+20:	nop
+	b	20b				@ loop waiting for sleep
+
+/*
+ * cpu_pxa_resume()
+ *
+ * entry point from bootloader into kernel during resume
+ *
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truely read-only.
+ */
+
+	.data
+	.align 5
+ENTRY(pxa_cpu_resume)
+	mov	r0, #I_BIT | F_BIT | MODE_SVC	@ set SVC, irqs off
+	msr	cpsr_c, r0
+
+	ldr	r0, sleep_save_sp		@ stack phys addr
+	ldr	r2, =resume_after_mmu		@ its absolute virtual address
+	ldmfd	r0, {r4 - r9, sp}		@ CP regs + virt stack ptr
+
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
+
+#ifdef CONFIG_XSCALE_CACHE_ERRATA
+	bic     r9, r9, #0x0004			@ see cpu_xscale_proc_init
+#endif
+
+	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
+	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
+	b	resume_turn_on_mmu		@ cache align execution
+
+	.align 5
+resume_turn_on_mmu:
+	mcr 	p15, 0, r9, c1, c0, 0		@ turn on MMU, caches, etc.
+
+	@ Let us ensure we jump to resume_after_mmu only when the mcr above
+	@ actually took effect.  They call it the "cpwait" operation.
+	mrc	p15, 0, r1, c2, c0, 0		@ queue a dependency on CP15
+	sub	pc, r2, r1, lsr #32		@ jump to virtual addr 
+	nop
+	nop
+	nop
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
+
+	.text
+resume_after_mmu:
+#ifdef CONFIG_XSCALE_CACHE_ERRATA
+	bl	cpu_xscale_proc_init
+#endif
+	ldmfd	sp!, {r2, r3}
+	mar	acc0, r2, r3
+	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
+
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/trizeps2.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,105 @@
+/*
+ *  linux/arch/arm/mach-pxa/trizeps2.c
+ *
+ *  Support for the Keith&Koep MT6N Development Platform.
+ *  
+ *  Author:	Luc De Cock
+ *  Created:	Jan 13, 2003
+ *  Copyright:	Teradyne DS, Ltd.
+ *  
+ *  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/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>
+
+#include "generic.h"
+
+static unsigned long trizeps2_irq_en_mask;
+unsigned short trizeps2_bcr_shadow = 0x50; // 0x70
+
+
+static void __init trizeps2_init_irq(void)
+{
+	int irq;
+	
+	pxa_init_irq();
+
+	set_GPIO_IRQ_edge(GPIO_ETHERNET_IRQ, GPIO_RISING_EDGE);
+}
+
+static int __init trizeps2_init(void)
+{
+	/* Configure the BCR register */
+	unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
+
+	*bcr = trizeps2_bcr_shadow;
+	return 0;
+}
+
+__initcall(trizeps2_init);
+
+static void __init
+fixup_trizeps2(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+#ifdef TRIZEPS2_MEM_64MB
+	SET_BANK (0, 0xa0000000, 64*1024*1024);
+#else
+	SET_BANK (0, 0xa0000000, 32*1024*1024);
+#endif
+	mi->nr_banks      = 1;
+}
+
+static struct map_desc trizeps2_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+  { 0xf0000000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* BCR */
+  { 0xf0100000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA STATUS */
+  { 0xf1000000, 0x0c800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
+  { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
+  { 0xf2000000, 0x0d800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* TTL-IO */
+  LAST_DESC
+};
+
+static void __init trizeps2_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(trizeps2_io_desc);
+
+	/* This is for the SMC chip select */
+	set_GPIO_mode(GPIO79_nCS_3_MD);
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(TRIZEPS2, "Keith-n-Koep MT6N Development Platform")
+	MAINTAINER("Luc De Cock")
+	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+	FIXUP(fixup_trizeps2)
+	MAPIO(trizeps2_map_io)
+	INITIRQ(trizeps2_init_irq)
+MACHINE_END
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb-char.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,719 @@
+/*
+ * (C) Copyright 2000-2001 Extenex Corporation
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  usb-char.c
+ *
+ *  Miscellaneous character device interface for SA1100 USB function
+ *	driver.
+ *
+ *  Background:
+ *  The SA1100 function driver ported from the Compaq Itsy project
+ *  has an interface, usb-eth.c, to feed network packets over the
+ *  usb wire and into the Linux TCP/IP stack.
+ *
+ *  This file replaces that one with a simple character device
+ *  interface that allows unstructured "byte pipe" style reads and
+ *  writes over the USB bulk endpoints by userspace programs.
+ *
+ *  A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
+ *  when set, (the default) causes the ethernet interface to be used.
+ *  When not set, this more pedestrian character interface is linked
+ *  in instead.
+ *
+ *  Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
+ *
+ *  ward.willats@extenex.com
+ *
+ *  To do:
+ *  - Can't dma into ring buffer directly with pci_map/unmap usb_recv
+ *    uses and get bytes out at the same time DMA is going on. Investigate:
+ *    a) changing usb_recv to use alloc_consistent() at client request; or
+ *    b) non-ring-buffer based data structures. In the meantime, I am using
+ *    a bounce buffer. Simple, but wasteful.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/poll.h>
+#include <linux/circ_buf.h>
+#include <linux/timer.h>
+
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/proc/page.h>
+#include <asm/mach-types.h>
+
+#include "usb-char.h"
+#include "pxa_usb.h"
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Driver  Options
+//////////////////////////////////////////////////////////////////////////////
+
+#define VERSION 	"0.4"
+
+
+#define VERBOSITY 1
+
+#if VERBOSITY
+# define	PRINTK(x, a...)	printk (x, ## a)
+#else
+# define	PRINTK(x, a...)	/**/
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Globals - Macros - Enums - Structures
+//////////////////////////////////////////////////////////////////////////////
+#ifndef MIN
+#define MIN( a, b ) ((a)<(b)?(a):(b))
+#endif
+
+typedef int bool; enum { false = 0, true = 1 };
+
+static const char pszMe[] = "usbchr: ";
+
+static wait_queue_head_t wq_read;
+static wait_queue_head_t wq_write;
+static wait_queue_head_t wq_poll;
+
+/* Serialze multiple writers onto the transmit hardware
+.. since we sleep the writer during transmit to stay in
+.. sync. (Multiple writers don't make much sense, but..) */
+static DECLARE_MUTEX( xmit_sem );
+
+// size of usb DATA0/1 packets. 64 is standard maximum
+// for bulk transport, though most hosts seem to be able
+// to handle larger.
+#define TX_PACKET_SIZE 64
+#define RX_PACKET_SIZE 64
+#define RBUF_SIZE  (4*PAGE_SIZE)
+
+static struct wcirc_buf {
+  char *buf;
+  int in;
+  int out;
+} rx_ring = { NULL, 0, 0 };
+
+static struct {
+	 unsigned long  cnt_rx_complete;
+	 unsigned long  cnt_rx_errors;
+	 unsigned long  bytes_rx;
+	 unsigned long  cnt_tx_timeouts;
+	 unsigned long  cnt_tx_errors;
+	 unsigned long  bytes_tx;
+} charstats;
+
+
+static char * tx_buf = NULL;
+static char * packet_buffer = NULL;
+static int sending = 0;
+static int usb_ref_count = 0;
+static int last_tx_result = 0;
+static int last_rx_result = 0;
+static int last_tx_size = 0;
+static struct timer_list tx_timer;
+
+//////////////////////////////////////////////////////////////////////////////
+// Prototypes
+//////////////////////////////////////////////////////////////////////////////
+static char * 	what_the_f( int e );
+static void 	free_txrx_buffers( void );
+static void     twiddle_descriptors( void );
+static void     free_string_descriptors( void ) ;
+static int      usbc_open( struct inode *pInode, struct file *pFile );
+static void     rx_done_callback_packet_buffer( int flag, int size );
+
+static void     tx_timeout( unsigned long );
+static void     tx_done_callback( int flag, int size );
+
+static ssize_t  usbc_read( struct file *, char *, size_t, loff_t * );
+static ssize_t  usbc_write( struct file *, const char *, size_t, loff_t * );
+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
+                       unsigned int nCmd, unsigned long argument );
+static int      usbc_close( struct inode *pInode, struct file *pFile );
+
+#ifdef CONFIG_SA1100_EXTENEX1
+static void     extenex_configured_notify_proc( void );
+#endif
+//////////////////////////////////////////////////////////////////////////////
+// Private Helpers
+//////////////////////////////////////////////////////////////////////////////
+
+static char * what_the_f( int e )
+{
+	 char * p;
+	 switch( e ) {
+	 case 0:
+		  p = "noErr";
+		  break;
+	 case -ENODEV:
+		  p = "ENODEV - usb not in config state";
+		  break;
+	 case -EBUSY:
+		  p = "EBUSY - another request on the hardware";
+		  break;
+	 case -EAGAIN:
+		  p = "EAGAIN";
+		  break;
+	 case -EINTR:
+		  p = "EINTR - interrupted\n";
+		  break;
+	 case -EPIPE:
+		  p = "EPIPE - zero length xfer\n";
+		  break;
+	 default:
+		  p = "????";
+		  break;
+	 }
+	 return p;
+}
+
+static void free_txrx_buffers( void )
+{
+	 if ( rx_ring.buf != NULL ) {
+		  kfree( rx_ring.buf );
+		  rx_ring.buf = NULL;
+	 }
+	 if ( packet_buffer != NULL ) {
+		  kfree( packet_buffer );
+		  packet_buffer = NULL;
+	 }
+	 if ( tx_buf != NULL ) {
+		  kfree( tx_buf );
+		  tx_buf = NULL;
+	 }
+}
+
+/* twiddle_descriptors()
+ * It is between open() and start(). Setup descriptors.
+ */
+static void twiddle_descriptors( void )
+{
+	 desc_t * pDesc = pxa_usb_get_descriptor_ptr();
+	 string_desc_t * pString;
+
+	 pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
+	 pDesc->b.ep1.bmAttributes   = USB_EP_BULK;
+	 pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
+	 pDesc->b.ep2.bmAttributes   = USB_EP_BULK;
+
+         if ( machine_is_extenex1() ) {
+#ifdef CONFIG_SA1100_EXTENEX1
+		  pDesc->dev.idVendor = make_word_c( 0xC9F );
+		  pDesc->dev.idProduct = 1;
+		  pDesc->dev.bcdDevice = make_word_c( 0x0001 );
+		  pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
+		  pDesc->b.cfg.MaxPower = 0;
+
+		  pString = pxa_usb_kmalloc_string_descriptor( "Extenex" );
+		  if ( pString ) {
+			   pxa_usb_set_string_descriptor( 1, pString );
+			   pDesc->dev.iManufacturer = 1;
+		  }
+
+		  pString = pxa_usb_kmalloc_string_descriptor( "Handheld Theater" );
+		  if ( pString ) {
+			   pxa_usb_set_string_descriptor( 2, pString );
+			   pDesc->dev.iProduct = 2;
+		  }
+
+		  pString = pxa_usb_kmalloc_string_descriptor( "00000000" );
+		  if ( pString ) {
+			   pxa_usb_set_string_descriptor( 3, pString );
+			   pDesc->dev.iSerialNumber = 3;
+		  }
+
+		  pString = pxa_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
+		  if ( pString ) {
+			   pxa_usb_set_string_descriptor( 4, pString );
+			   pDesc->b.intf.iInterface = 4;
+		  }
+		  pxa_set_configured_callback( extenex_configured_notify_proc );
+#endif
+	 }
+}
+
+static void free_string_descriptors( void )
+{
+	 if ( machine_is_extenex1() ) {
+		  string_desc_t * pString;
+		  int i;
+		  for( i = 1 ; i <= 4 ; i++ ) {
+			   pString = pxa_usb_get_string_descriptor( i );
+			   if ( pString )
+					kfree( pString );
+		  }
+	 }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ASYNCHRONOUS
+//////////////////////////////////////////////////////////////////////////////
+static  void kick_start_rx( void )
+{
+	 if ( usb_ref_count ) {
+		  int total_space  = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
+		  if ( total_space >= RX_PACKET_SIZE ) {
+			   pxa_usb_recv( packet_buffer,
+								RX_PACKET_SIZE,
+								rx_done_callback_packet_buffer
+						      );
+		  }
+	 }
+}
+/*
+ * rx_done_callback_packet_buffer()
+ * We have completed a DMA xfer into the temp packet buffer.
+ * Move to ring.
+ *
+ * flag values:
+ * on init,  -EAGAIN
+ * on reset, -EINTR
+ * on RPE, -EIO
+ * on short packet -EPIPE
+ */
+static void
+rx_done_callback_packet_buffer( int flag, int size )
+{
+	 charstats.cnt_rx_complete++;
+
+	 if ( flag == 0 || flag == -EPIPE ) {
+		  size_t n;
+
+		  charstats.bytes_rx += size;
+
+		  n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
+		  n = MIN( n, size );
+		  size -= n;
+
+		  memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
+		  rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
+		  memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
+		  rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
+
+		  wake_up_interruptible( &wq_read );
+		  wake_up_interruptible( &wq_poll );
+
+		  last_rx_result = 0;
+
+		  kick_start_rx();
+
+	 } else if ( flag != -EAGAIN ) {
+		  charstats.cnt_rx_errors++;
+		  last_rx_result = flag;
+		  wake_up_interruptible( &wq_read );
+		  wake_up_interruptible( &wq_poll );
+	 }
+	 else  /* init, start a read */
+		  kick_start_rx();
+}
+
+
+static void tx_timeout( unsigned long unused )
+{
+	printk( "%stx timeout\n", pszMe );
+	pxa_usb_send_reset();
+	charstats.cnt_tx_timeouts++;
+}
+
+
+// on init, -EAGAIN
+// on reset, -EINTR
+// on TPE, -EIO
+static void tx_done_callback( int flags, int size )
+{
+	 if ( flags == 0 )
+		  charstats.bytes_tx += size;
+	 else
+		  charstats.cnt_tx_errors++;
+	 last_tx_size = size;
+	 last_tx_result = flags;
+	 sending = 0;
+	 wake_up_interruptible( &wq_write );
+	 wake_up_interruptible( &wq_poll );
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Workers
+//////////////////////////////////////////////////////////////////////////////
+
+static int usbc_open( struct inode *pInode, struct file *pFile )
+{
+	 int retval = 0;
+
+	 PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
+
+	 /* start usb core */
+	 retval = pxa_usb_open( "usb-char" );
+	 if ( retval ) return retval;
+
+	 /* allocate memory */
+	 if ( usb_ref_count == 0 ) {
+		  tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
+		  if ( tx_buf == NULL ) {
+			   printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
+			   goto malloc_fail;
+		  }
+		  rx_ring.buf =
+			(char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
+
+		  if ( rx_ring.buf == NULL ) {
+			   printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
+			   goto malloc_fail;
+		  }
+
+		  packet_buffer =
+			(char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA  );
+
+		  if ( packet_buffer == NULL ) {
+			   printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
+			   goto malloc_fail;
+		  }
+		  rx_ring.in = rx_ring.out = 0;
+		  memset( &charstats, 0, sizeof( charstats ) );
+		  sending = 0;
+		  last_tx_result = 0;
+		  last_tx_size = 0;
+	 }
+
+	 /* modify default descriptors */
+	 twiddle_descriptors();
+
+	 retval = pxa_usb_start();
+	 if ( retval ) {
+		  printk( "%sAGHH! Could not USB core\n", pszMe );
+		  free_txrx_buffers();
+		  return retval;
+	 }
+	 usb_ref_count++;   /* must do _before_ kick_start() */
+	 MOD_INC_USE_COUNT;
+	 kick_start_rx();
+	 return 0;
+
+ malloc_fail:
+	 free_txrx_buffers();
+	 return -ENOMEM;
+}
+
+/*
+ * Read endpoint. Note that you can issue a read to an
+ * unconfigured endpoint. Eventually, the host may come along
+ * and configure underneath this module and data will appear.
+ */
+static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
+                        size_t stCount, loff_t *pPos )
+{
+	 ssize_t retval;
+	 int flags;
+	 DECLARE_WAITQUEUE( wait, current );
+
+	 PRINTK( KERN_DEBUG "%sread()\n", pszMe );
+
+	 local_irq_save( flags );
+	 if ( last_rx_result == 0 ) {
+		  local_irq_restore( flags );
+	 } else {  /* an error happended and receiver is paused */
+		  local_irq_restore( flags );
+		  last_rx_result = 0;
+		  kick_start_rx();
+	 }
+
+	 add_wait_queue( &wq_read, &wait );
+	 while( 1 ) {
+		  ssize_t bytes_avail;
+		  ssize_t bytes_to_end;
+
+		  set_current_state( TASK_INTERRUPTIBLE );
+
+		  /* snap ring buf state */
+		  local_irq_save( flags );
+		  bytes_avail  = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
+		  bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
+		  local_irq_restore( flags );
+
+		  if ( bytes_avail != 0 ) {
+			   ssize_t bytes_to_move = MIN( stCount, bytes_avail );
+			   retval = 0;		// will be bytes transfered
+			   if ( bytes_to_move != 0 ) {
+					size_t n = MIN( bytes_to_end, bytes_to_move );
+					if ( copy_to_user( pUserBuffer,
+									   &rx_ring.buf[ rx_ring.out ],
+									   n ) ) {
+						 retval = -EFAULT;
+						 break;
+					}
+					bytes_to_move -= n;
+ 					retval += n;
+					// might go 1 char off end, so wrap
+					rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
+					if ( copy_to_user( pUserBuffer + n,
+									   &rx_ring.buf[ rx_ring.out ],
+									   bytes_to_move )
+						 ) {
+						 retval = -EFAULT;
+						 break;
+					}
+					rx_ring.out += bytes_to_move;		// cannot wrap
+					retval += bytes_to_move;
+					kick_start_rx();
+			   }
+			   break;
+		  }
+		  else if ( last_rx_result ) {
+			   retval = last_rx_result;
+			   break;
+		  }
+		  else if ( pFile->f_flags & O_NONBLOCK ) {  // no data, can't sleep
+			   retval = -EAGAIN;
+			   break;
+		  }
+		  else if ( signal_pending( current ) ) {   // no data, can sleep, but signal
+			   retval = -ERESTARTSYS;
+			   break;
+		  }
+		  schedule();					   			// no data, can sleep
+	 }
+	 set_current_state( TASK_RUNNING );
+	 remove_wait_queue( &wq_read, &wait );
+
+	 if ( retval < 0 )
+		  printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
+	 return retval;
+}
+
+/*
+ * Write endpoint. This routine attempts to break the passed in buffer
+ * into usb DATA0/1 packet size chunks and send them to the host.
+ * (The lower-level driver tries to do this too, but easier for us
+ * to manage things here.)
+ *
+ * We are at the mercy of the host here, in that it must send an IN
+ * token to us to pull this data back, so hopefully some higher level
+ * protocol is expecting traffic to flow in that direction so the host
+ * is actually polling us. To guard against hangs, a 5 second timeout
+ * is used.
+ *
+ * This routine takes some care to only report bytes sent that have
+ * actually made it across the wire. Thus we try to stay in lockstep
+ * with the completion routine and only have one packet on the xmit
+ * hardware at a time. Multiple simultaneous writers will get
+ * "undefined" results.
+ *
+  */
+static ssize_t  usbc_write( struct file *pFile, const char * pUserBuffer,
+							 size_t stCount, loff_t *pPos )
+{
+	 ssize_t retval = 0;
+	 ssize_t stSent = 0;
+
+	 DECLARE_WAITQUEUE( wait, current );
+
+	 PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
+
+	 down( &xmit_sem );  // only one thread onto the hardware at a time
+
+	 while( stCount != 0 && retval == 0 ) {
+		  int nThisTime  = MIN( TX_PACKET_SIZE, stCount );
+		  copy_from_user( tx_buf, pUserBuffer, nThisTime );
+		  sending = nThisTime;
+ 		  retval = pxa_usb_send( tx_buf, nThisTime, tx_done_callback );
+		  if ( retval < 0 ) {
+			   char * p = what_the_f( retval );
+			   printk( "%sCould not queue xmission. rc=%d - %s\n",
+					   pszMe, retval, p );
+			   sending = 0;
+			   break;
+		  }
+		  /* now have something on the diving board */
+		  add_wait_queue( &wq_write, &wait );
+		  tx_timer.expires = jiffies + ( HZ * 5 );
+		  add_timer( &tx_timer );
+		  while( 1 ) {
+			   set_current_state( TASK_INTERRUPTIBLE );
+			   if ( sending == 0 ) {  /* it jumped into the pool */
+					del_timer( &tx_timer );
+					retval = last_tx_result;
+					if ( retval == 0 ) {
+						 stSent		 += last_tx_size;
+						 pUserBuffer += last_tx_size;
+						 stCount     -= last_tx_size;
+					}
+					else
+						 printk( "%sxmission error rc=%d - %s\n",
+								 pszMe, retval, what_the_f(retval) );
+					break;
+			   }
+			   else if ( signal_pending( current ) ) {
+					del_timer( &tx_timer );
+					printk( "%ssignal\n", pszMe  );
+					retval = -ERESTARTSYS;
+					break;
+			   }
+			   schedule();
+		  }
+		  set_current_state( TASK_RUNNING );
+		  remove_wait_queue( &wq_write, &wait );
+	 }
+
+	 up( &xmit_sem );
+
+	 if ( 0 == retval )
+		  retval = stSent;
+	 return retval;
+}
+
+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
+{
+	 unsigned int retval = 0;
+
+	 PRINTK( KERN_DEBUG "%poll()\n", pszMe );
+
+	 poll_wait( pFile, &wq_poll, pWait );
+
+	 if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
+		  retval |= POLLIN | POLLRDNORM;
+	 if ( pxa_usb_xmitter_avail() )
+		  retval |= POLLOUT | POLLWRNORM;
+	 return retval;
+}
+
+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
+                       unsigned int nCmd, unsigned long argument )
+{
+	 int retval = 0;
+
+	 switch( nCmd ) {
+
+	 case USBC_IOC_FLUSH_RECEIVER:
+		  pxa_usb_recv_reset();
+		  rx_ring.in = rx_ring.out = 0;
+		  break;
+
+	 case USBC_IOC_FLUSH_TRANSMITTER:
+		  pxa_usb_send_reset();
+		  break;
+
+	 case USBC_IOC_FLUSH_ALL:
+		  pxa_usb_recv_reset();
+		  rx_ring.in = rx_ring.out = 0;
+		  pxa_usb_send_reset();
+		  break;
+
+	 default:
+		  retval = -ENOIOCTLCMD;
+		  break;
+
+	 }
+	 return retval;
+}
+
+
+static int usbc_close( struct inode *pInode, struct file * pFile )
+{
+	PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
+	if ( --usb_ref_count == 0 ) {
+		 down( &xmit_sem );
+		 pxa_usb_stop();
+		 free_txrx_buffers();
+		 free_string_descriptors();
+		 del_timer( &tx_timer );
+		 pxa_usb_close();
+		 up( &xmit_sem );
+	}
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+#ifdef CONFIG_SA1100_EXTENEX1
+#include "../../../drivers/char/ex_gpio.h"
+void extenex_configured_notify_proc( void )
+{
+	 if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
+		  printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////
+// Initialization
+//////////////////////////////////////////////////////////////////////////////
+
+static struct file_operations usbc_fops = {
+		owner:      THIS_MODULE,
+		open:		usbc_open,
+		read:		usbc_read,
+		write:		usbc_write,
+		poll:		usbc_poll,
+		ioctl:		usbc_ioctl,
+		release:	usbc_close,
+};
+
+static struct miscdevice usbc_misc_device = {
+    USBC_MINOR, "usb_char", &usbc_fops
+};
+
+/*
+ * usbc_init()
+ */
+
+int __init usbc_init( void )
+{
+	 int rc;
+
+	 if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
+		  printk( KERN_WARNING "%sCould not register device 10, "
+				  "%d. (%d)\n", pszMe, USBC_MINOR, rc );
+		  return -EBUSY;
+	 }
+
+	 // initialize wait queues
+	 init_waitqueue_head( &wq_read );
+	 init_waitqueue_head( &wq_write );
+	 init_waitqueue_head( &wq_poll );
+
+	 // initialize tx timeout timer
+	 init_timer( &tx_timer );
+	 tx_timer.function = tx_timeout;
+
+	  printk( KERN_INFO "USB Function Character Driver Interface"
+				  " - %s, (C) 2001, Extenex Corp.\n", VERSION
+		   );
+
+	 return rc;
+}
+
+void __exit usbc_exit( void )
+{
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init(usbc_init);
+module_exit(usbc_exit);
+
+
+
+// end: usb-char.c
+
+
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb-char.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2001 Extenex Corporation
+ *
+ * usb-char.h
+ *
+ * Character device emulation client for SA-1100 client usb core.
+ *
+ *
+ *
+ */
+#ifndef _USB_CHAR_H
+#define _USB_CHAR_H
+
+#define USBC_MAJOR 10      /* miscellaneous character device */
+#define USBC_MINOR 240     /* in the "reserved for local use" range */
+
+#define USBC_MAGIC 0x8E
+
+/* zap everything in receive ring buffer */
+#define USBC_IOC_FLUSH_RECEIVER    _IO( USBC_MAGIC, 0x01 )
+
+/* reset transmitter */
+#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
+
+/* do both of above */
+#define USBC_IOC_FLUSH_ALL         _IO( USBC_MAGIC, 0x03 )
+
+
+
+
+
+
+#endif /* _USB_CHAR_H */
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb-eth.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,479 @@
+/*
+ * Ethernet driver for the PXA USB client function
+ * Copyright (c) 2001 by Nicolas Pitre
+ *
+ * This code was loosely inspired by the original initial ethernet test driver
+ * Copyright (c) Compaq Computer Corporation, 1999
+ *
+ * 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 still work in progress...
+ *
+ * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
+ * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
+ *		Now, since we do not know what size of packet we are receiving
+ *		last usb packet in sequence will always be less than max packet
+ *		receive endpoint can accept.
+ *		Now the only way to check correct start of frame is to compare
+ *		MAC address. Also now we are stalling on each receive error.
+ *
+ * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
+ *		aligned buffer, but this breaks IP code (unaligned access).
+ *
+ * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
+ *              they are disabled now.
+ *
+ * 03/06/2001 - Readded "zerocopy" receive path (tunable).
+ *
+ */
+
+// Define DMA_NO_COPY if you want data to arrive directly into the
+// receive network buffers, instead of arriving into bounce buffer
+// and then get copied to network buffer.
+// This does not work correctly right now.
+#undef DMA_NO_COPY
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+
+#include "pxa_usb.h"
+
+
+#define ETHERNET_VENDOR_ID 0x49f
+#define ETHERNET_PRODUCT_ID 0x505A
+#define MAX_PACKET 32768
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+// Should be global, so that insmod can change these
+int usb_rsize=64;
+int usb_wsize=64;
+
+static struct usbe_info_t {
+  struct net_device *dev;
+  u16 packet_id;
+  struct net_device_stats stats;
+} usbe_info;
+
+static char usb_eth_name[16] = "usbf";
+static struct net_device usb_eth_device;
+static struct sk_buff *cur_tx_skb, *next_tx_skb;
+static struct sk_buff *cur_rx_skb, *next_rx_skb;
+static volatile int terminating;
+#ifndef DMA_NO_COPY
+static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
+#endif
+
+static int usb_change_mtu (struct net_device *net, int new_mtu)
+{
+	if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
+		return -EINVAL;
+	// no second zero-length packet read wanted after mtu-sized packets
+	if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
+		return -EDOM;
+
+	net->mtu = new_mtu;
+	return 0;
+}
+
+static struct sk_buff *
+usb_new_recv_skb(void)
+{
+	struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
+
+	if (skb) {
+		skb_reserve(skb, 2);
+	}
+	return skb;
+}
+
+static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
+static void
+usb_recv_callback(int flag, int size)
+{
+	struct sk_buff *skb;
+
+	if (terminating)
+		return;
+
+	skb = cur_rx_skb;
+
+	/* flag validation */
+	if (flag == 0) {
+		if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
+			usbe_info.stats.rx_over_errors++;
+			goto error;
+		}
+#ifndef DMA_NO_COPY
+		memcpy(skb->tail,dmabuf,size);
+#endif
+		skb_put(skb, size);
+	} else {
+		if (flag == -EIO) {
+			usbe_info.stats.rx_errors++;
+		}
+		goto error;
+	}
+	
+
+	/*
+	 * If the real size of the packet is divisible by usb_rsize
+	 * an extra byte will be added. Thus size == usb_rsize
+	 * should only happen if more data is to come.
+	 */
+	/* validate packet length */
+	if (size == usb_rsize ) {
+		/* packet not complete yet */
+		skb = NULL;
+	}
+
+	/*
+	 * At this point skb is non null if we have a complete packet.
+	 * If so take a fresh skb right away and restart USB receive without
+	 * further delays, then process the packet.  Otherwise resume USB
+	 * receive on the current skb and exit.
+	 */
+
+	if (skb)
+		cur_rx_skb = next_rx_skb;
+#ifndef DMA_NO_COPY
+	pxa_usb_recv(dmabuf, usb_rsize,
+			usb_recv_callback);
+#else
+	pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
+			usb_recv_callback);
+#endif
+	if (!skb)
+		return;
+
+	next_rx_skb = usb_new_recv_skb();
+	if (!next_rx_skb) {
+		/*
+		 * We can't aford loosing buffer space...
+		 * So we drop the current packet and recycle its skb.
+		 */
+		printk("%s: can't allocate new skb\n", __FUNCTION__);
+		usbe_info.stats.rx_dropped++;
+		skb_trim(skb, 0);
+		next_rx_skb = skb;
+		return;
+	}
+	if ( skb->len >= sizeof(struct ethhdr)) {
+		if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
+			// This frame is not for us. nor it is broadcast
+			usbe_info.stats.rx_frame_errors++;
+			kfree_skb(skb);
+			goto error;
+		}
+
+#if 0
+{
+        int i;
+
+        for (i = 0; i < skb->len; i++)
+	{
+                printk("%02X ", skb->data[i]);
+		if( (i%8)==7) printk("\n");
+	}
+        printk("...\n");
+}
+#endif
+
+	}
+
+	if (skb->len) {
+		int     status;
+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
+
+		skb->dev = &usb_eth_device;
+		skb->protocol = eth_type_trans (skb, &usb_eth_device);
+		usbe_info.stats.rx_packets++;
+		usbe_info.stats.rx_bytes += skb->len;
+		skb->ip_summed = CHECKSUM_NONE;
+		status = netif_rx (skb);
+		if (status != NET_RX_SUCCESS)
+			printk("netif_rx failed with code %d\n",status);
+	} else {
+error:
+//printk("ERROR... tailroom=%d size=%d len=%d flag=%d\n", skb_tailroom(skb), size, skb->len, flag);
+		/*
+		 * Error due to HW addr mismatch, or IO error.
+		 * Recycle the current skb and reset USB reception.
+		 */
+		skb_trim(cur_rx_skb, 0);
+//		if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
+#ifndef DMA_NO_COPY
+			pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
+#else
+			pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
+#endif
+	}
+}
+
+
+static void
+usb_send_callback(int flag, int size)
+{
+	struct net_device *dev = usbe_info.dev;
+	struct net_device_stats *stats;
+	struct sk_buff *skb=cur_tx_skb;
+	int ret;
+
+	if (terminating)
+		return;
+
+	stats = &usbe_info.stats;
+	switch (flag) {
+	    case 0:
+		stats->tx_packets++;
+		stats->tx_bytes += size;
+		break;
+	    case -EIO:
+		stats->tx_errors++;
+		break;
+	    default:
+		stats->tx_dropped++;
+		break;
+	}
+
+	cur_tx_skb = next_tx_skb;
+	next_tx_skb = NULL;
+	dev_kfree_skb_irq(skb);
+	if (!cur_tx_skb)
+		return;
+
+	dev->trans_start = jiffies;
+	ret = pxa_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
+	if (ret) {
+		/* If the USB core can't accept the packet, we drop it. */
+		dev_kfree_skb_irq(cur_tx_skb);
+		cur_tx_skb = NULL;
+		usbe_info.stats.tx_carrier_errors++;
+	}
+	netif_wake_queue(dev);
+}
+
+static int
+usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int ret;
+	long flags;
+
+	if (next_tx_skb) {
+		printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
+		return 1;
+	}
+
+	if (skb_shared (skb)) {
+		struct sk_buff  *skb2 = skb_unshare(skb, GFP_ATOMIC);
+		if (!skb2) {
+			usbe_info.stats.tx_dropped++;
+			dev_kfree_skb(skb);
+			return 1;
+		}
+		skb = skb2;
+	}
+
+	if ((skb->len % usb_wsize) == 0) {
+		skb->len++; // other side will ignore this one, anyway.
+	}
+
+	save_flags_cli(flags);
+	if (cur_tx_skb) {
+		next_tx_skb = skb;
+		netif_stop_queue(dev);
+	} else {
+		cur_tx_skb = skb;
+		dev->trans_start = jiffies;
+		ret = pxa_usb_send(skb->data, skb->len, usb_send_callback);
+		if (ret) {
+			/* If the USB core can't accept the packet, we drop it. */
+			dev_kfree_skb(skb);
+			cur_tx_skb = NULL;
+			usbe_info.stats.tx_carrier_errors++;
+		}
+	}
+	restore_flags(flags);
+	return 0;
+}
+
+static void
+usb_xmit_timeout(struct net_device *dev )
+{
+	pxa_usb_send_reset();
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+}
+
+
+static int
+usb_eth_open(struct net_device *dev)
+{
+	int rc;
+	rc = pxa_usb_open( "usb-eth" );
+	if ( rc == 0 ) {
+		 string_desc_t * pstr;
+		 desc_t * pd = pxa_usb_get_descriptor_ptr();
+
+		 pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
+		 pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
+		 pd->dev.idVendor	  = ETHERNET_VENDOR_ID;
+		 pd->dev.idProduct     = ETHERNET_PRODUCT_ID;
+		 pstr = pxa_usb_kmalloc_string_descriptor( "PXA USB NIC" );
+		 if ( pstr ) {
+			  pxa_usb_set_string_descriptor( 1, pstr );
+			  pd->dev.iProduct = 1;
+		 }
+		 rc = pxa_usb_start();
+	}
+
+	if( rc == 0)
+	{
+		terminating = 0;
+		cur_tx_skb = next_tx_skb = NULL;
+		cur_rx_skb = usb_new_recv_skb();
+		next_rx_skb = usb_new_recv_skb();
+		if (!cur_rx_skb || !next_rx_skb) {
+			printk("%s: can't allocate new skb\n", __FUNCTION__);
+			if (cur_rx_skb)
+				kfree_skb(cur_rx_skb);
+			if (next_rx_skb)
+				kfree_skb(next_rx_skb);
+
+			pxa_usb_stop();
+			pxa_usb_close();
+			return -ENOMEM;;
+		}
+
+		MOD_INC_USE_COUNT;
+#ifndef DMA_NO_COPY
+		pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
+#else
+		pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
+				usb_recv_callback);
+#endif
+	}
+
+	return rc;
+}
+
+static int
+usb_eth_release(struct net_device *dev)
+{
+	string_desc_t * pstr;
+
+	terminating = 1;
+	pxa_usb_send_reset();
+	pxa_usb_recv_reset();
+	if (cur_tx_skb)
+		kfree_skb(cur_tx_skb);
+	if (next_tx_skb)
+		kfree_skb(next_tx_skb);
+	if (cur_rx_skb)
+		kfree_skb(cur_rx_skb);
+	if (next_rx_skb)
+		kfree_skb(next_rx_skb);
+
+	pxa_usb_stop();
+	pxa_usb_close();
+	if ( (pstr = pxa_usb_get_string_descriptor(1)) != NULL )
+		kfree( pstr );
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static struct net_device_stats *
+usb_eth_stats(struct net_device *dev)
+{
+	struct usbe_info_t *priv =  (struct usbe_info_t*) dev->priv;
+	struct net_device_stats *stats=NULL;
+
+	if (priv)
+		stats = &priv->stats;
+	return stats;
+}
+
+static int
+usb_eth_probe(struct net_device *dev)
+{
+	u8 node_id [ETH_ALEN];
+
+	get_random_bytes (node_id, sizeof node_id);
+	node_id [0] &= 0xfe;    // clear multicast bit
+
+	/*
+	 * Assign the hardware address of the board:
+	 * generate it randomly, as there can be many such
+	 * devices on the bus.
+	 */
+	memcpy (dev->dev_addr, node_id, sizeof node_id);
+
+	dev->open = usb_eth_open;
+	dev->change_mtu = usb_change_mtu;
+	dev->stop = usb_eth_release;
+	dev->hard_start_xmit = usb_eth_xmit;
+	dev->get_stats = usb_eth_stats;
+	dev->watchdog_timeo = 1*HZ;
+	dev->tx_timeout = usb_xmit_timeout;
+	dev->priv = &usbe_info;
+
+	usbe_info.dev = dev;
+
+	/* clear the statistics */
+	memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
+
+	ether_setup(dev);
+	dev->flags &= ~IFF_MULTICAST;
+	dev->flags &= ~IFF_BROADCAST;
+	//dev->flags |= IFF_NOARP;
+
+	return 0;
+}
+
+#ifdef MODULE
+MODULE_PARM(usb_rsize, "1i");
+MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to pxa");
+MODULE_PARM(usb_wsize, "1i");
+MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from pxa to host");
+#endif
+
+static int __init
+usb_eth_init(void)
+{
+#ifndef DMA_NO_COPY
+	dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
+	if (!dmabuf)
+		return -ENOMEM;
+#endif
+	strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
+	usb_eth_device.init = usb_eth_probe;
+	if (register_netdev(&usb_eth_device) != 0)
+		return -EIO;
+
+	printk( KERN_INFO "USB Function Ethernet Driver Interface\n");
+
+	return 0;
+}
+
+static void __exit
+usb_eth_cleanup(void)
+{
+#ifndef DMA_NO_COPY
+	kfree(dmabuf);
+#endif
+	unregister_netdev(&usb_eth_device);
+}
+
+module_init(usb_eth_init);
+module_exit(usb_eth_cleanup);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb_ctl.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,769 @@
+/*
+ *  Copyright (C) Compaq Computer Corporation, 1998, 1999
+ *  Copyright (C) Extenex Corporation, 2001
+ *  Copyright (C) Intrinsyc, Inc., 2002
+ *
+ *  PXA USB controller core driver.
+ *
+ *  This file provides interrupt routing and overall coordination
+ *  of the endpoints.
+ *
+ *  Please see:
+ *    linux/Documentation/arm/SA1100/SA1100_USB 
+ *  for more info.
+ *
+ *  02-May-2002
+ *   Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/tqueue.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include "pxa_usb.h"
+#include "usb_ctl.h"
+
+//#define DEBUG 1
+
+#if DEBUG
+static unsigned int usb_debug = DEBUG;
+#else
+#define usb_debug 0     /* gcc will remove all the debug code for us */
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Prototypes
+//////////////////////////////////////////////////////////////////////////////
+
+int usbctl_next_state_on_event( int event );
+static void udc_int_hndlr(int, void *, struct pt_regs *);
+static void initialize_descriptors( void );
+static void soft_connect_hook( int enable );
+static void udc_disable(void);
+static void udc_enable(void);
+
+#if CONFIG_PROC_FS
+#define PROC_NODE_NAME "driver/pxausb"
+static int usbctl_read_proc(char *page, char **start, off_t off,
+							int count, int *eof, void *data);
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Globals
+//////////////////////////////////////////////////////////////////////////////
+static const char pszMe[] = "usbctl: ";
+struct usb_info_t usbd_info;  /* global to ep0, usb_recv, usb_send */
+
+/* device descriptors */
+static desc_t desc;
+
+#define MAX_STRING_DESC 8
+static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
+static string_desc_t sd_zero;  /* special sd_zero holds language codes */
+
+// called when configured
+static usb_notify_t configured_callback = NULL;
+
+enum {
+    kStateZombie		= 0,
+    kStateZombieSuspend		= 1,
+    kStateDefault		= 2,
+    kStateDefaultSuspend	= 3,
+    kStateAddr			= 4,
+    kStateAddrSuspend		= 5,
+    kStateConfig		= 6,
+    kStateConfigSuspend		= 7
+};
+
+/*
+ * FIXME: The PXA UDC handles several host device requests without user 
+ * notification/intervention. The table could be collapsed quite a bit...
+ */
+static int device_state_machine[8][6] = {
+//              suspend               reset          resume         adddr       config        deconfig
+/* zombie */  { kStateZombieSuspend , kStateDefault, kStateZombie , kError    , kError      , kError },
+/* zom sus */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError    , kError      , kError },
+/* default */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kStateAddr, kStateConfig, kError },
+/* def sus */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kError    , kError      , kError },
+/* addr */    { kStateAddrSuspend   , kStateDefault, kStateAddr   , kError    , kStateConfig, kError },
+/* addr sus */{ kStateAddrSuspend   , kStateDefault, kStateAddr   , kError    , kError      , kError },
+/* config */  { kStateConfigSuspend , kStateDefault, kStateConfig , kError    , kError      , kStateDefault },
+/* cfg sus */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError    , kError      , kError }
+};
+
+/* "device state" is the usb device framework state, as opposed to the
+   "state machine state" which is whatever the driver needs and is much
+   more fine grained
+*/
+static int sm_state_to_device_state[8] = { 
+//  zombie            zom suspend       
+USB_STATE_POWERED, USB_STATE_SUSPENDED, 
+//  default           default sus
+USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
+//  addr              addr sus         
+USB_STATE_ADDRESS, USB_STATE_SUSPENDED, 
+//  config            config sus
+USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
+};
+
+static char * state_names[8] =
+{ "zombie", "zombie suspended", 
+  "default", "default suspended",
+  "address", "address suspended", 
+  "configured", "config suspended"
+};
+
+static char * event_names[6] =
+{ "suspend", "reset", "resume",
+  "address assigned", "configure", "de-configure"
+};
+
+static char * device_state_names[] =
+{ "not attached", "attached", "powered", "default",
+  "address", "configured", "suspended" };
+
+static int sm_state = kStateZombie;
+
+//////////////////////////////////////////////////////////////////////////////
+// Async
+//////////////////////////////////////////////////////////////////////////////
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+
+void udc_set_mask_UDCCR( int mask )
+{
+	UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
+}
+
+void udc_clear_mask_UDCCR( int mask)
+{
+	UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
+}
+
+void udc_ack_int_UDCCR( int mask)
+{
+	/* udccr contains the bits we dont want to change */
+	__u32 udccr = UDCCR & UDCCR_MASK_BITS; 
+
+	UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
+}
+
+static void
+udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
+{
+  	__u32 status = UDCCR;
+  	__u32 ir0_status = USIR0;
+  	__u32 ir1_status = USIR1;
+  	__u32 uicr0 = UICR0;
+  	__u32 uicr1 = UICR1;
+
+	//mask ints
+	udc_set_mask_UDCCR( UDCCR_REM | UDCCR_SRM);
+	UICR0 = 0xff;
+	UICR1 = 0xff;
+
+	if( usb_debug > 2)
+	{
+		printk("%s--- udc_int_hndlr\n"
+		   "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"
+		   "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n", 
+		    pszMe, status, UDCCS0, UDCCS1, UDCCS2, ir0_status, ir1_status, uicr0, uicr1);
+	}
+
+	/* SUSpend Interrupt Request */
+	if ( status & UDCCR_SUSIR )
+	{
+		udc_ack_int_UDCCR( UDCCR_SUSIR);
+		if( usb_debug) printk("%sSuspend...\n", pszMe);
+		usbctl_next_state_on_event( kEvSuspend );
+	}
+
+	/* RESume Interrupt Request */
+	if ( status & UDCCR_RESIR )
+	{
+		udc_ack_int_UDCCR( UDCCR_RESIR);
+		if( usb_debug) printk("%sResume...\n", pszMe);
+		usbctl_next_state_on_event( kEvResume );
+	}
+
+	/* ReSeT Interrupt Request - UDC has been reset */
+	if ( status & UDCCR_RSTIR )
+	{
+		/* clear the reset interrupt */
+		udc_ack_int_UDCCR( UDCCR_RSTIR);
+
+		/* check type of reset */
+		if( (UDCCR & UDCCR_UDA) == 0)
+		{
+			/* reset assertion took place, nothing to do */
+			if( usb_debug) printk("%sReset assertion...\n", pszMe);
+		}
+
+		/* ok, it's a reset negation, go on with reset */
+		else if ( usbctl_next_state_on_event( kEvReset ) != kError )
+		{
+			/* starting reset sequence now... */
+			if( usb_debug) printk("%sResetting\n", pszMe);
+
+			ep0_reset();
+			ep_bulk_in1_reset();
+			ep_bulk_out1_reset();
+
+			usbctl_next_state_on_event( kEvConfig );
+		}
+		else
+		{
+			printk("%sUnexpected reset\n", pszMe);
+		}
+	}
+	else
+	{
+		/* ep0 int */
+		if (ir0_status & USIR0_IR0)
+			ep0_int_hndlr();
+
+		/* transmit bulk */
+		if (ir0_status & USIR0_IR1)
+			ep_bulk_in1_int_hndlr(ir0_status);
+
+		/* receive bulk */
+		if ( ir0_status & USIR0_IR2)
+			ep_bulk_out1_int_hndlr(ir0_status);
+
+		while (UDCCS2 & UDCCS_BO_RNE)
+		{
+			if( usb_debug) printk("More Bulk-out data...\n");
+			ep_bulk_out1_int_hndlr(ir0_status);
+		}
+	}
+
+	UICR0 = uicr0;
+	UICR1 = uicr1;
+	udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); /* enable suspend/resume, reset */
+
+	/* clear all endpoint ints */
+	USIR0 |= 0xff;
+	USIR1 |= 0xff;
+
+	if( usb_debug > 2)
+	{
+		printk("%sudc_int_hndlr\n"
+		       "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"
+		       "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n", 
+			pszMe, UDCCR, UDCCS0, UDCCS1, UDCCS2, USIR0, USIR1, UICR0, UICR1);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Public Interface
+//////////////////////////////////////////////////////////////////////////////
+
+/* Open PXA usb core on behalf of a client, but don't start running */
+
+int
+pxa_usb_open( const char * client )
+{
+	if ( usbd_info.client_name != NULL )
+	{
+		printk( "%sUnable to register %s (%s already registered).\n", 
+			pszMe, client, usbd_info.client_name );
+		return -EBUSY;
+	}
+
+	usbd_info.client_name = (char*) client;
+	memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
+	memset(string_desc_array, 0, sizeof(string_desc_array));
+
+	/* hack to start in zombie suspended state */
+	sm_state = kStateZombieSuspend;
+	usbd_info.state = USB_STATE_SUSPENDED;
+
+	/* create descriptors for enumeration */
+	initialize_descriptors();
+
+	printk( "%s%s registered.\n", pszMe, client );
+	return 0;
+}
+
+/* Start running. Must have called usb_open (above) first */
+int
+pxa_usb_start( void )
+{
+	if ( usbd_info.client_name == NULL ) {
+		printk( "%s%s - no client registered\n",
+				pszMe, __FUNCTION__ );
+		return -EPERM;
+	}
+
+	/* start UDC internal machinery running */
+	udc_enable();
+	udelay( 100 );
+
+	/* flush DMA and fire through some -EAGAINs */
+	ep_bulk_out1_init( usbd_info.dmach_rx );
+	ep_bulk_in1_init( usbd_info.dmach_tx );
+
+	/* give endpoint notification we are starting */
+	ep_bulk_out1_state_change_notify( USB_STATE_SUSPENDED );
+	ep_bulk_in1_state_change_notify( USB_STATE_SUSPENDED );
+
+	/* enable any platform specific hardware */
+	soft_connect_hook( 1 );
+
+	/* enable suspend/resume, reset */
+	udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); 
+	/* enable ep0, ep1, ep2 */
+	UICR0 &= ~(UICR0_IM0 | UICR0_IM1 | UICR0_IM2); 
+
+	if( usb_debug) printk( "%sStarted %s\n", pszMe, usbd_info.client_name );
+	return 0;
+}
+
+/* Stop USB core from running */
+int
+pxa_usb_stop( void )
+{
+	if ( usbd_info.client_name == NULL ) {
+		printk( "%s%s - no client registered\n",
+				pszMe, __FUNCTION__ );
+		return -EPERM;
+	}
+	/* mask everything */
+	/* disable suspend/resume, reset */
+	udc_set_mask_UDCCR( UDCCR_SRM | UDCCR_REM); 
+	/* disable ep0, ep1, ep2 */
+	UICR0 |= (UICR0_IM0 | UICR0_IM1 | UICR0_IM2); 
+
+	ep_bulk_out1_reset();
+	ep_bulk_in1_reset();
+
+	udc_disable();
+	if( usb_debug) printk( "%sStopped %s\n", pszMe, usbd_info.client_name );
+	return 0;
+}
+
+/* Tell PXA core client is through using it */
+int
+pxa_usb_close( void )
+{
+	 if ( usbd_info.client_name == NULL ) {
+		  printk( "%s%s - no client registered\n",
+				  pszMe, __FUNCTION__ );
+		  return -EPERM;
+	 }
+	 printk( "%s%s closed.\n", pszMe, (char*)usbd_info.client_name );
+	 usbd_info.client_name = NULL;
+	 return 0;
+}
+
+/* set a proc to be called when device is configured */
+usb_notify_t pxa_set_configured_callback( usb_notify_t func )
+{
+	 usb_notify_t retval = configured_callback;
+	 configured_callback = func;
+	 return retval;
+}
+
+/*====================================================
+ * Descriptor Manipulation.
+ * Use these between open() and start() above to setup
+ * the descriptors for your device.
+ *
+ */
+
+/* get pointer to static default descriptor */
+desc_t *
+pxa_usb_get_descriptor_ptr( void ) { return &desc; }
+
+/* optional: set a string descriptor */
+int
+pxa_usb_set_string_descriptor( int i, string_desc_t * p )
+{
+	 int retval;
+	 if ( i < MAX_STRING_DESC ) {
+		  string_desc_array[i] = p;
+		  retval = 0;
+	 } else {
+		  retval = -EINVAL;
+	 }
+	 return retval;
+}
+
+/* optional: get a previously set string descriptor */
+string_desc_t *
+pxa_usb_get_string_descriptor( int i )
+{
+	 return ( i < MAX_STRING_DESC )
+		    ? string_desc_array[i]
+		    : NULL;
+}
+
+
+/* optional: kmalloc and unicode up a string descriptor */
+string_desc_t *
+pxa_usb_kmalloc_string_descriptor( const char * p )
+{
+	 string_desc_t * pResult = NULL;
+
+	 if ( p ) {
+		  int len = strlen( p );
+		  int uni_len = len * sizeof( __u16 );
+		  pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
+		  if ( pResult != NULL ) {
+			   int i;
+			   pResult->bLength = uni_len + 2;
+			   pResult->bDescriptorType = USB_DESC_STRING;
+			   for( i = 0; i < len ; i++ ) {
+					pResult->bString[i] = make_word( (__u16) p[i] );
+			   }
+		  }
+	 }
+	 return pResult;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Exports to rest of driver
+//////////////////////////////////////////////////////////////////////////////
+
+/* called by the int handler here and the two endpoint files when interesting
+   .."events" happen */
+
+int
+usbctl_next_state_on_event( int event )
+{
+	int next_state = device_state_machine[ sm_state ][ event ];
+	if ( next_state != kError )
+	{
+		int next_device_state = sm_state_to_device_state[ next_state ];
+		if( usb_debug) printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
+				pszMe, state_names[ sm_state ], event_names[ event ],
+				state_names[ next_state ], device_state_names[ next_device_state ] );
+
+		sm_state = next_state;
+		if ( usbd_info.state != next_device_state )
+		{
+			if ( configured_callback != NULL
+				 &&
+				 next_device_state == USB_STATE_CONFIGURED
+				 &&
+				 usbd_info.state != USB_STATE_SUSPENDED
+			   ) {
+			  configured_callback();
+			}
+			usbd_info.state = next_device_state;
+
+			ep_bulk_out1_state_change_notify( next_device_state );
+			ep_bulk_in1_state_change_notify( next_device_state );
+		}
+	}
+#if 1
+	else
+		printk( "%s%s --> [%s] --> ??? is an error.\n",
+				pszMe, state_names[ sm_state ], event_names[ event ] );
+#endif
+	return next_state;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Private Helpers
+//////////////////////////////////////////////////////////////////////////////
+
+/* setup default descriptors */
+
+static void
+initialize_descriptors(void)
+{
+	desc.dev.bLength               = sizeof( device_desc_t );
+	desc.dev.bDescriptorType       = USB_DESC_DEVICE;
+	desc.dev.bcdUSB                = 0x100; /* 1.0 */
+	desc.dev.bDeviceClass          = 0xFF;	/* vendor specific */
+	desc.dev.bDeviceSubClass       = 0;
+	desc.dev.bDeviceProtocol       = 0;
+	desc.dev.bMaxPacketSize0       = 16;	/* ep0 max fifo size */
+	desc.dev.idVendor              = 0;	/* vendor ID undefined */
+	desc.dev.idProduct             = 0; /* product */
+	desc.dev.bcdDevice             = 0; /* vendor assigned device release num */
+	desc.dev.iManufacturer         = 0;	/* index of manufacturer string */
+	desc.dev.iProduct              = 0; /* index of product description string */
+	desc.dev.iSerialNumber         = 0;	/* index of string holding product s/n */
+	desc.dev.bNumConfigurations    = 1;
+
+	desc.b.cfg.bLength             = sizeof( config_desc_t );
+	desc.b.cfg.bDescriptorType     = USB_DESC_CONFIG;
+	desc.b.cfg.wTotalLength        = make_word_c( sizeof(struct cdb) );
+	desc.b.cfg.bNumInterfaces      = 1;
+	desc.b.cfg.bConfigurationValue = 1;
+	desc.b.cfg.iConfiguration      = 0;
+	desc.b.cfg.bmAttributes        = USB_CONFIG_BUSPOWERED;
+	desc.b.cfg.MaxPower            = USB_POWER( 500 );
+
+	desc.b.intf.bLength            = sizeof( intf_desc_t );
+	desc.b.intf.bDescriptorType    = USB_DESC_INTERFACE;
+	desc.b.intf.bInterfaceNumber   = 0; /* unique intf index*/
+	desc.b.intf.bAlternateSetting  = 0;
+	desc.b.intf.bNumEndpoints      = 2;
+	desc.b.intf.bInterfaceClass    = 0xFF; /* vendor specific */
+	desc.b.intf.bInterfaceSubClass = 0;
+	desc.b.intf.bInterfaceProtocol = 0;
+	desc.b.intf.iInterface         = 0;
+
+/*
+ * FIXME...
+ * The host usbnet driver expects EP1=out EP2=in. On the PXA UDC EP1=in, EP2=out
+ */
+	desc.b.ep1.bLength             = sizeof( ep_desc_t );
+	desc.b.ep1.bDescriptorType     = USB_DESC_ENDPOINT;
+	desc.b.ep1.bEndpointAddress    = USB_EP_ADDRESS( 1, USB_IN );
+	desc.b.ep1.bmAttributes        = USB_EP_BULK;
+	desc.b.ep1.wMaxPacketSize      = make_word_c( 64 );
+	desc.b.ep1.bInterval           = 0;
+
+	desc.b.ep2.bLength             = sizeof( ep_desc_t );
+	desc.b.ep2.bDescriptorType     = USB_DESC_ENDPOINT;
+	desc.b.ep2.bEndpointAddress    = USB_EP_ADDRESS( 2, USB_OUT );
+	desc.b.ep2.bmAttributes        = USB_EP_BULK;
+	desc.b.ep2.wMaxPacketSize      = make_word_c( 64 );
+	desc.b.ep2.bInterval           = 0;
+
+// FIXME: Add support for all endpoint...
+
+	/* set language */
+	/* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
+	sd_zero.bDescriptorType = USB_DESC_STRING;
+	sd_zero.bLength         = sizeof( string_desc_t );
+	sd_zero.bString[0]      = make_word_c( 0x409 ); /* American English */
+	pxa_usb_set_string_descriptor( 0, &sd_zero );
+}
+
+/* soft_connect_hook()
+ * Some devices have platform-specific circuitry to make USB
+ * not seem to be plugged in, even when it is. This allows
+ * software to control when a device 'appears' on the USB bus
+ * (after Linux has booted and this driver has loaded, for
+ * example). If you have such a circuit, control it here.
+ */
+static void
+soft_connect_hook( int enable )
+{
+}
+
+/* disable the UDC at the source */
+static void
+udc_disable(void)
+{
+	soft_connect_hook( 0 );
+	/* clear UDC-enable */
+	udc_clear_mask_UDCCR( UDCCR_UDE); 
+
+        /* Disable clock for USB device */
+        CKEN &= ~CKEN11_USB;
+}
+
+
+/*  enable the udc at the source */
+static void
+udc_enable(void)
+{
+        /* Enable clock for USB device */
+        CKEN |= CKEN11_USB;
+
+	/* try to clear these bits before we enable the udc */
+	udc_ack_int_UDCCR( UDCCR_SUSIR);
+	udc_ack_int_UDCCR( UDCCR_RSTIR);
+	udc_ack_int_UDCCR( UDCCR_RESIR);
+
+	/* set UDC-enable */
+	udc_set_mask_UDCCR( UDCCR_UDE); 
+	if( (UDCCR & UDCCR_UDA) == 0)
+	{
+		/* There's a reset on the bus,
+		 * clear the interrupt bit and keep going
+		 */
+		udc_ack_int_UDCCR( UDCCR_RSTIR);
+	}
+	
+	/* "USB test mode" to work around errata 40-42 (stepping a0, a1) 
+	 * which could result in missing packets and interrupts. 
+	 * Supposedly this turns off double buffering for all endpoints.
+	 */
+	if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
+	UDC_RES1 = 0x00;
+	UDC_RES2 = 0x00;
+	if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Proc Filesystem Support
+//////////////////////////////////////////////////////////////////////////////
+
+#if CONFIG_PROC_FS
+
+#define SAY( fmt, args... )  p += sprintf(p, fmt, ## args )
+#define SAYV(  num )         p += sprintf(p, num_fmt, "Value", num )
+#define SAYC( label, yn )    p += sprintf(p, yn_fmt, label, yn )
+#define SAYS( label, v )     p += sprintf(p, cnt_fmt, label, v )
+
+static int usbctl_read_proc(char *page, char **start, off_t off,
+			    int count, int *eof, void *data)
+{
+	 const char * num_fmt   = "%25.25s: %8.8lX\n";
+	 const char * cnt_fmt   = "%25.25s: %lu\n";
+	 const char * yn_fmt    = "%25.25s: %s\n";
+	 const char * yes       = "YES";
+	 const char * no        = "NO";
+	 unsigned long v;
+	 char * p = page;
+	 int len;
+
+ 	 SAY( "PXA USB Controller Core\n" );
+ 	 SAY( "Active Client: %s\n", usbd_info.client_name ? usbd_info.client_name : "none");
+	 SAY( "USB state: %s (%s) %d\n",
+		  device_state_names[ sm_state_to_device_state[ sm_state ] ],
+		  state_names[ sm_state ],
+		  sm_state );
+
+	 SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
+	 SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
+	 SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
+	 SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
+
+	 SAY( "\n" );
+
+	 v = UDCCR;
+	 SAY( "\nUDC Control Register\n" );
+	 SAYV( v );
+	 SAYC( "UDC Enabled",                ( v & UDCCR_UDE ) ? yes : no );
+	 SAYC( "UDC Active",                ( v & UDCCR_UDA ) ? yes : no );
+	 SAYC( "Suspend/Resume interrupts masked", ( v & UDCCR_SRM ) ? yes : no );
+	 SAYC( "Reset interrupts masked",   ( v & UDCCR_REM ) ? yes : no );
+	 SAYC( "Reset pending",      ( v & UDCCR_RSTIR ) ? yes : no );
+	 SAYC( "Suspend pending",    ( v & UDCCR_SUSIR ) ? yes : no );
+	 SAYC( "Resume pending",     ( v & UDCCR_RESIR ) ? yes : no );
+
+	 len = ( p - page ) - off;
+	 if ( len < 0 )
+		  len = 0;
+	 *eof = ( len <=count ) ? 1 : 0;
+	 *start = page + off;
+	 return len;
+}
+
+#endif  /* CONFIG_PROC_FS */
+
+#if 0
+static void irq_handler(int channel, void *data, struct pt_regs *regs)
+{
+	if( channel == usbd_info.dmach_rx)
+	{
+	    printk( "USB receive DMA\n");
+	}
+	else if( channel == usbd_info.dmach_tx)
+	{
+	    printk( "USB transmit DMA\n");
+	}
+	else
+	{
+	    printk( "USB unknown DMA channel\n");
+	}
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Module Initialization and Shutdown
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * usbctl_init()
+ * Module load time. Allocate dma and interrupt resources. Setup /proc fs
+ * entry. Leave UDC disabled.
+ */
+int __init usbctl_init( void )
+{
+	int retval = 0;
+
+	udc_disable();
+
+	memset( &usbd_info, 0, sizeof( usbd_info ) );
+
+#if CONFIG_PROC_FS
+	create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
+#endif
+
+#if 0
+	/* setup rx dma */
+	usbd_info.dmach_rx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/);
+	if (usbd_info.dmach_rx < 0) {
+		printk("%sunable to register for rx dma rc=%d\n", pszMe, usbd_info.dmach_rx );
+		goto err_rx_dma;
+	}
+
+	/* setup tx dma */
+	usbd_info.dmach_tx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/);
+	if (usbd_info.dmach_tx < 0) {
+		printk("%sunable to register for tx dma rc=%d\n",pszMe,usbd_info.dmach_tx);
+		goto err_tx_dma;
+	}
+#endif
+
+	/* now allocate the IRQ. */
+	retval = request_irq(IRQ_USB, udc_int_hndlr, SA_INTERRUPT, "PXA USB core", NULL);
+	if (retval) {
+		printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
+		goto err_irq;
+	}
+
+	printk( "PXA USB Controller Core Initialized\n");
+	return 0;
+
+err_irq:
+#if 0
+	pxa_free_dma(usbd_info.dmach_tx);
+	usbd_info.dmach_tx = 0;
+err_tx_dma:
+	pxa_free_dma(usbd_info.dmach_rx);
+	usbd_info.dmach_rx = 0;
+err_rx_dma:
+#endif
+	return retval;
+}
+/*
+ * usbctl_exit()
+ * Release DMA and interrupt resources
+ */
+void __exit usbctl_exit( void )
+{
+	printk("Unloading PXA USB Controller\n");
+
+	udc_disable();
+
+#if CONFIG_PROC_FS
+	remove_proc_entry ( PROC_NODE_NAME, NULL);
+#endif
+
+	pxa_free_dma(usbd_info.dmach_rx);
+	pxa_free_dma(usbd_info.dmach_tx);
+	free_irq(IRQ_USB, NULL);
+}
+
+module_init( usbctl_init );
+module_exit( usbctl_exit );
+
+EXPORT_SYMBOL( pxa_usb_open );
+EXPORT_SYMBOL( pxa_usb_start );
+EXPORT_SYMBOL( pxa_usb_stop );
+EXPORT_SYMBOL( pxa_usb_close );
+EXPORT_SYMBOL( pxa_usb_get_descriptor_ptr );
+EXPORT_SYMBOL( pxa_usb_set_string_descriptor );
+EXPORT_SYMBOL( pxa_usb_get_string_descriptor );
+EXPORT_SYMBOL( pxa_usb_kmalloc_string_descriptor );
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb_ctl.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) Compaq Computer Corporation, 1998, 1999
+ *  Copyright (C) Extenex Corporation 2001
+ *  Copyright (C) Intrinsyc, Inc., 2002
+ *
+ *  usb_ctl.h
+ *
+ *  PRIVATE interface used to share info among components of the PXA USB
+ *  core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
+ *  should use pxa_usb.h.
+ *
+ *  02-May-2002
+ *   Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.h
+ *
+ */
+
+#ifndef _USB_CTL_H
+#define _USB_CTL_H
+
+/* Interrupt mask bits and UDC enable bit */
+#define UDCCR_MASK_BITS         (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
+
+/*
+ * These states correspond to those in the USB specification v1.0
+ * in chapter 8, Device Framework.
+ */
+enum { 
+	USB_STATE_NOTATTACHED	=0,
+	USB_STATE_ATTACHED	=1,
+	USB_STATE_POWERED	=2,
+	USB_STATE_DEFAULT	=3,
+	USB_STATE_ADDRESS	=4,
+	USB_STATE_CONFIGURED	=5,
+	USB_STATE_SUSPENDED	=6
+};
+
+struct usb_stats_t {
+	 unsigned long ep0_fifo_write_failures;
+	 unsigned long ep0_bytes_written;
+	 unsigned long ep0_fifo_read_failures;
+	 unsigned long ep0_bytes_read;
+};
+
+struct usb_info_t
+{
+	 char * client_name;
+	 dmach_t dmach_tx, dmach_rx;
+	 int state;
+	 unsigned char address;
+	 struct usb_stats_t stats;
+};
+
+/* in usb_ctl.c */
+extern struct usb_info_t usbd_info;
+
+/*
+ * Function Prototypes
+ */
+enum { 
+	kError		=-1,
+	kEvSuspend	=0,
+	kEvReset	=1,
+	kEvResume	=2,
+	kEvAddress	=3,
+	kEvConfig	=4,
+	kEvDeConfig	=5 
+};
+int usbctl_next_state_on_event( int event );
+
+/* endpoint zero */
+void ep0_reset(void);
+void ep0_int_hndlr(void);
+
+/* receiver */
+void ep_bulk_out1_state_change_notify( int new_state );
+int  ep_bulk_out1_recv(void);
+int  ep_bulk_out1_init(int chn);
+void ep_bulk_out1_int_hndlr(int status);
+void ep_bulk_out1_reset(void);
+void ep_bulk_out1_stall(void);
+
+/* xmitter */
+void ep_bulk_in1_state_change_notify( int new_state );
+void ep_bulk_in1_reset(void);
+int  ep_bulk_in1_init(int chn);
+void ep_bulk_in1_int_hndlr(int status);
+void ep_bulk_in1_stall(void);
+
+#endif /* _USB_CTL_H */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb_ep0.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,556 @@
+/*
+ *  Copyright (C) Extenex Corporation 2001
+ *  Copyright (C) Compaq Computer Corporation, 1998, 1999
+ *  Copyright (C) Intrinsyc, Inc., 2002
+ *
+ *  PXA USB controller driver - Endpoint zero management
+ *
+ *  Please see:
+ *    linux/Documentation/arm/SA1100/SA1100_USB 
+ *  for more info.
+ *
+ *  02-May-2002
+ *   Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/tqueue.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+
+#include "pxa_usb.h"  /* public interface */
+#include "usb_ctl.h"  /* private stuff */
+#include "usb_ep0.h"
+
+
+// 1 == lots of trace noise,  0 = only "important' stuff
+#define VERBOSITY 0
+
+enum { true = 1, false = 0 };
+typedef int bool;
+#ifndef MIN
+#define MIN( a, b ) ((a)<(b)?(a):(b))
+#endif
+
+#if 1 && !defined( ASSERT )
+#  define ASSERT(expr) \
+if(!(expr)) { \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+#expr,__FILE__,__FUNCTION__,__LINE__); \
+}
+#else
+#  define ASSERT(expr)
+#endif
+
+#if VERBOSITY
+#define PRINTKD(fmt, args...) printk( fmt , ## args)
+#else
+#define PRINTKD(fmt, args...)
+#endif
+
+static EP0_state ep0_state = EP0_IDLE;
+
+/***************************************************************************
+  Prototypes
+ ***************************************************************************/
+/* "setup handlers" -- the main functions dispatched to by the
+   .. isr. These represent the major "modes" of endpoint 0 operation */
+static void sh_setup_begin(void);				/* setup begin (idle) */
+static void sh_write( void );      				/* writing data */
+static int  read_fifo( usb_dev_request_t * p );
+static void write_fifo( void );
+static void get_descriptor( usb_dev_request_t * pReq );
+static void queue_and_start_write( void * p, int req, int act );
+
+/***************************************************************************
+  Inline Helpers
+ ***************************************************************************/
+
+inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
+
+/* print string descriptor */
+static inline void psdesc( string_desc_t * p )
+{
+	int i;
+	int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
+	printk( "'" );
+	for( i = 0 ; i < nchars ; i++ ) {
+		printk( "%c", (char) p->bString[i] );
+	}
+	printk( "'\n" );
+}
+
+#if VERBOSITY
+/* "pcs" == "print control status" */
+static inline void pcs( void )
+{
+	__u32 foo = UDCCS0;
+	printk( "%08x: %s %s %s %s %s %s\n",
+			foo,
+			foo & UDCCS0_SA   ? "SA" : "",
+			foo & UDCCS0_OPR  ? "OPR" : "",
+			foo & UDCCS0_RNE  ? "RNE" : "",
+			foo & UDCCS0_SST  ? "SST" : "",
+			foo & UDCCS0_FST  ? "FST" : "",
+			foo & UDCCS0_DRWF ? "DRWF" : ""
+	      );
+}
+static inline void preq( usb_dev_request_t * pReq )
+{
+	static char * tnames[] = { "dev", "intf", "ep", "oth" };
+	static char * rnames[] = { "std", "class", "vendor", "???" };
+	char * psz;
+	switch( pReq->bRequest ) {
+		case GET_STATUS:        psz = "get stat"; break;
+		case CLEAR_FEATURE:     psz = "clr feat"; break;
+		case SET_FEATURE:       psz = "set feat"; break;
+		case SET_ADDRESS:       psz = "set addr"; break;
+		case GET_DESCRIPTOR:    psz = "get desc"; break;
+		case SET_DESCRIPTOR:    psz = "set desc"; break;
+		case GET_CONFIGURATION: psz = "get cfg"; break;
+		case SET_CONFIGURATION: psz = "set cfg"; break;
+		case GET_INTERFACE:     psz = "get intf"; break;
+		case SET_INTERFACE:     psz = "set intf"; break;
+		case SYNCH_FRAME:       psz = "synch frame"; break;
+		default:                psz = "unknown"; break;
+	}
+	printk( "- [%s: %s req to %s. dir=%s]\n", psz,
+			rnames[ (pReq->bmRequestType >> 5) & 3 ],
+			tnames[ pReq->bmRequestType & 3 ],
+			( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
+}
+
+#else
+static inline void pcs( void ){}
+static inline void preq( usb_dev_request_t *x){}
+#endif
+
+/***************************************************************************
+  Globals
+ ***************************************************************************/
+static const char pszMe[] = "usbep0: ";
+
+/* pointer to current setup handler */
+static void (*current_handler)(void) = sh_setup_begin;
+
+/* global write struct to keep write
+   ..state around across interrupts */
+static struct {
+	unsigned char *p;
+	int bytes_left;
+} wr;
+
+/***************************************************************************
+  Public Interface
+ ***************************************************************************/
+
+/* reset received from HUB (or controller just went nuts and reset by itself!)
+   so udc core has been reset, track this state here  */
+void ep0_reset(void)
+{
+	PRINTKD( "%sep0_reset\n", pszMe);
+	/* reset state machine */
+	current_handler = sh_setup_begin;
+	wr.p = NULL;
+	wr.bytes_left = 0;
+	usbd_info.address=0;
+}
+
+/* handle interrupt for endpoint zero */
+void ep0_int_hndlr( void )
+{
+	PRINTKD( "%sep0_int_hndlr\n", pszMe);
+	pcs();
+	(*current_handler)();
+}
+
+/***************************************************************************
+  Setup Handlers
+ ***************************************************************************/
+/*
+ * sh_setup_begin()
+ * This setup handler is the "idle" state of endpoint zero. It looks for OPR
+ * (OUT packet ready) to see if a setup request has been been received from the
+ * host. 
+ *
+ */
+static void sh_setup_begin( void )
+{
+	usb_dev_request_t req;
+	int request_type;
+	int n;
+	__u32 cs_reg_in = UDCCS0;
+
+	PRINTKD( "%ssh_setup_begin\n", pszMe);
+
+	/* Be sure out packet ready, otherwise something is wrong */
+	if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
+		/* we can get here early...if so, we'll int again in a moment  */
+		PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
+		goto sh_sb_end;
+	}
+
+	if( ((cs_reg_in & UDCCS0_SA) == 0) && (ep0_state == EP0_IN_DATA_PHASE))
+	{
+		PRINTKD( "%ssetup begin: premature status\n", pszMe );
+
+		/* premature status, reset tx fifo and go back to idle state*/
+		UDCCS0 = UDCCS0_OPR | UDCCS0_FTF;
+
+		ep0_state = EP0_IDLE;
+		return;
+	}
+
+	if( (UDCCS0 & UDCCS0_RNE) == 0)
+	{
+		/* zero-length OUT? */
+		printk( "%ssetup begin: zero-length OUT?\n", pszMe );
+		goto sh_sb_end;
+	}
+
+	/* read the setup request */
+	n = read_fifo( &req );
+	if ( n != sizeof( req ) ) {
+		printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
+				" Stalling out...\n",
+				pszMe, sizeof( req ), n );
+		/* force stall, serviced out */
+		UDCCS0 = UDCCS0_FST;
+		goto sh_sb_end;
+	}
+
+	/* Is it a standard request? (not vendor or class request) */
+	request_type = type_code_from_request( req.bmRequestType );
+	if ( request_type != 0 ) {
+		printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
+				pszMe, request_type );
+		goto sh_sb_end;
+	}
+
+#if VERBOSITY
+	{
+		unsigned char * pdb = (unsigned char *) &req;
+		PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
+				pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
+		       );
+		preq( &req );
+	}
+#endif
+
+	/* Handle it */
+	switch( req.bRequest ) {
+
+		case SET_ADDRESS:
+			PRINTKD( "%sSET_ADDRESS handled by UDC\n", pszMe);
+			break;
+#if 0 /* NOT_NEEDED */
+
+		case SET_FEATURE:
+			PRINTKD( "%sSET_FEATURE handled by UDC\n", pszMe);
+			break;
+
+		case CLEAR_FEATURE:
+			PRINTKD( "%sCLEAR_FEATURE handled by UDC\n", pszMe);
+			break;
+
+		case GET_CONFIGURATION:
+			PRINTKD( "%sGET_CONFIGURATION handled by UDC\n", pszMe );
+			break;
+
+		case GET_STATUS:
+			PRINTKD( "%s%sGET_STATUS handled by UDC\n", pszMe );
+			break;
+
+		case GET_INTERFACE:
+			PRINTKD( "%sGET_INTERFACE handled by UDC\n", pszMe);
+			break;
+
+		case SYNCH_FRAME:
+			PRINTKD( "%sSYNCH_FRAME handled by UDC\n", pszMe );
+			break;
+#endif
+
+		case GET_DESCRIPTOR:
+			PRINTKD( "%sGET_DESCRIPTOR\n", pszMe );
+			get_descriptor( &req );
+			break;
+
+		case SET_INTERFACE:
+			PRINTKD( "%sSET_INTERFACE TODO...\n", pszMe);
+			break;
+
+		case SET_DESCRIPTOR:
+			PRINTKD( "%sSET_DESCRIPTOR TODO...\n", pszMe );
+			break;
+
+		case SET_CONFIGURATION:
+			PRINTKD( "%sSET_CONFIGURATION %d\n", pszMe, req.wValue);
+
+/*
+ * FIXME: Something is not quite right here... I only ever get a 
+ * de-configure from the host. Ignoring it for now, since usb
+ * ethernet won't do anything unless usb is 'configured'.
+ *
+ */
+#if 0
+			switch( req.wValue)
+			{
+				case 0:
+					/* configured */
+					usbctl_next_state_on_event( kEvConfig );
+					break;
+				case 1:
+					/* de-configured */
+					usbctl_next_state_on_event( kEvDeConfig );
+					break;
+				default:
+					PRINTKD( "%sSET_CONFIGURATION: unknown configuration value (%d)\n", pszMe, req.wValue);
+					break;
+			}
+#endif
+			break;
+		default :
+			printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
+			break;
+	} /* switch( bRequest ) */
+
+sh_sb_end:
+	return;
+}
+
+/*
+ * sh_write()
+ * 
+ * Due to UDC bugs we push everything into the fifo in one go.
+ * Using interrupts just didn't work right...
+ * This should be ok, since control request are small.
+ */
+static void sh_write()
+{
+	PRINTKD( "sh_write\n" );
+	do
+	{
+	    write_fifo();
+	} while( ep0_state != EP0_END_XFER);
+}
+
+/***************************************************************************
+  Other Private Subroutines
+ ***************************************************************************/
+/*
+ * queue_and_start_write()
+ * data == data to send
+ * req == bytes host requested
+ * act == bytes we actually have
+ *
+ * Sets up the global "wr"-ite structure and load the outbound FIFO 
+ * with data.
+ *
+ */
+static void queue_and_start_write( void * data, int req, int act )
+{
+	PRINTKD( "write start: bytes requested=%d actual=%d\n", req, act);
+
+	wr.p = (unsigned char*) data;
+	wr.bytes_left = MIN( act, req );
+
+	ep0_state = EP0_IN_DATA_PHASE;
+	sh_write();
+
+	return;
+}
+/*
+ * write_fifo()
+ * Stick bytes in the endpoint zero FIFO.
+ *
+ */
+static void write_fifo( void )
+{
+	int bytes_this_time = MIN( wr.bytes_left, EP0_FIFO_SIZE );
+	int bytes_written = 0;
+
+	while( bytes_this_time-- ) {
+//		PRINTKD( "%2.2X ", *wr.p );
+		UDDR0 = *wr.p++;
+		bytes_written++;
+	}
+	wr.bytes_left -= bytes_written;
+
+	usbd_info.stats.ep0_bytes_written += bytes_written;
+
+	if( (wr.bytes_left==0))
+	{
+		wr.p = NULL;  				/* be anal */
+
+ 		if(bytes_written < EP0_FIFO_SIZE)
+		{
+			int count;
+			int udccs0;
+
+			/* We always end the transfer with a short or zero length packet */
+			ep0_state = EP0_END_XFER;
+			current_handler = sh_setup_begin;
+
+			/* Let the packet go... */
+			UDCCS0 = UDCCS0_IPR;
+
+			/* Wait until we get to status-stage, then ack.
+			 *
+			 * When the UDC sets the UDCCS0[OPR] bit, an interrupt
+			 * is supposed to be generated (see 12.5.1 step 14ff, PXA Dev Manual).   
+			 * That approach didn't work out. Usually a new SETUP command was
+			 * already in the fifo. I tried many approaches but was always losing 
+			 * at least some OPR interrupts. Thus the polling below...
+			 */
+			count = 1000;
+			udccs0 = UDCCS0;
+			do
+			{
+				if( (UDCCS0 & UDCCS0_OPR)) 
+				{
+					/* clear OPR, generate ack */
+					UDCCS0 = UDCCS0_OPR;
+					break;
+				}
+				count--;	
+				udelay(1);
+			} while( count);
+
+			PRINTKD( "write fifo: count=%d UDCCS0=%x UDCCS0=%x\n", count, udccs0, UDCCS0);
+		}
+	}
+	/* something goes poopy if I dont wait here ... */
+	udelay(500);
+
+	PRINTKD( "write fifo: bytes sent=%d, bytes left=%d\n", bytes_written, wr.bytes_left);
+}
+
+/*
+ * read_fifo()
+ * Read bytes out of FIFO and put in request.
+ * Called to do the initial read of setup requests
+ * from the host. Return number of bytes read.
+ *
+ */
+static int read_fifo( usb_dev_request_t * request )
+{
+	int bytes_read = 0;
+	unsigned char * pOut = (unsigned char*) request;
+
+	int udccs0 = UDCCS0;
+
+	if( (udccs0 & SETUP_READY) == SETUP_READY)
+	{
+		/* ok it's a setup command */
+		while( UDCCS0 & UDCCS0_RNE)
+		{
+			if( bytes_read >= sizeof( usb_dev_request_t))
+			{
+				/* We've already read enought o fill usb_dev_request_t.
+				 * Our tummy is full. Go barf... 
+				 */
+				printk( "%sread_fifo(): read failure\n", pszMe );
+				usbd_info.stats.ep0_fifo_read_failures++;
+				break;
+			}
+
+			*pOut++ = UDDR0;
+			bytes_read++;
+		}
+	}
+	PRINTKD( "read_fifo %d bytes\n", bytes_read );
+
+	/* clear SA & OPR */
+	UDCCS0 = SETUP_READY;
+
+	usbd_info.stats.ep0_bytes_read += bytes_read;
+	return bytes_read;
+}
+
+/*
+ * get_descriptor()
+ * Called from sh_setup_begin to handle data return
+ * for a GET_DESCRIPTOR setup request.
+ */
+static void get_descriptor( usb_dev_request_t * pReq )
+{
+	string_desc_t * pString;
+	ep_desc_t * pEndpoint = 0;
+
+	desc_t * pDesc = pxa_usb_get_descriptor_ptr();
+	int type = pReq->wValue >> 8;
+	int idx  = pReq->wValue & 0xFF;
+
+//	PRINTKD( "%sget_descriptor for %d\n", pszMe, type );
+	switch( type ) {
+		case USB_DESC_DEVICE:
+			queue_and_start_write( &pDesc->dev,
+					pReq->wLength,
+					pDesc->dev.bLength );
+			break;
+
+			// return config descriptor buffer, cfg, intf, 2 ep
+		case USB_DESC_CONFIG:
+			queue_and_start_write( &pDesc->b,
+					pReq->wLength,
+					sizeof( struct cdb ) );
+			break;
+
+			// not quite right, since doesn't do language code checking
+		case USB_DESC_STRING:
+			pString = pxa_usb_get_string_descriptor( idx );
+			if ( pString ) {
+				if ( idx != 0 ) {  // if not language index
+					printk( "%sReturn string %d: ", pszMe, idx );
+					psdesc( pString );
+				}
+				queue_and_start_write( pString,
+						pReq->wLength,
+						pString->bLength );
+			}
+			else {
+				printk("%sunkown string index %d Stall.\n", pszMe, idx );
+			}
+			break;
+
+		case USB_DESC_INTERFACE:
+			if ( idx == pDesc->b.intf.bInterfaceNumber ) {
+				queue_and_start_write( &pDesc->b.intf,
+						pReq->wLength,
+						pDesc->b.intf.bLength );
+			}
+			break;
+
+		case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
+			if ( idx == 1 )
+				pEndpoint = &pDesc->b.ep1; //[BULK_IN1];
+			else if ( idx == 2 )
+				pEndpoint = &pDesc->b.ep2; //[BULK_OUT1];
+			else
+				pEndpoint = NULL;
+			if ( pEndpoint ) {
+				queue_and_start_write( pEndpoint,
+						pReq->wLength,
+						pEndpoint->bLength );
+			} else {
+				printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
+			}
+			break;
+
+
+		default :
+			printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
+			break;
+
+	}
+}
+
+/* end usb_ep0.c - who needs this comment? */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb_ep0.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (C) Intrinsyc, Inc., 2002
+ *
+ *  usb_ep0.h - PXA USB controller driver.
+ *              Endpoint zero management
+ *
+ *  Please see:
+ *    linux/Documentation/arm/SA1100/SA1100_USB
+ *  for details.
+ *
+ *  02-May-2002
+ *   Frank Becker (Intrinsyc) - 
+ * 
+ */
+
+#ifndef __USB_EP0_H
+#define __USB_EP0_H
+
+#define EP0_FIFO_SIZE	16
+#define SETUP_READY (UDCCS0_SA | UDCCS0_OPR)
+
+/*================================================
+ * USB Protocol Stuff
+ */
+
+/* Request Codes   */
+enum { 
+	GET_STATUS		=0,
+	CLEAR_FEATURE		=1,
+	/* reserved		=2 */
+	SET_FEATURE		=3,
+	/* reserved		=4 */
+	SET_ADDRESS		=5,        
+	GET_DESCRIPTOR		=6,
+	SET_DESCRIPTOR		=7,
+	GET_CONFIGURATION	=8,
+	SET_CONFIGURATION	=9,
+	GET_INTERFACE		=10,
+	SET_INTERFACE		=11,
+	SYNCH_FRAME		=12
+};
+
+typedef enum {
+	EP0_IDLE,
+	EP0_IN_DATA_PHASE,
+	EP0_END_XFER,
+	EP0_OUT_DATA_PHASE
+} EP0_state;
+
+/* USB Device Requests */
+typedef struct
+{
+	__u8 bmRequestType;
+	__u8 bRequest;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+} usb_dev_request_t  __attribute__ ((packed));
+
+/* Data extraction from usb_request_t fields */
+enum { 
+	kTargetDevice	=0,
+	kTargetInterface=1,
+	kTargetEndpoint	=2 
+};
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb_recv.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,173 @@
+/*
+ * Generic receive layer for the PXA USB client function
+ *
+ * This code was loosely inspired by the original version which was
+ * Copyright (c) Compaq Computer Corporation, 1998-1999
+ * Copyright (c) 2001 by Nicolas Pitre
+ *
+ * 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.
+ *
+ * 02-May-2002
+ *   Frank Becker (Intrinsyc) - derived from sa1100 usb_recv.c
+ * 
+ * TODO: Add support for DMA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+
+#include "pxa_usb.h"
+#include "usb_ctl.h"
+
+#if DEBUG
+static unsigned int usb_debug = DEBUG;
+#else
+#define usb_debug 0     /* gcc will remove all the debug code for us */
+#endif
+
+static char *ep_bulk_out1_buf;
+static int   ep_bulk_out1_len;
+static int   ep_bulk_out1_remain;
+static usb_callback_t ep_bulk_out1_callback;
+static int rx_pktsize;
+
+static void
+ep_bulk_out1_start(void)
+{
+	/* disable DMA */
+	UDCCS2 &= ~UDCCS_BO_DME;
+
+	/* enable interrupts for endpoint 2 (bulk out) */
+        UICR0 &= ~UICR0_IM2;
+}
+
+static void
+ep_bulk_out1_done(int flag)
+{
+	int size = ep_bulk_out1_len - ep_bulk_out1_remain;
+
+	if (!ep_bulk_out1_len)
+		return;
+
+	ep_bulk_out1_len = 0;
+	if (ep_bulk_out1_callback) {
+		ep_bulk_out1_callback(flag, size);
+	}
+}
+
+void
+ep_bulk_out1_state_change_notify( int new_state )
+{
+}
+
+void
+ep_bulk_out1_stall( void )
+{
+	/* SET_FEATURE force stall at UDC */
+	UDCCS2 |= UDCCS_BO_FST;
+}
+
+int
+ep_bulk_out1_init(int chn)
+{
+	desc_t * pd = pxa_usb_get_descriptor_ptr();
+	rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
+	ep_bulk_out1_done(-EAGAIN);
+	return 0;
+}
+
+void
+ep_bulk_out1_reset(void)
+{
+	desc_t * pd = pxa_usb_get_descriptor_ptr();
+	rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
+	UDCCS2 &= ~UDCCS_BO_FST;
+	ep_bulk_out1_done(-EINTR);
+}
+
+void
+ep_bulk_out1_int_hndlr(int udcsr)
+{
+	int status = UDCCS2;
+	if( usb_debug) printk("ep_bulk_out1_int_hndlr: UDCCS2=%x\n", status);
+
+	if( (status & (UDCCS_BO_RNE | UDCCS_BO_RSP)) == UDCCS_BO_RSP)
+	{
+		/* zero-length packet */
+	}
+
+	if( status & UDCCS_BO_RNE)
+	{
+		int len;
+		int i;
+		char *buf = ep_bulk_out1_buf + ep_bulk_out1_len - ep_bulk_out1_remain;
+
+		/* bytes in FIFO */
+		len = (UBCR2 & 0xff) +1;
+		
+		if( usb_debug) printk("usb_recv: "
+			"len=%d out1_len=%d out1_remain=%d\n",
+			len,ep_bulk_out1_len,ep_bulk_out1_remain);
+
+		if( len > ep_bulk_out1_remain)
+		{
+			/* FIXME: if this happens, we need a temporary overflow buffer */
+			printk("usb_recv: Buffer overwrite warning...\n");
+			len = ep_bulk_out1_remain;
+		}
+
+		/* read data out of fifo */
+		for( i=0; i<len; i++)
+		{
+			*buf++ = UDDR2 & 0xff;
+		}
+
+		ep_bulk_out1_remain -= len;
+		ep_bulk_out1_done((len) ? 0 : -EPIPE);
+	}
+
+	/* ack RPC - FIXME: '|=' we may ack SST here, too */
+	UDCCS2 |= UDCCS_BO_RPC;
+	return;
+}
+
+int
+pxa_usb_recv(char *buf, int len, usb_callback_t callback)
+{
+	int flags;
+
+	if (ep_bulk_out1_len)
+		return -EBUSY;
+
+	local_irq_save(flags);
+	ep_bulk_out1_buf = buf;
+	ep_bulk_out1_len = len;
+	ep_bulk_out1_callback = callback;
+	ep_bulk_out1_remain = len;
+	ep_bulk_out1_start();
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void
+pxa_usb_recv_reset(void)
+{
+	ep_bulk_out1_reset();
+}
+
+void
+pxa_usb_recv_stall(void)
+{
+	ep_bulk_out1_stall();
+}
+
+EXPORT_SYMBOL(pxa_usb_recv_stall);
+EXPORT_SYMBOL(pxa_usb_recv);
+EXPORT_SYMBOL(pxa_usb_recv_reset);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-pxa/usb_send.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,190 @@
+/*
+ * Generic xmit layer for the PXA USB client function
+ *
+ * This code was loosely inspired by the original version which was
+ * Copyright (c) Compaq Computer Corporation, 1998-1999
+ * Copyright (c) 2001 by Nicolas Pitre
+ *
+ * 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.
+ *
+ * 02-May-2002
+ *   Frank Becker (Intrinsyc) - derived from sa1100 usb_send.c
+ *
+ * TODO: Add support for DMA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+#include "pxa_usb.h"
+#include "usb_ctl.h"
+
+#if DEBUG
+static unsigned int usb_debug = DEBUG;
+#else
+#define usb_debug 0     /* gcc will remove all the debug code for us */
+#endif
+
+static char *ep_bulk_in1_buf;
+static int   ep_bulk_in1_len;
+static int   ep_bulk_in1_remain;
+static usb_callback_t ep_bulk_in1_callback;
+static int tx_pktsize;
+
+/* device state is changing, async */
+void
+ep_bulk_in1_state_change_notify( int new_state )
+{
+}
+
+/* set feature stall executing, async */
+void
+ep_bulk_in1_stall( void )
+{
+	UDCCS1 |= UDCCS_BI_FST;
+}
+
+static void
+ep_bulk_in1_send_packet(void)
+{
+	int i;
+	char *buf = ep_bulk_in1_buf + ep_bulk_in1_len - ep_bulk_in1_remain;
+	int out_size = tx_pktsize;
+
+	if( usb_debug) printk( "ep_bulk_in1_send_packet: UICR0=%x UDCCS1=%x\n", UICR0, UDCCS1);
+
+	if( out_size > ep_bulk_in1_remain) 
+	{
+		out_size = ep_bulk_in1_remain;
+	}
+
+	for( i=0; i<out_size; i++)
+	{
+		UDDR1 = *buf++;	
+	}
+
+	UDCCS1 = UDCCS_BI_TPC;
+	if( out_size < tx_pktsize)
+	{
+		/* short packet */
+		UDCCS1 = UDCCS_BI_TSP;
+	}
+	ep_bulk_in1_remain -= out_size;
+
+	if( usb_debug) printk( "ep_bulk_in1_send_packet: "
+		"UICR0=%x UDCCS1=%x send bytes=%d left=%d\n", 
+		UICR0, UDCCS1, out_size, ep_bulk_in1_remain);
+}
+
+static void
+ep_bulk_in1_start(void)
+{
+	if (!ep_bulk_in1_len)
+		return;
+
+        UICR0 &= ~UICR0_IM1;
+
+	ep_bulk_in1_send_packet();
+}
+
+static void
+ep_bulk_in1_done(int flag)
+{
+	int size = ep_bulk_in1_len - ep_bulk_in1_remain;
+	if (ep_bulk_in1_len) {
+		ep_bulk_in1_len = 0;
+		if (ep_bulk_in1_callback)
+			ep_bulk_in1_callback(flag, size);
+	}
+}
+
+int
+ep_bulk_in1_init(int chn)
+{
+	desc_t * pd = pxa_usb_get_descriptor_ptr();
+	tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
+	ep_bulk_in1_done(-EAGAIN);
+	return 0;
+}
+
+void
+ep_bulk_in1_reset(void)
+{
+	desc_t * pd = pxa_usb_get_descriptor_ptr();
+	tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
+	UDCCS1 &= ~UDCCS_BI_FST;
+	ep_bulk_in1_done(-EINTR);
+}
+
+void
+ep_bulk_in1_int_hndlr(int usir0)
+{
+	int status = UDCCS1;
+
+	if (ep_bulk_in1_remain != 0) {
+		/* more data to go */
+		ep_bulk_in1_start();
+	} else {
+		if( status & UDCCS_BI_TPC)
+		{
+			UDCCS1 = UDCCS_BI_TPC;
+		}
+		ep_bulk_in1_done(0);
+	}
+}
+
+int
+pxa_usb_send(char *buf, int len, usb_callback_t callback)
+{
+	int flags;
+
+	if( usb_debug) printk( "pxa_usb_send: "
+		"data len=%d state=%d blen=%d\n", 
+		len, usbd_info.state, ep_bulk_in1_len);
+
+	if (usbd_info.state != USB_STATE_CONFIGURED)
+		return -ENODEV;
+
+	if (ep_bulk_in1_len)
+		return -EBUSY;
+
+	local_irq_save(flags);
+	ep_bulk_in1_buf = buf;
+	ep_bulk_in1_len = len;
+	ep_bulk_in1_callback = callback;
+	ep_bulk_in1_remain = len;
+	ep_bulk_in1_start();
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+void
+pxa_usb_send_reset(void)
+{
+	ep_bulk_in1_reset();
+}
+
+int 
+pxa_usb_xmitter_avail( void )
+{
+	if (usbd_info.state != USB_STATE_CONFIGURED)
+		return -ENODEV;
+	if (ep_bulk_in1_len)
+		return -EBUSY;
+	return 0;
+}
+
+
+EXPORT_SYMBOL(pxa_usb_xmitter_avail);
+EXPORT_SYMBOL(pxa_usb_send);
+EXPORT_SYMBOL(pxa_usb_send_reset);
--- linux-2.4.25/arch/arm/mach-sa1100/sa1111-ohci.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-sa1100/sa1111-ohci.c	2004-03-31 17:15:11.000000000 +0200
@@ -54,7 +54,7 @@
 	 *  address as its return value, and the DMA address via
 	 *  the dma_addr_t pointer.
 	 */
-	vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
+	vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf, 0);
 
 	SADTSA = (unsigned long)dma_buf;
 	SADTCA = 4;
--- linux-2.4.25/arch/arm/mach-sa1100/sa1111.c~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/mach-sa1100/sa1111.c	2004-03-31 17:15:11.000000000 +0200
@@ -243,9 +243,15 @@
 	 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
 	 * (SA-1110 Developer's Manual, section 9.1.2.1)
 	 */
+#if CONFIG_ARCH_SA1100
 	GAFR |= GPIO_32_768kHz;
 	GPDR |= GPIO_32_768kHz;
 	TUCR = TUCR_3_6864MHz;
+#elif CONFIG_ARCH_PXA
+	set_GPIO_mode(GPIO11_3_6MHz_MD);
+#else
+#error missing clock setup
+#endif
 
 	/*
 	 * Turn VCO on, and disable PLL Bypass.
@@ -300,6 +306,8 @@
 	SBI_SMCR = smcr;
 }
 
+#ifdef CONFIG_ARCH_SA1100
+
 /*
  * Disable the memory bus request/grant signals on the SA1110 to
  * ensure that we don't receive spurious memory requests.  We set
@@ -341,5 +349,7 @@
 	local_irq_restore(flags);
 }
 
+#endif
+
 EXPORT_SYMBOL(sa1111_wake);
 EXPORT_SYMBOL(sa1111_doze);
--- linux-2.4.25/arch/arm/mm/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/arch/arm/mm/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -44,6 +44,7 @@
 p-$(CONFIG_CPU_ARM1026)	+= proc-arm1026.o
 p-$(CONFIG_CPU_SA110)	+= proc-sa110.o
 p-$(CONFIG_CPU_SA1100)	+= proc-sa110.o
+p-$(CONFIG_CPU_XSCALE)	+= proc-xscale.o
 
 # Integrator follows "new style"
 # Soon, others will do too, and we can get rid of this
--- linux-2.4.25/arch/arm/mm/consistent.c~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.25/arch/arm/mm/consistent.c	2004-03-31 17:15:11.000000000 +0200
@@ -37,7 +37,8 @@
  *
  * Note that this does *not* zero the allocated area!
  */
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle,
+		       unsigned long cache_flags)
 {
 	struct page *page, *end, *free;
 	unsigned long order;
@@ -55,7 +56,7 @@
 		goto no_page;
 
 	*dma_handle = page_to_bus(page);
-	ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0);
+	ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, cache_flags);
 	if (!ret)
 		goto no_remap;
 
@@ -106,7 +107,7 @@
 #endif
 		gfp |= GFP_DMA;
 
-	return consistent_alloc(gfp, size, handle);
+	return consistent_alloc(gfp, size, handle, 0);
 }
 
 /*
--- linux-2.4.25/arch/arm/mm/init.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/arch/arm/mm/init.c	2004-03-31 17:15:11.000000000 +0200
@@ -49,6 +49,9 @@
 static unsigned long totalram_pages;
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern char _stext, _text, _etext, _end, __init_begin, __init_end;
+#ifdef CONFIG_XIP_KERNEL
+extern char _endtext, _sdata;
+#endif
 extern unsigned long phys_initrd_start;
 extern unsigned long phys_initrd_size;
 
@@ -347,7 +350,11 @@
 	 * Register the kernel text and data with bootmem.
 	 * Note that this can only be in node 0.
 	 */
+#ifdef CONFIG_XIP_KERNEL
+	reserve_bootmem_node(pgdat, __pa(&_sdata), &_end - &_sdata);
+#else
 	reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+#endif
 
 #ifdef CONFIG_CPU_32
 	/*
@@ -601,8 +608,13 @@
 	unsigned int codepages, datapages, initpages;
 	int i, node;
 
+#ifndef CONFIG_XIP_KERNEL
 	codepages = &_etext - &_text;
 	datapages = &_end - &_etext;
+#else
+	codepages = &_endtext - &_text;
+	datapages = &_end - &_sdata;
+#endif
 	initpages = &__init_end - &__init_begin;
 
 	high_memory = (void *)__va(meminfo.end);
@@ -658,11 +670,13 @@
 
 void free_initmem(void)
 {
+#ifndef CONFIG_XIP_KERNEL
 	if (!machine_is_integrator()) {
 		free_area((unsigned long)(&__init_begin),
 			  (unsigned long)(&__init_end),
 			  "init");
 	}
+#endif
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
--- linux-2.4.25/arch/arm/mm/mm-armv.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/arch/arm/mm/mm-armv.c	2004-03-31 17:15:11.000000000 +0200
@@ -356,6 +356,19 @@
 	p ++;
 #endif
 
+#ifdef CONFIG_XIP_KERNEL
+	p->physical   = KERNEL_XIP_BASE_PHYS;
+	p->virtual    = KERNEL_XIP_BASE_VIRT;
+	p->length     = PGDIR_SIZE * 8;
+	p->domain     = DOMAIN_KERNEL;
+	p->prot_read  = 0;	/* r=0, b=0 --> read-only for kernel mode */
+	p->prot_write = 0;
+	p->cacheable  = 1;
+	p->bufferable = 1;
+
+	p ++;
+#endif
+
 	/*
 	 * Go through the initial mappings, but clear out any
 	 * pgdir entries that are not in the description.
@@ -386,7 +399,7 @@
 	init_maps->prot_read  = 0;
 	init_maps->prot_write = 0;
 	init_maps->cacheable  = 1;
-	init_maps->bufferable = 0;
+	init_maps->bufferable = 1;
 
 	create_mapping(init_maps);
 
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/mm/proc-xscale.S	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,1086 @@
+/*
+ *  linux/arch/arm/mm/proc-xscale.S
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	November 2000
+ *  Copyright:	(C) 2000, 2001 MontaVista Software 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.
+ *
+ * MMU functions for the Intel XScale CPUs
+ *
+ * 2001 Aug 21:	
+ *	some contributions by Brett Gaines <brett.w.gaines@intel.com>
+ *	Copyright 2001 by Intel Corp.
+ *
+ * 2001 Sep 08:
+ *	Completely revisited, many important fixes
+ *	Nicolas Pitre <nico@cam.org>
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+#include <asm/proc/pgtable.h>
+
+/*
+ * Some knobs for cache allocation policy.
+ * Allocate on write may or may not be beneficial depending on the memory
+ * usage pattern of your main application.  Write through cache is definitely
+ * a performance loss in most cases, but might be used for special purposes.
+ */
+#define PMD_CACHE_WRITE_ALLOCATE 1
+#define PTE_CACHE_WRITE_ALLOCATE 1
+#define CACHE_WRITE_THROUGH 0
+
+/*
+ * There are errata that say that dirty status bits in the cache may get
+ * corrupted. The workaround significantly affects performance, and the bug
+ * _might_ just not be that visible or critical to you, so it is configurable.
+ * Let's hope a future core revision will tell us this was only a bad dream.
+ * But in the mean time the risk and tradeoff is yours to decide....
+ */
+#ifdef CONFIG_XSCALE_CACHE_ERRATA
+#undef CACHE_WRITE_THROUGH
+#define CACHE_WRITE_THROUGH 1
+#endif
+
+/* 
+ * This is the maximum size of an area which will be flushed.  If the area
+ * is larger than this, then we flush the whole cache
+ */
+#define MAX_AREA_SIZE	32768
+
+/*
+ * the cache line size of the I and D cache
+ */
+#define CACHELINESIZE	32
+
+/*
+ * the size of the data cache
+ */
+#define CACHESIZE	32768
+
+/*
+ * and the page size
+ */
+#define PAGESIZE	4096
+
+/*
+ * Virtual address used to allocate the cache when flushed
+ *
+ * This must be an address range which is _never_ used.  It should 
+ * apparently have a mapping in the corresponding page table for 
+ * compatibility with future CPUs that _could_ require it.  For instance we
+ * don't care.
+ *
+ * This must be aligned on a 2*CACHESIZE boundary.  The code selects one of
+ * the 2 areas in alternance each time the clean_d_cache macro is used.
+ * Without this the XScale core exhibits cache eviction problems and no one
+ * knows why.  
+ *
+ * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
+ */
+#define CLEAN_ADDR	0xfffe0000
+
+/*
+ * This macro is used to wait for a CP15 write and is needed
+ * when we have to ensure that the last operation to the co-pro
+ * was completed before continuing with operation.
+ */
+	.macro	cpwait, rd
+	mrc	p15, 0, \rd, c2, c0, 0		@ arbitrary read of cp15
+	mov	\rd, \rd			@ wait for completion
+	sub 	pc, pc, #4			@ flush instruction pipeline
+	.endm	
+
+	.macro	cpwait_ret, lr, rd
+	mrc	p15, 0, \rd, c2, c0, 0		@ arbitrary read of cp15
+	sub	pc, \lr, \rd, LSR #32		@ wait for completion and
+						@ flush instruction pipeline
+	.endm
+
+#if !CACHE_WRITE_THROUGH
+
+/*
+ * This macro cleans the entire dcache using line allocate.
+ * The main loop has been unrolled to reduce loop overhead.
+ * rd and rs are two scratch registers.
+ */
+	.macro  clean_d_cache, rd, rs
+	ldr	\rs, =clean_addr
+	ldr	\rd, [\rs]
+	eor	\rd, \rd, #CACHESIZE
+	str	\rd, [\rs]
+	add	\rs, \rd, #CACHESIZE
+1:	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
+	add	\rd, \rd, #CACHELINESIZE
+	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
+	add	\rd, \rd, #CACHELINESIZE
+	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
+	add	\rd, \rd, #CACHELINESIZE
+	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
+	add	\rd, \rd, #CACHELINESIZE
+	teq	\rd, \rs
+	bne	1b
+	.endm
+
+	.macro	clean_d_line,	rd
+	mcr	p15, 0, \rd, c7, c10, 1
+	.endm
+
+	.data
+clean_addr:	.word	CLEAN_ADDR
+
+#else
+
+/*
+ * If cache is write-through, there is no need to clean it.
+ * Simply invalidating will do.
+ */
+
+	.macro  clean_d_cache, rd, rs
+	mcr	p15, 0, \rd, c7, c6, 0
+	.endm
+
+	/* let's try to skip this needless operations at least within loops */
+	.macro	clean_d_line,	rd
+	.endm
+
+#endif
+
+	.text
+
+/*
+ * cpu_xscale_data_abort()
+ *
+ * obtain information about current aborted instruction.
+ * Note: we read user space.  This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture.  Unfortunately, this does happen.  We live with it.
+ *
+ *  r2 = address of aborted instruction
+ *  r3 = saved SPSR
+ *
+ * Returns:
+ *  r0 = address of abort
+ *  r1 = FSR, bit 11 = write
+ *  r3 = corrupted
+ */
+	.align	5
+ENTRY(cpu_xscale_data_abort)
+	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
+	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
+	ldr	r3, [r2]			@ read aborted instruction
+	bic	r1, r1, #1 << 11		@ clear bits 11 of FSR
+	tst	r3, #1 << 20			@ check write
+	orreq	r1, r1, #1 << 11
+	mov	pc, lr
+
+/*
+ * cpu_xscale_check_bugs()
+ */
+ENTRY(cpu_xscale_check_bugs)
+	mrs	ip, cpsr
+	bic	ip, ip, #F_BIT
+	msr	cpsr, ip
+	mov	pc, lr
+
+#ifndef CONFIG_XSCALE_CACHE_ERRATA
+/*
+ * cpu_xscale_proc_init()
+ *
+ * Nothing too exciting at the moment
+ */
+ENTRY(cpu_xscale_proc_init)
+	mov	pc, lr
+#else
+/*
+ * We enable the cache here, but we make sure all the status bits for dirty
+ * lines are cleared as well (see PXA250 erratum #120).
+ */
+ENTRY(cpu_xscale_proc_init)
+	@ enable data cache
+	ldr	r0, cr_p
+	ldmia	r0, {r1, r2}
+	orr	r1, r1, #0x4
+	orr	r2, r2, #0x4
+	stmia	r0, {r1, r2}
+	mcr	p15, 0, r1, c1, c0, 0
+	cpwait	r0
+
+	@ invalidate data cache
+	mcr	p15, 0, r0, c7, c6, 0
+
+	@ fill main cache with write-through lines
+	bic	r0, pc, #0x1f
+	add	r1, r0, #CACHESIZE
+1:	ldr	r2, [r0], #32
+	cmp	r0, r1
+	bne	1b
+
+	@ enable test feature to force all fills to the mini-cache
+	mov	r1, #0x8
+	mcr	p15, 0, r1, c15, c15, 3
+
+	@ fill mini-cache with write-through lines (2kbytes, 64 lines)
+	add	r1, r0, #2048
+2:	ldr	r2, [r0], #32
+	cmp	r0, r1
+	bne	2b
+
+	@ disable test feature to force all fills to the mini-cache
+	mov	r1, #0x0
+	mcr	p15, 0, r1, c15, c15, 3
+
+	@ invalidate data cache again
+	mcr	p15, 0, r1, c7, c6, 0
+	mov	pc, lr
+
+cr_p:	.long	SYMBOL_NAME(cr_alignment)
+#endif
+
+/*
+ * cpu_xscale_proc_fin()
+ */
+ENTRY(cpu_xscale_proc_fin)
+	str	lr, [sp, #-4]!
+	mov	r0, #F_BIT|I_BIT|SVC_MODE
+	msr	cpsr_c, r0
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x1800			@ ...IZ...........
+	bic	r0, r0, #0x0006			@ .............CA.
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	bl	cpu_xscale_cache_clean_invalidate_all	@ clean caches
+	ldr	pc, [sp], #4
+
+/*
+ * cpu_xscale_reset(loc)
+ *
+ * Perform a soft reset of the system.  Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_xscale_reset)
+	mov	r1, #F_BIT|I_BIT|SVC_MODE
+	msr	cpsr_c, r1			@ reset CPSR
+	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
+	bic	r1, r1, #0x0086			@ ........B....CA.
+	bic	r1, r1, #0x1900			@ ...IZ..S........
+	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches & BTB
+	bic	r1, r1, #0x0001			@ ...............M
+	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
+	@ CAUTION: MMU turned off from this point. We count on the pipeline 
+	@ already containing those two last instructions to survive.
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mov	pc, r0
+
+/*
+ * cpu_xscale_do_idle(type)
+ *
+ * Cause the processor to idle
+ *
+ * type: 
+ *   0 = slow idle
+ *   1 = fast idle
+ *   2 = switch to slow processor clock
+ *   3 = switch to fast processor clock
+ *
+ * For now we do nothing but go to idle mode for every case
+ *
+ * XScale supports clock switching, but using idle mode support
+ * allows external hardware to react to system state changes.
+ */
+	.align	5
+
+ENTRY(cpu_xscale_do_idle)
+	mov	r0, #1
+	mcr	p14, 0, r0, c7, c0, 0		@ Go to IDLE
+	mov	pc, lr
+
+/* ================================= CACHE ================================ */
+
+/*
+ * cpu_xscale_cache_clean_invalidate_all (void)
+ *
+ * clean and invalidate all cache lines
+ *
+ * Note:
+ *  1. We should preserve r0 at all times.
+ *  2. Even if this function implies cache "invalidation" by its name,
+ *     we don't need to actually use explicit invalidation operations
+ *     since the goal is to discard all valid references from the cache
+ *     and the cleaning of it already has that effect.
+ *  3. Because of 2 above and the fact that kernel space memory is always
+ *     coherent across task switches there is no need to worry about
+ *     inconsistencies due to interrupts, ence no irq disabling.
+ */
+	.align	5
+ENTRY(cpu_xscale_cache_clean_invalidate_all)
+	mov	r2, #1
+cpu_xscale_cache_clean_invalidate_all_r2:
+	clean_d_cache r0, r1
+	teq	r2, #0
+	mcrne	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/*
+ * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * start: Area start address
+ * end:   Area end address
+ * flags: nonzero for I cache as well
+ */
+	.align	5
+ENTRY(cpu_xscale_cache_clean_invalidate_range)
+	bic	r0, r0, #CACHELINESIZE - 1	@ round down to cache line
+	sub	r3, r1, r0
+	cmp	r3, #MAX_AREA_SIZE
+	bhi	cpu_xscale_cache_clean_invalidate_all_r2
+1:	clean_d_line r0				@ Clean D cache line
+	mcr	p15, 0, r0, c7, c6, 1		@ Invalidate D cache line
+	add	r0, r0, #CACHELINESIZE
+	cmp	r0, r1
+	blo	1b
+	teq	r2, #0
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	moveq	pc, lr
+	sub	r0, r0, r3
+1:	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	add	r0, r0, #CACHELINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
+	mov	pc, lr 
+
+/*
+ * cpu_xscale_flush_ram_page(page)
+ *
+ * clean all cache lines associated with this memory page
+ *
+ * page: page to clean
+ */
+	.align	5
+ENTRY(cpu_xscale_flush_ram_page)
+#if !CACHE_WRITE_THROUGH
+	mov	r1, #PAGESIZE
+1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	subs	r1, r1, #2 * CACHELINESIZE
+	bne	1b
+#endif
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/* ================================ D-CACHE =============================== */
+
+/*
+ * cpu_xscale_dcache_invalidate_range(start, end)
+ *
+ * throw away all D-cached data in specified region without an obligation
+ * to write them back.  Note however that on XScale we must clean all
+ * entries also due to hardware errata (80200 A0 & A1 only).
+ *
+ * start: virtual start address
+ * end:   virtual end address
+ */
+	.align	5
+ENTRY(cpu_xscale_dcache_invalidate_range)
+	mrc	p15, 0, r2, c0, c0, 0		@ Read part no.
+	eor	r2, r2, #0x69000000
+	eor	r2, r2, #0x00052000		@ 80200 XX part no.
+	bics	r2, r2, #0x1			@ Clear LSB in revision field
+	moveq	r2, #0
+	beq	cpu_xscale_cache_clean_invalidate_range	@ An 80200 A0 or A1
+
+	tst	r0, #CACHELINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	tst	r1, #CACHELINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ Clean D cache line
+	bic	r0, r0, #CACHELINESIZE - 1	@ round down to cache line
+1:	mcr	p15, 0, r0, c7, c6, 1		@ Invalidate D cache line
+	add	r0, r0, #CACHELINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	pc, lr
+
+/*
+ * cpu_xscale_dcache_clean_range(start, end)
+ *
+ * For the specified virtual address range, ensure that all caches contain
+ * clean data, such that peripheral accesses to the physical RAM fetch
+ * correct data.
+ *
+ * start: virtual start address
+ * end:   virtual end address
+ */
+	.align	5
+ENTRY(cpu_xscale_dcache_clean_range)
+#if !CACHE_WRITE_THROUGH
+	bic	r0, r0, #CACHELINESIZE - 1
+	sub	r2, r1, r0
+	cmp	r2, #MAX_AREA_SIZE
+	movhi	r2, #0
+	bhi	cpu_xscale_cache_clean_invalidate_all_r2
+
+1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	cmp	r0, r1
+	blo	1b
+#endif
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/*
+ * cpu_xscale_clean_dcache_page(page)
+ *
+ * Cleans a single page of dcache so that if we have any future aliased
+ * mappings, they will be consistent at the time that they are created.
+ *
+ * Note:
+ *  1. we don't need to flush the write buffer in this case. [really? -Nico]
+ *  2. we don't invalidate the entries since when we write the page
+ *     out to disk, the entries may get reloaded into the cache.
+ */
+	.align	5
+ENTRY(cpu_xscale_dcache_clean_page)
+#if !CACHE_WRITE_THROUGH
+	mov	r1, #PAGESIZE
+1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	add	r0, r0, #CACHELINESIZE
+	subs	r1, r1, #4 * CACHELINESIZE
+	bne	1b
+#endif
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/*
+ * cpu_xscale_dcache_clean_entry(addr)
+ *
+ * Clean the specified entry of any caches such that the MMU
+ * translation fetches will obtain correct data.
+ *
+ * addr: cache-unaligned virtual address
+ */
+	.align	5
+ENTRY(cpu_xscale_dcache_clean_entry)
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/* ================================ I-CACHE =============================== */
+
+/*
+ * cpu_xscale_icache_invalidate_range(start, end)
+ *
+ * invalidate a range of virtual addresses from the Icache
+ *
+ * start: virtual start address
+ * end:   virtual end address
+ *
+ * Note: This is vaguely defined as supposed to bring the dcache and the 
+ *       icache in sync by the way this function is used.
+ */
+	.align	5
+ENTRY(cpu_xscale_icache_invalidate_range)
+	bic	r0, r0, #CACHELINESIZE - 1
+1:	clean_d_line r0				@ Clean D cache line
+	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	add	r0, r0, #CACHELINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/*
+ * cpu_xscale_icache_invalidate_page(page)
+ *
+ * invalidate all Icache lines associated with this area of memory
+ *
+ * page: page to invalidate
+ */
+	.align	5
+ENTRY(cpu_xscale_icache_invalidate_page)
+	mov	r1, #PAGESIZE
+1:	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	add	r0, r0, #CACHELINESIZE
+	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	add	r0, r0, #CACHELINESIZE
+	subs	r1, r1, #4 * CACHELINESIZE
+	bne	1b
+	mcr	p15, 0, r0, c7, c5, 6		@ Invalidate BTB
+	mov	pc, lr
+
+/* ================================ CACHE LOCKING============================ 
+ *
+ * The XScale MicroArchitecture implements support for locking entries into
+ * the data and instruction cache.  The following functions implement the core
+ * low level instructions needed to accomplish the locking.  The developer's
+ * manual states that the code that performs the locking must be in non-cached
+ * memory.  To accomplish this, the code in xscale-cache-lock.c copies the
+ * following functions from the cache into a non-cached memory region that
+ * is allocated through consistent_alloc().
+ *
+ */
+	.align	5
+/*
+ * xscale_icache_lock
+ *
+ * r0: starting address to lock
+ * r1: end address to lock
+ */
+ENTRY(xscale_icache_lock)
+
+iLockLoop:
+	bic	r0, r0, #CACHELINESIZE - 1
+	mcr	p15, 0, r0, c9, c1, 0	@ lock into cache
+	cmp	r0, r1			@ are we done?
+	add	r0, r0, #CACHELINESIZE	@ advance to next cache line
+	bls	iLockLoop
+	mov	pc, lr
+
+/*
+ * xscale_icache_unlock
+ */
+ENTRY(xscale_icache_unlock)
+	mcr	p15, 0, r0, c9, c1, 1	@ Unlock icache
+	mov	pc, lr
+	
+/*
+ * xscale_dcache_lock
+ *
+ * r0: starting address to lock
+ * r1: end address to lock
+ */
+ENTRY(xscale_dcache_lock)
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	r2, #1
+	mcr	p15, 0, r2, c9, c2, 0	@ Put dcache in lock mode
+	cpwait	ip			@ Wait for completion
+
+	mrs	r2, cpsr
+	orr	r3, r2, #F_BIT | I_BIT
+dLockLoop:
+	msr	cpsr_c, r3
+	mcr	p15, 0, r0, c7, c10, 1	@ Write back line if it is dirty 
+	mcr	p15, 0, r0, c7, c6, 1	@ Flush/invalidate line
+	msr	cpsr_c, r2
+	ldr	ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from 
+					@ location [r0]. Post-increment
+					@ r3 to next cache line
+	cmp	r0, r1			@ Are we done?
+	bls	dLockLoop
+
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	r2, #0
+	mcr	p15, 0, r2, c9, c2, 0	@ Get out of lock mode
+	cpwait_ret lr, ip
+
+/*
+ * xscale_dcache_unlock
+ */
+ENTRY(xscale_dcache_unlock)
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcr	p15, 0, ip, c9, c2, 1	@ Unlock cache
+	mov	pc, lr
+
+/*
+ * Needed to determine the length of the code that needs to be copied.
+ */
+	.align	5
+ENTRY(xscale_cache_dummy)
+	mov	pc, lr
+
+/* ================================== TLB ================================= */
+
+/*
+ * cpu_xscale_tlb_invalidate_all()
+ *
+ * Invalidate all TLB entries
+ */
+	.align	5
+ENTRY(cpu_xscale_tlb_invalidate_all)
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	cpwait_ret lr, ip
+
+/*
+ * cpu_xscale_tlb_invalidate_range(start, end)
+ *
+ * invalidate TLB entries covering the specified range
+ *
+ * start: range start address
+ * end:   range end address
+ */
+	.align	5
+ENTRY(cpu_xscale_tlb_invalidate_range)
+	bic	r0, r0, #(PAGESIZE - 1) & 0x00ff
+	bic	r0, r0, #(PAGESIZE - 1) & 0xff00
+	sub	r3, r1, r0
+	cmp	r3, #256 * PAGESIZE		@ arbitrary, should be tuned
+	bhi	cpu_xscale_tlb_invalidate_all
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+1:	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
+	mcr	p15, 0, r0, c8, c5, 1		@ invalidate I TLB entry
+	add	r0, r0, #PAGESIZE
+	cmp	r0, r1
+	blo	1b
+	cpwait_ret lr, ip
+
+/*
+ * cpu_xscale_tlb_invalidate_page(page, flags)
+ *
+ * invalidate the TLB entries for the specified page.
+ *
+ * page:  page to invalidate
+ * flags: non-zero if we include the I TLB
+ */
+	.align	5
+ENTRY(cpu_xscale_tlb_invalidate_page)
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	teq	r1, #0
+	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
+	mcrne	p15, 0, r3, c8, c5, 1		@ invalidate I TLB entry
+	cpwait_ret lr, ip
+
+/* ================================ TLB LOCKING==============================
+ *
+ * The XScale MicroArchitecture implements support for locking entries into
+ * the Instruction and Data TLBs.  The following functions provide the
+ * low level support for supporting these under Linux.  xscale-lock.c 
+ * implements some higher level management code.  Most of the following
+ * is taken straight out of the Developer's Manual.
+ */
+
+/*
+ * Lock I-TLB entry
+ *
+ * r0: Virtual address to translate and lock
+ */
+	.align	5
+ENTRY(xscale_itlb_lock)
+	mrs	r2, cpsr
+	orr	r3, r2, #F_BIT | I_BIT
+	msr	cpsr_c, r3			@ Disable interrupts
+	mcr	p15, 0, r0, c8, c5, 1		@ Invalidate I-TLB entry
+	mcr	p15, 0, r0, c10, c4, 0		@ Translate and lock
+	msr	cpsr_c, r2			@ Restore interrupts
+	cpwait_ret lr, ip
+
+/*
+ * Lock D-TLB entry
+ *
+ * r0: Virtual address to translate and lock
+ */
+	.align	5
+ENTRY(xscale_dtlb_lock)
+	mrs	r2, cpsr
+	orr	r3, r2, #F_BIT | I_BIT
+	msr	cpsr_c, r3			@ Disable interrupts
+	mcr	p15, 0, r0, c8, c6, 1		@ Invalidate D-TLB entry
+	mcr	p15, 0, r0, c10, c8, 0		@ Translate and lock
+	msr	cpsr_c, r2			@ Restore interrupts
+	cpwait_ret lr, ip
+
+/*
+ * Unlock all I-TLB entries
+ */
+	.align	5
+ENTRY(xscale_itlb_unlock)
+	mcr	p15, 0, ip, c10, c4, 1		@ Unlock I-TLB
+	mcr	p15, 0, ip, c8, c5, 0		@ Invalidate I-TLB
+	cpwait_ret lr, ip
+
+/*
+ * Unlock all D-TLB entries
+ */
+ENTRY(xscale_dtlb_unlock)
+	mcr	p15, 0, ip, c10, c8, 1		@ Unlock D-TBL
+	mcr	p15, 0, ip, c8, c6, 0		@ Invalidate D-TLB
+	cpwait_ret lr, ip
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_xscale_set_pgd(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+	.align	5
+ENTRY(cpu_xscale_set_pgd)
+	clean_d_cache r1, r2
+	mcr	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	cpwait_ret lr, ip
+
+/*
+ * cpu_xscale_set_pmd(pmdp, pmd)
+ *
+ * Set a level 1 translation table entry, and clean it out of
+ * any caches such that the MMUs can load it correctly.
+ *
+ * pmdp: pointer to PMD entry
+ * pmd:  PMD value to store
+ */
+	.align	5
+ENTRY(cpu_xscale_set_pmd)
+#if PMD_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
+	and	r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
+	cmp	r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
+	orreq	r1, r1, #PMD_SECT_TEX(1)
+#elif CACHE_WRITE_THROUGH
+	and	r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
+	cmp	r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
+	biceq	r1, r1, #PMD_SECT_BUFFERABLE
+#endif
+	str	r1, [r0]
+	mov	ip, #0
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+/*
+ * cpu_xscale_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ *
+ * Errata 40: must set memory to write-through for user read-only pages.
+ */
+	.align	5
+ENTRY(cpu_xscale_set_pte)
+	str	r1, [r0], #-1024		@ linux version
+
+	bic	r2, r1, #0xff0
+	orr	r2, r2, #PTE_TYPE_EXT		@ extended page
+
+	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+	tst	r3, #L_PTE_USER | L_PTE_EXEC	@ User or Exec?
+	orrne	r2, r2, #PTE_EXT_AP_URO_SRW	@ yes -> user r/o, system r/w
+
+	tst	r3, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
+	orreq	r2, r2, #PTE_EXT_AP_UNO_SRW	@ yes -> user n/a, system r/w
+						@ combined with user -> user r/w
+
+	@
+	@ Handle the X bit.  We want to set this bit for the minicache
+	@ (U = E = B = W = 0, C = 1) or when write allocate is enabled,
+	@ and we have a writeable, cacheable region.  If we ignore the
+	@ U and E bits, we can allow user space to use the minicache as
+	@ well.
+	@
+	@  X = C & ~W & ~B
+	@      | C & W & B & write_allocate
+	@
+	eor	ip, r1, #L_PTE_CACHEABLE
+	tst	ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
+#if PTE_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
+	eorne	ip, r1, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
+	tstne	ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
+#endif
+	orreq	r2, r2, #PTE_EXT_TEX(1)
+
+#if CACHE_WRITE_THROUGH
+	tst	r1, #L_PTE_CACHEABLE
+	bicne	r2, r2, #L_PTE_BUFFERABLE	@ clear B only if C is set
+#else
+	@
+	@ Errata 40: The B bit must be cleared for a user read-only
+	@ cacheable page.
+	@
+	@  B = B & ~((U|E) & C & ~W)
+	@
+	and	ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE
+	teq	ip, #L_PTE_USER | L_PTE_CACHEABLE
+	teqne	ip, #L_PTE_EXEC | L_PTE_CACHEABLE
+	teqne	ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE
+	biceq	r2, r2, #PTE_BUFFERABLE
+#endif
+
+	tst	r3, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
+	movne	r2, #0				@ no -> fault
+
+	str	r2, [r0]			@ hardware version
+
+	@ We try to map 64K page entries when possible.  
+	@ We do that for kernel space only since the usage pattern from
+	@ the setting of VM area is quite simple.  User space is not worth
+	@ the implied complexity because of ever randomly changing PTEs 
+	@ (page aging, swapout, etc) requiring constant coherency checks.
+	@ Since PTEs are usually set in increasing order, we test the
+	@ possibility for a large page only when given the last PTE of a
+	@ 64K boundary.
+	tsteq	r1, #L_PTE_USER
+	andeq	r1, r0, #(15 << 2)
+	teqeq	r1, #(15 << 2)
+	beq	1f
+
+	mov	ip, #0
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+	@ See if we have 16 identical PTEs but with consecutive base addresses
+1:	bic	r3, r2, #0x0000f000
+	mov	r1, #0x0000f000
+2:	eor	r2, r2, r3
+	teq	r2, r1
+	bne	4f
+	subs	r1, r1, #0x00001000
+	ldr	r2, [r0, #-4]!
+	bne	2b
+	eors	r2, r2, r3
+	bne	4f
+
+	@ Now create our LARGE PTE from the current EXT one.
+	bic	r3, r3, #PTE_TYPE_MASK
+	orr	r3, r3, #PTE_TYPE_LARGE
+	and	r2, r3, #0x30			@ EXT_AP --> LARGE_AP0
+	orr	r2, r2, r2, lsl #2		@ add LARGE_AP1
+	orr	r2, r2, r2, lsl #4		@ add LARGE_AP3 + LARGE_AP2
+	and	r1, r3, #0x3c0			@ EXT_TEX
+	bic	r3, r3, #0x3c0
+	orr	r2, r2, r1, lsl #(12 - 6)	@ --> LARGE_TEX
+	orr	r2, r2, r3			@ add remaining bits
+
+	@ then put it in the pagetable
+	mov	r3, r2
+3:	strd	r2, [r0], #8
+	tst	r0, #(15 << 2)
+	bne	3b
+
+	@ Then sync the 2 corresponding cache lines
+	sub	r0, r0, #(16 << 2)
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+4:	orr	r0, r0, #(15 << 2)
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
+
+	.ltorg
+
+cpu_manu_name:
+	.asciz	"Intel"
+
+cpu_80200_name:
+	.asciz	"XScale-80200"
+
+cpu_pxa210_name:
+	.asciz	"XScale-PXA210"
+
+cpu_pxa250_name:
+	.asciz	"XScale-PXA250"
+
+cpu_pxa255_name:
+	.asciz	"XScale-PXA255"
+
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+__xscale_setup:
+	mov	r0, #F_BIT|I_BIT|SVC_MODE
+	msr	cpsr_c, r0
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I, D caches & BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I, D TLBs
+	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
+	mov	r0, #0x1f			@ Domains 0, 1 = client
+	mcr	p15, 0, r0, c3, c0, 0		@ load domain access register
+	mov	r0, #1				@ Allow user space to access
+	mcr	p15, 0, r0, c15, c1, 0		@ ... CP 0 only.
+#if CACHE_WRITE_THROUGH
+	mov	r0, #0x20
+#else
+	mov	r0, #0x00
+#endif
+	mcr	p15, 0, r0, c1, c1, 0		@ set auxiliary control reg
+	mrc	p15, 0, r0, c1, c0, 0		@ get control register
+	bic	r0, r0, #0x0200			@ ......R.........
+	bic	r0, r0, #0x0082			@ ........B.....A.
+	orr	r0, r0, #0x0005			@ .............C.M
+	orr	r0, r0, #0x3900			@ ..VIZ..S........
+#ifdef CONFIG_XSCALE_CACHE_ERRATA
+	bic	r0, r0, #0x0004			@ see cpu_xscale_proc_init
+#endif
+	mov	pc, lr
+
+	.text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+
+	.type	xscale_processor_functions, #object
+ENTRY(xscale_processor_functions)
+	.word	cpu_xscale_data_abort
+	.word	cpu_xscale_check_bugs
+	.word	cpu_xscale_proc_init
+	.word	cpu_xscale_proc_fin
+	.word	cpu_xscale_reset
+	.word	cpu_xscale_do_idle
+
+	/* cache */
+	.word	cpu_xscale_cache_clean_invalidate_all
+	.word	cpu_xscale_cache_clean_invalidate_range
+	.word	cpu_xscale_flush_ram_page
+
+	/* dcache */
+	.word	cpu_xscale_dcache_invalidate_range
+	.word	cpu_xscale_dcache_clean_range
+	.word	cpu_xscale_dcache_clean_page
+	.word	cpu_xscale_dcache_clean_entry
+
+	/* icache */
+	.word	cpu_xscale_icache_invalidate_range
+	.word	cpu_xscale_icache_invalidate_page
+
+	/* tlb */
+	.word	cpu_xscale_tlb_invalidate_all
+	.word	cpu_xscale_tlb_invalidate_range
+	.word	cpu_xscale_tlb_invalidate_page
+
+	/* pgtable */
+	.word	cpu_xscale_set_pgd
+	.word	cpu_xscale_set_pmd
+	.word	cpu_xscale_set_pte
+	.size	xscale_processor_functions, . - xscale_processor_functions
+
+	.type	cpu_80200_info, #object
+cpu_80200_info:
+	.long	cpu_manu_name
+	.long	cpu_80200_name
+	.size	cpu_80200_info, . - cpu_80200_info
+
+	.type	cpu_pxa210_info, #object
+cpu_pxa210_info:
+	.long	cpu_manu_name
+	.long	cpu_pxa210_name
+	.size	cpu_pxa210_info, . - cpu_pxa210_info
+
+	.type	cpu_pxa250_info, #object
+cpu_pxa250_info:
+	.long	cpu_manu_name
+	.long	cpu_pxa250_name
+	.size	cpu_pxa250_info, . - cpu_pxa250_info
+
+	.type	cpu_pxa255_info, #object
+cpu_pxa255_info:
+	.long	cpu_manu_name
+	.long	cpu_pxa255_name
+	.size	cpu_pxa255_info, . - cpu_pxa255_info
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv5te"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v5"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info", #alloc, #execinstr
+
+	.type	__80200_proc_info,#object
+__80200_proc_info:
+	.long	0x69052000
+	.long	0xfffffff0
+#if CACHE_WRITE_THROUGH
+	.long	0x00000c0a
+#else
+	.long	0x00000c0e
+#endif
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
+	.long	cpu_80200_info
+	.long	xscale_processor_functions
+	.size	__80200_proc_info, . - __80200_proc_info
+
+	.type	__pxa210_proc_info,#object
+__pxa210_proc_info:
+	.long	0x69052120
+	.long	0xfffff3f0
+#if CACHE_WRITE_THROUGH
+	.long	0x00000c0a
+#else
+	.long	0x00000c0e
+#endif
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
+	.long	cpu_pxa210_info
+	.long	xscale_processor_functions
+	.size	__pxa210_proc_info, . - __pxa210_proc_info
+
+	.type	__pxa250_proc_info,#object
+__pxa250_proc_info:
+	.long	0x69052100
+	.long	0xfffff7f0
+#if CACHE_WRITE_THROUGH
+	.long	0x00000c0a
+#else
+	.long	0x00000c0e
+#endif
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
+	.long	cpu_pxa250_info
+	.long	xscale_processor_functions
+	.size	__pxa250_proc_info, . - __pxa250_proc_info
+
+	.type	__pxa255_proc_info,#object
+__pxa255_proc_info:
+	.long	0x69052d00
+	.long	0xfffffff0
+#if CACHE_WRITE_THROUGH
+	.long	0x00000c0a
+#else
+	.long	0x00000c0e
+#endif
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
+	.long	cpu_pxa255_info
+	.long	xscale_processor_functions
+	.size	__pxa255_proc_info, . - __pxa255_proc_info
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/arch/arm/vmlinux-armv-xip.lds.in	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,125 @@
+/*
+ * ld script to make ARM Linux kernel
+ *
+ * (C) Copyright 2001 Lineo Japan, Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Based on arch/arm/vmlinux-armv.lds.in
+ *
+ * taken from the i386 version by Russell King
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+OUTPUT_ARCH(arm)
+ENTRY(stext)
+SECTIONS
+{
+	. = TEXTADDR;
+	.init : {			/* Init code and data		*/
+		_stext = .;
+		__init_begin = .;
+			*(.text.init)
+		__proc_info_begin = .;
+			*(.proc.info)
+		__proc_info_end = .;
+		__arch_info_begin = .;
+			*(.arch.info)
+		__arch_info_end = .;
+		__tagtable_begin = .;
+			*(.taglist)
+		__tagtable_end = .;
+		. = ALIGN(16);
+		__setup_start = .;
+			*(.setup.init)
+		__setup_end = .;
+		__initcall_start = .;
+			*(.initcall.init)
+		__initcall_end = .;
+		. = ALIGN(4096);
+		__init_end = .;
+	}
+
+	/DISCARD/ : {			/* Exit code and data		*/
+		*(.text.exit)
+		*(.data.exit)
+		*(.exitcall.exit)
+	}
+
+	.text : {			/* Real text segment		*/
+		_text = .;		/* Text and read-only data	*/
+			*(.text)
+			*(.fixup)
+			*(.gnu.warning)
+			*(.text.lock)	/* out-of-line lock text */
+			*(.rodata)
+			*(.rodata.*)
+			*(.glue_7)
+			*(.glue_7t)
+			*(.kstrtab)
+		*(.got)			/* Global offset table		*/
+		*(.got.plt)
+
+		_etext = .;		/* End of text section		*/
+	}
+
+	. = ALIGN(16);
+	__ex_table : {			/* Exception table		*/
+		__start___ex_table = .;
+			*(__ex_table)
+		__stop___ex_table = .;
+	}
+
+	__ksymtab : {			/* Kernel symbol table		*/
+		__start___ksymtab = .;
+			*(__ksymtab)
+		__stop___ksymtab = .;
+	}
+
+	_endtext = .;
+
+	. = DATAADDR;
+
+	_sdata = .;
+
+	. = ALIGN(8192);
+
+	.data : {
+		/*
+		 * first, the init task union, aligned
+		 * to an 8192 byte boundary.
+		 */
+		*(.init.task)
+
+		/*
+		 * then the cacheline aligned data
+		 */
+		. = ALIGN(32);
+		*(.data.cacheline_aligned)
+
+		/*
+		 * and the usual data section
+		 */
+		*(.data)
+		CONSTRUCTORS
+
+		*(.data.init)
+
+		_edata = .;
+	}
+
+	.bss : {
+		__bss_start = .;	/* BSS				*/
+		*(.bss)
+		*(COMMON)
+		_end = . ;
+	}
+					/* Stabs debugging sections.	*/
+	.stab 0 : { *(.stab) }
+	.stabstr 0 : { *(.stabstr) }
+	.stab.excl 0 : { *(.stab.excl) }
+	.stab.exclstr 0 : { *(.stab.exclstr) }
+	.stab.index 0 : { *(.stab.index) }
+	.stab.indexstr 0 : { *(.stab.indexstr) }
+	.comment 0 : { *(.comment) }
+}
--- linux-2.4.25/drivers/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -25,6 +25,7 @@
 subdir-$(CONFIG_NUBUS)		+= nubus
 subdir-$(CONFIG_TC)		+= tc
 subdir-$(CONFIG_VT)		+= video
+subdir-$(CONFIG_MMC)		+= mmc
 subdir-$(CONFIG_MAC)		+= macintosh
 subdir-$(CONFIG_PPC32)		+= macintosh
 subdir-$(CONFIG_USB)		+= usb
--- linux-2.4.25/drivers/char/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/char/Config.in	2004-03-31 17:15:11.000000000 +0200
@@ -253,6 +253,7 @@
       dep_tristate '  DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
       dep_tristate '  NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
       dep_tristate '  SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
+      dep_tristate '  PXA250/210 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_PXA
       dep_tristate '  EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
       dep_tristate '  Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
       dep_tristate '  AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
@@ -335,6 +336,9 @@
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
 fi
+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
+   tristate 'PXA250/210 Real Time Clock' CONFIG_PXA_RTC
+fi
 if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
    tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
 fi
@@ -417,4 +421,8 @@
    dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV
 fi
 
+if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then
+   tristate ' MT6N TTL I/O suport' CONFIG_TRIZEPS2_TTLIO
+fi
+
 endmenu
--- linux-2.4.25/drivers/char/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/char/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -280,6 +280,7 @@
 obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
 obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
 obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
+obj-$(CONFIG_PXA_RTC) += sa1100-rtc.o
 obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
 ifeq ($(CONFIG_PPC),)
   obj-$(CONFIG_NVRAM) += nvram.o
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/char/mt6n_ttl.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,316 @@
+/*
+ *	Trizeps-2 MT6N development board TTL-IO interface for Linux	
+ *
+ *	Copyright (C) 2003 Luc De Cock
+ *
+ * 	This driver allows use of the TTL-IO interface on the MT6N
+ * 	from user space. It exports the /dev/ttlio interface supporting
+ * 	some ioctl() and also the /proc/driver/ttlio pseudo-file
+ * 	for status information.
+ *
+ *	The ioctls can be used to set individual TTL output lines.
+ *	Only ioctls are supported.
+ *
+ *	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.
+ *
+ *	Based on other minimal char device drivers, like Alan's
+ *	watchdog, Ted's random, Paul's rtc, etc. etc.
+ *
+ *	1.00	Luc De Cock: initial version.
+ */
+
+#define TTLIO_VERSION		"1.00"
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+/* Writing to the register sets the output lines
+*  Reading from the register returns the status of the input lines
+*/
+static unsigned short *ttlio_base = (unsigned short *) TRIZEPS2_TTLIO_BASE;
+static unsigned short ttlio_shadow = 0;
+
+/* interrupt stuff */
+static struct fasync_struct *ttlio_async_queue;
+static DECLARE_WAIT_QUEUE_HEAD(ttlio_wait);
+static int ttlio_irq_arrived = 0;
+static spinlock_t ttlio_lock;
+static unsigned short ttlio_in = 0;
+static volatile unsigned long teller = 0;
+
+
+static int ttlio_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg);
+
+static int ttlio_read_proc(char *page, char **start, off_t off,
+                           int count, int *eof, void *data);
+
+
+static void ttlio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ttlio_in = *ttlio_base;
+
+	ttlio_irq_arrived = 1;
+	teller++;
+	
+	/* wake up the waiting process */
+	wake_up_interruptible(&ttlio_wait);
+	kill_fasync(&ttlio_async_queue, SIGIO, POLL_IN);
+}
+
+/*
+ *	Now all the various file operations that we export.
+ */
+
+static int ttlio_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		       unsigned long arg)
+{
+	unsigned long ttlio_val;
+
+	switch (cmd) {
+	case TTLIO_RESET:	/* clear all lines */
+	{
+		*ttlio_base = 0;
+		return 0;
+	}
+	case TTLIO_GET:		/* get state of TTL input lines	*/
+	{
+		ttlio_val = *ttlio_base;
+		return put_user(ttlio_val, (unsigned long *)arg);
+	}
+	case TTLIO_SET:		/* set state of TTL output lines */
+	{
+		unsigned long user_val;
+		if (copy_from_user(&user_val, arg, sizeof(unsigned long)))
+			return -EFAULT;
+		ttlio_shadow |= (unsigned short) user_val;
+		*ttlio_base = ttlio_shadow;
+		return 0;
+	}
+	case TTLIO_UNSET:	/* unset (clear) state of TTL output lines */
+	{
+		unsigned long user_val;
+		if (copy_from_user(&user_val, arg, sizeof(unsigned long)))
+			return -EFAULT;
+		ttlio_shadow &= ~((unsigned short) user_val);
+		*ttlio_base = ttlio_shadow;
+		return 0;
+	}
+	case 100:		/* get counter */
+	{
+		return put_user(teller, (unsigned long *)arg);
+	}
+	case 101:		/* reset counter */
+	{
+		teller = 0;
+		return 0;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static ssize_t ttlio_read(struct file *file, char *buf,
+			  size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned short data;
+	ssize_t retval;
+
+	if (count < sizeof(unsigned short))
+		return -EINVAL;
+
+	if (file->f_flags & O_NONBLOCK) {
+		spin_lock_irq(&ttlio_lock);
+		data = *ttlio_base;
+		spin_unlock_irq(&ttlio_lock);
+		retval = put_user(data, (unsigned short *) buf); 
+		if (!retval)
+			retval = sizeof(unsigned short);
+		return retval;
+	}
+	/* blocking read: wait for interrupt */
+	add_wait_queue(&ttlio_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	for (;;) {
+		spin_lock_irq(&ttlio_lock);
+		data = *ttlio_base;
+		if (ttlio_irq_arrived) {
+			ttlio_irq_arrived = 0;
+			break;
+		}
+		spin_unlock_irq(&ttlio_lock);
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+		schedule();
+	}
+
+	spin_unlock_irq(&ttlio_lock);
+	retval = put_user(data, (unsigned short *)buf);
+	if (!retval)
+		retval = sizeof(unsigned short);
+
+out:
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&ttlio_wait, &wait);
+	return retval;
+}
+
+static ssize_t ttlio_write(struct file *file,
+		           const char *buf, size_t count, loff_t *ppos)
+{
+	unsigned short content;
+
+	if (count < sizeof(unsigned short))
+		return -EINVAL;
+	
+	if (copy_from_user (&content, buf, sizeof(unsigned short)))
+		return -EFAULT;
+
+	ttlio_shadow = content;
+	*ttlio_base = ttlio_shadow;
+
+	*ppos += sizeof(unsigned short);
+
+	return sizeof(unsigned short);
+}
+
+static int ttlio_open(struct inode *inode, struct file *file)
+{
+	ttlio_irq_arrived = 0;
+	return 0;
+}
+
+static int ttlio_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &ttlio_async_queue);
+}
+
+static unsigned int ttlio_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &ttlio_wait, wait);
+	return ttlio_irq_arrived ? 0 : POLLIN | POLLRDNORM;
+}
+
+static loff_t ttlio_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations ttlio_fops = {
+	owner:		THIS_MODULE,
+	llseek:		ttlio_llseek,
+	read:		ttlio_read,
+	poll:		ttlio_poll,
+	write:		ttlio_write,
+	ioctl:		ttlio_ioctl,
+	open:		ttlio_open,
+	fasync:		ttlio_fasync,
+};
+
+static struct miscdevice ttlio_dev = {
+	TTLIO_MINOR,
+	"ttlio",
+	&ttlio_fops
+};
+
+static int __init ttlio_init(void)
+{
+	printk(KERN_INFO "MT6N TTL-I/O driver (release %s)\n",
+			TTLIO_VERSION);
+	
+	misc_register(&ttlio_dev);
+	create_proc_read_entry ("driver/ttlio", 0, 0, ttlio_read_proc, NULL);
+
+	set_GPIO_IRQ_edge(GPIO_TTLIO_IRQ, GPIO_FALLING_EDGE);
+	if (request_irq(TTLIO_IRQ, ttlio_interrupt, SA_INTERRUPT, "ttlio irq", NULL)) {
+		printk(KERN_ERR "ttlio: irq %d already in use\n", TTLIO_IRQ);
+		return 1;
+	}
+	return 0;
+}
+
+static void __exit ttlio_exit(void)
+{
+	free_irq(TTLIO_IRQ, NULL);
+	remove_proc_entry ("driver/ttlio", NULL);
+	misc_deregister(&ttlio_dev);
+}
+
+module_init(ttlio_init);
+module_exit(ttlio_exit);
+EXPORT_NO_SYMBOLS;
+
+/*
+ *	Info exported via "/proc/driver/ttlio".
+ */
+
+static int ttlio_proc_output(char *buf)
+{
+	char *p;
+	unsigned short val;
+	int i;
+
+	p = buf;
+
+	p += sprintf(p, "input : ");
+	/* write the state of the input lines */
+	val = *ttlio_base;
+	for (i = 0; i < 8*sizeof(unsigned short); i++) {
+		*p++ = (val & 1) ? '1' : '0';
+		val >>= 1;
+	}
+	*p = 0;
+	p += sprintf(p, "\noutput: ");
+	/* write the state of the output lines */
+	val = ttlio_shadow;
+	for (i = 0; i < 8*sizeof(unsigned short); i++) {
+		*p++ = (val & 1) ? '1' : '0';
+		val >>= 1;
+	}
+	*p = 0;
+	p += sprintf(p, "\n");
+
+	return  p - buf;
+}
+
+static int ttlio_read_proc(char *page, char **start, off_t off,
+                           int count, int *eof, void *data)
+{
+        int len = ttlio_proc_output (page);
+        if (len <= off+count) *eof = 1;
+        *start = page + off;
+        len -= off;
+        if (len > count) len = count;
+        if (len < 0) len = 0;
+        return len;
+}
+
+MODULE_AUTHOR("Luc De Cock");
+MODULE_DESCRIPTION("MT6N TTL-I/O driver");
+MODULE_LICENSE("GPL");
--- linux-2.4.25/drivers/char/sa1100-rtc.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/char/sa1100-rtc.c	2004-03-31 17:15:11.000000000 +0200
@@ -1,5 +1,6 @@
 /*
  *	Real Time Clock interface for Linux on StrongARM SA1100
+ *	and XScale PXA250/210.
  *
  *	Copyright (c) 2000 Nils Faerber
  *
@@ -470,5 +471,5 @@
 module_exit(rtc_exit);
 
 MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
-MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
+MODULE_DESCRIPTION("SA1100/PXA Realtime Clock Driver (RTC)");
 EXPORT_NO_SYMBOLS;
--- linux-2.4.25/drivers/char/sa1100_wdt.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/char/sa1100_wdt.c	2004-03-31 17:15:11.000000000 +0200
@@ -1,5 +1,5 @@
 /*
- *	Watchdog driver for the SA11x0
+ *	Watchdog driver for the SA11x0/PXA
  *
  *      (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
  *          Based on SoftDog driver by Alan Cox <alan@redhat.com>
@@ -35,13 +35,20 @@
 
 #define TIMER_MARGIN	60		/* (secs) Default is 1 minute */
 
-static int sa1100_margin = TIMER_MARGIN;	/* in seconds */
+static int timer_margin = TIMER_MARGIN;	/* in seconds */
 static int sa1100wdt_users;
 static int pre_margin;
 #ifdef MODULE
-MODULE_PARM(sa1100_margin,"i");
+MODULE_PARM(timer_margin,"i");
 #endif
 
+static void sa1100dog_ping( void)
+{
+	/* reload counter with (new) margin */
+	pre_margin=3686400 * timer_margin;
+	OSMR3 = OSCR + pre_margin;
+}
+
 /*
  *	Allow only one person to hold it open
  */
@@ -51,9 +58,7 @@
 	if(test_and_set_bit(1,&sa1100wdt_users))
 		return -EBUSY;
 	MOD_INC_USE_COUNT;
-	/* Activate SA1100 Watchdog timer */
-	pre_margin=3686400 * sa1100_margin;
-	OSMR3 = OSCR + pre_margin;
+	sa1100dog_ping();
 	OSSR = OSSR_M3;
 	OWER = OWER_WME;
 	OIER |= OIER_E3;
@@ -93,8 +98,11 @@
 	unsigned int cmd, unsigned long arg)
 {
 	static struct watchdog_info ident = {
-		identity: "SA1100 Watchdog",
+		identity: "PXA/SA1100 Watchdog",
+		options: WDIOF_SETTIMEOUT,
+		firmware_version: 0,
 	};
+	int new_margin;
 
 	switch(cmd){
 	default:
@@ -108,6 +116,16 @@
 	case WDIOC_KEEPALIVE:
 		OSMR3 = OSCR + pre_margin;
 		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int *)arg))
+			return -EFAULT;
+		if (new_margin < 1)
+			return -EINVAL;
+		timer_margin = new_margin;
+		sa1100dog_ping();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user(timer_margin, (int *)arg);
 	}
 }
 
@@ -123,7 +141,11 @@
 static struct miscdevice sa1100dog_miscdev=
 {
 	WATCHDOG_MINOR,
-	"SA1100 watchdog",
+#if defined(CONFIG_SA1100_WATCHDOG)
+	"SA1100_watchdog",
+#elif defined(CONFIG_PXA_WATCHDOG)
+	"PXA_watchdog",
+#endif
 	&sa1100dog_fops
 };
 
@@ -136,7 +158,7 @@
 	if (ret)
 		return ret;
 
-	printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
+	printk("SA1100/PXA Watchdog Timer: timer margin %d sec\n", timer_margin);
 
 	return 0;
 }
--- linux-2.4.25/drivers/char/serial.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/char/serial.c	2004-03-31 17:15:11.000000000 +0200
@@ -133,6 +133,16 @@
 #endif
 #endif
 
+#ifdef CONFIG_ARCH_PXA
+#define pxa_port(x) ((x) == PORT_PXA)
+#define pxa_buggy_port(x) ({ \
+	int cpu_ver; asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); \
+	((x) == PORT_PXA && (cpu_ver & ~1) == 0x69052100); })
+#else
+#define pxa_port(x) (0)
+#define pxa_buggy_port(x) (0)
+#endif
+
 /* Set of debugging defines */
 
 #undef SERIAL_DEBUG_INTR
@@ -311,6 +321,7 @@
 	{ "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO |
 		  UART_STARTECH },
 	{ "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, 
+	{ "PXA UART", 32, UART_CLEAR_FIFO | UART_USE_FIFO },
 	{ 0, 0}
 };
 
@@ -424,6 +435,9 @@
 	case SERIAL_IO_MEM:
 		return readb((unsigned long) info->iomem_base +
 			     (offset<<info->iomem_reg_shift));
+	case SERIAL_IO_MEM32:
+		return readl((unsigned long) info->iomem_base +
+			     (offset<<info->iomem_reg_shift));
 	default:
 		return inb(info->port + offset);
 	}
@@ -443,6 +457,10 @@
 		writeb(value, (unsigned long) info->iomem_base +
 			      (offset<<info->iomem_reg_shift));
 		break;
+	case SERIAL_IO_MEM32:
+		writel(value, (unsigned long) info->iomem_base +
+			      (offset<<info->iomem_reg_shift));
+		break;
 	default:
 		outb(value, info->port+offset);
 	}
@@ -1306,6 +1324,16 @@
 	}
 #endif
 
+#ifdef CONFIG_ARCH_PXA
+	if (state->type == PORT_PXA) {
+		switch ((long)state->iomem_base) {
+			case (long)&FFUART: CKEN |= CKEN6_FFUART; break;
+			case (long)&BTUART: CKEN |= CKEN7_BTUART; break;
+			case (long)&STUART: CKEN |= CKEN5_STUART; break;
+		}
+	}
+#endif
+
 	/*
 	 * Clear the FIFO buffers and disable them
 	 * (they will be reenabled in change_speed())
@@ -1403,6 +1431,8 @@
 	{
 		if (state->irq != 0)
 			info->MCR |= UART_MCR_OUT2;
+		if (pxa_buggy_port(state->type) && state->irq != 0)
+			info->MCR ^= UART_MCR_OUT2;
 	}
 	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
 	serial_outp(info, UART_MCR, info->MCR);
@@ -1411,6 +1441,8 @@
 	 * Finally, enable interrupts
 	 */
 	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+	if (pxa_port(state->type))
+		info->IER |= UART_IER_UUE | UART_IER_RTOIE;
 	serial_outp(info, UART_IER, info->IER);	/* enable interrupts */
 	
 #ifdef CONFIG_SERIAL_MANY_PORTS
@@ -1542,6 +1574,8 @@
 	} else
 #endif
 		info->MCR &= ~UART_MCR_OUT2;
+		if (pxa_buggy_port(state->type))
+			info->MCR ^= UART_MCR_OUT2;
 	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
 	
 	/* disable break condition */
@@ -1567,6 +1601,20 @@
 		state->baud_base = SERIAL_RSA_BAUD_BASE_LO;
 #endif
 	
+#ifdef CONFIG_ARCH_PXA
+	if (state->type == PORT_PXA
+#ifdef CONFIG_SERIAL_CONSOLE
+	    && sercons.index != info->line
+#endif
+	   ) {
+		switch ((long)state->iomem_base) {
+			case (long)&FFUART: CKEN &= ~CKEN6_FFUART; break;
+			case (long)&BTUART: CKEN &= ~CKEN7_BTUART; break;
+			case (long)&STUART: CKEN &= ~CKEN5_STUART; break;
+		}
+	}
+#endif
+
 
 	(void)serial_in(info, UART_RX);    /* read data port to reset things */
 	
@@ -1857,6 +1905,8 @@
 	save_flags(flags); cli();
 	info->IER |= UART_IER_THRI;
 	serial_out(info, UART_IER, info->IER);
+	if (pxa_buggy_port(info->state->type))
+		rs_interrupt_single(info->state->irq, NULL, NULL);
 	restore_flags(flags);
 }
 
@@ -1933,6 +1983,11 @@
 	    && !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_IER, info->IER);
+		if (pxa_buggy_port(info->state->type)) {
+			save_flags(flags); cli();
+			rs_interrupt_single(info->state->irq, NULL, NULL);
+			restore_flags(flags);
+		}
 	}
 	return ret;
 }
@@ -1990,6 +2045,8 @@
 		/* Make sure transmit interrupts are on */
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_IER, info->IER);
+		if (pxa_buggy_port(info->state->type))
+			rs_interrupt_single(info->state->irq, NULL, NULL);
 	}
 }
 
@@ -5517,7 +5574,6 @@
 	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
 		state->magic = SSTATE_MAGIC;
 		state->line = i;
-		state->type = PORT_UNKNOWN;
 		state->custom_divisor = 0;
 		state->close_delay = 5*HZ/10;
 		state->closing_wait = 30*HZ;
@@ -5531,14 +5587,18 @@
 		state->irq = irq_cannonicalize(state->irq);
 		if (state->hub6)
 			state->io_type = SERIAL_IO_HUB6;
-		if (state->port && check_region(state->port,8))
+		if (state->port && check_region(state->port,8)) {
+			state->type = PORT_UNKNOWN;
 			continue;
+		}
 #ifdef CONFIG_MCA			
 		if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus)
 			continue;
 #endif			
-		if (state->flags & ASYNC_BOOT_AUTOCONF)
+		if (state->flags & ASYNC_BOOT_AUTOCONF) {
+			state->type = PORT_UNKNOWN;
 			autoconfig(state);
+		}
 	}
 	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
 		if (state->type == PORT_UNKNOWN)
@@ -5858,6 +5918,8 @@
 	 */
 	ier = serial_in(info, UART_IER);
 	serial_out(info, UART_IER, 0x00);
+	if (pxa_port(info->state->type))
+		serial_out(info, UART_IER, UART_IER_UUE);
 
 	/*
 	 *	Now, do each character
@@ -6009,6 +6071,8 @@
 	serial_out(info, UART_DLM, quot >> 8);		/* MS of divisor */
 	serial_out(info, UART_LCR, cval);		/* reset DLAB */
 	serial_out(info, UART_IER, 0);
+	if (pxa_port(info->state->type))
+		serial_out(info, UART_IER, UART_IER_UUE);
 	serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
 
 	/*
--- linux-2.4.25/drivers/i2c/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/i2c/Config.in	2004-03-31 17:15:11.000000000 +0200
@@ -54,6 +54,11 @@
       fi
    fi
 
+   if [ "$CONFIG_ARCH_PXA" = "y" ]; then
+      dep_tristate 'PXA I2C Algorithm' CONFIG_I2C_PXA_ALGO $CONFIG_I2C
+      dep_tristate 'PXA I2C Adapter'   CONFIG_I2C_PXA_ADAP $CONFIG_I2C_PXA_ALGO
+   fi
+
    if [ "$CONFIG_ALL_PPC" = "y" ] ; then
       dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
    fi
--- linux-2.4.25/drivers/i2c/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/i2c/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -6,7 +6,7 @@
 
 export-objs	:= i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \
 		   i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
-		   i2c-proc.o
+		   i2c-algo-pxa.o i2c-proc.o
 
 # Init order: core, chardev, bit adapters, pcf adapters
 
@@ -35,6 +35,10 @@
 obj-$(CONFIG_I2C_MAX1617)	+= i2c-max1617.o
 obj-$(CONFIG_I2C_ALGO_SGI)	+= i2c-algo-sgi.o
 
+# PXA adapters
+obj-$(CONFIG_I2C_PXA_ALGO)	+= i2c-algo-pxa.o
+obj-$(CONFIG_I2C_PXA_ADAP)	+= i2c-adap-pxa.o
+
 # This is needed for automatic patch generation: sensors code starts here
 # This is needed for automatic patch generation: sensors code ends here
 
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/i2c/i2c-adap-pxa.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,396 @@
+/*
+ *  i2c_adap_pxa.c
+ *
+ *  I2C adapter for the PXA I2C bus access.
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Apr 2002: Initial version [CS]
+ *    Jun 2002: Properly seperated algo/adap [FB]
+ *    Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
+ *    Jan 2003: added limited signal handling [Kai-Uwe Bloem]
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>              /* for IRQ_I2C */
+
+#include "i2c-pxa.h"
+
+/*
+ * Set this to zero to remove all debug statements via dead code elimination.
+ */
+//#define DEBUG       1
+
+#if DEBUG
+static unsigned int i2c_debug = DEBUG;
+#else
+#define i2c_debug	0
+#endif
+
+static int irq = 0;
+static volatile int i2c_pending = 0;             /* interrupt pending when 1 */
+static volatile int bus_error = 0;
+static volatile int tx_finished = 0;
+static volatile int rx_finished = 0;
+
+static wait_queue_head_t i2c_wait;
+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte);
+
+/* place a byte in the transmit register */
+static void i2c_pxa_write_byte(u8 value)
+{
+	IDBR = value;
+}
+
+/* read byte in the receive register */
+static u8 i2c_pxa_read_byte(void)
+{
+	return (u8) (0xff & IDBR);
+}
+
+static void i2c_pxa_start(void)
+{
+	unsigned long icr = ICR;
+	icr |= ICR_START;
+	icr &= ~(ICR_STOP | ICR_ALDIE | ICR_ACKNAK);
+	ICR = icr;
+
+	bus_error=0;            /* clear any bus_error from previous txfers */
+	tx_finished=0;          /* clear rx and tx interrupts from previous txfers */
+	rx_finished=0;
+	i2c_pending = 0;
+}
+
+static void i2c_pxa_repeat_start(void)
+{
+	unsigned long icr = ICR;
+	icr |= ICR_START;
+	icr &= ~(ICR_STOP | ICR_ALDIE);
+	ICR = icr;
+
+	bus_error=0;            /* clear any bus_error from previous txfers */
+	tx_finished=0;          /* clear rx and tx interrupts from previous txfers */
+	rx_finished=0;
+	i2c_pending = 0;
+}
+
+static void i2c_pxa_stop(void)
+{
+	unsigned long icr = ICR;
+	icr |= ICR_STOP;
+	icr &= ~(ICR_START);
+	ICR = icr;
+}
+
+static void i2c_pxa_midbyte(void)
+{
+	unsigned long icr = ICR;
+	icr &= ~(ICR_START | ICR_STOP);
+	ICR = icr;
+}
+
+static void i2c_pxa_abort(void)
+{
+	unsigned long timeout = jiffies + HZ/4;
+
+#ifdef PXA_ABORT_MA
+	while ((long)(timeout - jiffies) > 0 && (ICR & ICR_TB)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
+	ICR |= ICR_MA;
+	udelay(100);
+#else
+	while ((long)(timeout - jiffies) > 0 && (IBMR & 0x1) == 0) {
+		i2c_pxa_transfer( 1, I2C_RECEIVE, 1);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+#endif
+	ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
+}
+
+static int i2c_pxa_wait_bus_not_busy( void)
+{
+	int timeout = DEF_TIMEOUT;
+
+	while (timeout-- && (ISR & ISR_IBB)) {
+		udelay(100); /* wait for 100 us */
+	}
+
+	return (timeout<=0);
+}
+
+static void i2c_pxa_wait_for_ite(void){
+	unsigned long flags;
+	if (irq > 0) {
+		save_flags_cli(flags);
+		if (i2c_pending == 0) {
+			interruptible_sleep_on_timeout(&i2c_wait, I2C_SLEEP_TIMEOUT );
+		}
+		i2c_pending = 0;
+		restore_flags(flags);
+	} else {
+		udelay(100);
+	}
+}
+
+static int i2c_pxa_wait_for_int( int wait_type)
+{
+	int timeout = DEF_TIMEOUT;
+#ifdef DEBUG
+	if (bus_error)
+		printk(KERN_INFO"i2c_pxa_wait_for_int: Bus error on enter\n");
+	if (rx_finished)
+		printk(KERN_INFO"i2c_pxa_wait_for_int: Receive interrupt on enter\n");
+	if (tx_finished)
+		printk(KERN_INFO"i2c_pxa_wait_for_int: Transmit interrupt on enter\n");
+#endif
+
+	if (wait_type == I2C_RECEIVE){         /* wait on receive */
+
+		do {
+			i2c_pxa_wait_for_ite();
+		} while (!(rx_finished) && timeout-- && !signal_pending(current));
+
+#ifdef DEBUG
+		if (timeout<0){
+			if (tx_finished)
+				printk("Error: i2c-algo-pxa.o: received a tx"
+						" interrupt while waiting on a rx in wait_for_int");
+		}
+#endif
+	} else {                  /* wait on transmit */
+
+		do {
+			i2c_pxa_wait_for_ite();
+		} while (!(tx_finished) && timeout-- && !signal_pending(current));
+
+#ifdef DEBUG
+		if (timeout<0){
+			if (rx_finished)
+				printk("Error: i2c-algo-pxa.o: received a rx"
+					" interrupt while waiting on a tx in wait_for_int");
+		}
+#endif
+	}
+
+	udelay(ACK_DELAY);      /* this is needed for the bus error */
+
+	tx_finished=0;
+	rx_finished=0;
+
+	if (bus_error){
+		bus_error=0;
+		if( i2c_debug > 2)printk("wait_for_int: error - no ack.\n");
+		return BUS_ERROR;
+	}
+
+	if (signal_pending(current)) {
+		return (-ERESTARTSYS);
+	} else if (timeout < 0) {
+		if( i2c_debug > 2)printk("wait_for_int: timeout.\n");
+		return(-EIO);
+	} else
+		return(0);
+}
+
+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte)
+{
+	if( lastbyte)
+	{
+		if( receive==I2C_RECEIVE) ICR |= ICR_ACKNAK;
+		i2c_pxa_stop();
+	}
+	else if( midbyte)
+	{
+		i2c_pxa_midbyte();
+	}
+	ICR |= ICR_TB;
+}
+
+static void i2c_pxa_reset( void)
+{
+#ifdef DEBUG
+	printk("Resetting I2C Controller Unit\n");
+#endif
+
+	/* abort any transfer currently under way */
+	i2c_pxa_abort();
+
+	/* reset according to 9.8 */
+	ICR = ICR_UR;
+	ISR = I2C_ISR_INIT;
+	ICR &= ~ICR_UR;
+
+	/* set the global I2C clock on */
+	CKEN |= CKEN14_I2C;
+
+	/* set our slave address */
+	ISAR = I2C_PXA_SLAVE_ADDR;
+
+	/* set control register values */
+	ICR = I2C_ICR_INIT;
+
+	/* clear any leftover states from prior transmissions */
+	i2c_pending = rx_finished = tx_finished = bus_error = 0;
+
+	/* enable unit */
+	ICR |= ICR_IUE;
+	udelay(100);
+}
+
+static void i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+	int status, wakeup = 0;
+	status = (ISR);
+
+	if (status & ISR_BED){
+		(ISR) |= ISR_BED;
+		bus_error=ISR_BED;
+		wakeup = 1;
+	}
+	if (status & ISR_ITE){
+		(ISR) |= ISR_ITE;
+		tx_finished=ISR_ITE;
+		wakeup = 1;
+	}
+	if (status & ISR_IRF){
+		(ISR) |= ISR_IRF;
+		rx_finished=ISR_IRF;
+		wakeup = 1;
+	}
+	if (wakeup) {
+		i2c_pending = 1;
+		wake_up_interruptible(&i2c_wait);
+	}
+}
+
+static int i2c_pxa_resource_init( void)
+{
+	init_waitqueue_head(&i2c_wait);
+
+	if (request_irq(IRQ_I2C, &i2c_pxa_handler, SA_INTERRUPT, "I2C_PXA", 0) < 0) {
+		irq = 0;
+		if( i2c_debug)
+			printk(KERN_INFO "I2C: Failed to register I2C irq %i\n", IRQ_I2C);
+		return -ENODEV;
+	}else{
+		irq = IRQ_I2C;
+		enable_irq(irq);
+	}
+	return 0;
+}
+
+static void i2c_pxa_resource_release( void)
+{
+	if( irq > 0)
+	{
+		disable_irq(irq);
+		free_irq(irq,0);
+		irq=0;
+	}
+}
+
+static void i2c_pxa_inc_use(struct i2c_adapter *adap)
+{
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+}
+
+static void i2c_pxa_dec_use(struct i2c_adapter *adap)
+{
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+}
+
+static int i2c_pxa_client_register(struct i2c_client *client)
+{
+	return 0;
+}
+
+static int i2c_pxa_client_unregister(struct i2c_client *client)
+{
+	return 0;
+}
+
+static struct i2c_algo_pxa_data i2c_pxa_data = {
+	write_byte:		i2c_pxa_write_byte,
+	read_byte:		i2c_pxa_read_byte,
+
+	start:			i2c_pxa_start,
+	repeat_start:		i2c_pxa_repeat_start,
+	stop:			i2c_pxa_stop,
+	abort:			i2c_pxa_abort,
+
+	wait_bus_not_busy:	i2c_pxa_wait_bus_not_busy,
+	wait_for_interrupt:	i2c_pxa_wait_for_int,
+	transfer:		i2c_pxa_transfer,
+	reset:			i2c_pxa_reset,
+
+	udelay:			10,
+	timeout:		DEF_TIMEOUT,
+};
+
+static struct i2c_adapter i2c_pxa_ops = {
+	name:                   "PXA-I2C-Adapter",
+	id:                     I2C_ALGO_PXA,
+	algo_data:              &i2c_pxa_data,
+	inc_use:                i2c_pxa_inc_use,
+	dec_use:                i2c_pxa_dec_use,
+	client_register:        i2c_pxa_client_register,
+	client_unregister:      i2c_pxa_client_unregister,
+	retries:                2,
+};
+
+extern int i2c_pxa_add_bus(struct i2c_adapter *);
+extern int i2c_pxa_del_bus(struct i2c_adapter *);
+
+static int __init i2c_adap_pxa_init(void)
+{
+	if( i2c_pxa_resource_init() == 0) {
+
+		if (i2c_pxa_add_bus(&i2c_pxa_ops) < 0) {
+			i2c_pxa_resource_release();
+			printk(KERN_INFO "I2C: Failed to add bus\n");
+			return -ENODEV;
+		}
+	} else {
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "I2C: Successfully added bus\n");
+
+	return 0;
+}
+
+static void i2c_adap_pxa_exit(void)
+{
+	i2c_pxa_del_bus( &i2c_pxa_ops);
+	i2c_pxa_resource_release();
+
+	printk(KERN_INFO "I2C: Successfully removed bus\n");
+}
+
+module_init(i2c_adap_pxa_init);
+module_exit(i2c_adap_pxa_exit);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/i2c/i2c-algo-pxa.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,376 @@
+/*
+ *  i2c-algo-pxa.c
+ *
+ *  I2C algorithm for the PXA I2C bus access.
+ *  Byte driven algorithm similar to pcf.
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Apr 2002: Initial version [CS]
+ *    Jun 2002: Properly seperated algo/adap [FB]
+ *    Jan 2003: added limited signal handling [Kai-Uwe Bloem]
+ *    Jan 2003: allow SMBUS_QUICK as valid msg [FB]
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>          /* struct i2c_msg and others */
+#include <linux/i2c-id.h>
+
+#include "i2c-pxa.h"
+
+/*
+ * Set this to zero to remove all the debug statements via dead code elimination.
+ */
+//#define DEBUG		1
+
+#if DEBUG
+static unsigned int i2c_debug = DEBUG;
+#else
+#define i2c_debug	0
+#endif
+
+static int pxa_scan = 1;
+
+static int i2c_pxa_valid_messages( struct i2c_msg msgs[], int num)
+{
+	int i;
+	if (num < 1 || num > MAX_MESSAGES){
+		if( i2c_debug)
+			printk(KERN_INFO "Invalid number of messages (max=%d, num=%d)\n",
+				MAX_MESSAGES, num);
+		return -EINVAL;
+	}
+
+	/* check consistency of our messages */
+	for (i=0;i<num;i++){
+		if (&msgs[i]==NULL){
+			if( i2c_debug) printk(KERN_INFO "Msgs is NULL\n");
+			return -EINVAL;
+		} else {
+			if (msgs[i].len < 0 || msgs[i].buf == NULL){
+				if( i2c_debug)printk(KERN_INFO "Length is less than zero");
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 1;
+}
+
+static int i2c_pxa_readbytes(struct i2c_adapter *i2c_adap, char *buf,
+			int count, int last)
+{
+
+	int i, timeout=0;
+	struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
+
+	/* increment number of bytes to read by one -- read dummy byte */
+	for (i = 0; i <= count; i++) {
+		if (i!=0){
+			/* set ACK to NAK for last received byte ICR[ACKNAK] = 1
+			   only if not a repeated start */
+
+			if ((i == count) && last) {
+				adap->transfer( last, I2C_RECEIVE, 0);
+			}else{
+				adap->transfer( 0, I2C_RECEIVE, 1);
+			}
+
+			timeout = adap->wait_for_interrupt(I2C_RECEIVE);
+
+#ifdef DEBUG
+			if (timeout==BUS_ERROR){
+				printk(KERN_INFO "i2c_pxa_readbytes: bus error -> forcing reset\n");
+				adap->reset();
+				return I2C_RETRY;
+			} else
+#endif
+			if (timeout == -ERESTARTSYS) {
+				adap->abort();
+				return timeout;
+			} else
+			if (timeout){
+#ifdef DEBUG
+				printk(KERN_INFO "i2c_pxa_readbytes: timeout -> forcing reset\n");
+#endif
+				adap->reset();
+				return I2C_RETRY;
+			}
+
+		}
+
+		if (i) {
+			buf[i - 1] = adap->read_byte();
+		} else {
+			adap->read_byte(); /* dummy read */
+		}
+	}
+	return (i - 1);
+}
+
+static int i2c_pxa_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
+                         int count, int last)
+{
+
+	struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
+	int wrcount, timeout;
+
+	for (wrcount=0; wrcount<count; ++wrcount) {
+
+		adap->write_byte(buf[wrcount]);
+		if ((wrcount==(count-1)) && last) {
+			adap->transfer( last, I2C_TRANSMIT, 0);
+		}else{
+			adap->transfer( 0, I2C_TRANSMIT, 1);
+		}
+
+		timeout = adap->wait_for_interrupt(I2C_TRANSMIT);
+
+#ifdef DEBUG
+		if (timeout==BUS_ERROR) {
+			printk(KERN_INFO "i2c_pxa_sendbytes: bus error -> forcing reset.\n");
+			adap->reset();
+			return I2C_RETRY;
+		} else
+#endif
+		if (timeout == -ERESTARTSYS) {
+			adap->abort();
+			return timeout;
+		} else
+		if (timeout) {
+#ifdef DEBUG
+			printk(KERN_INFO "i2c_pxa_sendbytes: timeout -> forcing reset\n");
+#endif
+			adap->reset();
+			return I2C_RETRY;
+		}
+	}
+	return (wrcount);
+}
+
+
+static inline int i2c_pxa_set_ctrl_byte(struct i2c_algo_pxa_data * adap, struct i2c_msg *msg)
+{
+	u16 flags = msg->flags;
+	u8 addr;
+	addr = (u8) ( (0x7f & msg->addr) << 1 );
+	if (flags & I2C_M_RD )
+		addr |= 1;
+	if (flags & I2C_M_REV_DIR_ADDR )
+		addr ^= 1;
+	adap->write_byte(addr);
+	return 0;
+}
+
+static int i2c_pxa_do_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+	struct i2c_algo_pxa_data * adap;
+	struct i2c_msg *pmsg=NULL;
+	int i;
+	int ret=0, timeout;
+
+	adap = i2c_adap->algo_data;
+
+	timeout = adap->wait_bus_not_busy();
+
+	if (timeout) {
+		return I2C_RETRY;
+	}
+
+	for (i = 0;ret >= 0 && i < num; i++) {
+		int last = i + 1 == num;
+		pmsg = &msgs[i];
+
+		ret = i2c_pxa_set_ctrl_byte(adap,pmsg);
+
+		/* Send START */
+		if (i == 0) {
+			adap->start();
+		}else{
+			adap->repeat_start();
+		}
+
+		adap->transfer(0, I2C_TRANSMIT, 0);
+
+		/* Wait for ITE (transmit empty) */
+		timeout = adap->wait_for_interrupt(I2C_TRANSMIT);
+
+#ifdef DEBUG
+		/* Check for ACK (bus error) */
+		if (timeout==BUS_ERROR){
+			printk(KERN_INFO "i2c_pxa_do_xfer: bus error -> forcing reset\n");
+			adap->reset();
+			return I2C_RETRY;
+		} else
+#endif
+		if (timeout == -ERESTARTSYS) {
+			adap->abort();
+			return timeout;
+		} else
+		if (timeout) {
+#ifdef DEBUG
+			printk(KERN_INFO "i2c_pxa_do_xfer: timeout -> forcing reset\n");
+#endif
+			adap->reset();
+			return I2C_RETRY;
+		}
+/* FIXME: handle arbitration... */
+#if 0
+		/* Check for bus arbitration loss */
+		if (adap->arbitration_loss()){
+			printk("Arbitration loss detected \n");
+			adap->reset();
+			return I2C_RETRY;
+		}
+#endif
+
+		/* Read */
+		if (pmsg->flags & I2C_M_RD) {
+			/* read bytes into buffer*/
+			ret = i2c_pxa_readbytes(i2c_adap, pmsg->buf, pmsg->len, last);
+#if DEBUG > 2
+			if (ret != pmsg->len) {
+				printk(KERN_INFO"i2c_pxa_do_xfer: read %d/%d bytes.\n",
+					ret, pmsg->len);
+			} else {
+				printk(KERN_INFO"i2c_pxa_do_xfer: read %d bytes.\n",ret);
+			}
+#endif
+		} else { /* Write */
+			ret = i2c_pxa_sendbytes(i2c_adap, pmsg->buf, pmsg->len, last);
+#if DEBUG > 2
+			if (ret != pmsg->len) {
+				printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d/%d bytes.\n",
+					ret, pmsg->len);
+			} else {
+				printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d bytes.\n",ret);
+			}
+#endif
+		}
+	}
+
+	if (ret<0){
+		return ret;
+	}else{
+		return i;
+	}
+}
+
+static int i2c_pxa_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+	int retval = i2c_pxa_valid_messages( msgs, num);
+	if( retval > 0)
+	{
+		int i;
+		for (i=i2c_adap->retries; i>=0; i--){
+			int retval = i2c_pxa_do_xfer(i2c_adap,msgs,num);
+			if (retval!=I2C_RETRY){
+				return retval;
+			}
+			if( i2c_debug)printk(KERN_INFO"Retrying transmission \n");
+			udelay(100);
+		}
+		if( i2c_debug)printk(KERN_INFO"Retried %i times\n",i2c_adap->retries);
+		return -EREMOTEIO;
+
+	}
+	return retval;
+}
+
+struct i2c_algorithm i2c_pxa_algorithm  = {
+	name:                   "PXA-I2C-Algorithm",
+	id:                     I2C_ALGO_PXA,
+	master_xfer:            i2c_pxa_xfer,
+	smbus_xfer:             NULL,
+	slave_send:             NULL,
+	slave_recv:             NULL,
+	algo_control:           NULL,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_pxa_add_bus(struct i2c_adapter *i2c_adap)
+{
+	struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
+
+	printk(KERN_INFO"I2C: Adding %s.\n", i2c_adap->name);
+
+	i2c_adap->algo = &i2c_pxa_algorithm;
+
+	MOD_INC_USE_COUNT;
+
+	/* register new adapter to i2c module... */
+	i2c_add_adapter(i2c_adap);
+
+	adap->reset();
+
+	/* scan bus */
+	if (pxa_scan) {
+		int i;
+		printk(KERN_INFO "I2C: Scanning bus ");
+		for (i = 0x02; i < 0xff; i+=2) {
+			if( i==(I2C_PXA_SLAVE_ADDR<<1)) continue;
+
+			if (adap->wait_bus_not_busy()) {
+				printk(KERN_INFO "I2C: scanning bus %s - TIMEOUTed.\n",
+						i2c_adap->name);
+				return -EIO;
+			}
+			adap->write_byte(i);
+			adap->start();
+			adap->transfer(0, I2C_TRANSMIT, 0);
+
+			if ((adap->wait_for_interrupt(I2C_TRANSMIT) != BUS_ERROR)) {
+				printk("(%02x)",i>>1);
+				adap->abort();
+			} else {
+//				printk(".");
+				adap->stop();
+			}
+			udelay(adap->udelay);
+		}
+		printk("\n");
+	}
+	return 0;
+}
+
+int i2c_pxa_del_bus(struct i2c_adapter *i2c_adap)
+{
+	int res;
+	if ((res = i2c_del_adapter(i2c_adap)) < 0)
+		return res;
+
+	MOD_DEC_USE_COUNT;
+
+	printk(KERN_INFO "I2C: Removing %s.\n", i2c_adap->name);
+
+	return 0;
+}
+
+static int __init i2c_algo_pxa_init (void)
+{
+	printk(KERN_INFO "I2C: PXA algorithm module loaded.\n");
+	return 0;
+}
+
+EXPORT_SYMBOL(i2c_pxa_add_bus);
+EXPORT_SYMBOL(i2c_pxa_del_bus);
+
+MODULE_PARM(pxa_scan, "i");
+MODULE_PARM_DESC(pxa_scan, "Scan for active chips on the bus");
+
+MODULE_AUTHOR("Intrinsyc Software Inc.");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_algo_pxa_init);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/i2c/i2c-pxa.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,76 @@
+/*
+ *  i2c_pxa.h
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ */
+#ifndef _I2C_PXA_H_
+#define _I2C_PXA_H_
+
+struct i2c_algo_pxa_data
+{
+        void (*write_byte) (u8 value);
+        u8   (*read_byte) (void);
+        void (*start) (void);
+        void (*repeat_start) (void);
+        void (*stop) (void);
+        void (*abort) (void);
+        int  (*wait_bus_not_busy) (void);
+        int  (*wait_for_interrupt) (int wait_type);
+        void (*transfer) (int lastbyte, int receive, int midbyte);
+        void (*reset) (void);
+
+	int udelay;
+	int timeout;
+};
+
+#define DEF_TIMEOUT             3
+#define BUS_ERROR               (-EREMOTEIO)
+#define ACK_DELAY               0       /* time to delay before checking bus error */
+#define MAX_MESSAGES            65536   /* maximum number of messages to send */
+
+#define I2C_SLEEP_TIMEOUT       2       /* time to sleep for on i2c transactions */
+#define I2C_RETRY               (-2000) /* an error has occurred retry transmit */
+#define I2C_TRANSMIT		1
+#define I2C_RECEIVE		0
+#define I2C_PXA_SLAVE_ADDR      0x1    /* slave pxa unit address */
+#define I2C_ICR_INIT            (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) /* ICR initialization value */
+/* ICR initialize bit values 
+*                       
+*  15. FM       0 (100 Khz operation)
+*  14. UR       0 (No unit reset)
+*  13. SADIE    0 (Disables the unit from interrupting on slave addresses 
+*                                       matching its slave address)
+*  12. ALDIE    0 (Disables the unit from interrupt when it loses arbitration 
+*                                       in master mode)
+*  11. SSDIE    0 (Disables interrupts from a slave stop detected, in slave mode)  
+*  10. BEIE     1 (Enable interrupts from detected bus errors, no ACK sent)
+*  9.  IRFIE    1 (Enable interrupts from full buffer received)
+*  8.  ITEIE    1 (Enables the I2C unit to interrupt when transmit buffer empty)
+*  7.  GCD      1 (Disables i2c unit response to general call messages as a slave) 
+*  6.  IUE      0 (Disable unit until we change settings)
+*  5.  SCLE     1 (Enables the i2c clock output for master mode (drives SCL)   
+*  4.  MA       0 (Only send stop with the ICR stop bit)
+*  3.  TB       0 (We are not transmitting a byte initially)
+*  2.  ACKNAK   0 (Send an ACK after the unit receives a byte)
+*  1.  STOP     0 (Do not send a STOP)
+*  0.  START    0 (Do not send a START)
+*
+*/
+
+#define I2C_ISR_INIT            0x7FF  /* status register init */
+/* I2C status register init values 
+ *
+ * 10. BED      1 (Clear bus error detected)
+ * 9.  SAD      1 (Clear slave address detected)
+ * 7.  IRF      1 (Clear IDBR Receive Full)
+ * 6.  ITE      1 (Clear IDBR Transmit Empty)
+ * 5.  ALD      1 (Clear Arbitration Loss Detected)
+ * 4.  SSD      1 (Clear Slave Stop Detected)
+ */
+
+#endif
--- linux-2.4.25/drivers/misc/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/misc/Config.in	2004-03-31 17:15:11.000000000 +0200
@@ -13,5 +13,6 @@
 dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
 dep_tristate '  Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
 dep_tristate '  Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
+dep_tristate '  UCB1400 Touchscreen support' CONFIG_MCP_UCB1400_TS $CONFIG_ARCH_PXA $CONFIG_SOUND
 
 endmenu
--- linux-2.4.25/drivers/misc/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/misc/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -11,13 +11,15 @@
 
 O_TARGET := misc.o
 
-export-objs			:= mcp-core.o mcp-sa1100.o ucb1x00-core.o
+export-objs			:= mcp-core.o mcp-sa1100.o mcp-pxa.o \
+				   ucb1x00-core.o 
 
-obj-$(CONFIG_MCP)		+= mcp-core.o
-obj-$(CONFIG_MCP_SA1100)	+= mcp-sa1100.o
+obj-$(CONFIG_MCP_SA1100)	+= mcp-core.o mcp-sa1100.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
 obj-$(CONFIG_MCP_UCB1200_AUDIO)	+= ucb1x00-audio.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
+obj-$(CONFIG_MCP_UCB1400_TS)	+= mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o
+obj-$(CONFIG_PXA_CERF_PDA)	+= cerf_ucb1400gpio.o
 
 include $(TOPDIR)/Rules.make
 
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/misc/cerf_ucb1400gpio.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,189 @@
+/*
+ *  cerf_ucb1400gpio.c
+ *
+ *  UCB1400 GPIO control stuff for the cerf.
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Mar 2002: Initial version [FB]
+ *    Jun 2002: Removed ac97 dependency [FB]
+ * 
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "ucb1x00.h"
+
+/*
+ * Set this to zero to remove all the debug statements via
+ * dead code elimination.
+ */
+#define DEBUGGING       0
+
+#if DEBUGGING
+static unsigned int ucb_debug = DEBUGGING;
+#else
+#define ucb_debug       0
+#endif
+
+#define UP	1
+#define DOWN	0
+
+/* -- -- */
+
+void cerf_ucb1400gpio_lcd_enable( void)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+	if( ucb_debug > 2) printk( KERN_INFO "Enabling LCD.\n");
+	/* Enable [not] LCD_RESET to enable the LCD display */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET);
+	ucb1x00_io_write( ucb, UCB1400_GPIO_LCD_RESET, 0);
+
+	/* Enable the Contrast circuit */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA);
+	ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_ENA, 0);
+}
+
+void cerf_ucb1400gpio_lcd_disable( void)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+	if( ucb_debug > 2) printk( KERN_INFO "Disabling LCD.\n");
+	/* Disable the Contrast circuit  */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA);
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_ENA);
+
+	/* Disable [not] LCD_RESET to enable the LCD display */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET);
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_LCD_RESET);
+}
+
+void cerf_ucb1400gpio_lcd_contrast_step( int direction)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+        // Assert the chip select and the up modifier
+        ucb1x00_io_set_dir( ucb, 0, 
+			(UCB1400_GPIO_CONT_CS |
+                         UCB1400_GPIO_CONT_DOWN |
+                         UCB1400_GPIO_CONT_INC));
+
+	if( direction == DOWN)
+	{
+		if( ucb_debug > 3)
+			printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: "
+				"stepping up\n");
+		//goin' up
+		ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_DOWN, 0);
+	}
+	else
+	{
+		if( ucb_debug > 3)
+			printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: "
+				"stepping down\n");
+		//goin' down
+		ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN);
+	}
+
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_CS);
+
+        // Assert the line up, down then up again
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC);
+        udelay(1);
+	ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_INC, 0);
+        udelay(1);
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC);
+
+        // Deassert the chip select and the up modifier
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN);
+	ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_CS, 0);
+}
+
+/* -- -- */
+
+void cerf_ucb1400gpio_irda_enable( void)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+	printk( KERN_INFO "Enabling IRDA.\n");
+	/* Enable IRDA (active low) */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
+}
+
+void cerf_ucb1400gpio_irda_disable( void)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+	printk( KERN_INFO "Disabling IRDA.\n");
+	/* Disable IRDA (active low) */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
+	ucb1x00_io_write( ucb, UCB1400_GPIO_IRDA_ENABLE, 0);
+}
+
+/* -- -- */
+
+void cerf_ucb1400gpio_bt_enable( void)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+	printk( KERN_INFO "Enabling Bluetooth.\n");
+	/* Enable BT (active low) */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE);
+	ucb1x00_io_write( ucb, 0, UCB1400_GPIO_BT_ENABLE);
+}
+
+void cerf_ucb1400gpio_bt_disable( void)
+{
+	struct ucb1x00 * ucb = ucb1x00_get();
+	printk( KERN_INFO "Disabling Bluetooth.\n");
+	/* Disable BT (active low) */
+	ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE);
+	ucb1x00_io_write( ucb, UCB1400_GPIO_BT_ENABLE, 0);
+}
+
+/* -- -- */
+
+/* -- Enable Bluetooth and IRDA automatically via pseudo module -- */
+#if defined(CONFIG_BLUEZ) || defined(CONFIG_IRDA)
+static int __init cerf_ucb1400gpio_module_init (void)
+{
+#ifdef CONFIG_BLUEZ
+        cerf_ucb1400gpio_bt_enable();
+#endif
+
+#ifdef CONFIG_IRDA
+        cerf_ucb1400gpio_irda_enable();
+#endif
+	return 0;
+}
+
+static void __exit cerf_ucb1400gpio_module_exit (void)
+{
+#ifdef CONFIG_BLUEZ
+        cerf_ucb1400gpio_bt_disable();
+#endif
+
+#ifdef CONFIG_IRDA
+        cerf_ucb1400gpio_irda_disable();
+#endif
+}
+
+module_init(cerf_ucb1400gpio_module_init);
+module_exit(cerf_ucb1400gpio_module_exit);
+#endif
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/misc/mcp-pxa.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ *  linux/drivers/misc/mcp-pxa.c
+ *
+ *  2002-01-10 Jeff Sutherland <jeffs@accelent.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.
+ *
+ * NOTE: This is a quick hack to gain access to the aclink codec's
+ *       touch screen facility.  Its audio is handled by a separate
+ *       (non-mcp) driver at the present time.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ac97_codec.h>
+
+#include "mcp.h"
+
+
+extern int pxa_ac97_get(struct ac97_codec **codec);
+extern void pxa_ac97_put(void);
+
+
+struct mcp *mcp_get(void)
+{
+	struct ac97_codec *codec;
+	if (pxa_ac97_get(&codec) < 0)
+		return NULL;
+	return (struct mcp *)codec;
+}
+
+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+	struct ac97_codec *codec = (struct ac97_codec *)mcp;
+	codec->codec_write(codec, reg, val);
+}
+
+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
+{
+	struct ac97_codec *codec = (struct ac97_codec *)mcp;
+	return codec->codec_read(codec, reg);
+}
+
+void mcp_enable(struct mcp *mcp)
+{
+	/* 
+	 * Should we do something here to make sure the aclink
+	 * codec is alive???
+	 * A: not for now  --NP
+	*/
+}
+
+void mcp_disable(struct mcp *mcp)
+{
+}
--- linux-2.4.25/drivers/misc/mcp.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/misc/mcp.h	2004-03-31 17:15:11.000000000 +0200
@@ -10,16 +10,22 @@
 #ifndef MCP_H
 #define MCP_H
 
+#ifdef CONFIG_ARCH_SA1100
+#include <asm/dma.h>
+#endif
+
 struct mcp {
 	struct module	*owner;
 	spinlock_t	lock;
 	int		use_count;
 	unsigned int	sclk_rate;
 	unsigned int	rw_timeout;
+#ifdef CONFIG_ARCH_SA1100
 	dma_device_t	dma_audio_rd;
 	dma_device_t	dma_audio_wr;
 	dma_device_t	dma_telco_rd;
 	dma_device_t	dma_telco_wr;
+#endif
 	void		(*set_telecom_divisor)(struct mcp *, unsigned int);
 	void		(*set_audio_divisor)(struct mcp *, unsigned int);
 	void		(*reg_write)(struct mcp *, unsigned int, unsigned int);
--- linux-2.4.25/drivers/misc/ucb1x00-core.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/misc/ucb1x00-core.c	2004-03-31 17:15:11.000000000 +0200
@@ -23,12 +23,18 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
+#include <linux/tqueue.h>
+#include <linux/config.h>
 
-#include <asm/dma.h>
-#include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
+
+#ifdef CONFIG_ARCH_SA1100
+#include <asm/arch/assabet.h>
 #include <asm/arch/shannon.h>
+#endif
+
+#include <asm/hardware.h>
 
 #include "ucb1x00.h"
 
@@ -155,6 +161,10 @@
  *
  *	If called for a synchronised ADC conversion, it may sleep
  *	with the ADC semaphore held.
+ *	
+ *	See ucb1x00.h for definition of the UCB_ADC_DAT macro.  It
+ *	addresses a bug in the ucb1200/1300 which, of course, Philips
+ *	decided to finally fix in the ucb1400 ;-) -jws
  */
 unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
 {
@@ -218,22 +228,75 @@
  * Since we need to read an internal register, we must re-enable
  * SIBCLK to talk to the chip.  We leave the clock running until
  * we have finished processing all interrupts from the chip.
+ *
+ * A restriction with interrupts exists when using the ucb1400, as
+ * the codec read/write routines may sleep while waiting for codec
+ * access completion and uses semaphores for access control to the
+ * AC97 bus.  A complete codec read cycle could take  anywhere from
+ * 60 to 100uSec so we *definitely* don't want to spin inside the
+ * interrupt handler waiting for codec access.  So, we handle the
+ * interrupt by scheduling a RT kernel thread to run in process
+ * context instead of interrupt context.
  */
-static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
+
+static int ucb1x00_thread(void *_ucb)
 {
-	struct ucb1x00 *ucb = devid;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	struct ucb1x00 *ucb = _ucb;
 	struct ucb1x00_irq *irq;
 	unsigned int isr, i;
 
-	ucb1x00_enable(ucb);
-	isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+	ucb->rtask = tsk;
 
-	for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
-		if (isr & 1 && irq->fn)
-			irq->fn(i, irq->devid);
-	ucb1x00_disable(ucb);
+	daemonize();
+	reparent_to_init();
+	tsk->tty = NULL;
+	tsk->policy = SCHED_FIFO;
+	tsk->rt_priority = 1;
+	strcpy(tsk->comm, "kUCB1x00d");
+
+	/* only want to receive SIGKILL */
+	spin_lock_irq(&tsk->sigmask_lock);
+	siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
+	recalc_sigpending(tsk);
+	spin_unlock_irq(&tsk->sigmask_lock);
+
+	add_wait_queue(&ucb->irq_wait, &wait);
+	set_task_state(tsk, TASK_INTERRUPTIBLE);
+	complete(&ucb->complete);
+
+	for (;;) {
+		if (signal_pending(tsk))
+			break;
+		enable_irq(ucb->irq);
+		schedule();
+
+		ucb1x00_enable(ucb);
+		isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
+		ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
+		ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+		for (i = 0, irq = ucb->irq_handler;
+		     i < 16 && isr; 
+		     i++, isr >>= 1, irq++)
+			if (isr & 1 && irq->fn)
+				irq->fn(i, irq->devid);
+		ucb1x00_disable(ucb);
+
+		set_task_state(tsk, TASK_INTERRUPTIBLE);
+	}
+
+	remove_wait_queue(&ucb->irq_wait, &wait);
+	ucb->rtask = NULL;
+	complete_and_exit(&ucb->complete, 0);
+}
+
+static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
+{
+	struct ucb1x00 *ucb = devid;
+	disable_irq(irqnr);
+	wake_up(&ucb->irq_wait);
 }
 
 /**
@@ -291,6 +354,11 @@
 		spin_lock_irqsave(&ucb->lock, flags);
 
 		ucb1x00_enable(ucb);
+
+		/* This prevents spurious interrupts on the UCB1400 */
+		ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx);
+		ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
 		if (edges & UCB_RISING) {
 			ucb->irq_ris_enbl |= 1 << idx;
 			ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
@@ -456,6 +524,7 @@
 	unsigned int irq_gpio_pin = 0;
 	int irq, default_irq = NO_IRQ;
 
+#ifdef CONFIG_ARCH_SA1100
 	if (machine_is_adsbitsy())
 		default_irq = IRQ_GPCIN4;
 
@@ -514,12 +583,40 @@
 	}
 #endif
 
+#endif /* CONFIG_ARCH_SA1100 */
+
+#ifdef CONFIG_ARCH_PXA_IDP
+	if (machine_is_pxa_idp()) {
+		default_irq = TOUCH_PANEL_IRQ;
+		irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
+		GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
+	}
+#endif
+
+#ifdef CONFIG_ARCH_TRIZEPS2
+	if (machine_is_trizeps2()) {
+		default_irq = TOUCH_PANEL_IRQ;
+		irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
+		GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
+	}
+#endif
+
+
+#ifdef CONFIG_PXA_CERF_PDA
+	if (machine_is_pxa_cerf()) {
+		irq_gpio_pin = CERF_GPIO_UCB1400_IRQ;
+	}
+#endif
+
 	/*
 	 * Eventually, this will disappear.
 	 */
 	if (irq_gpio_pin)
+#ifdef CONFIG_ARCH_PXA_IDP
+		set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE);
+#else
 		set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
-
+#endif
 	irq = ucb1x00_detect_irq(ucb);
 	if (irq != NO_IRQ) {
 		if (default_irq != NO_IRQ && irq != default_irq)
@@ -541,21 +638,7 @@
 
 struct ucb1x00 *my_ucb;
 
-/**
- *	ucb1x00_get - get the UCB1x00 structure describing a chip
- *	@ucb: UCB1x00 structure describing chip
- *
- *	Return the UCB1x00 structure describing a chip.
- *
- *	FIXME: Currently very noddy indeed, which currently doesn't
- *	matter since we only support one chip.
- */
-struct ucb1x00 *ucb1x00_get(void)
-{
-	return my_ucb;
-}
-
-static int __init ucb1x00_init(void)
+static int ucb1x00_init_helper(void)
 {
 	struct mcp *mcp;
 	unsigned int id;
@@ -568,23 +651,28 @@
 	mcp_enable(mcp);
 	id = mcp_reg_read(mcp, UCB_ID);
 
-	if (id != UCB_ID_1200 && id != UCB_ID_1300) {
+	if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_1400) {
 		printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
 		goto out;
 	}
 
+	/* distinguish between UCB1400 revs 1B and 2A */
+	if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a)
+		id = UCB_ID_1400_BUGGY;
+
 	my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
 	ret = -ENOMEM;
 	if (!my_ucb)
 		goto out;
 
+#ifdef CONFIG_ARCH_SA1100
 	if (machine_is_shannon()) {
 		/* reset the codec */
 		GPDR |= SHANNON_GPIO_CODEC_RESET;
 		GPCR = SHANNON_GPIO_CODEC_RESET;
 		GPSR = SHANNON_GPIO_CODEC_RESET;
-
 	}
+#endif
 
 	memset(my_ucb, 0, sizeof(struct ucb1x00));
 
@@ -599,13 +687,12 @@
 	if (ret)
 		goto out;
 
+	init_waitqueue_head(&my_ucb->irq_wait);
 	ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
 	if (ret) {
 		printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
 			my_ucb->irq, ret);
-		kfree(my_ucb);
-		my_ucb = NULL;
-		goto out;
+		goto irq_err;
 	}
 
 #ifdef CONFIG_PM
@@ -616,16 +703,55 @@
 		my_ucb->pmdev->data = my_ucb;
 #endif
 
+	init_completion(&my_ucb->complete);
+	ret = kernel_thread(ucb1x00_thread, my_ucb, CLONE_FS | CLONE_FILES);
+	if (ret >= 0) {
+		wait_for_completion(&my_ucb->complete);
+		ret = 0;
+		goto out;
+	}
+
+	free_irq(my_ucb->irq, my_ucb);
+irq_err:
+	kfree(my_ucb);
+	my_ucb = NULL;
 out:
 	mcp_disable(mcp);
 no_mcp:
 	return ret;
 }
 
+/**
+ *	ucb1x00_get - get the UCB1x00 structure describing a chip
+ *	@ucb: UCB1x00 structure describing chip
+ *
+ *	Return the UCB1x00 structure describing a chip.
+ *
+ *	FIXME: Currently very noddy indeed, which currently doesn't
+ *	matter since we only support one chip.
+ */
+struct ucb1x00 *ucb1x00_get(void)
+{
+	if( !my_ucb) ucb1x00_init_helper();
+
+	return my_ucb;
+}
+
+static int __init ucb1x00_init(void)
+{
+	/* check if driver is already initialized */
+	if( my_ucb) return 0;
+
+	return ucb1x00_init_helper();
+}
+
 static void __exit ucb1x00_exit(void)
 {
+	send_sig(SIGKILL, my_ucb->rtask, 1);
+	wait_for_completion(&my_ucb->complete);
 	free_irq(my_ucb->irq, my_ucb);
 	kfree(my_ucb);
+	my_ucb = 0;
 }
 
 module_init(ucb1x00_init);
--- linux-2.4.25/drivers/misc/ucb1x00-ts.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/misc/ucb1x00-ts.c	2004-03-31 17:15:11.000000000 +0200
@@ -35,7 +35,11 @@
 /*
  * Define this if you want the UCB1x00 stuff to talk to the input layer
  */
+#ifdef CONFIG_INPUT
+#define USE_INPUT
+#else
 #undef USE_INPUT
+#endif
 
 #ifndef USE_INPUT
 
@@ -73,7 +77,7 @@
 	struct pm_dev		*pmdev;
 #endif
 
-	wait_queue_head_t	irq_wait;
+	struct semaphore	irq_wait;
 	struct semaphore	sem;
 	struct completion	init_exit;
 	struct task_struct	*rtask;
@@ -259,6 +263,11 @@
 	input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
 }
 
+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
+{
+	input_report_abs(&ts->idev, ABS_PRESSURE, 0);
+}
+
 static int ucb1x00_ts_open(struct input_dev *idev)
 {
 	struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
@@ -304,10 +313,15 @@
  */
 static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
 {
-	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-			UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-			UCB_TS_CR_MODE_INT);
+	if (ts->ucb->id == UCB_ID_1400_BUGGY)
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+				UCB_TS_CR_MODE_INT);
+	else
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+				UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+				UCB_TS_CR_MODE_INT);
 }
 
 /*
@@ -397,13 +411,13 @@
 /*
  * This is a RT kernel thread that handles the ADC accesses
  * (mainly so we can use semaphores in the UCB1200 core code
- * to serialise accesses to the ADC).
+ * to serialise accesses to the ADC).  The UCB1400 access
+ * functions are expected to be able to sleep as well.
  */
 static int ucb1x00_thread(void *_ts)
 {
 	struct ucb1x00_ts *ts = _ts;
 	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
 	int valid;
 
 	ts->rtask = tsk;
@@ -429,10 +443,8 @@
 
 	valid = 0;
 
-	add_wait_queue(&ts->irq_wait, &wait);
 	for (;;) {
 		unsigned int x, y, p, val;
-		signed long timeout;
 
 		ts->restart = 0;
 
@@ -457,8 +469,6 @@
 		val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
 
 		if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
-			set_task_state(tsk, TASK_INTERRUPTIBLE);
-
 			ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
 			ucb1x00_disable(ts->ucb);
 
@@ -471,7 +481,15 @@
 				valid = 0;
 			}
 
-			timeout = MAX_SCHEDULE_TIMEOUT;
+			/*
+			 * Since ucb1x00_enable_irq() might sleep due
+			 * to the way the UCB1400 regs are accessed, we
+			 * can't use set_task_state() before that call,
+			 * and not changing state before enabling the
+			 * interrupt is racy.  A semaphore solves all
+			 * those issues quite nicely.
+			 */
+			down_interruptible(&ts->irq_wait);
 		} else {
 			ucb1x00_disable(ts->ucb);
 
@@ -486,16 +504,13 @@
 			}
 
 			set_task_state(tsk, TASK_INTERRUPTIBLE);
-			timeout = HZ / 100;
+			schedule_timeout(HZ / 100);
 		}
 
-		schedule_timeout(timeout);
 		if (signal_pending(tsk))
 			break;
 	}
 
-	remove_wait_queue(&ts->irq_wait, &wait);
-
 	ts->rtask = NULL;
 	ucb1x00_ts_evt_clear(ts);
 	complete_and_exit(&ts->init_exit, 0);
@@ -509,7 +524,7 @@
 {
 	struct ucb1x00_ts *ts = id;
 	ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-	wake_up(&ts->irq_wait);
+	up(&ts->irq_wait);
 }
 
 static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
@@ -525,7 +540,7 @@
 	if (ts->rtask)
 		panic("ucb1x00: rtask running?");
 
-	init_waitqueue_head(&ts->irq_wait);
+	sema_init(&ts->irq_wait, 0);
 	ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
 	if (ret < 0)
 		goto out;
@@ -585,7 +600,7 @@
 		 * after sleep.
 		 */
 		ts->restart = 1;
-		wake_up(&ts->irq_wait);
+		up(&ts->irq_wait);
 	}
 	return 0;
 }
--- linux-2.4.25/drivers/misc/ucb1x00.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/misc/ucb1x00.h	2004-03-31 17:15:11.000000000 +0200
@@ -10,8 +10,47 @@
 #ifndef UCB1200_H
 #define UCB1200_H
 
+#ifdef CONFIG_ARCH_PXA
+
+/* ucb1400 aclink register mappings: */
+
+#define UCB_IO_DATA	0x5a
+#define UCB_IO_DIR	0x5c
+#define UCB_IE_RIS	0x5e
+#define UCB_IE_FAL	0x60
+#define UCB_IE_STATUS	0x62
+#define UCB_IE_CLEAR	0x62
+#define UCB_TS_CR	0x64
+#define UCB_ADC_CR	0x66
+#define UCB_ADC_DATA	0x68
+#define UCB_ID		0x7e /* 7c is mfr id, 7e part id (from aclink spec) */
+
+#define UCB_ADC_DAT(x)		((x) & 0x3ff)
+
+#else
+
+/* ucb1x00 SIB register mappings: */
+
 #define UCB_IO_DATA	0x00
 #define UCB_IO_DIR	0x01
+#define UCB_IE_RIS	0x02
+#define UCB_IE_FAL	0x03
+#define UCB_IE_STATUS	0x04
+#define UCB_IE_CLEAR	0x04
+#define UCB_TC_A	0x05
+#define UCB_TC_B	0x06
+#define UCB_AC_A	0x07
+#define UCB_AC_B	0x08
+#define UCB_TS_CR	0x09
+#define UCB_ADC_CR	0x0a
+#define UCB_ADC_DATA	0x0b
+#define UCB_ID		0x0c
+#define UCB_MODE	0x0d
+
+#define UCB_ADC_DAT(x)		(((x) & 0x7fe0) >> 5)
+
+#endif
+
 
 #define UCB_IO_0		(1 << 0)
 #define UCB_IO_1		(1 << 1)
@@ -24,10 +63,6 @@
 #define UCB_IO_8		(1 << 8)
 #define UCB_IO_9		(1 << 9)
 
-#define UCB_IE_RIS	0x02
-#define UCB_IE_FAL	0x03
-#define UCB_IE_STATUS	0x04
-#define UCB_IE_CLEAR	0x04
 #define UCB_IE_ADC		(1 << 11)
 #define UCB_IE_TSPX		(1 << 12)
 #define UCB_IE_TSMX		(1 << 13)
@@ -36,11 +71,9 @@
 
 #define UCB_IRQ_TSPX		12
 
-#define UCB_TC_A	0x05
 #define UCB_TC_A_LOOP		(1 << 7)	/* UCB1200 */
 #define UCB_TC_A_AMPL		(1 << 7)	/* UCB1300 */
 
-#define UCB_TC_B	0x06
 #define UCB_TC_B_VOICE_ENA	(1 << 3)
 #define UCB_TC_B_CLIP		(1 << 4)
 #define UCB_TC_B_ATT		(1 << 6)
@@ -49,14 +82,11 @@
 #define UCB_TC_B_IN_ENA		(1 << 14)
 #define UCB_TC_B_OUT_ENA	(1 << 15)
 
-#define UCB_AC_A	0x07
-#define UCB_AC_B	0x08
 #define UCB_AC_B_LOOP		(1 << 8)
 #define UCB_AC_B_MUTE		(1 << 13)
 #define UCB_AC_B_IN_ENA		(1 << 14)
 #define UCB_AC_B_OUT_ENA	(1 << 15)
 
-#define UCB_TS_CR	0x09
 #define UCB_TS_CR_TSMX_POW	(1 << 0)
 #define UCB_TS_CR_TSPX_POW	(1 << 1)
 #define UCB_TS_CR_TSMY_POW	(1 << 2)
@@ -72,7 +102,6 @@
 #define UCB_TS_CR_TSPX_LOW	(1 << 12)
 #define UCB_TS_CR_TSMX_LOW	(1 << 13)
 
-#define UCB_ADC_CR	0x0a
 #define UCB_ADC_SYNC_ENA	(1 << 0)
 #define UCB_ADC_VREFBYP_CON	(1 << 1)
 #define UCB_ADC_INP_TSPX	(0 << 2)
@@ -87,15 +116,13 @@
 #define UCB_ADC_START		(1 << 7)
 #define UCB_ADC_ENA		(1 << 15)
 
-#define UCB_ADC_DATA	0x0b
 #define UCB_ADC_DAT_VAL		(1 << 15)
-#define UCB_ADC_DAT(x)		(((x) & 0x7fe0) >> 5)
 
-#define UCB_ID		0x0c
 #define UCB_ID_1200		0x1004
 #define UCB_ID_1300		0x1005
+#define UCB_ID_1400		0x4304
+#define UCB_ID_1400_BUGGY	0x4303	/* fake ID */
 
-#define UCB_MODE	0x0d
 #define UCB_MODE_DYN_VFLAG_ENA	(1 << 12)
 #define UCB_MODE_AUD_OFF_CAN	(1 << 13)
 
@@ -115,6 +142,9 @@
 	unsigned int		irq;
 	struct semaphore	adc_sem;
 	spinlock_t		io_lock;
+	wait_queue_head_t	irq_wait;
+	struct completion	complete;
+	struct task_struct	*rtask;
 	u16			id;
 	u16			io_dir;
 	u16			io_out;
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/Config.in	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,12 @@
+mainmenu_option next_comment
+comment 'MMC device drivers'
+tristate 'Multi Media Card support' CONFIG_MMC
+if [ "$CONFIG_MMC" = "y" -o "$CONFIG_MMC" = "m" ]; then
+   dep_tristate 'PXA250 MMC driver' CONFIG_MMC_PXA  $CONFIG_MMC
+   dep_tristate 'MMC block driver' CONFIG_MMC_BLOCK  $CONFIG_MMC
+   if [ "$CONFIG_MMC_BLOCK" = "y" -o "$CONFIG_MMC_BLOCK" = "m" ]; then
+      bool '  MMC partitioning support' CONFIG_MMC_PARTITIONS
+   fi
+fi				       
+endmenu
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,14 @@
+#
+# Makefile for MMC drivers
+#
+
+export-objs	:= mmc_core.o
+
+obj-$(CONFIG_MMC)	+= mmc_core.o # mmc_test.o
+obj-$(CONFIG_MMC_BLOCK)	+= mmc_block.o
+obj-$(CONFIG_MMC_PXA)	+= mmc_pxa.o
+# EXTRA_CFLAGS += -DCONFIG_MMC_DEBUG -DCONFIG_MMC_DEBUG_VERBOSE=2
+
+O_TARGET := mmcdrivers.o
+
+include $(TOPDIR)/Rules.make
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/error.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+ *  linux/include/linux/mmc/error.h 
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *	$Id: error.h,v 0.2 2002/07/11 16:27:01 ted Exp ted $
+ *
+ *  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 __MMC_ERROR_H__
+#define __MMC_ERROR_H__
+
+/* MMC protocol card error codes */
+#define MMC_CARD_STATUS_OUT_OF_RANGE (1<<31)
+#define MMC_CARD_STATUS_ADDRESS_ERROR (1<<30)
+#define MMC_CARD_STATUS_BLOCK_LEN_ERROR (1<<29)
+#define MMC_CARD_STATUS_ERASE_SEQ_ERROR (1<<28)
+#define MMC_CARD_STATUS_ERASE_PARAM (1<<27)
+#define MMC_CARD_STATUS_WP_VIOLATION (1<<26)
+#define MMC_CARD_STATUS_CARD_IS_LOCKED (1<<25)
+#define MMC_CARD_STATUS_LOCK_UNLOCK_FAILED (1<<24)
+#define MMC_CARD_STATUS_COM_CRC_ERROR (1<<23)
+#define MMC_CARD_STATUS_ILLEGAL_COMMAND (1<<22)
+#define MMC_CARD_STATUS_CARD_ECC_FAILED (1<<21)
+#define MMC_CARD_STATUS_CC_ERROR (1<<20)
+#define MMC_CARD_STATUS_ERROR (1<<19)
+#define MMC_CARD_STATUS_UNDERRUN (1<<18)
+#define MMC_CARD_STATUS_OVERRUN (1<<17)
+#define MMC_CARD_STATUS_CID_CSD_OVERWRITE (1<<16)
+#define MMC_CARD_STATUS_ERASE_RESET (1<<13)
+
+#define MMC_ERROR( fmt, args... ) printk( KERN_ERR "%s(): " fmt, __FUNCTION__, ##args )
+
+/* 
+ * Error codes returned by MMC subsystem functions and
+ * error reporting function prototypes 
+ */
+enum _mmc_error {
+/* controller errors */
+	MMC_ERROR_GENERIC = -10000,
+	MMC_ERROR_CRC_WRITE_ERROR = -10001,
+	MMC_ERROR_CRC_READ_ERROR = -10002,
+	MMC_ERROR_RES_CRC_ERROR = -10003,
+	MMC_ERROR_READ_TIME_OUT = -10004,
+	MMC_ERROR_TIME_OUT_RESPONSE = -10005,
+	MMC_ERROR_INVAL = -10006,
+/* protocol errors reported in card status (R1 response) */		
+	MMC_ERROR_OUT_OF_RANGE = -10007,
+	MMC_ERROR_ADDRESS_ERROR = -10008,
+	MMC_ERROR_BLOCK_LEN_ERROR = -10009,
+	MMC_ERROR_ERASE_SEQ_ERROR = -10010,
+	MMC_ERROR_ERASE_PARAM = -10011,
+	MMC_ERROR_WP_VIOLATION = -10012,
+	MMC_ERROR_CARD_IS_LOCKED = -10013,
+	MMC_ERROR_LOCK_UNLOCK_FAILED = -10014,
+	MMC_ERROR_COM_CRC_ERROR = -10015,
+	MMC_ERROR_ILLEGAL_COMMAND = -10016,
+	MMC_ERROR_CARD_ECC_FAILED = -10017,
+	MMC_ERROR_CC_ERROR = -10018,
+	MMC_ERROR_ERROR = -10019,
+	MMC_ERROR_UNDERRUN = -10020,
+	MMC_ERROR_OVERRUN = -10021,
+	MMC_ERROR_CID_CSD_OVERWRITE = -10022,
+	/* FIXME: incomplete */
+	MMC_ERROR_ERASE_RESET = -10025
+};
+#endif /* __MMC_ERROR_H__ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/mmc.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,463 @@
+/*
+ *  linux/drivers/mmc/mmc.h
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *  
+ *  $Id: mmc.h,v 0.3.1.8 2002/09/18 12:58:00 ted Exp ted $
+ *  
+ *  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 __MMC_P_H__
+#define __MMC_P_H__
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/slab.h>
+
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
+
+#include <asm/semaphore.h>
+#include <mmc/types.h>
+#include <mmc/mmc.h>
+
+#include "types.h"
+
+#include "error.h"
+
+#define MMC_CONTROLLERS_MAX (4)
+#define MMC_CARDS_MAX (16)
+
+/* test device */
+#define MMC_TEST_MAJOR (240)
+#define MMC_TEST_TRANSFER_MODE_DEFAULT MMC_TRANSFER_MODE_BLOCK_SINGLE
+
+/* block device */
+#define MMC_BLOCK_MAJOR (241) /* FIXME: MMC_MAJOR */
+#define MMC_BLOCK_DEVICES_MAX (1<<MINORBITS) /* FIXME */
+#define MMC_BLOCK_SECT_SIZE (512) /* FIXME */
+#define MMC_BLOCK_PARTNBITS (3)
+
+/* Device minor number encoding:
+ *   [7:6] - host
+ *   [5:3] - card slot number
+ *   [2:0] - partition number 
+ */
+#define MMC_MINOR_HOST_SHIFT (6)
+#define MMC_MINOR_CARD_MASK (0x07)
+
+/*
+ *  MMC controller abstraction
+ */
+enum _mmc_controller_state {
+	MMC_CONTROLLER_ABSENT = 0,
+	MMC_CONTROLLER_FOUND,
+	MMC_CONTROLLER_INITIALIZED,
+	MMC_CONTROLLER_UNPLUGGED
+};
+
+enum _mmc_dir {
+	MMC_READ = 1,
+	MMC_WRITE
+};
+
+enum _mmc_buftype {
+	MMC_USER = 1,
+	MMC_KERNEL
+};
+
+struct _mmc_data_transfer_req_rec {
+	mmc_dir_t cmd; /* read or write operation requested */
+	mmc_transfer_mode_t mode; /* requested data transfer mode */
+	mmc_buftype_t type; /* whether supplied buffer resides in user or kernel space */
+	char *buf; /* poiner to the caller's buffer */
+	ssize_t cnt; /* number of bytes to transfer */
+	loff_t addr; /* card address */
+	ssize_t blksz; /* block size as for CSD[READ_BL_LEN] or CSD[WRITE_BL_LEN] */
+	ssize_t nob; /* number of blocks to transfer */
+};
+
+struct _mmc_controller_tmpl_rec {
+	struct module *owner;	/* driver module */
+	char name[16];
+
+	const ssize_t block_size_max; /* max acceptable block size */
+	const ssize_t nob_max; /* max blocks per one data transfer */
+
+	int (*probe)( mmc_controller_t ); /* hardware probe */
+	int (*init)( mmc_controller_t ); /* initialize, e.g. request irq, DMA and allocate buffers */
+	void (*remove)( mmc_controller_t ); /* free resources */
+#if 0 /* CONFIG_HOTPLUG */
+	void (*attach)( void ); /|* controller hotplug callbacks *|/
+	void (*detach)( void );
+#endif
+#ifdef CONFIG_PM 
+	int (*suspend)( mmc_controller_t ); /* power management callbacks */
+	void (*resume)( mmc_controller_t );
+#endif
+	
+/* MMC protocol macros, v3.4, p.120 */
+	int (*init_card_stack)( mmc_controller_t );
+	int (*update_acq)( mmc_controller_t ); /* update card stack management data */
+	int (*single_card_acq)( mmc_controller_t );
+	int (*check_card_stack)( mmc_controller_t );
+	int (*setup_card)( mmc_controller_t, mmc_card_t );
+	int (*stream_read)( mmc_controller_t, mmc_data_transfer_req_t );
+	int (*read_block)( mmc_controller_t,  mmc_data_transfer_req_t ); 
+	int (*read_mblock)( mmc_controller_t, mmc_data_transfer_req_t  );
+	int (*stream_write)( mmc_controller_t, mmc_data_transfer_req_t  );
+	int (*write_block)( mmc_controller_t, mmc_data_transfer_req_t );
+	int (*write_mblock)( mmc_controller_t, mmc_data_transfer_req_t  );
+/* TODO:
+	int (*sg_io)( mmc_controller_t, sg_list_t );
+*/
+/* TODO: 
+ *	1) erase group macros 
+ *	   int (*erase_group)( mmc_controller_t, mmc_erase_group_info_t );
+ * 	2) write protection macros;
+ * 	   int (*set_write_prot)( mmc_controller_t, mmc_write_protection_info_t )
+ * 	3) lock/password management macros;
+ */
+};
+
+#ifndef MMC_CTRLR_BLKSZ_DEFAULT 
+#define MMC_CTRLR_BLKSZ_DEFAULT (512)
+#endif
+
+#ifndef MMC_CTRLR_NOB_DEFAULT 
+#define MMC_CTRLR_NOB_DEFAULT (1)
+#endif
+
+struct _mmc_card_rec {
+/* public card interface */
+	struct _mmc_card_info_rec info; /* see <linux/mmc/mmc.h> */
+
+/* private kernel specific data */
+	mmc_state_t state;  /* card's state as per last operation */
+	mmc_card_t next;     /* link to the stack */
+	mmc_controller_t ctrlr;		/* back reference to the controller */
+	int usage;			/* reference count */
+	int slot;			/* card's number for device reference */
+/* TODO: async I/O queue */
+#ifdef CONFIG_PROC_FS
+	proc_dir_entry_t proc;
+	char proc_name[16];
+#endif
+	unsigned long card_data[0]	/* card specific data */
+	__attribute__((aligned (sizeof(unsigned long))));
+};
+
+struct _mmc_card_stack_rec {
+	mmc_card_t first;	/* first card on the stack */
+	mmc_card_t last;	/* last card on the stack */
+	mmc_card_t selected;    /* currently selected card */
+	int ncards;
+};
+
+struct _mmc_controller_rec {
+	mmc_controller_state_t state; /* found, initialized, unplugged... */
+	int usage;		     /* reference count */
+	int slot;		     /* host's number for device reference */
+	semaphore_t io_sem;	     /* I/O serialization */
+	rwsemaphore_t update_sem;    /* card stack check/update serialization */
+
+	mmc_controller_tmpl_t tmpl; /* methods provided by the driver */
+	mmc_card_stack_rec_t stack; /* card stack management data */
+
+	u32 rca_next;  /* next RCA to assign */
+	int slot_next; /* next slot number to assign */
+#ifdef CONFIG_PROC_FS
+	char proc_name[16];
+	proc_dir_entry_t proc;
+#endif
+	unsigned long host_data[0]  /* driver can request some extra space */
+	__attribute__((aligned (sizeof(unsigned long))));
+};
+
+/*
+ * MMC core interface
+ */
+enum _mmc_reg_type {
+	MMC_REG_TYPE_USER = 1,
+	MMC_REG_TYPE_HOST,
+	MMC_REG_TYPE_CARD
+};
+
+struct _mmc_notifier_rec {
+	struct _mmc_notifier_rec *next;
+	mmc_notifier_fn_t add;
+	mmc_notifier_fn_t remove;
+};
+
+enum _mmc_response {
+	MMC_NORESPONSE = 1,
+	MMC_R1,
+	MMC_R2,
+	MMC_R3,
+	MMC_R4,
+	MMC_R5
+};
+
+#undef EXTERN
+#ifndef __MMC_CORE_IMPLEMENTATION__
+#define EXTERN extern
+#else
+#define EXTERN /* empty */
+#endif
+
+EXTERN void *mmc_register( mmc_reg_type_t, void *, size_t ); 
+EXTERN void mmc_unregister( mmc_reg_type_t, void * );
+EXTERN int mmc_update_card_stack( int );
+
+EXTERN mmc_card_t mmc_get_card( int, int );/* get reference to the card */
+EXTERN void mmc_put_card( mmc_card_t );  /* release card reference */
+
+EXTERN int mmc_notify_add( mmc_card_t ); /* user notification */
+EXTERN int mmc_notify_remove( mmc_card_t );
+
+EXTERN ssize_t mmc_read( mmc_card_t, mmc_transfer_mode_t, char *, size_t, loff_t * ); /* generic read */
+EXTERN ssize_t mmc_write( mmc_card_t, mmc_transfer_mode_t, const char *, size_t, loff_t * ); /* generic write */
+EXTERN int mmc_ioctl( mmc_card_t, unsigned int, unsigned long ); /* generic ioctl */ 
+/*
+ * TODO: [?m.b. ioctl()] to erase, lock and write protect
+ *    1) mmc_erase
+ *    2) mmc_write_prot
+ *    3) mmc_lock
+ */
+#undef EXTERN
+
+static inline mmc_card_t __mmc_card_alloc( size_t extra )
+{
+	mmc_card_t ret = kmalloc( sizeof( mmc_card_rec_t ) + extra, GFP_KERNEL );
+	
+	if ( ret ) {
+		memset( ret, 0, sizeof( mmc_card_rec_t ) + extra );
+	}
+	
+	return ret;
+}
+
+static inline void __mmc_card_free( mmc_card_t card )
+{
+	if ( card ) {
+		kfree( card );
+	}
+}
+
+static inline mmc_card_stack_t __mmc_card_stack_init( mmc_card_stack_t stack )
+{
+	mmc_card_stack_t ret = NULL;
+	if ( stack ) {
+		memset( stack, 0, sizeof( mmc_card_stack_rec_t ) );
+		ret = stack;
+	}
+	return ret;
+}
+
+static inline mmc_card_stack_t __mmc_card_stack_add( mmc_card_stack_t stack, mmc_card_t card )
+{
+	mmc_card_stack_t ret = NULL;
+	
+	if ( stack && card ) {
+		card->next = NULL;
+		
+		if ( stack->first ) {
+			stack->last->next = card;
+			stack->last = card;
+		} else 
+			stack->first = stack->last = card;
+		
+		++stack->ncards;
+		ret = stack;
+	}
+	return ret;
+}
+
+static inline mmc_card_stack_t __mmc_card_stack_remove( mmc_card_stack_t stack, mmc_card_t card )
+{
+	mmc_card_stack_t ret = NULL;
+	register mmc_card_t prev;
+	int found = FALSE;
+
+	if ( !stack || !card )
+		goto error;
+	
+	if ( stack->ncards > 0 ) {
+		if ( stack->first == card ) {
+			stack->first = stack->first->next;
+			if ( stack->last == card )
+				stack->last = stack->last->next;
+			found = TRUE;		
+		} else {
+			for ( prev = stack->first; prev; prev = prev->next )
+				if ( prev->next == card ) {
+					found = TRUE;
+					break;
+				}
+			if ( found ) {
+				if ( prev->next == stack->last )
+					stack->last = prev->next;
+				prev->next = prev->next->next;
+			}
+		}
+		if ( found ) {
+			--stack->ncards;
+			ret = stack;
+		}
+	}
+error:
+	return ret;
+}
+
+static inline void __mmc_card_stack_free( mmc_card_stack_t stack )
+{
+	mmc_card_t card, next;
+	
+	if ( stack && (stack->ncards > 0) ) {
+		card = stack->first;
+		while ( card ) {
+			next = card->next;
+			kfree( card );
+			card = next;
+		}
+		__mmc_card_stack_init( stack );
+	}
+}
+
+static inline int __mmc_card_stack_foreach( mmc_card_stack_t stack, mmc_notifier_fn_t fn, int unplugged_also )
+{
+	int ret = 0;
+	register mmc_card_t card = NULL;
+
+	if ( stack && fn ) {
+		for ( card = stack->first; card; card = card->next ) 
+			if ( (card->state != MMC_CARD_STATE_UNPLUGGED) 
+					|| unplugged_also )
+				if ( fn( card ) ) {
+					ret = -card->slot;
+					break;
+				}
+	}
+	
+	return ret;	
+}
+
+/*
+ * Debugging macros
+ */
+#ifdef CONFIG_MMC_DEBUG
+
+#define MMC_DEBUG_LEVEL0 (0)     /* major */
+#define MMC_DEBUG_LEVEL1 (1)
+#define MMC_DEBUG_LEVEL2 (2)     /* device */
+#define MMC_DEBUG_LEVEL3 (3)     /* protocol */
+#define MMC_DEBUG_LEVEL4 (4)     /* everything */
+
+#define MMC_DEBUG(n, args...) \
+if (n <=  CONFIG_MMC_DEBUG_VERBOSE) { \
+	printk(KERN_INFO __FUNCTION__ "(): " args); \
+}
+#define __ENTER0( )	MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry\n" );
+#define __LEAVE0( )	MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit\n" );
+#define __ENTER( format, args... )	MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry: " format "\n", args );
+#define __LEAVE( format, args... )	MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit: " format "\n", args );
+
+#define MMC_DUMP_CSD( card ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
+"CSD register:\n" \
+"    csd_structure=%u\n" \
+"    spec_vers=%u\n" \
+"    taac=%x\n" \
+"    nsac=%x\n" \
+"    tran_speed=%x\n" \
+"    ccc=%x\n" \
+"    read_bl_len=%u\n" \
+"    read_bl_partial=%u\n" \
+"    write_blk_misalign=%u\n" \
+"    read_blk_misalign=%u\n" \
+"    dsr_imp=%u\n" \
+"    c_size=%u\n" \
+"    vdd_r_curr_min=%u\n" \
+"    vdd_r_curr_max=%u\n" \
+"    vdd_w_curr_min=%u\n" \
+"    vdd_w_curr_max=%u\n" \
+"    c_size_mult=%u\n" \
+"    erase_grp_size=%u\n" \
+"    erase_grp_mult=%u\n" \
+"    wp_grp_size=%u\n" \
+"    wp_grp_enable=%u\n" \
+"    default_ecc=%u\n" \
+"    r2w_factor=%u\n" \
+"    write_bl_len=%u\n" \
+"    write_bl_partial=%u\n" \
+"    content_prot_app=%u\n" \
+"    file_format_grp=%u\n" \
+"    copy=%u\n" \
+"    perm_write_protect=%d\n" \
+"    tmp_write_protect=%d\n" \
+"    file_format=%d\n" \
+"    ecc=%d\n", \
+card->info.csd.csd_structure, \
+card->info.csd.spec_vers, \
+card->info.csd.taac, \
+card->info.csd.nsac, \
+card->info.csd.tran_speed, \
+card->info.csd.ccc, \
+card->info.csd.read_bl_len, \
+card->info.csd.read_bl_partial, \
+card->info.csd.write_blk_misalign, \
+card->info.csd.read_blk_misalign, \
+card->info.csd.dsr_imp, \
+card->info.csd.c_size, \
+card->info.csd.vdd_r_curr_min, \
+card->info.csd.vdd_r_curr_max, \
+card->info.csd.vdd_w_curr_min, \
+card->info.csd.vdd_w_curr_max, \
+card->info.csd.c_size_mult, \
+card->info.csd.erase_grp_size, \
+card->info.csd.erase_grp_mult, \
+card->info.csd.wp_grp_size, \
+card->info.csd.wp_grp_enable, \
+card->info.csd.default_ecc, \
+card->info.csd.r2w_factor, \
+card->info.csd.write_bl_len, \
+card->info.csd.write_bl_partial, \
+card->info.csd.content_prot_app, \
+card->info.csd.file_format_grp, \
+card->info.csd.copy, \
+card->info.csd.perm_write_protect, \
+card->info.csd.tmp_write_protect, \
+card->info.csd.file_format, \
+card->info.csd.ecc );
+
+#else /* CONFIG_MMC_DEBUG */
+#define MMC_DEBUG(n, args...)	/* empty */
+#define __ENTER0( )	/* empty */
+#define __LEAVE0( )	/* empty */
+#define __ENTER( args... )	/* empty */
+#define __LEAVE( args... )	/* empty */
+#define MMC_DUMP_CSD( card ) /* empty */
+#endif /* CONFIG_MMC_DEBUG */
+
+/* 
+ * Miscellaneous defines
+ */
+#ifndef MMC_DUMP_R1
+#define MMC_DUMP_R1( ctrlr ) /* empty */
+#endif
+#ifndef MMC_DUMP_R2
+#define MMC_DUMP_R2( ctrlr ) /* empty */
+#endif
+#ifndef MMC_DUMP_R3
+#define MMC_DUMP_R3( ctrlr ) /* empty */
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __MMC_P_H__ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/mmc_block.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,989 @@
+/*
+ *  linux/drivers/mmc/mmc_block.c 
+ *  	 driver for the block device on the MMC card
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *	$Id: mmc_block.c,v 0.3.1.16 2002/09/27 17:36:09 ted Exp ted $
+ *
+ *  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/version.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/hdreg.h>
+#include <linux/blkpg.h>
+#include <asm/uaccess.h>
+
+#include <mmc/types.h>
+#include <mmc/mmc.h>
+
+#include "types.h"
+#include "mmc.h"
+#include "error.h"
+
+#define MAJOR_NR MMC_BLOCK_MAJOR
+#define MAJOR_NAME "mmc"
+#define DEVICE_NAME "mmc_block"
+#define DEVICE_REQUEST mmc_block_request
+#define DEVICE_NR(device) (device)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+#define DEVICE_NO_RANDOM
+#include <linux/blk.h>
+/* for old kernels... */
+#ifndef QUEUE_EMPTY
+#define QUEUE_EMPTY  (!CURRENT)
+#endif
+#if LINUX_VERSION_CODE < 0x20300
+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync)
+#else
+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged)
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14)
+#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
+#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#else
+#define BLK_INC_USE_COUNT do {} while(0)
+#define BLK_DEC_USE_COUNT do {} while(0)
+#endif
+
+#define MMC_BLOCK_RAW_DEVICE( device ) ((device>>MMC_BLOCK_PARTNBITS)<<MMC_BLOCK_PARTNBITS)
+#define MMC_BLOCK_MKDEV( host, slot ) \
+	MKDEV( MMC_BLOCK_MAJOR, \
+	(host<<MMC_MINOR_HOST_SHIFT) \
+	| (slot<<MMC_BLOCK_PARTNBITS) )
+
+typedef struct _mmc_block_device mmc_block_device_rec_t;
+typedef struct _mmc_block_device *mmc_block_device_t;
+
+struct _mmc_block_device {
+	mmc_card_t card;
+	int host;
+	int slot;
+	kdev_t rdev;
+	int usage;
+	semaphore_t sem;
+};
+
+static int mmc_block_blk_sizes[1<<MINORBITS];
+static int mmc_block_blk_blksizes[1<<MINORBITS];
+static int mmc_block_hardsect_sizes[1<<MINORBITS];
+static struct hd_struct mmc_block_partitions[1<<MINORBITS];
+
+/* Accessed under device table lock */
+static gendisk_rec_t mmc_block_gendisk = {
+	major:		MMC_BLOCK_MAJOR,
+	major_name:	MAJOR_NAME,
+	minor_shift:	MMC_BLOCK_PARTNBITS,
+	max_p:		(1<<MMC_BLOCK_PARTNBITS),
+	sizes:		mmc_block_blk_sizes,
+	part:		mmc_block_partitions
+};
+
+static mmc_block_device_rec_t mmc_block_device[1<<MINORBITS];
+static rwsemaphore_t mmc_block_device_sem;
+
+static inline void __mmc_block_rdlock_devices( void )
+{
+	down_read( &mmc_block_device_sem );
+}
+
+static inline void __mmc_block_rdunlock_devices( void )
+{
+	up_read( &mmc_block_device_sem );
+}
+
+static inline void __mmc_block_wrlock_devices( void )
+{
+	down_write( &mmc_block_device_sem );
+}
+
+static inline void __mmc_block_wrunlock_devices( void )
+{
+	up_write( &mmc_block_device_sem );
+}
+
+static inline void __mmc_block_lock_device( kdev_t rdev )
+{
+	__mmc_block_rdlock_devices();
+	down( &mmc_block_device[MINOR( rdev )].sem );
+}
+
+static inline void __mmc_block_unlock_device( kdev_t rdev )
+{
+	up( &mmc_block_device[MINOR( rdev )].sem );
+	__mmc_block_rdunlock_devices();
+}
+
+static inline void __mmc_block_device_init( int minor )
+{
+	mmc_block_device_t dev = &mmc_block_device[minor];
+	
+	dev->usage = 0;
+	dev->card = NULL;
+	dev->host = minor >> MMC_MINOR_HOST_SHIFT;
+	dev->slot = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS;
+	dev->rdev = MKDEV( MMC_BLOCK_MAJOR, minor );
+}
+
+static inline int __mmc_block_validate_device( kdev_t rdev )
+{
+	int ret = -1;
+	int minor = MINOR( rdev );
+	
+	if ( mmc_block_device[minor].card 
+			&& (mmc_block_gendisk.part[minor].nr_sects > 0) )
+		ret = 0;
+
+	return ret;
+}
+
+static inline int __mmc_block_invalidate_card( mmc_card_t card, int invalidate )
+{
+	int ret = 0;
+	kdev_t start;
+	int minor;
+
+	__ENTER( "card = 0x%p", card );
+	
+	if ( card && card->ctrlr ) {
+		register int i;
+		
+		start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );
+		minor = MINOR( start );
+
+		__mmc_block_wrlock_devices();
+		for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
+			if ( invalidate )
+				invalidate_device( start + i, 0 );
+			
+			__mmc_block_device_init( minor + i );
+			
+			mmc_block_gendisk.part[minor + i].nr_sects = 0;
+			mmc_block_gendisk.part[minor + i].start_sect = 0;
+		}
+		__mmc_block_wrunlock_devices();
+	}
+	
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static inline int mmc_block_invalidate_card( int host, int slot, int invalidate )
+{
+	int ret = 0;
+	kdev_t start;
+	int minor;
+
+	__ENTER( "host=%d slot=%d", host, slot );
+	
+	if ( (host >= 0) && (slot >= 0) ) {
+		register int i;
+		mmc_card_t card = NULL;
+		
+		start = MMC_BLOCK_MKDEV( host, slot );
+		minor = MINOR( start );
+
+		__mmc_block_wrlock_devices();
+		for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
+			if ( !card ) 
+				card = mmc_block_device[minor + i].card;
+			
+			if ( invalidate )
+				invalidate_device( start + i, 0 );
+			
+			__mmc_block_device_init( minor + i );
+			
+			mmc_block_gendisk.part[minor + i].nr_sects = 0;
+			mmc_block_gendisk.part[minor + i].start_sect = 0;
+		}
+		if ( card )
+			mmc_put_card( card );
+		__mmc_block_wrunlock_devices();
+	}
+	
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+/* Get device reference locked for writing */
+static inline mmc_block_device_t __mmc_block_get_device( kdev_t rdev )
+{
+	mmc_block_device_t ret = NULL;
+	u8 minor = MINOR( rdev );
+	int host_no, card_no;
+
+	__ENTER( "rdev=%x:%x", MAJOR( rdev ), MINOR( rdev ) );
+
+	host_no = minor >> MMC_MINOR_HOST_SHIFT;
+	if ( host_no >= MMC_CONTROLLERS_MAX )
+		goto error;
+
+	card_no = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS;
+	if ( card_no >= MMC_CARDS_MAX )
+		goto error;
+	
+	__mmc_block_lock_device( rdev );
+	if ( __mmc_block_validate_device( rdev ) ) {
+		__mmc_block_unlock_device( rdev );	
+		goto error;
+	}
+
+	ret = &mmc_block_device[minor];
+	MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n",
+			MAJOR( ret->rdev ), MINOR( ret->rdev ), 
+			ret->card, ret->usage );
+error:
+	__LEAVE( "ret=0x%p", ret );
+	return ret;
+}
+
+/* Unlocks the device */
+static inline void __mmc_block_put_device( mmc_block_device_t dev )
+{
+	__ENTER0();
+	
+	if ( dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n",
+				MAJOR( dev->rdev ), MINOR( dev->rdev ), 
+				dev->card, dev->usage );
+		__mmc_block_unlock_device( dev->rdev );
+	}
+	
+	__LEAVE0();
+}
+
+/* Atomically increases use count of the valid device */
+static inline mmc_block_device_t mmc_block_get_device( kdev_t rdev )
+{
+	mmc_block_device_t ret = NULL;
+	
+	__ENTER0();
+	
+	ret = __mmc_block_get_device( rdev );
+	if ( !ret )
+		goto error;
+	
+	ret->usage++;
+	__mmc_block_put_device( ret );
+error:
+	__LEAVE( "ret=0x%p dusage=%d card=0x%p cusage=%d",
+			ret, ret ? ret->usage : -1, 
+			ret ? ret->card : NULL, 
+			ret ? (ret->card ? ret->card->usage : -1) : -1 );
+	return ret;
+}
+
+/* Check is there references to the card */
+static inline int __mmc_block_check_card( kdev_t rdev ) 
+{
+	int ret = TRUE;
+	int start = MINOR( MMC_BLOCK_RAW_DEVICE( rdev ) );
+	register int i;
+
+	for ( i = 0; i < mmc_block_gendisk.max_p; i++ )
+		if ( mmc_block_device[start + i].usage > 0 ) {
+			ret = FALSE;
+			break;
+		}
+
+	return ret;
+}
+
+/* Atomically decreases device use count */
+static inline void mmc_block_put_device( mmc_block_device_t dev )
+{
+	__ENTER0();
+	
+	if ( dev ) {
+		int invalidate = FALSE;
+		
+		__mmc_block_get_device( dev->rdev );
+		if ( dev->usage > 0 )
+			--dev->usage;
+		
+		if ( dev->usage ) {
+			__mmc_block_put_device( dev );
+			goto out;
+
+		} else {
+			int host, slot;
+			mmc_card_t card = NULL;
+			
+			invalidate = __mmc_block_check_card( dev->rdev );	
+			if ( invalidate ) {
+				host = dev->card->ctrlr->slot;
+				slot = dev->card->slot;
+
+				if ( dev->card ) {
+					card = dev->card;
+					mmc_put_card( dev->card );
+					dev->card = NULL;
+				}
+			}
+			__mmc_block_put_device( dev );
+
+			if ( invalidate )
+				__mmc_block_invalidate_card( card, TRUE );
+		}
+		
+	}
+out:
+	__LEAVE0();
+}
+
+static int mmc_block_open( struct inode *inode, struct file *file )
+{
+	int ret = -ENODEV;
+	mmc_block_device_t dev = NULL;
+	
+	__ENTER0();
+
+	if ( !inode || !file )
+		goto error;
+	
+	BLK_INC_USE_COUNT;
+	
+	check_disk_change( inode->i_rdev );
+	
+	dev = mmc_block_get_device( inode->i_rdev );
+	if ( !dev )
+		goto error;
+	
+	dev = __mmc_block_get_device( inode->i_rdev );
+	if ( !dev )
+		goto error;
+	
+	if ( file->f_mode & FMODE_WRITE ) { /* FIXME */
+		if ( dev->usage > 1 ) {
+			ret = -EBUSY;
+			__mmc_block_put_device( dev );
+			mmc_block_put_device( dev );
+			goto error;
+		}
+	}
+	
+	__mmc_block_put_device( dev );
+	
+	if ( file )
+		file->private_data = dev;
+
+	ret = 0;
+	goto out;
+error:
+	BLK_DEC_USE_COUNT;
+out:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static int mmc_block_release( struct inode *inode, struct file *file )
+{
+	int ret = -EINVAL;
+	mmc_block_device_t dev = NULL;
+	
+	__ENTER( "inode=0x%p file=0x%p rdev=(%x:%x)", inode, file,
+			inode ? MAJOR( inode->i_rdev ) : 0xff,
+			inode ? MINOR( inode->i_rdev ) : 0xff );
+
+	if ( !file && !inode )
+		goto error;
+	
+	if ( file )
+		dev = file->private_data;
+	else
+		dev = __mmc_block_get_device( inode->i_rdev );
+
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );
+		goto error;
+	}
+	
+	if ( file ) {
+		mmc_block_put_device( dev );
+		file->private_data = NULL;
+
+	} else {
+		int invalidate = FALSE;
+		
+		if ( dev->usage > 0 )
+			--dev->usage;
+		
+		if ( dev->usage ) {
+			__mmc_block_put_device( dev );
+			goto out;
+			
+		} else {
+			int host, slot;
+			mmc_card_t card = NULL;
+			
+			invalidate = __mmc_block_check_card( dev->rdev );	
+			if ( invalidate ) {
+				host = dev->card->ctrlr->slot;
+				slot = dev->card->slot;
+
+				if ( dev->card ) {
+					card = dev->card;
+					mmc_put_card( dev->card );
+					dev->card = NULL;
+				}
+			}
+			__mmc_block_put_device( dev );
+
+			if ( invalidate )
+				__mmc_block_invalidate_card( card, TRUE );
+	
+		}
+	}
+	
+out:
+	BLK_DEC_USE_COUNT;
+	ret = 0;
+error:
+	__LEAVE0();
+	return ret;
+}  
+
+static int mmc_block_check_disk_change( kdev_t rdev )
+{
+	int ret = 0;
+#if 0
+	mmc_block_device_t dev = &mmc_block_device[MINOR( rdev )];
+	
+	__mmc_block_lock_device( rdev );
+	if ( !dev->card )
+		ret = 1;
+	__mmc_block_unlock_device( rdev );
+#else
+	ret = 1;
+#endif
+	return ret;
+}
+
+static int mmc_block_revalidate( kdev_t rdev )
+{
+	int ret = 1;
+	mmc_card_t card;
+	mmc_block_device_t dev;
+	kdev_t start = MMC_BLOCK_RAW_DEVICE( rdev );
+	int minor = MINOR( start );
+	int host, slot;
+	int i;
+	
+	__ENTER0();
+
+	(void)mmc_update_card_stack( MINOR( start )>>MMC_MINOR_HOST_SHIFT );
+
+	__mmc_block_wrlock_devices();
+
+	dev = &mmc_block_device[minor];
+	host = dev->host;
+	slot = dev->slot;
+
+	if ( dev->card ) { /* card has not been changed actually */
+		__mmc_block_wrunlock_devices();
+		goto out;
+		
+	} else {
+		card = mmc_get_card( host, slot );
+		if ( !card ) {
+			MMC_DEBUG( MMC_DEBUG_LEVEL2, "failed to get card: "
+					"host=%d, slot=%d\n", host, slot );
+			__mmc_block_wrunlock_devices();
+			goto error;
+		}
+		dev->card = card;
+	}
+	__mmc_block_wrunlock_devices();
+ 	/* FIXME */
+	__mmc_block_rdlock_devices(); /* handle the request for sector 0 */
+	grok_partitions( &mmc_block_gendisk, MINOR( start ),
+			 mmc_block_gendisk.max_p,
+			 card->info.capacity>>9 /* sectors */
+		       );
+	__mmc_block_rdunlock_devices();
+	/* FIXME */
+	__mmc_block_wrlock_devices();
+	for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
+		int minor = MINOR( i );
+		
+		dev = &mmc_block_device[minor];
+		if ( mmc_block_gendisk.part[minor].nr_sects > 0 )
+			dev->card = card;
+	}
+	__mmc_block_wrunlock_devices();
+out:
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static void mmc_block_handle_request( void )
+{
+	struct request *request;
+	mmc_block_device_t dev;
+	mmc_card_t card;
+	char *buf;
+	loff_t pos;
+	unsigned int result = 0;
+
+	for (;;) {
+		int minor;
+		
+		INIT_REQUEST;
+		request = CURRENT;
+		spin_unlock_irq( &io_request_lock );
+		
+		minor = MINOR( request->rq_dev );
+		dev = __mmc_block_get_device( request->rq_dev );
+		if ( !dev ) {
+			MMC_DEBUG( MMC_DEBUG_LEVEL2, "invalid device (%x:%x)\n",
+					MAJOR( request->rq_dev ), minor );
+				
+			goto end_req;
+		}
+		
+		card = dev->card;
+		(void)__mmc_block_put_device( dev );
+		
+		MMC_DEBUG( MMC_DEBUG_LEVEL2, 
+//		printk( KERN_INFO __FUNCTION__"(): "
+				"request %p: cmd %i sec %li (nr. %li)\n", 
+				CURRENT, CURRENT->cmd, CURRENT->sector, 
+				CURRENT->current_nr_sectors );
+		
+		if ( request->current_nr_sectors >
+				mmc_block_gendisk.part[minor].nr_sects )
+			goto end_req;
+		
+		// Handle the request
+		// TODO: handle clusterred requests in multiple block transfer mode 
+		buf = request->buffer;
+		pos = (mmc_block_gendisk.part[minor].start_sect +
+			request->sector) * MMC_BLOCK_SECT_SIZE;
+		
+		switch ( request->cmd )
+		{
+			int i, ret;
+			
+			case READ:
+#if 0
+				ret = mmc_read( card, 
+					(request->current_nr_sectors > 1) ?
+					MMC_TRANSFER_MODE_BLOCK_MULTIPLE :
+					MMC_TRANSFER_MODE_BLOCK_SINGLE,
+					buf, 
+					request->current_nr_sectors 
+					     * MMC_BLOCK_SECT_SIZE, /* FIXME */
+					&pos );
+				if ( ret < 0 ) 
+					goto end_req;
+				
+#else
+				for ( i = 0;
+				      i < request->current_nr_sectors;
+				      i++ ) {
+					ret = mmc_read( card,
+						MMC_TRANSFER_MODE_BLOCK_SINGLE,
+						buf,
+						MMC_BLOCK_SECT_SIZE, /* FIXME */
+						&pos );
+					if ( ret < 0 )
+						goto end_req;
+					else
+						buf += ret;
+				}
+#endif
+				result = 1;
+				break;
+
+			case WRITE:
+			// TODO: Read only device
+#if 0
+				ret = mmc_write( card, 
+					(request->current_nr_sectors > 1) ?
+					MMC_TRANSFER_MODE_BLOCK_MULTIPLE :
+					MMC_TRANSFER_MODE_BLOCK_SINGLE,
+					buf, 
+					request->current_nr_sectors 
+					    * MMC_BLOCK_SECT_SIZE, /* FIXME */
+					&pos );
+				if ( ret < 0 ) 
+					goto end_req;
+				
+#else
+				for ( i = 0;
+				      i < request->current_nr_sectors;
+				      i++ ) {
+					ret = mmc_write( card,
+						MMC_TRANSFER_MODE_BLOCK_SINGLE,
+						buf,
+						MMC_BLOCK_SECT_SIZE, /* FIXME */
+						&pos ); 
+					if ( ret < 0 )
+						goto end_req;
+					else
+						buf += ret;
+				}
+#endif
+				result = 1;
+				break;
+		}
+
+end_req:
+		__LEAVE( "result=%d", result );
+		spin_lock_irq( &io_request_lock );
+		end_request( result );
+	}
+}
+
+static volatile int leaving = 0;
+static DECLARE_MUTEX_LOCKED( thread_sem );
+static DECLARE_WAIT_QUEUE_HEAD( thr_wq );
+static pid_t thr_id = -1;
+
+int mmc_block_thread( void *arg )
+{
+	struct task_struct *task = current;
+	DECLARE_WAITQUEUE(wait, task);
+
+	__ENTER0();
+	
+	task->session = 1;
+	task->pgrp = 1;
+	task->flags |= PF_MEMALLOC;
+	strcpy( task->comm, "mmcblockd" );
+	task->tty = NULL;
+	spin_lock_irq( &task->sigmask_lock );
+	sigfillset( &task->blocked );
+	recalc_sigpending( task );
+	spin_unlock_irq( &task->sigmask_lock );
+	exit_mm( task );
+	exit_files( task );
+	exit_sighand( task );
+	exit_fs( task );
+
+	while ( !leaving ) {
+		add_wait_queue( &thr_wq, &wait);
+		set_current_state( TASK_INTERRUPTIBLE );
+		spin_lock_irq( &io_request_lock );
+		if ( QUEUE_EMPTY || QUEUE_PLUGGED ) {
+			spin_unlock_irq( &io_request_lock );
+			schedule();
+			remove_wait_queue( &thr_wq, &wait ); 
+		} else {
+			remove_wait_queue( &thr_wq, &wait ); 
+			set_current_state( TASK_RUNNING );
+			mmc_block_handle_request(); /* handle the request */
+			spin_unlock_irq( &io_request_lock );
+		}
+	}
+
+	up( &thread_sem );
+	
+	__LEAVE0();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < 0x20300
+#define RQFUNC_ARG void
+#else
+#define RQFUNC_ARG request_queue_t *q
+#endif
+
+static void mmc_block_request( RQFUNC_ARG )
+{
+	wake_up( &thr_wq );
+}
+
+static int mmc_block_ioctl( struct inode * inode, struct file * file,
+		      unsigned int cmd, unsigned long arg )
+{
+	int ret = -ENODEV;
+	mmc_block_device_t dev;
+	mmc_card_t card;
+	int minor;
+	__ENTER0();
+	
+	if ( !inode || !file ) {
+		ret = -EINVAL;
+		goto error;
+	}
+	minor = MINOR( inode->i_rdev );
+	
+	dev = __mmc_block_get_device( inode->i_rdev );
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );
+		goto error;
+	}
+	
+	card = dev->card; 
+	__mmc_block_put_device( dev );
+	
+	switch ( cmd ) {
+	case BLKGETSIZE:   /* Return device size */
+		{
+			unsigned long value;
+			
+			__mmc_block_rdlock_devices();
+			value = mmc_block_gendisk.part[minor].nr_sects;
+			__mmc_block_rdunlock_devices();
+			
+			if ( put_user( value, (unsigned long *) arg) ) {
+				ret = -EFAULT;
+				goto error;
+			}
+		}
+		break;
+
+#ifdef BLKGETSIZE64
+	case BLKGETSIZE64:
+		{
+			unsigned long value;
+			
+			__mmc_block_rdlock_devices();
+			value = mmc_block_gendisk.part[minor].nr_sects;
+			__mmc_block_rdunlock_devices();
+			
+			if ( put_user( (u64)value, (u64 *) arg) ) {
+				ret = -EFAULT;
+				goto error;
+			}
+		}
+		break;
+#endif
+
+	case HDIO_GETGEO:
+		{
+			struct hd_geometry geo;
+			
+			ret = !access_ok( VERIFY_WRITE, arg, sizeof( geo ) );
+			if ( ret ) {
+				ret = -EFAULT;
+				goto error;
+			}
+
+			geo.heads = 1;
+			geo.sectors = 1;
+
+			__mmc_block_rdlock_devices();
+			geo.cylinders = mmc_block_gendisk.part[minor].nr_sects;
+			geo.start = mmc_block_gendisk.part[minor].start_sect;
+			__mmc_block_rdunlock_devices();
+
+			if ( copy_to_user( (int *)arg, &geo, sizeof( geo ) ) ) {
+				ret = -EFAULT;
+				goto error;
+			}
+		}
+		break;
+		
+	case BLKRRPART:
+		if ( !capable( CAP_SYS_ADMIN ) ) {
+			ret = -EACCES;
+			goto error;
+		}
+		(void)mmc_block_revalidate( inode->i_rdev );
+		break;
+		
+	default:
+		ret = blk_ioctl( inode->i_rdev, cmd, arg );
+		goto out;
+	}
+
+	ret = 0;
+error:	
+out:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < 0x20326
+static struct file_operations mmc_block_fops =
+{
+	open: 			mmc_block_open,
+	ioctl:			mmc_block_ioctl,
+	release:		mmc_block_release,
+	check_media_change:	mmc_block_check_disk_change,
+	revalidate:		mmc_block_revalidate,
+	read:			block_read,
+	write:			block_write
+};
+#else
+static struct block_device_operations mmc_block_fops = 
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
+	owner:			THIS_MODULE,
+#endif
+	open:			mmc_block_open,
+	release:		mmc_block_release,
+	ioctl:			mmc_block_ioctl,
+	check_media_change:	mmc_block_check_disk_change,
+	revalidate:		mmc_block_revalidate
+};
+#endif
+
+
+static int mmc_block_notify_add( mmc_card_t card )
+{
+	int ret = -1;
+	mmc_block_device_t dev;
+	kdev_t start;
+	int minor;
+
+	__ENTER0();
+	
+	if ( !card || !card->ctrlr ) 
+		goto error;
+	
+	start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );
+	dev = &mmc_block_device[MINOR( start )];
+		
+	__mmc_block_wrlock_devices();
+	if ( !dev->card ) {
+		dev->card = card;
+		ret = 0;
+	}
+	__mmc_block_wrunlock_devices();
+
+	if ( !ret ) {
+		int i;
+
+		/* allow to read partition table */
+		__mmc_block_rdlock_devices(); 
+		grok_partitions( &mmc_block_gendisk, MINOR( start ),
+			 mmc_block_gendisk.max_p,
+			 card->info.capacity>>9 /* sectors */
+		);
+		__mmc_block_rdunlock_devices();
+		
+		__mmc_block_wrlock_devices();
+		for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
+			minor = MINOR( i );
+			dev = &mmc_block_device[minor];
+			if ( mmc_block_gendisk.part[minor].nr_sects > 0 )
+				dev->card = card;
+		}
+		__mmc_block_wrunlock_devices();
+	}
+error:	
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+
+static int mmc_block_notify_remove( mmc_card_t card )
+{
+	int ret = -1;
+	
+	__ENTER( "card=0x%p", card );
+	
+	if ( card && card->ctrlr )
+		ret = __mmc_block_invalidate_card( card, FALSE );
+	
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static mmc_notifier_rec_t mmc_block_notifier = {
+	add: mmc_block_notify_add,
+	remove: mmc_block_notify_remove
+};
+
+static int __init mmc_block_module_init( void )
+{
+	int ret = -ENODEV;
+	int i;
+
+	__ENTER0();
+	
+	init_rwsem( &mmc_block_device_sem );
+	
+	if ( devfs_register_blkdev( MAJOR_NR, MAJOR_NAME, &mmc_block_fops ) ) {
+		MMC_ERROR( "Can't allocate major number %d for MMC block devices.\n", MMC_BLOCK_MAJOR );
+		ret = -EAGAIN;
+		goto error;
+	}
+	
+	for ( i = 0; i < (1<<MINORBITS); i++ ) {
+		__mmc_block_device_init( i );
+		init_MUTEX( &mmc_block_device[i].sem );
+
+		/* We fill it in at open() time. */
+		mmc_block_blk_sizes[i] = 0;
+		mmc_block_blk_blksizes[i] = BLOCK_SIZE;
+		mmc_block_hardsect_sizes[i] = 0;
+	}
+	
+	init_waitqueue_head( &thr_wq );
+	/* Allow the block size to default to BLOCK_SIZE. */
+	blksize_size[MAJOR_NR] = mmc_block_blk_blksizes;
+	hardsect_size[MAJOR_NR] = mmc_block_hardsect_sizes;
+	/* Gendisk stuff */
+	memset( mmc_block_partitions, 0, sizeof( mmc_block_partitions ) );
+	add_gendisk( &mmc_block_gendisk );
+
+/* FIXME: per controller request queue, I/O and card stack update threads */	
+	blk_init_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ), &mmc_block_request );
+	thr_id = kernel_thread( mmc_block_thread, NULL, 
+			CLONE_FS|CLONE_FILES|CLONE_SIGHAND );
+
+	if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_block_notifier, 0 ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );
+		goto error;
+	}
+
+	ret = 0;
+	goto out;
+error:
+	if ( thr_id != -1 ) {
+/* quit the thread */
+		leaving = 1;
+		wake_up(&thr_wq);
+	
+		down(&thread_sem);
+	}
+	blksize_size[MAJOR_NR] = NULL;
+	blk_size[MAJOR_NR] = NULL;
+	hardsect_size[MAJOR_NR] = NULL;
+out:	
+	__LEAVE0();
+	return ret;
+}
+
+static void __exit mmc_block_module_cleanup( void )
+{
+/* quit the thread */
+	leaving = 1;
+	wake_up(&thr_wq);
+	
+	down(&thread_sem);
+	
+	mmc_unregister( MMC_REG_TYPE_USER, &mmc_block_notifier );
+	del_gendisk( &mmc_block_gendisk );
+	devfs_unregister_blkdev( MAJOR_NR, MAJOR_NAME );
+	
+	blk_cleanup_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ) );
+	blksize_size[MAJOR_NR] = NULL;
+	blk_size[MAJOR_NR] = NULL;
+	hardsect_size[MAJOR_NR] = NULL;
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init( mmc_block_module_init );
+module_exit( mmc_block_module_cleanup );
+
+
+MODULE_LICENSE("GPL");
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/mmc_core.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,1124 @@
+/*
+ *  linux/drivers/mmc/mmc_core.c 
+ *  	MultiMediaCard subsystem core implementation
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *	$Id: mmc_core.c,v 0.3.1.14 2002/09/27 17:36:09 ted Exp ted $
+ *
+ *  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/version.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include <mmc/types.h>
+#include <mmc/mmc.h>
+#include <mmc/ioctl.h>
+
+#include "types.h"
+
+#define __MMC_CORE_IMPLEMENTATION__
+#include "mmc.h"
+
+/* MMC controllers registered in the system */ 
+static mmc_controller_t mmc_controller[MMC_CONTROLLERS_MAX];
+static int mmc_ncontrollers = 0;
+static rwsemaphore_t mmc_controller_sem; /* controller table lock */
+#ifdef CONFIG_PM
+static struct pm_dev *mmc_pm_dev = NULL;
+#endif
+
+/* users' notification list */
+static mmc_notifier_t mmc_notifier = NULL;
+static rwsemaphore_t mmc_notifier_sem; /* notifiers' list lock */ 
+#ifdef CONFIG_PROC_FS
+static proc_dir_entry_t mmc_proc_dir = NULL;
+#endif
+
+/************************************************
+ * service function prototypes and declarations *
+ ************************************************/
+static inline int mmc_acquire_io( mmc_controller_t ctrlr, mmc_card_t card )
+{
+	int ret = -EIO;
+
+	__ENTER0();
+	
+	if ( !card || !ctrlr ) {
+		ret = -EINVAL;
+		goto error;
+	}
+#ifdef CONFIG_HOTPLUG
+/* TODO: account for controller removal */
+#endif
+	down( &ctrlr->io_sem );
+#if 0	
+	down_read( &ctrlr->update_sem ); /* FIXME */
+	if ( card->state != MMC_CARD_STATE_UNPLUGGED )
+		ret = 0;
+	up_read( &ctrlr->update_sem );
+	
+	if ( ret )
+		up( &ctrlr->io_sem );
+#else
+	ret = 0;
+#endif
+
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static inline void mmc_release_io( mmc_controller_t ctrlr, mmc_card_t card )
+{
+	__ENTER0();
+#ifdef CONFIG_HOTPLUG
+/* TODO: account for controller removal */
+#endif
+	if ( !card && !ctrlr ) { /* FIXME */
+		MMC_DEBUG( MMC_DEBUG_LEVEL2, "bad card reference\n" );
+		goto error;
+	}
+	up( &ctrlr->io_sem );	
+error:
+	__LEAVE0();
+}
+
+/* TODO: there should be a separate context to be awaken 
+ * by the card intertion interrupt; called under ctrlr->update_sem
+ * held down by now */
+static int __mmc_update_card_stack( mmc_controller_t ctrlr )
+{
+	int ret = -1;
+	mmc_card_t card, prev;
+	
+	__ENTER0();
+	
+	if ( !ctrlr || !ctrlr->tmpl )
+		goto error;
+	
+	/* check unplugged cards first... */
+	if ( (ret = ctrlr->tmpl->check_card_stack( ctrlr )) )
+		goto error;
+	
+	/* unregister unplugged cards and free 'em immediately */
+	if ( ctrlr->stack.ncards > 0 ) {
+		prev = ctrlr->stack.first;
+		/* process the stack tail first */
+		if ( prev->next ) {
+			card = prev->next; 
+			while ( card ) {
+				if ( card->state == MMC_CARD_STATE_UNPLUGGED ) {
+					if ( ctrlr->stack.selected == card )
+						ctrlr->stack.selected = NULL;
+#ifdef CONFIG_PROC_FS
+					if ( card->proc ) {
+						remove_proc_entry( card->proc_name, ctrlr->proc );
+						card->proc = NULL;
+					}
+#endif
+					ctrlr->slot_next = card->slot; /* FIXME */
+					prev->next = card->next;
+					if ( ctrlr->stack.last == card )
+						ctrlr->stack.last = prev;
+					/* FIXME: controller use count */
+					mmc_notify_remove( card );
+					--ctrlr->stack.ncards;
+					if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) {
+						--ctrlr->usage;
+						MMC_DEBUG( MMC_DEBUG_LEVEL2,
+							"'%s' use count "
+							"decreased (%d)\n",
+							ctrlr->tmpl->name,
+							ctrlr->usage );
+						__MOD_DEC_USE_COUNT( 
+							ctrlr->tmpl->owner );
+					}
+					__mmc_card_free( card );
+				
+					card = prev->next;
+				}
+			}
+		}
+		/* then the head */		
+		card = ctrlr->stack.first;
+		if ( card && (card->state == MMC_CARD_STATE_UNPLUGGED) ) {
+			if ( ctrlr->stack.selected == card )
+				ctrlr->stack.selected = NULL;
+#ifdef CONFIG_PROC_FS
+			if ( card->proc ) {
+				remove_proc_entry( card->proc_name, ctrlr->proc );
+				card->proc = NULL;
+			}
+#endif
+			ctrlr->slot_next = card->slot; /* FIXME */
+			mmc_notify_remove( card ); /* FIXME: should unregister here */
+			ctrlr->stack.first = card->next;
+			if ( ctrlr->stack.last == card )
+				ctrlr->stack.last = NULL;
+			/* FIXME: controller use count */
+			--ctrlr->stack.ncards;
+			if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) {
+				--ctrlr->usage;
+				MMC_DEBUG( MMC_DEBUG_LEVEL2, "'%s' use count "
+					"decreased (%d)\n", ctrlr->tmpl->name,
+					ctrlr->usage );
+				__MOD_DEC_USE_COUNT( ctrlr->tmpl->owner );
+			}
+			__mmc_card_free( card );
+		}
+	}
+	MMC_DEBUG( MMC_DEBUG_LEVEL2, "after stack check: ncards=%d"
+			" first=0x%x last=0x%x\n", ctrlr->stack.ncards,
+			ctrlr->stack.first, ctrlr->stack.last );
+	/* ...then add newly inserted ones */
+	if ( (ret = ctrlr->tmpl->update_acq( ctrlr )) )
+		goto error;
+	/* ret = 0; */
+error:			
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+/*
+ * 	1) check error code returned by controller; it's up to
+ * 	   controller to detect error conditions reported by the card
+ * 	   and to abort data transfer requests properly (e.g. send
+ * 	   CMD12(STOP_TRANSMISSION) to abort ADDRESS_ERROR multiple
+ * 	   block transfers)
+ * 	2) arrange for card stack update when necessary
+ *	   (all pending i/o requests must be held pending,
+ *	   update procedure must start immediately after 
+ *	   error has been detected)
+ */
+static inline int __mmc_check_error( mmc_card_t card, int err )
+{
+	int ret = -EIO;
+	mmc_controller_t ctrlr;
+	
+	__ENTER0();
+
+	if ( !card || !card->ctrlr )
+		goto error;
+	
+	ctrlr = card->ctrlr;
+	
+	if ( err < 0 ) {
+		switch ( err ) {
+		/* bus error occurred */
+		case MMC_ERROR_CRC_WRITE_ERROR:
+		case MMC_ERROR_CRC_READ_ERROR:
+		case MMC_ERROR_RES_CRC_ERROR:
+		case MMC_ERROR_READ_TIME_OUT:
+		case MMC_ERROR_TIME_OUT_RESPONSE:
+			down_write( &ctrlr->update_sem ); /* FIXME */
+			if ( !__mmc_update_card_stack( ctrlr ) )
+				ret = -ENXIO;
+			up_write( &ctrlr->update_sem );
+			break;
+		}
+	} else
+		ret = err;
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static inline void __mmc_free_controller( mmc_controller_t ctrlr )
+{
+	if ( ctrlr ) {
+		if ( ctrlr->stack.ncards > 0 )
+			__mmc_card_stack_free( &ctrlr->stack );
+		kfree( ctrlr );
+	}
+}
+
+#ifdef CONFIG_PROC_FS
+static int mmc_proc_read_card_info( char *page, char **start, off_t off, int count, int *eof, void *data )
+{
+	int ret = -EINVAL;
+	mmc_card_t card = (mmc_card_t)data;
+	char *cp = page;
+	
+	if ( !card )
+		goto error;
+	
+	down_read( &card->ctrlr->update_sem );
+/* TODO: proc report
+ * Type: RO, RW or IO (by CCC)
+ * MID: 0x%02x card->info.cid.mid
+ * OID: 0x%04x card->info.cid.oid
+ * PNM: %s card->info.pnm
+ * PRV: %s card->info.prv
+ * PSN: 0x%08x card->info.cid.psn
+ * MDT: %s card->info.mdt
+ * Capacity: card->info.capacity (Bytes)
+ */
+#if 1
+	cp += sprintf( cp, "Capacity: %dKb.\n\n", (card->info.capacity>>10) );
+#else /* TODO */
+	cp += sprintf( cp, "Type    : %s\n", card->info.type );
+	cp += sprintf( cp, "MID     : 0x%02x\n", card->info.cid.mid );
+	cp += sprintf( cp, "OID     : 0x%04x\n", card->info.cid.oid );
+	cp += sprintf( cp, "PNM     : %s\n", card->info.pnm );
+	cp += sprintf( cp, "PRV     : %s\n", card->info.prv );
+	cp += sprintf( cp, "PSN     : 0x%08x\n", card->info.cid.psn );
+	cp += sprintf( cp, "MDT     : %s\n", card->info.mdt );
+	cp += sprintf( cp, "Capacity: %dKB\n", 
+			(card->info.capacity>>10) );
+#endif
+	up_read( &card->ctrlr->update_sem );
+	
+	ret = cp - page;
+error:
+	return ret;
+}
+#endif
+
+/*************************************
+ * MMC core interface implementation *
+ *************************************/
+int mmc_notify_add( mmc_card_t card )
+{
+	int ret = 0;
+	mmc_notifier_t notifier;
+	
+	__ENTER0();
+	if ( card ) {
+		for ( notifier = mmc_notifier; notifier;
+		      notifier = notifier->next )
+			if ( notifier->add )
+				if ( (ret = notifier->add( card )) )
+					break;
+	}
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+EXPORT_SYMBOL( mmc_notify_add );
+
+int mmc_notify_remove( mmc_card_t card )
+{
+	int ret = 0;
+	mmc_notifier_t notifier;
+	
+	__ENTER0();
+	if ( card ) {
+		for ( notifier = mmc_notifier; notifier; 
+		      notifier = notifier->next )
+			if ( notifier->remove )
+				if ( (ret = notifier->remove( card )) )
+					break;
+	}
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+EXPORT_SYMBOL( mmc_notify_remove );
+
+int mmc_update_card_stack( int host )
+{
+	int ret = -EINVAL;
+	mmc_controller_t ctrlr;
+
+	__ENTER0();
+	
+	if ( (host < 0) || (host >= MMC_CONTROLLERS_MAX) )
+		goto error;
+	
+	down_read( &mmc_controller_sem );
+	if ( (ctrlr = mmc_controller[host]) ) {
+		down_write( &ctrlr->update_sem );
+		(void)__mmc_update_card_stack( ctrlr );
+		up_write( &ctrlr->update_sem );
+	}
+	up_read( &mmc_controller_sem );
+	ret = 0;
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+EXPORT_SYMBOL( mmc_update_card_stack );
+
+ssize_t mmc_read( mmc_card_t card, mmc_transfer_mode_t mode, char *buf, size_t size, loff_t *paddr )
+{
+	ssize_t ret = -EIO;
+	mmc_controller_t ctrlr;	
+	mmc_data_transfer_req_rec_t transfer; 
+		
+	if ( !paddr ) {
+		ret = -EINVAL;
+		goto error;
+	}
+	
+	if ( !card ) {
+		ret = -ENODEV;
+		goto error;
+	}
+
+	__ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%x",
+		card, card->usage, mode, buf, size, *paddr );
+	
+	ctrlr = card->ctrlr;
+	if ( (ret = mmc_acquire_io( ctrlr, card )) )
+		goto error;
+	
+	memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) );
+	transfer.cmd = MMC_READ;
+	transfer.mode = mode;
+	transfer.type = MMC_USER; /* FIXME: buffer cache */
+	transfer.buf = buf;
+	transfer.addr = *paddr;
+	transfer.cnt = size;
+
+/* max block size defined by CSD[read_bl_len] */
+	transfer.blksz = card->info.read_bl_len;
+	transfer.nob = size / transfer.blksz;
+	if ( (size - (transfer.nob * transfer.blksz)) > 0 )
+		transfer.nob++;
+
+/* TODO: controller may restrict maximum block size; set block size
+ * and number of blocks that their accumulated length fit to
+ * CSD[READ_BL_LEN] not to bother with block misalignment in multiple
+ * block transfers */
+	ctrlr = card->ctrlr;
+	if ( transfer.blksz > ctrlr->tmpl->block_size_max ) { 
+		ret = -EINVAL; /* FIXME */
+		goto error;
+	}
+		
+    	if ( ctrlr->stack.selected != card ) {
+		if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) )
+			goto err_mmc;		
+		ctrlr->stack.selected = card;
+	}
+	
+	switch( mode ) {
+		case MMC_TRANSFER_MODE_STREAM:
+			if ( !ctrlr->tmpl->stream_read ) {
+				ret = -ENXIO;
+				goto err_down;
+			}
+/* TODO: The max clock frequency for stream read operation is given by
+   the following formula:
+   	max speed = min ( TRAN_SPEED, 8*2^(READ_BL_LEN) - NSAC/TAAC )
+
+   If the card is not able to sustain data transfer it will set the
+   UNDERRUN error bit in the status register, abort the transmission
+   and wait in the Data state for a stop command 
+ */
+			ret = ctrlr->tmpl->stream_read( ctrlr, &transfer );
+			break;
+
+		case MMC_TRANSFER_MODE_BLOCK_SINGLE:
+			if ( !ctrlr->tmpl->read_block ) {
+				ret = -ENXIO;
+				goto err_down;
+			}
+/* TODO: buffer size and data alignment (v3.4, p.29): 
+	if CSD[READ_BL_PARTIAL] is set, smaller blocks whose starting
+	and ending address are entirely contained within one physical
+	block (as defined by CSD[READ_BL_LEN]) may also be transmitted
+ */
+			transfer.type = MMC_KERNEL; /* FIXME */
+			ret = ctrlr->tmpl->read_block( ctrlr, &transfer );
+			break;
+			
+		case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
+			if ( !ctrlr->tmpl->read_mblock ) {
+				ret = -ENXIO;
+				goto err_down;
+			}
+			
+			if ( transfer.nob > ctrlr->tmpl->nob_max ) {
+				ret = -EINVAL;
+				goto error;
+			}
+/* TODO: buffer size and data alignment (v3.4, p.29): 
+	if the host uses patrial blocks whose accumulated length is
+	not block aligned and block misalignment is not allowed, the
+	card should detect a block misalignment error condition at the
+	beginning of the first misaligned block
+ */
+			transfer.type = MMC_KERNEL; /* FIXME */
+			ret = ctrlr->tmpl->read_mblock( card->ctrlr, &transfer );
+			break;
+		
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" );
+			ret = -EINVAL;
+	}
+err_mmc:
+	ret = __mmc_check_error( card, ret );
+	if ( ret >= 0 ) {
+		ret = size - transfer.cnt;
+		*paddr += ret;
+	}
+err_down:
+	mmc_release_io( ctrlr, card );
+error:
+	__LEAVE("ret=%d", ret);
+	return ret;
+}
+EXPORT_SYMBOL( mmc_read );
+
+ssize_t mmc_write( mmc_card_t card, mmc_transfer_mode_t mode, const char *buf, size_t size, loff_t *paddr )
+{
+	ssize_t ret = -ESPIPE;
+	mmc_controller_t ctrlr;
+	mmc_data_transfer_req_rec_t transfer; 
+		
+	if ( !paddr ) {
+		ret = -EINVAL;
+		goto error;
+	}
+	
+	if ( !card ) {
+		ret = -ENODEV;
+		goto error;
+	}
+
+	__ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%llx",
+		card, card->usage, mode, buf, size, *paddr );
+
+	ctrlr = card->ctrlr;	
+	if ( (ret = mmc_acquire_io( ctrlr, card )) )
+		goto error;
+	
+	memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) );
+	transfer.cmd = MMC_WRITE;
+	transfer.mode = mode;
+	transfer.type = MMC_USER; /* FIXME: buffer cache */
+	transfer.buf = (char *)buf;
+	transfer.addr = *paddr;
+	transfer.cnt = size;
+
+/* max block size defined by CSD[write_bl_len] */
+	transfer.blksz = card->info.write_bl_len;
+	transfer.nob = size / transfer.blksz;
+	if ( (size - (transfer.nob * transfer.blksz)) > 0 )
+		transfer.nob++;
+
+/* TODO: controller may restrict maximum block size; set block size
+ * and number of blocks that their accumulated length fit to
+ * CSD[WRITE_BL_LEN] not to bother with block misalignment in multiple
+ * block transfers */
+	ctrlr = card->ctrlr;
+	if ( transfer.blksz > ctrlr->tmpl->block_size_max ) { 
+		ret = -EINVAL; /* FIXME */
+		goto error;
+	}
+		
+	if ( ctrlr->stack.selected != card ) {
+		if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) )
+			goto err_mmc;		
+		ctrlr->stack.selected = card;
+	}
+	
+	transfer.cmd = MMC_WRITE;
+	transfer.mode = mode;
+	transfer.type = MMC_USER;
+	switch( mode ) {
+		case MMC_TRANSFER_MODE_STREAM:
+			if ( !ctrlr->tmpl->stream_write ) {
+				ret = -ENXIO;
+				goto err_down;
+			}
+			ret = ctrlr->tmpl->stream_write( ctrlr, &transfer );
+			break;
+
+		case MMC_TRANSFER_MODE_BLOCK_SINGLE:
+			if ( !ctrlr->tmpl->write_block ) {
+				ret = -ENXIO;
+				goto err_down;
+			}
+			transfer.type = MMC_KERNEL; /* FIXME */
+			ret = ctrlr->tmpl->write_block( ctrlr, &transfer );
+			break;
+			
+		case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
+			if ( !ctrlr->tmpl->write_mblock ) {
+				ret = -ENXIO;
+				goto err_down;
+			}
+			transfer.type = MMC_KERNEL; /* FIXME */
+			ret = ctrlr->tmpl->write_mblock( card->ctrlr, &transfer );
+			break;
+		
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" );
+	}
+
+err_mmc:
+	ret = __mmc_check_error( card, ret ); /* FIXME */
+	if ( ret >= 0 ) {
+		ret = size - transfer.cnt;
+		*paddr += ret;
+	}
+err_down:
+	mmc_release_io( ctrlr, card );
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+EXPORT_SYMBOL( mmc_write );
+
+int mmc_ioctl( mmc_card_t card, unsigned int cmd, unsigned long arg )
+{
+	int ret = -EINVAL;
+	mmc_controller_t ctrlr;
+	
+	if ( !card ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" )
+		goto error;
+	}
+		
+	ctrlr = card->ctrlr;
+	if ( mmc_acquire_io( ctrlr, card ) ) {  
+		ret = -ENXIO;
+		goto error;
+	}
+
+	switch ( cmd ) {
+		case IOCMMCGCARDESC:
+			if ( copy_to_user( (void *)arg, &card->info, sizeof( mmc_card_info_rec_t ) ) )
+				ret = -EFAULT;
+			break;
+/*	
+ * 1. TODO: erase region
+ * 2. TODO: set/unset write protection, lock/password 
+ */
+		default:
+			ret = -ENOIOCTLCMD;
+	}
+	
+	mmc_release_io( ctrlr, card );
+error:
+	return ret;
+}
+EXPORT_SYMBOL( mmc_ioctl );
+
+/* 
+ * registry stuff 
+ */
+mmc_card_t mmc_get_card( int host, int slot )
+{
+	mmc_card_t ret = NULL;
+	mmc_controller_t ctrlr = NULL;
+	int found;
+
+	__ENTER( "host=%d, card=%d", host, slot );
+	
+	if ( ((host < 0) || (host >= MMC_CONTROLLERS_MAX)) 
+	     && ((slot < 0) || (slot >= MMC_CARDS_MAX)) )
+		goto error;	
+
+ 	down_read( &mmc_controller_sem );
+	
+	if ( (ctrlr = mmc_controller[host]) ) {
+		down_write( &ctrlr->update_sem );
+		if ( ctrlr->stack.ncards > 0 ) {
+			ret = ctrlr->stack.first;
+			found = FALSE;
+			while ( ret ) {
+				if ( (ret->slot == slot) && (ret->state != 
+				     MMC_CARD_STATE_UNPLUGGED) ) {
+					found = TRUE;
+					break;
+				}
+				ret = ret->next;
+			}
+
+			if ( found ) {
+				if ( ctrlr->tmpl->owner ) {
+					++ctrlr->usage;
+					MMC_DEBUG( MMC_DEBUG_LEVEL2, 
+					    "'%s' use count increased (%d)\n", 
+					    ctrlr->tmpl->name, ctrlr->usage );
+					__MOD_INC_USE_COUNT( ctrlr->tmpl->owner );
+				}
+				++ret->usage;
+			} else
+				ret = NULL;
+		}
+		up_write( &ctrlr->update_sem );	
+	}
+	up_read( &mmc_controller_sem );
+error:
+	__LEAVE("ret=0x%p usage=%d", ret, ret ? ret->usage : -1 );
+	return ret;
+}
+EXPORT_SYMBOL( mmc_get_card );
+
+void mmc_put_card( mmc_card_t card )
+{
+	mmc_card_t tmp = NULL;
+	mmc_controller_t ctrlr;
+	int found;
+	
+	__ENTER( "card=0x%p", card );
+
+	if ( !card )
+	     	goto error;	
+
+	ctrlr = card->ctrlr;
+	
+ 	down_read( &mmc_controller_sem );
+	if ( !ctrlr || (ctrlr != mmc_controller[ctrlr->slot]) ) {
+		MMC_ERROR( "bad controller reference: ctrlr=0x%p\n", ctrlr );
+		goto err_down;
+	}
+	
+	down_write( &ctrlr->update_sem );
+	if ( ctrlr->stack.ncards > 0 ) {
+		tmp = ctrlr->stack.first;
+		found = FALSE;
+		while ( tmp ) {
+			if ( tmp == card ) {
+				found = TRUE;
+				break;
+			}
+			tmp = tmp->next;
+		}
+
+		if ( found ) {
+			if ( tmp->usage > 0 ) {
+				--tmp->usage;
+				MMC_DEBUG( MMC_DEBUG_LEVEL2, "usage=%d"
+					"owner=0x%p\n", tmp->usage, 
+					ctrlr->tmpl->owner );
+				if ( !tmp->usage && (ctrlr->usage > 0) 
+	  			     && ctrlr->tmpl->owner ) {
+					--ctrlr->usage;
+					MMC_DEBUG( MMC_DEBUG_LEVEL2, 
+						"'%s' use count "
+						"decreased (%d)\n", 
+						ctrlr->tmpl->name, 
+						ctrlr->usage );
+					__MOD_DEC_USE_COUNT( 
+							ctrlr->tmpl->owner );
+				}
+			}
+		} else
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" );
+			
+	}
+	up_write( &ctrlr->update_sem );	
+err_down:
+ 	up_read( &mmc_controller_sem );
+error:
+	__LEAVE( "found=%d", found );
+	return;
+}
+EXPORT_SYMBOL( mmc_put_card );
+
+static inline void *mmc_register_user( mmc_notifier_t notifier )
+{
+	mmc_notifier_t ret = NULL, last = mmc_notifier;
+	
+	MOD_INC_USE_COUNT;
+	if ( notifier ) {
+		down_write( &mmc_notifier_sem );
+		
+		notifier->next = NULL;
+		if ( !last ) {
+			mmc_notifier = notifier;
+			ret = notifier;	
+		} else {
+			while ( last->next ) {
+				if ( last == notifier ) {
+					MOD_DEC_USE_COUNT;
+					break;
+				}
+				last = last->next;
+			}
+			if ( last != notifier ) {
+				last->next = notifier;
+				ret = notifier;
+			}
+		}
+		up_write( &mmc_notifier_sem );
+	}
+/* notify new user about the cards present in the system */
+	if ( ret && ret->add ) {
+		int i;
+		
+		down_read( &mmc_controller_sem );
+		for ( i = 0; i < mmc_ncontrollers; i++ ) {
+			mmc_controller_t ctrlr = mmc_controller[i];
+			
+			down_read( &ctrlr->update_sem ); /* FIXME */
+			__mmc_card_stack_foreach( &ctrlr->stack, 
+					ret->add, FALSE );
+			up_read( &ctrlr->update_sem ); /* FIXME */
+		}
+		up_read( &mmc_controller_sem );
+	}
+/* error: */
+	__LEAVE( "mmc_notifier=0x%p, mmc_notifier->next=0x%p",
+			mmc_notifier, mmc_notifier ? mmc_notifier->next : NULL );
+	return ret;
+}
+
+static inline mmc_controller_t mmc_register_controller( mmc_controller_tmpl_t tmpl, size_t extra )
+{
+	mmc_controller_t ret = NULL;
+	int found;
+	int i;
+	
+	MOD_INC_USE_COUNT;
+	
+	down_write( &mmc_controller_sem );
+	
+	if ( mmc_ncontrollers >= MMC_CONTROLLERS_MAX ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're too many controllers\n" );
+		goto error;
+	}
+	
+	found = FALSE;
+	for ( i = 0; i < MMC_CONTROLLERS_MAX; i++ )
+		if ( !mmc_controller[i] ) {
+			found = TRUE;
+			break;
+		}
+	
+	if ( !found ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're no empty slots\n" );
+		goto error;
+	}
+
+	if ( !tmpl->init ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init()'\n" );
+		goto error;
+	}
+	
+	if ( !tmpl->probe ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'probe()'\n" );
+		goto error;
+	}
+	
+	if ( !tmpl->init_card_stack ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init_card_stack()'\n" );
+		goto error;
+	}
+	
+	if ( !tmpl->update_acq ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'update_acq()'\n" );
+		goto error;
+	}
+	
+	if ( !tmpl->check_card_stack ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'check_card_stack()'\n" );
+		goto error;
+	}
+	
+	if ( !tmpl->setup_card ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'setup_card()'\n" );
+		goto error;
+	}
+	
+	ret = kmalloc( sizeof( mmc_controller_rec_t ) + extra, GFP_ATOMIC ); /* FIXME: ISA + GFP_DMA */
+	if ( !ret ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "out of memory\n" );
+		goto error;
+	}
+
+	memset( ret, 0, sizeof( mmc_controller_rec_t ) + extra );
+	
+	if ( (tmpl->probe( ret ) != 1) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller probe failed\n" );
+		goto err_free;
+	}
+	
+	if ( tmpl->init( ret ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller initialization failure\n" );
+		goto err_free;
+	}
+	
+	ret->state = MMC_CONTROLLER_FOUND;
+	ret->slot = i;
+	ret->tmpl = tmpl;
+	init_MUTEX( &ret->io_sem );
+	init_rwsem( &ret->update_sem );
+#ifdef CONFIG_PROC_FS
+	if ( mmc_proc_dir ) {
+		snprintf( ret->proc_name, sizeof( ret->proc_name ),
+				"host%d", ret->slot );
+		ret->proc = proc_mkdir( ret->proc_name, mmc_proc_dir );
+	}
+#endif
+	
+/* initialize card stack */
+	if ( ret->tmpl->init_card_stack( ret ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "card stack initialization failure\n" );
+		if ( ret->tmpl->remove )
+			ret->tmpl->remove( ret ); /* FIXME */
+		goto err_free;
+	}
+	
+	mmc_controller[ret->slot] = ret;
+	++mmc_ncontrollers;
+
+/* notify users */
+	if ( ret->stack.ncards > 0 ) {
+		down_read( &mmc_notifier_sem );
+		if ( (i = __mmc_card_stack_foreach( &ret->stack, mmc_notify_add, FALSE ) ) < 0 )
+			MMC_ERROR( "device add notification failed at slot %d\n", -i );
+		up_read( &mmc_notifier_sem );
+	}
+	goto out;
+	
+err_free:
+#ifdef CONFIG_PROC_FS
+	if ( ret->proc )
+		remove_proc_entry( ret->proc_name, mmc_proc_dir );
+#endif
+	kfree( ret );
+error:
+	ret = NULL;
+	MOD_DEC_USE_COUNT;
+out:	
+	up_write( &mmc_controller_sem );
+	return ret;
+}
+
+static inline mmc_card_t mmc_register_card( mmc_card_t card )
+{
+	mmc_card_t ret = NULL;
+	mmc_controller_t ctrlr;
+	
+	if ( !card || !card->ctrlr )
+		goto error;
+	
+	ctrlr = card->ctrlr;
+#ifdef CONFIG_PROC_FS
+	if ( ctrlr->proc ) {
+		snprintf( card->proc_name, sizeof( card->proc_name ),
+					"card%d", card->slot );
+		card->proc = create_proc_read_entry( card->proc_name,
+					0444, ctrlr->proc,
+					mmc_proc_read_card_info, card );
+	}
+#endif
+	mmc_notify_add( card );
+error:
+	return ret;
+}
+
+void *mmc_register( mmc_reg_type_t reg_type, void *tmpl, size_t extra )
+{
+	void *ret = NULL;
+
+	switch ( reg_type ) {
+		case MMC_REG_TYPE_CARD:
+			ret = mmc_register_card( (mmc_card_t)tmpl );
+			break;
+
+		case MMC_REG_TYPE_USER:
+			ret = mmc_register_user( (mmc_notifier_t)tmpl );
+			break;
+
+		case MMC_REG_TYPE_HOST:
+			ret = mmc_register_controller( (mmc_controller_tmpl_t)tmpl, extra );
+			break;
+		
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "register request for unknown type\n" );
+	}
+	
+	return ret;
+}
+EXPORT_SYMBOL( mmc_register );
+
+static inline void mmc_unregister_user( mmc_notifier_t notifier )
+{
+	mmc_notifier_t prev = mmc_notifier;
+	int found = FALSE;
+	
+	if ( notifier ) {
+		down_write( &mmc_notifier_sem );
+		
+		if ( mmc_notifier == notifier) {
+			mmc_notifier = prev->next;
+			found = TRUE;
+			
+		} else if ( mmc_notifier ) {
+			while( prev ) {
+				if ( prev->next == notifier ) {
+					found = TRUE;
+					prev->next = prev->next->next;
+					break;
+				}
+				prev = prev->next;
+			}
+		}
+		
+		if ( found ) {
+			if ( notifier->remove ) {
+				int i;
+		
+				down_read( &mmc_controller_sem );
+				for ( i = 0; i < mmc_ncontrollers; i++ ) {
+					mmc_controller_t ctrlr = 
+						mmc_controller[i];
+	
+					down_read( &ctrlr->update_sem );
+					__mmc_card_stack_foreach( &ctrlr->stack, notifier->remove, FALSE );
+					up_read( &ctrlr->update_sem );
+				}
+				up_read( &mmc_controller_sem );
+			}
+		}
+		
+		up_write( &mmc_notifier_sem );
+	}
+	
+	MOD_DEC_USE_COUNT;
+}
+
+static inline void mmc_unregister_controller( mmc_controller_t ctrlr )
+{
+	if ( !ctrlr || (mmc_controller[ctrlr->slot] != ctrlr ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad unregister request\n" );
+		goto error;
+	}
+
+	down_write( &mmc_controller_sem );
+
+/* notify users */
+	if ( ctrlr->stack.ncards > 0 ) {
+		int slot;
+		
+		down_read( &mmc_notifier_sem );
+		if ( (slot = __mmc_card_stack_foreach( &ctrlr->stack, mmc_notify_remove, FALSE ) ) )
+			MMC_ERROR( "device remove notification failed at slot %d\n", -slot );
+		up_read( &mmc_notifier_sem );
+	}
+
+#ifdef CONFIG_PROC_FS
+	if ( ctrlr->proc ) 
+		remove_proc_entry( ctrlr->proc_name, mmc_proc_dir );
+#endif
+
+	if ( ctrlr->tmpl && ctrlr->tmpl->remove )
+			ctrlr->tmpl->remove( ctrlr );
+
+	mmc_controller[ctrlr->slot] = NULL;
+	--mmc_ncontrollers;
+
+	__mmc_free_controller( ctrlr ); 
+
+	up_write( &mmc_controller_sem );
+	MOD_DEC_USE_COUNT;
+error:
+	return;
+}
+
+void mmc_unregister( mmc_reg_type_t reg_type, void *tmpl )
+{
+	switch ( reg_type ) {
+		case MMC_REG_TYPE_USER:
+			mmc_unregister_user( (mmc_notifier_t)tmpl );
+			break;
+
+		case MMC_REG_TYPE_HOST:
+			mmc_unregister_controller( (mmc_controller_t)tmpl );
+			break;
+		
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "unregister request for unknown type\n" );
+	}
+}
+EXPORT_SYMBOL( mmc_unregister );
+
+#ifdef CONFIG_PM
+/* power management support */
+static int mmc_pm_callback( struct pm_dev *pmdev, pm_request_t pmreq, void *pmdata )
+{
+	int ret = -EINVAL;
+	mmc_controller_t ctrlr;
+	int i;
+	
+	__ENTER( "pmreq=%d", pmreq );
+	
+	down_read( &mmc_controller_sem );
+	
+	switch ( pmreq ) {
+	case PM_SUSPEND:
+		for ( ret = 0, i = 0; !ret && (i < mmc_ncontrollers); i++ ) {
+			ctrlr = mmc_controller[i];
+			if ( ctrlr->tmpl->suspend )
+				ret = ctrlr->tmpl->suspend( ctrlr );
+		}
+		if ( !ret )
+			break;
+		
+	case PM_RESUME:
+		for ( i = mmc_ncontrollers - 1; i >= 0; i-- ) {
+			ctrlr = mmc_controller[i];
+			if ( ctrlr->tmpl->resume )
+				ctrlr->tmpl->resume( ctrlr );
+		}
+		ret = 0;
+		break;
+
+	default:
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "unsupported PM request %d\n", 
+					pmreq );
+	}
+
+	up_read( &mmc_controller_sem );
+/* error: */	
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+#endif
+
+/* kernel module stuff */
+static int __init mmc_core_module_init( void )
+{
+	int ret = -ENODEV;
+	
+	memset( &mmc_controller, 0, sizeof( mmc_controller ) );
+	
+	init_rwsem( &mmc_controller_sem );
+	init_rwsem( &mmc_notifier_sem );
+#ifdef CONFIG_PM
+	if ( !(mmc_pm_dev = pm_register( PM_UNKNOWN_DEV, 0, mmc_pm_callback )) ) 		MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register PM callback\n" );
+#endif
+#ifdef CONFIG_PROC_FS
+	mmc_proc_dir = proc_mkdir( "mmc", NULL );
+#endif
+	ret = 0;
+/* error: */
+	return ret;
+}
+
+static void __exit mmc_core_module_cleanup( void )
+{
+#ifdef CONFIG_PROC_FS
+	if ( mmc_proc_dir )
+		remove_proc_entry( "mmc", NULL );
+#endif
+#ifdef CONFIG_PM
+	pm_unregister( mmc_pm_dev );
+#endif
+}
+
+module_init( mmc_core_module_init );
+module_exit( mmc_core_module_cleanup );
+
+MODULE_LICENSE( "GPL" );
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/mmc_pxa.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,1902 @@
+/*
+ *  linux/drivers/mmc/mmc_pxa.c 
+ *      driver for Cotulla MMC controller 
+ *
+ *  Authors:    Vladimir Shebordaev, Igor Oblakov   
+ *  Copyright:  MontaVista Software Inc.
+ *
+ *  $Id: mmc_pxa.c,v 0.3.1.12 2002/09/25 19:25:48 ted Exp ted $
+ *
+ *  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/version.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include <mmc/types.h>
+#include <mmc/mmc.h>
+#include <mmc/ioctl.h>
+
+#include "types.h"
+#include "mmc.h"
+#include "mmc_pxa.h"
+
+static mmc_controller_t host = NULL;
+
+/* service routines */
+static inline int pxa_mmc_check_state( mmc_controller_t ctrlr, pxa_mmc_state_t state )
+{
+    int ret = -1;
+    pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+    
+    if ( hostdata->state != state ) {
+        //MMC_DEBUG( MMC_DEBUG_LEVEL3,  "state (%s vs %s)\n",  PXA_MMC_STATE_LABEL( hostdata->state ),  PXA_MMC_STATE_LABEL( state ) );
+        goto error;
+    }
+    ret = 0;
+error:          
+    return ret;
+}
+
+static inline void pxa_mmc_set_state( mmc_controller_t ctrlr, pxa_mmc_state_t state )
+{
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+    
+	hostdata->state = state;
+}
+
+static inline int pxa_mmc_init_completion( mmc_controller_t ctrlr, u32 mask )
+{
+	int ret = -1;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+    
+	if ( xchg( &hostdata->busy, 1 ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "another interrupt "
+			"is already been expected\n" );
+		goto error;
+	}
+    
+#if CONFIG_MMC_DEBUG_IRQ 
+	hostdata->irqcnt = 1000;
+#endif
+	init_completion( &hostdata->completion );
+    
+	MMC_I_MASK = MMC_I_MASK_ALL & ~mask;
+	ret = 0;
+error:
+	return ret;
+}
+
+#if CONFIG_MMC_DEBUG_IRQ 
+static struct timer_list timer;
+static void wait_timeo( unsigned long arg ) {
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)arg;
+	hostdata->timeo = 1;
+	complete( &hostdata->completion );
+	return;
+}
+#endif
+
+static inline int pxa_mmc_wait_for_completion( mmc_controller_t ctrlr, u32 mask )
+{
+	int ret = -1;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+    
+	if ( !xchg( &hostdata->busy, 1 ) ) {
+        	MMC_DEBUG( MMC_DEBUG_LEVEL3, "there were no "
+				"interrupt awaited for\n" );
+		goto error;
+	}
+
+#if CONFIG_MMC_DEBUG_IRQ
+    	hostdata->timeo = 0;
+    	del_timer( &timer );
+	timer.function = wait_timeo;
+	timer.expires = jiffies + 1UL*HZ;
+	timer.data = (unsigned long)hostdata;
+	add_timer( &timer );
+#endif
+	wait_for_completion( &hostdata->completion );
+#if CONFIG_MMC_DEBUG_IRQ
+    	del_timer( &timer );
+	if ( hostdata->timeo ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "irq timed out: " "mask=%x stat=%x\n", mask, MMC_STAT );
+		goto error;
+	}
+#endif	
+	/*  verify interrupt */
+	if ( (mask == ~0UL) || !( hostdata->mmc_i_reg & ~mask ) ) 
+		ret = 0;
+    
+error:
+	xchg( &hostdata->busy, 0 ); 
+	return ret;
+}
+
+static inline int pxa_mmc_stop_bus_clock( mmc_controller_t ctrlr )
+{
+	int ret = -1;
+    
+	if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_CLK_OFF ) )
+		goto out;
+		
+	if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "BUFFER_IN_TRANSIT\n" );
+	        goto error;
+	}
+	
+	if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_CLK_IS_OFF ) )
+		goto error;
+    
+	MMC_STRPCL = MMC_STRPCL_STOP_CLK;
+	
+	if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_CLK_IS_OFF ) )
+		goto error;
+    
+	//MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is off\n" );
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_CLK_OFF );
+out:
+	ret = 0;
+error:
+	return ret;
+}
+
+static inline int pxa_mmc_start_bus_clock( mmc_controller_t ctrlr )
+{
+	int ret = -1;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;    
+
+	if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)
+	     && (hostdata->state != PXA_MMC_FSM_END_IO) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n", PXA_MMC_STATE_LABEL( hostdata->state ) );
+		goto error;
+	}
+    
+	MMC_STRPCL = MMC_STRPCL_START_CLK;
+	wmb();
+	//MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is on\n" ); 
+	ret = 0;
+error:
+	return ret;
+}
+
+/* 
+int pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t response )
+
+Effects: initializes completion to wait for END_CMD_RES intr,
+         waits for intr to occur, checks controller and card status 
+Requiers: controller is in CLK_OFF state
+Modifies: moves controller to the END_CMD state
+Returns: 
+*/ 
+static mmc_error_t pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t format, int send_abort )
+{
+	mmc_error_t ret = MMC_ERROR_GENERIC;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	int mask, nwords;
+	u32 status;
+    
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD%d(0x%04x%04x)\n", MMC_CMD & 0x3f, MMC_ARGH, MMC_ARGL);
+
+/* FIXME: check arguments */
+    
+	if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)
+	     && (hostdata->state != PXA_MMC_FSM_END_IO) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n",
+				PXA_MMC_STATE_LABEL( hostdata->state ) );
+		goto error;
+	}
+    
+	mask = MMC_I_MASK_END_CMD_RES;
+	if ( pxa_mmc_init_completion( ctrlr, mask ) )
+		goto error;
+    
+	MMC_PRTBUF = MMC_PRTBUF_BUF_FULL; 
+/* start the clock */
+	if ( pxa_mmc_start_bus_clock( ctrlr ) )
+		goto error;
+    
+/* wait for END_CMD_RES intr */
+	if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_END_CMD_RES ) )
+		goto error;
+
+/* check status */
+	if ( hostdata->mmc_stat & MMC_STAT_TIME_OUT_RESPONSE ) {
+		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "response timeout\n");
+		ret = MMC_ERROR_TIME_OUT_RESPONSE;
+		goto error;
+    
+	} else if ( hostdata->mmc_stat & MMC_STAT_READ_TIME_OUT ) {
+		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "read timeout\n");
+		ret = MMC_ERROR_READ_TIME_OUT;
+		goto error;
+    
+	} else if ( hostdata->mmc_stat & MMC_STAT_RES_CRC_ERROR ) {
+		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "response crc err\n");
+		ret = MMC_ERROR_RES_CRC_ERROR;
+		goto error;
+    
+	} else if ( hostdata->mmc_stat & MMC_STAT_CRC_READ_ERROR ) {
+		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "read crc err\n");
+		ret = MMC_ERROR_CRC_READ_ERROR;
+		goto error;
+        
+	} else if ( hostdata->mmc_stat & MMC_STAT_CRC_WRITE_ERROR ) {
+		// MMC_DEBUG(MMC_DEBUG_LEVEL3, "write crc err\n");
+		ret = MMC_ERROR_CRC_WRITE_ERROR;
+		goto error;
+	}
+    
+	nwords = (format == MMC_NORESPONSE) ? 0 :
+		(format == MMC_R1) ? 3 : 
+		(format == MMC_R2) ? 8 :
+		(format == MMC_R3) ? 3 : 
+		-1;
+	ret = nwords;
+	if ( nwords > 0 ) {
+		register int i;
+
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "nwords=%d\n", nwords );
+		for ( i = nwords - 1; i >= 0 ; i-- ) {
+			u32 res = MMC_RES;
+			int ibase = i<<1;
+
+			hostdata->mmc_res[ibase] = ((u8 *)&res)[0];
+			hostdata->mmc_res[ibase + 1] = ((u8 *)&res)[1];
+			--ret;
+		}
+#ifdef CONFIG_MMC_DEBUG
+		switch ( format ) {
+		case MMC_R1:
+			MMC_DUMP_R1( ctrlr );
+			break;
+		case MMC_R2:
+			MMC_DUMP_R2( ctrlr );
+			break;
+		case MMC_R3:
+			MMC_DUMP_R3( ctrlr );
+			break;
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL3, 
+					"unknown response format\n" );
+			ret = MMC_ERROR_GENERIC;
+			goto error;
+		}
+#endif
+
+/* check card status for R1(b) commands */
+		if ( format == MMC_R1 ) {
+			u8 cmd;
+			
+			((u8 *)&status)[0] = hostdata->mmc_res[1];
+			((u8 *)&status)[1] = hostdata->mmc_res[2];
+			((u8 *)&status)[2] = hostdata->mmc_res[3];
+			((u8 *)&status)[3] = hostdata->mmc_res[4];
+			cmd = PXA_MMC_RESPONSE( ctrlr, 5 )&0x3f;
+			MMC_DEBUG( MMC_DEBUG_LEVEL3, 
+			//printk( KERN_INFO __FUNCTION__"(): "
+				"cmd=%u status: 0x%08x\n",
+				cmd, status );
+			switch ( cmd ) {
+			case 11:
+			case 18:
+			case 20:
+			case 25:
+				if ( !(status & 0x00000100) ) /* FIXME */
+					goto mmc_error;
+			default:
+				break;
+			}
+			if ( status & MMC_CARD_STATUS_OUT_OF_RANGE ) {
+				ret = MMC_ERROR_OUT_OF_RANGE;
+				goto mmc_error;
+		    	} else if ( status & MMC_CARD_STATUS_ADDRESS_ERROR ) {
+				ret = MMC_ERROR_ADDRESS_ERROR;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_BLOCK_LEN_ERROR ) {
+				ret = MMC_ERROR_ADDRESS_ERROR;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_ERASE_SEQ_ERROR ) {
+				ret = MMC_ERROR_ERASE_SEQ_ERROR;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_ERASE_PARAM ) {
+				ret = MMC_ERROR_ERASE_PARAM;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_WP_VIOLATION ) {
+				ret = MMC_ERROR_WP_VIOLATION;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_CARD_IS_LOCKED ) {
+				ret = MMC_ERROR_CARD_IS_LOCKED;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_LOCK_UNLOCK_FAILED ) {
+				ret = MMC_ERROR_LOCK_UNLOCK_FAILED;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_COM_CRC_ERROR ) {
+				ret = MMC_ERROR_COM_CRC_ERROR;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_ILLEGAL_COMMAND ) {
+				ret = MMC_ERROR_ILLEGAL_COMMAND;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_CARD_ECC_FAILED ) {
+				ret = MMC_ERROR_CARD_ECC_FAILED;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_CC_ERROR ) {
+				ret = MMC_ERROR_CC_ERROR;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_ERROR ) {
+				ret = MMC_ERROR_ERROR;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_UNDERRUN ) {
+				ret = MMC_ERROR_UNDERRUN;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_OVERRUN ) {
+				ret = MMC_ERROR_OVERRUN;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_CID_CSD_OVERWRITE ) {
+				ret = MMC_ERROR_CID_CSD_OVERWRITE;
+				goto mmc_error;
+			} else if ( status & MMC_CARD_STATUS_ERASE_RESET ) {
+				ret = MMC_ERROR_ERASE_RESET;
+				goto mmc_error;
+			}
+		}
+	}
+    
+	if ( ret >= 0 )
+		pxa_mmc_set_state( ctrlr,  PXA_MMC_FSM_END_CMD );
+	goto out;
+mmc_error:
+#if 1
+	if ( send_abort ) {
+		/* send CMD12 to abort failed transfer */
+            	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+                	goto error;
+    
+	        MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
+        	MMC_CMDAT = MMC_CMDAT_R1;
+    		
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+		        goto error;
+    		
+		ret = -EIO;
+		goto error;
+	}
+#endif
+error:
+	/* move controller to the IDLE state */
+	pxa_mmc_stop_bus_clock( ctrlr );
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
+out:
+	return ret;
+}
+
+/* 
+int pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t cmd, mmc_dir_t dir, mmc_transfer_mode_t mode )
+
+Effects: finilizes data transfer request  
+Reqires: controller is in the END_BUFFER state
+Modifies: moves controller to the IDLE state
+Returns: zero upon success or error condition code otherwise
+ */
+static mmc_error_t pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t dir, mmc_transfer_mode_t mode )
+{
+	int ret = MMC_ERROR_GENERIC; 
+
+	if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_IO ) )
+		goto error;
+    
+	switch ( mode ) {
+	case MMC_TRANSFER_MODE_STREAM: /* FIXME */
+		if ( dir == MMC_WRITE ) {
+		/* 1. wait for STOP_CMD intr */
+			if ( (ret = pxa_mmc_init_completion( ctrlr,
+					MMC_I_MASK_STOP_CMD )) )
+				goto error;
+			if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+					MMC_I_REG_STOP_CMD )) )
+				goto error;
+		}
+		/* 2. send CMD12 */
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto error;
+    
+		MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
+		MMC_CMDAT = MMC_CMDAT_R1;
+		if ( dir == MMC_WRITE ) 
+			MMC_CMDAT |= MMC_CMDAT_BUSY;
+            
+		/* 3. wait for CMD12 to complete */
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "ready for CMD12\n" );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+			goto error;
+            
+		/* 4. wait for DATA_TRAN_DONE intr */
+		if ( (ret = pxa_mmc_init_completion( ctrlr,
+				MMC_I_MASK_DATA_TRAN_DONE )) )
+			goto error;
+		if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+				MMC_I_REG_DATA_TRAN_DONE )) )
+			goto error;
+	    
+		if ( dir == MMC_WRITE ) {
+		/* 5. wait for PRG_DONE intr */
+			if ( (ret = pxa_mmc_init_completion( ctrlr,
+					MMC_I_MASK_PRG_DONE )) )
+				goto error;
+        	        if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+                	        	MMC_I_REG_PRG_DONE )) )
+				goto error;
+		}
+		break;
+	case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
+		/* 1. wait for DATA_TRAN done intr */
+		if ( (ret = pxa_mmc_init_completion( ctrlr,
+				MMC_I_MASK_DATA_TRAN_DONE )) )
+			goto error;
+		if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+				MMC_I_REG_DATA_TRAN_DONE )) )
+			goto error;
+            
+		/* 2. send CMD12 */
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto error;
+    
+		MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
+		MMC_CMDAT = MMC_CMDAT_R1;
+		if ( dir == MMC_WRITE ) 
+			MMC_CMDAT |= MMC_CMDAT_BUSY;
+            
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD12\n" );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+			goto error;
+        
+		if ( dir == MMC_WRITE ) {
+		/* 3. wait for PRG_DONE intr */
+			if ( (ret = pxa_mmc_init_completion( ctrlr,
+					MMC_I_MASK_PRG_DONE )) )
+				goto error;
+			if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+					MMC_I_REG_PRG_DONE )) )
+				goto error;
+		}
+		break;
+	case MMC_TRANSFER_MODE_BLOCK_SINGLE:
+		/* 1. wait for DATA_TRAN_DONE intr */
+		if ( (ret = pxa_mmc_init_completion( ctrlr,
+				MMC_I_MASK_DATA_TRAN_DONE )) )
+			goto error;
+		if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+				MMC_I_REG_DATA_TRAN_DONE )) )
+			goto error;
+            
+		if ( dir == MMC_WRITE ) {
+		/* 2. wait for PRG_DONE intr */
+			if ( (ret = pxa_mmc_init_completion( ctrlr,
+					MMC_I_MASK_PRG_DONE )) )
+				goto error;
+			if ( (ret = pxa_mmc_wait_for_completion( ctrlr, 
+					MMC_I_REG_PRG_DONE )) )
+				goto error;
+		}
+		break;
+	default:
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown transfer mode\n" );
+		goto error;
+	}
+/* move the controller to the IDLE state */ 
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
+
+	ret = 0;
+error:
+	return ret;
+}
+
+static inline int pxa_mmc_update_acq( mmc_controller_t ctrlr )
+{
+	int ret = -EINVAL;
+	pxa_mmc_hostdata_t hostdata = NULL;
+	mmc_card_t card = NULL;
+	mmc_card_stack_rec_t fake;
+	mmc_card_stack_t stack = &fake;
+	u16 argl = 0U, argh = 0U;
+	int ncards = 0;
+
+	if ( !ctrlr )
+		goto error;
+
+	hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	
+	__mmc_card_stack_init( stack );
+	
+	/* max open-drain mode frequency is 400kHZ */
+	MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
+	MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */
+
+	/*  discover and add cards to the stack */  
+	/* I. bus operation condition setup */
+	/*      1) send CMD1 */
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto err_free;
+    
+	argl = 0x0000;
+	argh = 0x0004;
+
+	MMC_CMD = CMD(1);
+	MMC_ARGH = argh;
+	MMC_ARGL = argl; 
+    
+	MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3; 
+    
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl );
+	ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE );
+	if ( !ret ) {
+		argh = (PXA_MMC_RESPONSE( ctrlr, 4 ) << 8) 
+			| PXA_MMC_RESPONSE( ctrlr, 3 );
+		argl = (PXA_MMC_RESPONSE( ctrlr, 2 ) << 8)
+			| PXA_MMC_RESPONSE( ctrlr, 1 );
+
+	} else if ( ret != MMC_ERROR_TIME_OUT_RESPONSE ) 
+		goto err_free;
+    
+	if ( !argh && !argl ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, 
+			"assuming full voltage range support\n" );
+		argh = 0x00ff;
+		argl = 0xff00;
+	}
+    
+	/* 2) continuously send CMD1 'till there're busy cards */
+	for(;;) {
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto err_free;
+
+		MMC_CMD = CMD(1);
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+
+		MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl );
+		ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE );
+		if ( ret == MMC_ERROR_TIME_OUT_RESPONSE )
+			break; 
+
+		else if ( !ret ) {
+			/* busy state reported by LOW signal level 
+			 * (MMC v3.2, p.58)
+			 *
+			 * Thanks to Alexander Samoutin :)
+			 */
+			if ( !(PXA_MMC_RESPONSE( ctrlr, 4 ) & 0x80) ) {
+				MMC_DEBUG( MMC_DEBUG_LEVEL3, "busy state reported\n");
+				udelay( 20 );
+				continue;
+			} else 
+				break;
+		} else
+			goto err_free;
+	}
+
+/* II. card identification: the cards in Ready state 
+ *     are the only expected to respond 
+ */     
+	for (;;) {
+		argh = 0U;
+		argl = 0U;
+    
+		/* 1) send CMD2 */
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto err_free;
+        
+		MMC_CMD = CMD(2);
+		MMC_ARGH = 0x0003;
+		MMC_ARGL = 0xf300;
+		MMC_CMDAT = MMC_CMDAT_R2;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD2(0x%04x%04x)\n", argh, argl );
+		ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE );
+		if ( ret == MMC_ERROR_TIME_OUT_RESPONSE )
+			break;
+        
+		else if ( ret ) /* bus error */
+			goto err_free;
+        
+	        /* TODO: store CID for the card */
+        
+        	/* 2) assign RCA */
+		if ( !++ctrlr->rca_next ) /* overflow */
+			++ctrlr->rca_next;
+		argh = ctrlr->rca_next; 
+        
+        	/* 3) send it to the card last responded (CMD3) */
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto err_free;
+        
+		MMC_CMD = CMD(3);
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+		MMC_CMDAT = MMC_CMDAT_R1;
+
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD3(0x%04x%04x)\n", argh, argl );
+		ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );
+		if ( ret )   /* CMD3 failed */ 
+			goto err_free;
+
+		card = __mmc_card_alloc( sizeof( pxa_mmc_card_data_rec_t ) );
+		if ( !card ) {
+			MMC_ERROR( "out of memory\n" );
+			goto err_free;
+		}
+
+		card->info.rca = argh;  
+		card->slot = ctrlr->slot_next++; /* FIXME: minor encoding */
+		card->ctrlr = ctrlr;
+        
+		if ( !__mmc_card_stack_add( stack, card ) )
+			goto err_free;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL2, "added card: "
+				"slot %d, RCA=0x%04x\n", card->slot, argh );
+		++ncards;
+	}
+   
+	if ( ncards ) {
+/* III. read CSD registers of all cards; DSR support also reported there */
+		for ( card = stack->first; card; card = card->next ) {
+			pxa_mmc_card_data_t card_data = 
+				(pxa_mmc_card_data_t)card->card_data;
+	    
+			/* 1) send CMD9 */
+			argh = card->info.rca;
+			argl = 0U;
+        
+			if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+				goto err_free;
+        
+			MMC_CMD = CMD(9);
+			MMC_ARGH = argh;
+			MMC_ARGL = argl;
+			MMC_CMDAT = MMC_CMDAT_R2;
+        
+			MMC_DEBUG( MMC_DEBUG_LEVEL3, 
+				"CMD9(0x%04x%04x)\n", argh, argl );
+			if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE )) )
+				goto err_free; 
+       	
+			memcpy( &card->info.csd, hostdata->mmc_res, 15 );
+			MMC_DUMP_CSD( card );
+	    
+			card->info.read_bl_len = (1<<card->info.csd.read_bl_len);
+			card->info.write_bl_len = (1<<card->info.csd.write_bl_len);
+			card->info.capacity = (card->info.csd.c_size + 1) 
+					* (1<<(card->info.csd.c_size_mult + 2)) 
+					* card->info.read_bl_len;
+			MMC_DEBUG( MMC_DEBUG_LEVEL2, "card capacity=%dMb\n", 
+					card->info.capacity>>20 );
+			card->info.tran_speed = 20*1024; /* FIXME */
+			card->info.transfer_mode = MMC_TRANSFER_MODE_BLOCK_SINGLE; 
+		/* 2) set bus operation freq */
+			card_data->clkrt = pxa_mmc_clkrt( card->info.tran_speed );
+		/* 3) register card with MMC core */
+			mmc_register( MMC_REG_TYPE_CARD, card, 0 );
+		}
+/* IV. set DSR registers of the cards */
+#if 0 /* TODO */
+		if ( card->info.csd.dsr_imp ) {
+			set_dsr = TRUE;
+			/*  calculate DSR */
+		}
+#endif
+	}
+#if 0 /* TODO */
+	if ( set_dsr ) {
+			/* send CMD4 */
+	}
+#endif
+/* merge list of the newly inserted cards into controller card stack */
+	if ( !ctrlr->stack.ncards ) {
+		ctrlr->stack.first = stack->first;
+		ctrlr->stack.last = stack->last;
+	} else	
+		ctrlr->stack.last->next = stack->first;
+	
+	ctrlr->stack.ncards += stack->ncards;
+	
+	ret = 0;
+	goto out;
+err_free:
+	__mmc_card_stack_free( stack );
+error:
+out:
+	return ret;
+}
+
+/* MMC protocol macros: v3.4, p.120 */
+static int pxa_mmc_init_card_stack( mmc_controller_t ctrlr )
+{
+	int ret = -EIO;
+	u16 argl = 0U, argh = 0U;
+    
+	if ( !ctrlr || ctrlr->stack.ncards ) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* initialize stack */  
+	/*     1) send CMD0 */
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+
+	/* max open-drain mode frequency is 400kHZ */
+	MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
+	MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */
+	MMC_SPI = MMC_SPI_DISABLE;
+
+	MMC_CMD = CMD(0); /* CMD0 with zero argument */
+	MMC_ARGH = argh;
+	MMC_ARGL = argl; 
+	MMC_CMDAT = MMC_CMDAT_INIT;
+    
+	//MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, FALSE )) )
+		goto error;
+
+	/* update card stack */
+	if ( (ret = pxa_mmc_update_acq( ctrlr )) )
+		goto err_free;
+	
+	/* move the controller to the IDLE state */ 
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto err_free;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
+	
+	ret = 0;
+	MMC_DEBUG( MMC_DEBUG_LEVEL2, "ncards=%d\n", ctrlr->stack.ncards );
+	goto out;
+
+err_free:
+	__mmc_card_stack_free( &ctrlr->stack ); 
+error:
+out:
+	return ret;
+}
+
+static int pxa_mmc_check_card_stack( mmc_controller_t ctrlr )
+{
+	int ret = -1;
+	mmc_card_t card;
+	
+	if ( !ctrlr )
+		goto error;
+	
+	if ( ctrlr->stack.ncards > 0 )	 {
+/* for each card in the stack: */
+		for( card = ctrlr->stack.first; card; card = card->next ) {
+			u16 argh = card->info.rca;
+			u16 argl = 0UL;
+			
+/* 	1) send CMD9( card->rca ) */
+			if ( pxa_mmc_stop_bus_clock( ctrlr ) )
+				goto error;
+			
+			/* SanDisk's cards do not respond to CMD9 */	
+			MMC_CMD = CMD(13);
+			MMC_ARGH = argh;
+			MMC_ARGL = argl;
+			MMC_CMDAT = MMC_CMDAT_R1;
+			
+			MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD13(0x%04x%04x)\n", 
+					argh, argl );
+			ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );
+/* 	2) if card responded, it is still there */
+			if ( ret ) 
+				card->state = MMC_CARD_STATE_UNPLUGGED;
+		}
+	}
+	ret = 0;	
+error:
+	return ret;
+}
+
+/* This procedure links the bus master with a single card
+ *  1)  cross checks with the internal stack management data if a card still
+ *      exists in the slot
+ *  2)  send CMD7( card->public.rca )
+ *  3)  setup data path and controller options 
+ */
+static int pxa_mmc_setup_card( mmc_controller_t ctrlr, mmc_card_t card ) 
+{
+	int ret = -ENODEV;
+	pxa_mmc_hostdata_t hostdata;
+	pxa_mmc_card_data_t card_data;
+	u16 argh = 0U;
+#ifdef CONFIG_MMC_DEBUG
+	u16 argl = 0U;
+#endif
+    
+	if ( !ctrlr || !card ) {
+		ret = -EINVAL;
+		goto error;
+	}
+    
+	if ( card->ctrlr != ctrlr ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "card is on another bus\n" );
+		goto error;
+	}
+    
+	hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	card_data = (pxa_mmc_card_data_t)card->card_data;
+
+	argh = card->info.rca;
+    
+/* select requested card */ 
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) 
+		goto error;
+        
+	MMC_CMD = CMD(7);
+	MMC_ARGH = argh;
+	MMC_CMDAT = MMC_CMDAT_R1;
+
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD7(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+		goto error;
+
+/* set controller options */
+#ifndef CONFIG_MMC_DEBUG
+	MMC_CLKRT = card_data->clkrt; 
+#endif    
+/* move the controller to the IDLE state */ 
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
+	
+	ret = 0;
+error:  
+	return ret;
+}
+
+static inline int pxa_mmc_iobuf_init( mmc_controller_t ctrlr, ssize_t cnt )
+{
+#ifdef PIO
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+#endif 
+#ifndef PIO
+/* TODO */
+#else
+	hostdata->iobuf.buf.pos = hostdata->iobuf.iodata;
+	hostdata->iobuf.buf.cnt = cnt;
+#endif
+	return 0;
+}
+/* TODO: ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )
+effects: reads at most cnt bytes from the card to the controller I/O buffer;
+       takes care of partial data transfers
+requieres: 
+modifies: ctrlr->iobuf
+returns: number of bytes actually transferred or negative error code if there were any errors
+ */
+ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )
+{
+	ssize_t ret = -EIO;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+#ifndef PIO
+	register int ndesc;
+	int chan = hostdata->iobuf.buf.chan;
+	pxa_dma_desc *desc;
+#endif
+
+	if ( (hostdata->state != PXA_MMC_FSM_END_CMD) && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) {
+            goto error;
+	}
+	
+	if ( cnt > hostdata->iobuf.bufsz )
+		cnt = hostdata->iobuf.bufsz;
+
+	if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) )
+		goto error;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT );
+#ifndef PIO
+	if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */
+		goto error;
+	
+	if ( (desc = hostdata->iobuf.buf.last_read_desc) ) {
+		desc->ddadr &= ~DDADR_STOP;
+		desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH);
+		desc->dcmd |= (1<<5);
+	}
+/* 1) setup descriptors for DMA transfer from the device */
+	ndesc = (cnt>>5) - 1; /* FIXME: partial read */
+	desc = &hostdata->iobuf.buf.read_desc[ndesc];
+	hostdata->iobuf.buf.last_read_desc = desc;	
+	/* TODO: partial read */
+	desc->ddadr |= DDADR_STOP;
+	desc->dcmd |= DCMD_ENDIRQEN;
+/* 2) start DMA channel */
+	DDADR( chan ) = hostdata->iobuf.buf.read_desc_phys_addr;
+	DCSR( chan ) |= DCSR_RUN;
+#else
+	if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_RXFIFO_RD_REQ ) )
+		goto error;
+#endif
+
+	if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) )
+		goto error;
+
+	if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) )
+		goto error;
+
+	if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */  
+		ret = cnt;
+error:
+	return ret;
+}
+
+ssize_t pxa_mmc_write_buffer( mmc_controller_t ctrlr, ssize_t cnt )
+{
+	ssize_t ret = -EIO;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+#ifndef PIO
+	register int ndesc;
+	int chan = hostdata->iobuf.buf.chan;
+	pxa_dma_desc *desc;
+#endif
+	
+	if ( (hostdata->state != PXA_MMC_FSM_END_CMD) 
+	    && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state (%s)\n",
+			PXA_MMC_STATE_LABEL( hostdata->state ) ); 
+		goto error;
+	}
+    
+	if ( cnt > hostdata->iobuf.bufsz )
+		cnt = hostdata->iobuf.bufsz;
+	
+	if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) )
+		goto error;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT );
+#ifndef PIO
+	if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */
+		goto error;
+	if ( (desc = hostdata->iobuf.buf.last_write_desc) ) {
+		desc->ddadr &= ~DDADR_STOP;
+		desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH);
+		desc->dcmd |= (1<<5);
+	}
+/* 1) setup descriptors for DMA transfer to the device */
+	ndesc = (cnt>>5) - 1; /* FIXME: partial write */
+	desc = &hostdata->iobuf.buf.write_desc[ndesc];
+	/* TODO: partial write */
+	hostdata->iobuf.buf.last_write_desc = desc;	
+	desc->ddadr |= DDADR_STOP;
+	desc->dcmd |= DCMD_ENDIRQEN;
+/* 2) start DMA channel */
+	DDADR( chan ) = hostdata->iobuf.buf.write_desc_phys_addr;
+	DCSR( chan ) |= DCSR_RUN;
+#else
+	if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_TXFIFO_WR_REQ ) )
+		goto error;
+#endif
+	if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) )
+		goto error;
+    
+	if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) )
+		goto error;
+
+	if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */  
+		ret = cnt;
+error:
+	return ret;
+}
+
+/* TODO: ssize_t pxa_mmc_copy_from_buffer( ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
+effects: copies at most cnt bytes from the controller I/O buffer to the user or kernel buffer
+         pointed by buf
+requiers:
+modifies:
+returns: number of bytes actually transferred or negative error code if there were any errors
+ */ 
+ssize_t pxa_mmc_copy_from_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
+{
+	ssize_t ret = -EIO;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+
+#ifndef PIO
+/* TODO: check that DMA channel is not running */
+#endif
+	switch ( to ) {
+	case MMC_USER:
+		if ( copy_to_user( buf, hostdata->iobuf.iodata, cnt ) ) {
+			ret = -EFAULT;
+			goto error;
+		}
+		break;
+        case MMC_KERNEL:
+		memcpy( buf, hostdata->iobuf.iodata, cnt );
+		break;
+        default:
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" );
+		goto error;
+	}
+	ret = cnt;
+error:
+	return ret;
+}
+
+ssize_t pxa_mmc_copy_to_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
+{
+	ssize_t ret = -EIO;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+#ifndef PIO
+/* check that DMA channel is not running */
+#endif
+	switch ( to ) {
+	case MMC_USER:
+		if ( copy_from_user( hostdata->iobuf.iodata, buf, cnt ) ) {
+			ret = -EFAULT;
+			goto error;
+		}
+		break;
+	case MMC_KERNEL:
+		memcpy( hostdata->iobuf.iodata, buf, cnt );
+		break;
+	default:
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" );
+		goto error;
+	}
+	ret = cnt;
+error:
+	return ret;
+}
+
+/* This procedure sequentally passes the data from the user buffer to the card */
+static int pxa_mmc_stream_read( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
+{
+	int ret = -EIO;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	u16 argh = 0UL, argl = 0UL;
+	ssize_t size = 0;
+
+	while ( transfer->cnt > 0 ) {
+		size = (transfer->cnt < hostdata->iobuf.blksz) ?
+			transfer->cnt : hostdata->iobuf.blksz; 
+		/* 1. send CMD11 */
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto error;
+
+		argh = transfer->addr >> 16;
+		argl = transfer->addr;
+		/* 2. setup controller registers to start stream data transfer */
+		MMC_CMD = CMD(11); /* READ_DAT_UNTIL_STOP */
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+		MMC_NOB = 0xffff;
+		MMC_BLKLEN = size;
+		MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN;
+#ifndef PIO
+		MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; 
+#endif
+		/* 3. wait for cmd to complete */
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD11(0x%04x%04x)\n", argh, argl );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
+			goto error;	
+    
+		/* 4. transfer the data to the caller supplied buffer */
+		if ( (ret = pxa_mmc_read_buffer( ctrlr, size )) < 0 )
+			goto error;
+
+		if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
+			goto error;
+        
+		pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
+
+		if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
+			goto error;
+	        
+		transfer->buf += ret;
+		transfer->addr += ret;
+		transfer->cnt -= ret;
+	}
+	ret = 0;    
+error:
+	return ret;
+}
+
+/* This procedure reads a data block from a card at a given kernel address */ 
+static int pxa_mmc_read_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
+{
+	int ret = -ENODEV;
+	u16 argh = 0UL, argl = 0UL;
+
+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
+ * for the current card */  
+	if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
+		argh = transfer->blksz >> 16;
+		argl = transfer->blksz;
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) 
+			goto error;
+    
+		MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+		MMC_CMDAT = MMC_CMDAT_R1;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, 
+				"CMD16(0x%04x%04x)\n", argh, argl );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+			goto error;
+	}
+    
+/* CMD17 (READ_SINGLE_BLOCK) */
+	argh = transfer->addr >> 16;
+	argl = transfer->addr;
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+	
+	MMC_CMD = CMD(17); /* READ_SINGLE_BLOCK */
+	MMC_ARGH = argh;
+	MMC_ARGL = argl;
+	MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
+	MMC_NOB = 1;
+	MMC_BLKLEN = transfer->blksz;
+#ifndef PIO
+	MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; 
+#endif
+    
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD17(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+		goto error;
+    
+/* transfer the data to the caller supplied buffer */
+	if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->blksz )) < 0 )
+		goto error;
+
+	if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
+		goto error;
+        
+	transfer->buf += ret;
+	transfer->cnt -= ret;
+	transfer->nob -= 1;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
+
+	if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
+		goto error;
+    
+	ret = 0;    
+error:
+	return ret;
+}
+
+/* This procedure sequentally reads data blocks from
+ * a card to the user buffer. Controller options and block size 
+ * are already set by setup_card(). Data alignment and partial
+ * data accessibility assumed to be checked by mmc_core */
+static int pxa_mmc_read_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
+{
+	int ret = -EIO;
+	u16 argh = 0UL, argl = 0UL;
+
+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
+ * for the current card */  
+	if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
+		argh = transfer->blksz >> 16;
+		argl = transfer->blksz;
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto error;
+    
+		MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+		MMC_CMDAT = MMC_CMDAT_R1;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+			goto error;
+	}
+    
+	argh = transfer->addr >> 16;
+	argl = transfer->addr;
+/* 1. stop bus clock */
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+
+/* 2. setup controller registers to start multiple block transfer */
+	MMC_CMD = CMD(18); /* READ_MULTIPLE_BLOCK */
+	MMC_ARGH = argh;
+	MMC_ARGL = argl;
+	MMC_NOB = transfer->nob;
+	MMC_BLKLEN = transfer->blksz;
+	MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
+#ifndef PIO
+	MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; 
+#endif
+
+/* 3. start clock */
+	if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) )
+		goto error;
+    
+/* 4. wait for cmd to complete */
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD18(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
+		goto error;
+    
+/* 6. transfer the data to the caller supplied buffer */
+	while ( transfer->cnt > 0 ) {
+		if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->cnt )) < 0 )
+			goto error;
+
+		if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
+			goto error;
+        
+		transfer->buf += ret;
+		transfer->cnt -= ret;
+	}
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
+
+	if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
+		goto error;
+    
+	ret = 0;
+error:
+	return ret;
+}
+
+/* Sequentally writes the data from a user buffer to the card */
+static int pxa_mmc_stream_write( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
+{
+	int ret = -EIO;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	u16 argh = 0UL, argl = 0UL;
+	ssize_t size = 0;
+    
+	__ENTER( "transfer: cmd=%d mode=%d type=%d blksz=%d "
+		 "nob=%d buf=%p cnt=%d addr=%Lx", transfer->cmd, 
+		transfer->mode, transfer->type, transfer->blksz, 
+		transfer->nob, transfer->buf, transfer->cnt, transfer->addr );
+
+	argh = transfer->addr >> 16;
+	argl = transfer->addr;
+/* 1. stop bus clock */
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) 
+		goto error;
+
+/* 2. setup controller registers to start stream data transfer */
+	MMC_CMD = CMD(20); /* WRITE_DAT_UNTIL_STOP */
+	MMC_ARGH = argh;
+	MMC_ARGL = argl;
+	MMC_NOB = 0xffff;
+	MMC_BLKLEN = hostdata->iobuf.blksz;
+	MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN;
+#ifndef PIO
+	MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; 
+#endif
+
+/* 3. wait for cmd to complete */
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD20(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
+		goto error;
+    
+/* 4. transfer the data to the caller supplied buffer */
+	while ( transfer->cnt > 0 ) {
+		size = (transfer->cnt < hostdata->iobuf.blksz) ?
+			transfer->cnt : hostdata->iobuf.blksz; 
+		if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, 
+				transfer->type, transfer->buf, size )) < 0 )
+			goto error;
+        
+		if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
+			goto error;
+
+		transfer->buf += ret;
+		transfer->cnt -= ret;
+	}
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
+
+	if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
+		goto error;
+    
+	ret = 0;
+error:
+	return ret;
+}
+
+/* This procedure writes a data block to a card at a given address */
+static int pxa_mmc_write_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
+{
+	int ret = -ENODEV;
+	u16 argh = 0UL, argl = 0UL;
+
+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
+ * for the current card */  
+	if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
+		argh = transfer->blksz >> 16;
+		argl = transfer->blksz;
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) 
+			goto error;
+    
+		MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+		MMC_CMDAT = MMC_CMDAT_R1;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+			goto error;
+	}
+    
+/* CMD17 (READ_SINGLE_BLOCK) */
+	argh = transfer->addr >> 16;
+	argl = transfer->addr;
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+    
+	MMC_CMD = CMD(24); /* WRITE_BLOCK */
+	MMC_ARGH = argh;
+	MMC_ARGL = argl;
+	MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
+#ifndef PIO
+	MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; 
+#endif
+	MMC_NOB = 1;
+	MMC_BLKLEN = transfer->blksz;
+    
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD24(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+		goto error;
+    
+/* transfer the data to the caller supplied buffer */
+	if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type, transfer->buf, transfer->cnt )) < 0 )
+		goto error;
+        
+	if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
+		goto error;
+
+	transfer->buf += ret;
+	transfer->cnt -= ret;
+	transfer->nob -= 1;
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
+
+	if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
+		goto error;
+    
+	ret = 0;    
+error:
+	return ret;
+}
+
+/* This procedure sequentally writes data blocks to a card at a given address */
+static ssize_t pxa_mmc_write_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
+{
+	int ret = -EIO;
+	u16 argh = 0UL, argl = 0UL;
+    	
+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
+ * for the current card */  
+	if ( transfer->blksz != ctrlr->stack.selected->info.write_bl_len ) {
+		argh = transfer->blksz >> 16;
+		argl = transfer->blksz;
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto error;
+    
+		MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
+		MMC_ARGH = argh;
+		MMC_ARGL = argl;
+		MMC_CMDAT = MMC_CMDAT_R1;
+        
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
+			goto error;
+	}
+    
+	argh = transfer->addr >> 16;
+	argl = transfer->addr;
+/* 1. stop bus clock */
+	if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+		goto error;
+
+/* 2. setup controller registers to start multiple block transfer */
+	MMC_CMD = CMD(25); /* WRITE_MULTIPLE_BLOCK */
+	MMC_ARGH = argh;
+	MMC_ARGL = argl;
+	MMC_NOB = transfer->nob;
+	MMC_BLKLEN = transfer->blksz;
+	MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
+#ifndef PIO
+	MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; 
+#endif
+
+/* 3. start clock */
+	if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) )
+		goto error;
+    
+/* 4. wait for cmd to complete */
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD25(0x%04x%04x)\n", argh, argl );
+	if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) ) 
+		goto error;
+
+/* 6. transfer the data to the caller supplied buffer */
+	while ( transfer->cnt > 0 ) {
+		if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type,
+				transfer->buf, transfer->cnt )) < 0 )
+			goto error;
+        
+		if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
+			goto error;
+
+		transfer->buf += ret;
+		transfer->cnt -= ret;
+	}
+    
+	pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
+
+	if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
+		goto error;
+    
+	ret = 0;    
+error:
+	return ret;
+}
+
+static void pxa_mmc_irq( int irq, void *dev_id, struct pt_regs *regs )
+{
+	mmc_controller_t ctrlr = (mmc_controller_t)dev_id;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+#ifdef PIO
+	register int i, cnt;
+	register char *buf;
+#endif    
+
+	hostdata->mmc_i_reg = MMC_I_REG;
+	hostdata->mmc_stat = MMC_STAT;
+	hostdata->mmc_cmdat = MMC_CMDAT;
+#if 0
+	if (hostdata->mmc_i_reg != 0x0010) {
+	printk("IREG %08x", hostdata->mmc_i_reg);
+	if (hostdata->mmc_i_reg & 0x0001) printk(" DATA_TRAN_DONE");
+	if (hostdata->mmc_i_reg & 0x0002) printk(" PRG_DONE");
+	if (hostdata->mmc_i_reg & 0x0004) printk(" END_CMD");
+	if (hostdata->mmc_i_reg & 0x0008) printk(" STOP_CMD");
+	if (hostdata->mmc_i_reg & 0x0010) printk(" CLK_OFF");
+	if (hostdata->mmc_i_reg & 0x0020) printk(" RX_FIFO");
+	if (hostdata->mmc_i_reg & 0x0040) printk(" TX_FIFO");
+	printk("\nSTAT %08x", hostdata->mmc_stat);
+	if (hostdata->mmc_stat & 0x0001) printk(" READ_TO");
+	if (hostdata->mmc_stat & 0x0002) printk(" RESP_TO");
+	if (hostdata->mmc_stat & 0x0004) printk(" WR_CRC");
+	if (hostdata->mmc_stat & 0x0008) printk(" READ_CRC");
+	if (hostdata->mmc_stat & 0x0010) printk(" SPI_RD_TKN");
+	if (hostdata->mmc_stat & 0x0020) printk(" RESP_CRC");
+	if (hostdata->mmc_stat & 0x0040) printk(" TX_FIFO");
+	if (hostdata->mmc_stat & 0x0080) printk(" RX_FIFO");
+	if (hostdata->mmc_stat & 0x0100) printk(" CLK");
+	if (hostdata->mmc_stat & 0x0800) printk(" DATA_TRAN_DONE");
+	if (hostdata->mmc_stat & 0x1000) printk(" PRG_DONE");
+	if (hostdata->mmc_stat & 0x2000) printk(" END_CMD");
+	printk("\n");
+	}
+#endif
+
+#if CONFIG_MMC_DEBUG_IRQ 
+	if ( --hostdata->irqcnt <= 0 ) {
+		printk( KERN_INFO __FUNCTION__"(): irqcnt exceeded\n" );
+		goto complete;
+	}
+#endif
+	switch ( hostdata->state ) {
+	case PXA_MMC_FSM_IDLE:
+	case PXA_MMC_FSM_CLK_OFF:
+	case PXA_MMC_FSM_END_IO:
+	case PXA_MMC_FSM_END_BUFFER:
+	case PXA_MMC_FSM_END_CMD:
+		goto complete;
+#ifdef PIO   
+	case PXA_MMC_FSM_BUFFER_IN_TRANSIT:
+        	if ( hostdata->mmc_stat & MMC_STAT_ERRORS )
+         		goto complete;
+        
+		buf = hostdata->iobuf.buf.pos;
+        	cnt = (hostdata->iobuf.buf.cnt < 32) ? 
+			hostdata->iobuf.buf.cnt : 32;
+		if ( hostdata->mmc_cmdat & MMC_CMDAT_WRITE ) {
+			if ( !(hostdata->mmc_stat & MMC_STAT_XMIT_FIFO_EMPTY) )
+				break;
+			for ( i = 0; i < cnt; i++ ) 
+				MMC_TXFIFO = *buf++;
+			if ( cnt < 32 ) 
+				MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL; 
+		} else { /* i.e. MMC_CMDAT_READ */
+			if( !(hostdata->mmc_stat & MMC_STAT_RECV_FIFO_FULL) )
+				break;
+			for( i = 0; i < cnt; i++ ) 
+				*buf++ = MMC_RXFIFO;
+		}
+        
+		hostdata->iobuf.buf.pos = buf;
+		hostdata->iobuf.buf.cnt -= i;
+		if ( hostdata->iobuf.buf.cnt <= 0 ) {
+			pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER );
+			MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" );
+			goto complete;
+		}
+		break; 
+#endif /* PIO */
+	default:
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state %d\n", 
+				hostdata->state );
+		goto complete;
+	}   
+	return;	
+complete:   
+	MMC_I_MASK = MMC_I_MASK_ALL;
+	complete( &hostdata->completion );
+	return;
+}
+
+#ifndef PIO
+static void pxa_mmc_dma_irq( int irq, void *dev_id, struct pt_regs *regs )
+{
+	mmc_controller_t ctrlr = (mmc_controller_t)dev_id;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	u32 dcsr;
+	u32 ddadr;
+	int chan = hostdata->iobuf.buf.chan;
+	
+	ddadr = DDADR( chan );
+	dcsr = DCSR( chan );
+	DCSR( chan ) = dcsr & ~DCSR_STOPIRQEN;
+	
+	MMC_DEBUG( MMC_DEBUG_LEVEL3, 
+			"MMC DMA interrupt: chan=%d ddadr=0x%08x "
+			"dcmd=0x%08x dcsr=0x%08x\n", 
+			chan, ddadr, DCMD( chan ), dcsr );
+/* bus error */
+	if ( dcsr & DCSR_BUSERR ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "bus error on DMA channel %d\n",
+				chan );
+		pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_ERROR );
+		goto complete;
+	}
+/* data transfer completed */
+	if ( dcsr & DCSR_ENDINTR ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" );
+		pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER );
+		goto complete;
+	}
+	return;
+complete:
+	complete( &hostdata->completion );
+	return;
+}
+#endif
+
+
+static int pxa_mmc_init( mmc_controller_t ctrlr )
+{
+	int ret = -ENODEV;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+#ifndef PIO
+	register int i;
+	register pxa_dma_desc *desc;
+#endif
+
+/* hardware initialization */
+/* I. prepare to transfer data */
+/* 1. allocate buffer */
+#ifndef PIO
+	hostdata->iobuf.buf.read_desc = consistent_alloc( GFP_KERNEL,
+				(PXA_MMC_IODATA_SIZE>>5)
+				* sizeof( pxa_dma_desc ),
+				&hostdata->iobuf.buf.read_desc_phys_addr, 0 );
+	if ( !hostdata->iobuf.buf.read_desc ) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	hostdata->iobuf.buf.write_desc = consistent_alloc( GFP_KERNEL,
+				(PXA_MMC_IODATA_SIZE>>5)
+				* sizeof( pxa_dma_desc ),
+				&hostdata->iobuf.buf.write_desc_phys_addr, 0 );
+	if ( !hostdata->iobuf.buf.write_desc ) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	hostdata->iobuf.iodata = consistent_alloc( GFP_ATOMIC, 
+					PXA_MMC_IODATA_SIZE,
+					&hostdata->iobuf.buf.phys_addr, 0 );
+#else
+	hostdata->iobuf.iodata = kmalloc( PXA_MMC_IODATA_SIZE, GFP_ATOMIC );
+#endif
+	if ( !hostdata->iobuf.iodata ) {
+		ret = -ENOMEM;
+		goto error;
+	}
+/* 2. initialize iobuf */
+	hostdata->iobuf.blksz = PXA_MMC_BLKSZ_MAX;
+	hostdata->iobuf.bufsz = PXA_MMC_IODATA_SIZE;
+	hostdata->iobuf.nob = PXA_MMC_BLOCKS_PER_BUFFER;
+#ifndef PIO
+  /* request DMA channel */
+	if ( (hostdata->iobuf.buf.chan = pxa_request_dma( "MMC", DMA_PRIO_LOW,
+					pxa_mmc_dma_irq, ctrlr )) < 0 ) {
+		MMC_ERROR( "failed to request DMA channel\n" );
+		goto error;
+	}
+	
+	DRCMRRXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD;
+	DRCMRTXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD;
+	
+	for ( i = 0; i < ((PXA_MMC_IODATA_SIZE>>5) - 1); i++ ) {
+		desc = &hostdata->iobuf.buf.read_desc[i];
+		desc->ddadr = hostdata->iobuf.buf.read_desc_phys_addr
+				+ ((i + 1) * sizeof( pxa_dma_desc ));
+		desc->dsadr = MMC_RXFIFO_PHYS_ADDR;
+		desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5);
+		desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR
+				|DCMD_WIDTH1|DCMD_BURST32|(1<<5);
+		
+		desc = &hostdata->iobuf.buf.write_desc[i];
+		desc->ddadr = hostdata->iobuf.buf.write_desc_phys_addr
+				+ ((i + 1) * sizeof( pxa_dma_desc ));
+		desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5);
+		desc->dtadr = MMC_TXFIFO_PHYS_ADDR;
+		desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR
+				|DCMD_WIDTH1|DCMD_BURST32|(1<<5);
+	}
+	desc = &hostdata->iobuf.buf.read_desc[i];
+	desc->ddadr = (hostdata->iobuf.buf.read_desc_phys_addr +
+				(i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP;
+	desc->dsadr = MMC_RXFIFO_PHYS_ADDR;
+	desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5);
+	desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR
+			|DCMD_WIDTH1|DCMD_BURST32|(1<<5);
+		
+	desc = &hostdata->iobuf.buf.write_desc[i];
+	desc->ddadr = (hostdata->iobuf.buf.write_desc_phys_addr +
+				(i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP;
+	desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5);
+	desc->dtadr = MMC_TXFIFO_PHYS_ADDR;
+	desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR
+			|DCMD_WIDTH1|DCMD_BURST32|(1<<5);
+#endif
+/* II. MMC */
+/*  1) request irq */
+	if ( request_irq( IRQ_MMC, pxa_mmc_irq, 0, "MMC", ctrlr ) ) {
+		MMC_ERROR( "failed to request IRQ_MMC\n" );
+		goto error;
+	}
+    
+/*  2) initialize h/w and ctrlr */
+	set_GPIO_mode( GPIO6_MMCCLK_MD );
+	CKEN |= CKEN12_MMC; /* enable MMC unit clock */
+
+	ret = 0;
+	goto out;
+error:
+#ifndef PIO
+/* free DMA resources */
+	if ( hostdata->iobuf.buf.chan >= 0 ) {
+		DRCMRRXMMC = 0;
+		DRCMRTXMMC = 0;
+		pxa_free_dma( hostdata->iobuf.buf.chan );
+	}
+	if ( hostdata->iobuf.iodata )
+		consistent_free( hostdata->iobuf.iodata, 
+				 PXA_MMC_IODATA_SIZE,
+				 hostdata->iobuf.buf.phys_addr );
+	if ( hostdata->iobuf.buf.read_desc )	
+		consistent_free( hostdata->iobuf.buf.read_desc,
+				(PXA_MMC_IODATA_SIZE>>5)
+				* sizeof( pxa_dma_desc ),
+				hostdata->iobuf.buf.read_desc_phys_addr );
+	if ( hostdata->iobuf.buf.write_desc )	
+		consistent_free( hostdata->iobuf.buf.write_desc,
+				(PXA_MMC_IODATA_SIZE>>5)
+				* sizeof( pxa_dma_desc ),
+				hostdata->iobuf.buf.write_desc_phys_addr );
+#else
+	kfree( hostdata->iobuf.iodata );
+#endif
+out:
+	return ret; 
+}
+
+static void pxa_mmc_remove( mmc_controller_t ctrlr )
+{
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	
+/*  1) free buffer(s) */
+#ifndef PIO
+	consistent_free( hostdata->iobuf.iodata, PXA_MMC_IODATA_SIZE,
+			 hostdata->iobuf.buf.phys_addr );
+	consistent_free( hostdata->iobuf.buf.read_desc,
+	 		 (PXA_MMC_IODATA_SIZE>>5)
+			 * sizeof( pxa_dma_desc ),
+			 hostdata->iobuf.buf.read_desc_phys_addr );
+	consistent_free( hostdata->iobuf.buf.write_desc,
+			 (PXA_MMC_IODATA_SIZE>>5)
+			 * sizeof( pxa_dma_desc ),
+			 hostdata->iobuf.buf.write_desc_phys_addr );
+/*  2) release DMA channel */
+	if ( hostdata->iobuf.buf.chan >= 0 ) {
+		DRCMRRXMMC = 0;
+		DRCMRTXMMC = 0;
+		pxa_free_dma( hostdata->iobuf.buf.chan );
+	}
+#else
+	kfree( hostdata->iobuf.iodata );
+#endif
+/* II. MMC */
+/*  1) release irq */
+	free_irq( IRQ_MMC, ctrlr );
+	CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */
+}
+
+static int pxa_mmc_probe( mmc_controller_t ctrlr )
+{
+	return 1;
+}
+
+#ifdef CONFIG_PM
+static int pxa_mmc_suspend( mmc_controller_t ctrlr )
+{
+	int ret = -EBUSY;
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+	
+	MMC_DEBUG( MMC_DEBUG_LEVEL2, "state=%s\n", 
+			PXA_MMC_STATE_LABEL( hostdata->state ) );
+
+	if ( hostdata->state == PXA_MMC_FSM_IDLE ) {
+		/* save registers */
+		SAVED_MMC_CLKRT = MMC_CLKRT;
+		SAVED_MMC_RESTO = MMC_RESTO;
+		SAVED_MMC_SPI = MMC_SPI;
+		SAVED_DRCMRRXMMC = DRCMRRXMMC;
+		SAVED_DRCMRTXMMC = DRCMRTXMMC;
+
+#if 0 /* FIXME */
+		/* send CMD0 */
+		if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
+			goto error;
+
+		MMC_CMD = CMD(0); /* CMD0 with zero argument */
+		MMC_ARGH = 0UL;
+		MMC_ARGL = 0UL; 
+		MMC_CMDAT = 0UL;
+    
+		MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", 0UL, 0UL );
+		if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, 
+						FALSE )) ) 
+		{
+			ret = -EIO;
+			goto error;
+		}
+#endif		
+	
+		set_GPIO_mode( GPIO6_MMCCLK );
+		CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */
+		
+		hostdata->suspended = TRUE;
+		ret = 0;
+	}
+error:
+	return ret;
+}
+
+static void pxa_mmc_resume( mmc_controller_t ctrlr )
+{
+	pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
+
+	if ( hostdata->suspended == TRUE ) {
+		set_GPIO_mode( GPIO6_MMCCLK_MD );
+		CKEN |= CKEN12_MMC; /* enable MMC unit clock */
+		
+		/* restore registers */
+		MMC_CLKRT = SAVED_MMC_CLKRT;
+		MMC_RESTO = SAVED_MMC_RESTO;
+		MMC_SPI = SAVED_MMC_SPI;
+		DRCMRRXMMC = SAVED_DRCMRRXMMC;
+		DRCMRTXMMC = SAVED_DRCMRTXMMC;
+
+		hostdata->suspended = FALSE;
+
+		mmc_update_card_stack( ctrlr->slot ); /* FIXME */
+	}
+	
+	return;
+}
+#endif
+
+static mmc_controller_tmpl_rec_t pxa_mmc_controller_tmpl_rec = {
+	owner:			THIS_MODULE,
+	name:			"PXA250",
+	block_size_max:		PXA_MMC_BLKSZ_MAX,
+	nob_max:		PXA_MMC_NOB_MAX,
+	probe:			pxa_mmc_probe,
+	init:			pxa_mmc_init,
+	remove:			__devexit_p( pxa_mmc_remove ),
+#ifdef CONFIG_PM
+	suspend:		pxa_mmc_suspend,
+	resume:			pxa_mmc_resume,
+#endif /* CONFIG_PM */
+	update_acq:		pxa_mmc_update_acq,
+//	single_card_acq:	pxa_mmc_single_card_acq,
+	init_card_stack:	pxa_mmc_init_card_stack,
+	check_card_stack:	pxa_mmc_check_card_stack,
+	setup_card:		pxa_mmc_setup_card,
+	stream_read:		pxa_mmc_stream_read,
+	read_block:		pxa_mmc_read_block,
+	read_mblock:		pxa_mmc_read_mblock,
+	stream_write:		pxa_mmc_stream_write,
+	write_block:		pxa_mmc_write_block,
+	write_mblock:		pxa_mmc_write_mblock
+	/* TODO
+	sg_io:			pxa_mmc_sg_io
+	 */
+	/* TODO: 
+	 *  erase, 
+	 *  write protection,
+	 *  lock/password management methods
+	 */
+};
+
+static int __devinit mmc_pxa_module_init( void )
+{
+    	int ret = -ENODEV;
+#ifdef CONFIG_ARCH_RAMSES
+	RAMSES_MMC_ON();
+	udelay(1000);
+#endif
+
+	host = mmc_register( MMC_REG_TYPE_HOST, &pxa_mmc_controller_tmpl_rec,
+			sizeof( pxa_mmc_hostdata_rec_t ) );
+	if ( !host ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, 
+				"failed to register with MMC core\n" );
+		goto error;
+	}
+	
+	ret = 0;
+error:
+	return ret;
+}
+
+static void __devexit mmc_pxa_module_cleanup( void )
+{
+	mmc_unregister( MMC_REG_TYPE_HOST, host );
+#ifdef CONFIG_ARCH_RAMSES
+	RAMSES_MMC_OFF();
+#endif
+}
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_LICENSE( "GPL" );
+
+module_init( mmc_pxa_module_init );
+module_exit( mmc_pxa_module_cleanup );
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/mmc_pxa.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,278 @@
+/*
+ *  linux/drivers/mmc/mmc_pxa.h 
+ *
+ *  Author: Vladimir Shebordaev, Igor Oblakov   
+ *  Copyright:  MontaVista Software Inc.
+ *
+ *  $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $
+ *
+ *  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 __MMC_PXA_P_H__
+#define __MMC_PXA_P_H__
+
+#include <linux/completion.h>
+
+#define PIO
+
+/* PXA-250 MMC controller registers */
+
+/* MMC_STRPCL */
+#define MMC_STRPCL_STOP_CLK     (0x0001UL)
+#define MMC_STRPCL_START_CLK        (0x0002UL)
+
+/* MMC_STAT */
+#define MMC_STAT_END_CMD_RES        (0x0001UL << 13)
+#define MMC_STAT_PRG_DONE       (0x0001UL << 12)
+#define MMC_STAT_DATA_TRAN_DONE     (0x0001UL << 11)
+#define MMC_STAT_CLK_EN         (0x0001UL << 8)
+#define MMC_STAT_RECV_FIFO_FULL     (0x0001UL << 7)
+#define MMC_STAT_XMIT_FIFO_EMPTY    (0x0001UL << 6)
+#define MMC_STAT_RES_CRC_ERROR      (0x0001UL << 5)
+#define MMC_STAT_SPI_READ_ERROR_TOKEN   (0x0001UL << 4)
+#define MMC_STAT_CRC_READ_ERROR     (0x0001UL << 3)
+#define MMC_STAT_CRC_WRITE_ERROR    (0x0001UL << 2)
+#define MMC_STAT_TIME_OUT_RESPONSE  (0x0001UL << 1)
+#define MMC_STAT_READ_TIME_OUT      (0x0001UL)
+
+#define MMC_STAT_ERRORS (MMC_STAT_RES_CRC_ERROR|MMC_STAT_SPI_READ_ERROR_TOKEN\
+        |MMC_STAT_CRC_READ_ERROR|MMC_STAT_TIME_OUT_RESPONSE\
+        |MMC_STAT_READ_TIME_OUT)
+
+/* MMC_CLKRT */
+#define MMC_CLKRT_20MHZ         (0x0000UL)
+#define MMC_CLKRT_10MHZ         (0x0001UL)
+#define MMC_CLKRT_5MHZ          (0x0002UL)
+#define MMC_CLKRT_2_5MHZ        (0x0003UL)
+#define MMC_CLKRT_1_25MHZ       (0x0004UL)
+#define MMC_CLKRT_0_625MHZ      (0x0005UL)
+#define MMC_CLKRT_0_3125MHZ     (0x0006UL)
+
+/* MMC_SPI */
+#define MMC_SPI_DISABLE         (0x00UL)
+#define MMC_SPI_EN          (0x01UL)
+#define MMC_SPI_CS_EN           (0x01UL << 2)
+#define MMC_SPI_CS_ADDRESS      (0x01UL << 3)
+#define MMC_SPI_CRC_ON          (0x01UL << 1)
+
+/* MMC_CMDAT */
+#define MMC_CMDAT_MMC_DMA_EN        (0x0001UL << 7)
+#define MMC_CMDAT_INIT          (0x0001UL << 6)
+#define MMC_CMDAT_BUSY          (0x0001UL << 5)
+#define MMC_CMDAT_STREAM        (0x0001UL << 4)
+#define MMC_CMDAT_BLOCK         (0x0000UL << 4)
+#define MMC_CMDAT_WRITE         (0x0001UL << 3)
+#define MMC_CMDAT_READ          (0x0000UL << 3)
+#define MMC_CMDAT_DATA_EN       (0x0001UL << 2)
+#define MMC_CMDAT_R1            (0x0001UL)
+#define MMC_CMDAT_R2            (0x0002UL)
+#define MMC_CMDAT_R3            (0x0003UL)
+
+/* MMC_RESTO */
+#define MMC_RES_TO_MAX          (0x007fUL) /* [6:0] */
+
+/* MMC_RDTO */
+#define MMC_READ_TO_MAX         (0x0ffffUL) /* [15:0] */
+
+/* MMC_BLKLEN */
+#define MMC_BLK_LEN_MAX         (0x03ffUL) /* [9:0] */
+
+/* MMC_PRTBUF */
+#define MMC_PRTBUF_BUF_PART_FULL       (0x01UL) 
+#define MMC_PRTBUF_BUF_FULL		(0x00UL    )
+
+/* MMC_I_MASK */
+#define MMC_I_MASK_TXFIFO_WR_REQ        (0x01UL << 6)
+#define MMC_I_MASK_RXFIFO_RD_REQ        (0x01UL << 5)
+#define MMC_I_MASK_CLK_IS_OFF           (0x01UL << 4)
+#define MMC_I_MASK_STOP_CMD         (0x01UL << 3)
+#define MMC_I_MASK_END_CMD_RES          (0x01UL << 2)
+#define MMC_I_MASK_PRG_DONE         (0x01UL << 1)
+#define MMC_I_MASK_DATA_TRAN_DONE       (0x01UL)
+#define MMC_I_MASK_ALL              (0x07fUL)
+
+
+/* MMC_I_REG */
+#define MMC_I_REG_TXFIFO_WR_REQ     (0x01UL << 6)
+#define MMC_I_REG_RXFIFO_RD_REQ     (0x01UL << 5)
+#define MMC_I_REG_CLK_IS_OFF        (0x01UL << 4)
+#define MMC_I_REG_STOP_CMD      (0x01UL << 3)
+#define MMC_I_REG_END_CMD_RES       (0x01UL << 2)
+#define MMC_I_REG_PRG_DONE      (0x01UL << 1)
+#define MMC_I_REG_DATA_TRAN_DONE    (0x01UL)
+#define MMC_I_REG_ALL           (0x007fUL)
+
+/* MMC_CMD */
+#define MMC_CMD_INDEX_MAX       (0x006fUL)  /* [5:0] */
+#define CMD(x)  (x)
+
+/* MMC_ARGH */
+/* MMC_ARGL */
+/* MMC_RES */
+/* MMC_RXFIFO */
+#define MMC_RXFIFO_PHYS_ADDR 0x41100040 //MMC_RXFIFO physical address
+/* MMC_TXFIFO */ 
+#define MMC_TXFIFO_PHYS_ADDR 0x41100044 //MMC_TXFIFO physical address
+
+/* implementation specific declarations */
+#define PXA_MMC_BLKSZ_MAX (1<<9) /* actually 1023 */
+#define PXA_MMC_NOB_MAX ((1<<16)-2)
+#define PXA_MMC_BLOCKS_PER_BUFFER (2)
+
+#define PXA_MMC_IODATA_SIZE (PXA_MMC_BLOCKS_PER_BUFFER*PXA_MMC_BLKSZ_MAX) /* 1K */
+
+typedef enum _pxa_mmc_fsm {         /* command processing FSM */
+    PXA_MMC_FSM_IDLE = 1,
+    PXA_MMC_FSM_CLK_OFF,
+    PXA_MMC_FSM_END_CMD,
+    PXA_MMC_FSM_BUFFER_IN_TRANSIT,
+    PXA_MMC_FSM_END_BUFFER, 
+    PXA_MMC_FSM_END_IO, 
+    PXA_MMC_FSM_END_PRG,
+    PXA_MMC_FSM_ERROR
+} pxa_mmc_state_t;
+
+#define PXA_MMC_STATE_LABEL( state ) (\
+    (state == PXA_MMC_FSM_IDLE) ? "IDLE" :\
+    (state == PXA_MMC_FSM_CLK_OFF) ? "CLK_OFF" :\
+    (state == PXA_MMC_FSM_END_CMD) ? "END_CMD" :\
+    (state == PXA_MMC_FSM_BUFFER_IN_TRANSIT) ? "IN_TRANSIT" :\
+    (state == PXA_MMC_FSM_END_BUFFER) ? "END_BUFFER" :\
+    (state == PXA_MMC_FSM_END_IO) ? "END_IO" :\
+    (state == PXA_MMC_FSM_END_PRG) ? "END_PRG" : "UNKNOWN" )
+
+typedef enum _pxa_mmc_result {
+    PXA_MMC_NORMAL = 0,
+    PXA_MMC_INVALID_STATE = -1,
+    PXA_MMC_TIMEOUT = -2,
+    PXA_MMC_ERROR = -3
+} pxa_mmc_result_t;
+
+typedef u32 pxa_mmc_clkrt_t;
+
+typedef char *pxa_mmc_iodata_t;
+#ifdef PIO
+typedef struct _pxa_mmc_piobuf_rec {
+    char *pos; /* current buffer position */
+    int   cnt; /* byte counter */
+} pxa_mmc_piobuf_rec_t, *pxa_mmc_piobuf_t;
+#else /* i.e. DMA */
+typedef struct _pxa_mmc_dmabuf_rec { /* TODO: buffer ring, DMA irq completion */
+	int chan; /* dma channel no */
+	dma_addr_t phys_addr; /* iodata physical address */
+	pxa_dma_desc *read_desc; /* input descriptor array virtual address */
+	pxa_dma_desc *write_desc; /* output descriptor array virtual address */
+	dma_addr_t read_desc_phys_addr; /* descriptor array physical address */
+	dma_addr_t write_desc_phys_addr; /* descriptor array physical address */
+	pxa_dma_desc *last_read_desc; /* last input descriptor 
+				       * used by the previous transfer 
+				       */
+	pxa_dma_desc *last_write_desc; /* last output descriptor
+					* used by the previous transfer 
+					*/
+} pxa_mmc_dmabuf_rec_t, *pxa_mmc_dmabuf_t;
+#endif
+
+typedef struct _pxa_mmc_iobuf_rec {
+    ssize_t blksz; /* current block size in bytes */
+    ssize_t bufsz; /* buffer size for each transfer */
+    ssize_t nob; /* number of blocks pers buffer */ 
+#ifndef PIO 
+    pxa_mmc_dmabuf_rec_t buf; /* i.e. DMA buffer ring on the iodata */
+#else /* i.e. DMA */
+    pxa_mmc_piobuf_rec_t buf; /* PIO buffer accounting */
+#endif
+    pxa_mmc_iodata_t iodata; /* I/O data buffer */
+} pxa_mmc_iobuf_rec_t, *pxa_mmc_iobuf_t;
+
+typedef struct _pxa_mmc_hostdata_rec {
+    pxa_mmc_state_t state; /* FSM */
+#ifdef CONFIG_PM
+    int suspended;
+#endif
+    pxa_mmc_iobuf_rec_t iobuf; /* data transfer state */
+    
+    int busy;   /* atomic busy flag */
+    struct completion completion; /* completion */
+#if CONFIG_MMC_DEBUG_IRQ
+    int irqcnt;
+    int timeo;
+#endif
+    
+/* cached controller state */
+    u32 mmc_i_reg;  /* interrupt last requested */
+    u32 mmc_i_mask; /* mask to be set by intr handler */
+    u32 mmc_stat;   /* status register at the last intr */
+    u32 mmc_cmdat;  /* MMC_CMDAT at the last inr */
+    u8 mmc_res[16]; /* response to the last command in host order */ 
+    u32 saved_mmc_clkrt;
+    u32 saved_mmc_resto;
+    u32 saved_mmc_spi;
+    u32 saved_drcmrrxmmc;
+    u32 saved_drcmrtxmmc;
+
+/* controller options */
+    pxa_mmc_clkrt_t clkrt; /* current bus clock rate */
+} pxa_mmc_hostdata_rec_t, *pxa_mmc_hostdata_t;
+
+#define PXA_MMC_STATUS( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_stat)
+#define PXA_MMC_RESPONSE( ctrlr, idx ) ((((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_res)[idx])
+#define PXA_MMC_CLKRT( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->clkrt)  
+
+#define SAVED_MMC_CLKRT (hostdata->saved_mmc_clkrt)
+#define SAVED_MMC_RESTO (hostdata->saved_mmc_resto)
+#define SAVED_MMC_SPI (hostdata->saved_mmc_spi)
+#define SAVED_DRCMRRXMMC (hostdata->saved_drcmrrxmmc )
+#define SAVED_DRCMRTXMMC (hostdata->saved_drcmrtxmmc )
+
+static inline int pxa_mmc_clkrt( int speed )
+{
+    return MMC_CLKRT_20MHZ; /* TODO */
+}
+
+/* PXA MMC controller specific card data */
+typedef struct _pxa_mmc_card_data_rec { 
+    pxa_mmc_clkrt_t clkrt;   /* clock rate to be set for the card */
+} pxa_mmc_card_data_rec_t, *pxa_mmc_card_data_t;
+
+#ifdef CONFIG_MMC_DEBUG
+#undef MMC_DUMP_R1
+#undef MMC_DUMP_R2
+#undef MMC_DUMP_R3
+#define MMC_DUMP_R2( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
+"R2 response: %02x %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", \
+PXA_MMC_RESPONSE( ctrlr, 15 ), \
+PXA_MMC_RESPONSE( ctrlr, 14 ), \
+PXA_MMC_RESPONSE( ctrlr, 13 ), \
+PXA_MMC_RESPONSE( ctrlr, 12 ), \
+PXA_MMC_RESPONSE( ctrlr, 11 ), \
+PXA_MMC_RESPONSE( ctrlr, 10 ), \
+PXA_MMC_RESPONSE( ctrlr, 9 ), \
+PXA_MMC_RESPONSE( ctrlr, 8 ), \
+PXA_MMC_RESPONSE( ctrlr, 7 ), \
+PXA_MMC_RESPONSE( ctrlr, 6 ), \
+PXA_MMC_RESPONSE( ctrlr, 5 ), \
+PXA_MMC_RESPONSE( ctrlr, 4 ), \
+PXA_MMC_RESPONSE( ctrlr, 3 ), \
+PXA_MMC_RESPONSE( ctrlr, 2 ), \
+PXA_MMC_RESPONSE( ctrlr, 1 ), \
+PXA_MMC_RESPONSE( ctrlr, 0 ) );
+#define MMC_DUMP_R1( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
+"R1(b) response: %02x %02x%02x%02x%02x\n", \
+PXA_MMC_RESPONSE( ctrlr, 5 ), \
+PXA_MMC_RESPONSE( ctrlr, 4 ), \
+PXA_MMC_RESPONSE( ctrlr, 3 ), \
+PXA_MMC_RESPONSE( ctrlr, 2 ), \
+PXA_MMC_RESPONSE( ctrlr, 1 ) );
+#define MMC_DUMP_R3( ctrlr )	MMC_DEBUG( MMC_DEBUG_LEVEL3, \
+"R3 response: %02x %02x%02x%02x%02x\n", \
+PXA_MMC_RESPONSE( ctrlr, 5 ), \
+PXA_MMC_RESPONSE( ctrlr, 4 ), \
+PXA_MMC_RESPONSE( ctrlr, 3 ), \
+PXA_MMC_RESPONSE( ctrlr, 2 ), \
+PXA_MMC_RESPONSE( ctrlr, 1 ) );
+
+#endif
+#endif /* __MMC_PXA_P_H__ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/mmc_test.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,538 @@
+/*
+ *  linux/drivers/mmc/mmc_test.c 
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *	$Id: mmc_test.c,v 0.4 2002/08/01 12:26:40 ted Exp ted $
+ * 
+ *  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/version.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <linux/fs.h>
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#include <mmc/types.h>
+#include <mmc/mmc.h>
+#include <mmc/ioctl.h>
+
+#include "types.h"
+#include "mmc.h"
+
+typedef struct _mmc_test_device_rec mmc_test_device_rec_t;
+typedef struct _mmc_test_device_rec *mmc_test_device_t;
+
+struct _mmc_test_device_rec {
+	mmc_card_t card;
+	mmc_transfer_mode_t transfer_mode;
+	int usage;
+#ifdef CONFIG_DEVFS_FS
+	devfs_handle_t devfs_handle;
+#endif
+};
+
+/* MMC device table */
+static mmc_test_device_rec_t mmc_test_device[MMC_CONTROLLERS_MAX][MMC_CARDS_MAX];
+static DECLARE_MUTEX(mmc_test_device_mutex);
+
+static inline mmc_test_device_t __mmc_test_get_device( kdev_t rdev )
+{
+	mmc_test_device_t ret = NULL;
+	u8 minor = MINOR( rdev );
+	int host_no, card_no;
+
+	host_no = minor >> MMC_MINOR_HOST_SHIFT;
+	if ( host_no >= MMC_CONTROLLERS_MAX )
+		goto error;
+	
+	card_no = minor & MMC_MINOR_CARD_MASK;
+	if ( card_no >= MMC_CARDS_MAX )
+		goto error;
+	
+	ret = &mmc_test_device[host_no][card_no];
+	if ( !ret->card ) {
+		ret->card = mmc_get_card( host_no, card_no );
+		if ( !ret->card ) {
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to get card: host=%d, card=%d\n", host_no, card_no );
+			ret = NULL;
+			goto error;
+		}
+		
+	}
+	++ret->usage;
+	
+error:
+	return ret;
+}
+
+static inline void __mmc_test_put_device( mmc_test_device_t dev )
+{
+	mmc_put_card( dev->card );
+	--dev->usage;
+}
+
+static inline mmc_test_device_t mmc_test_get_device( kdev_t kdev )
+{
+	mmc_test_device_t ret = NULL;
+	
+	down( &mmc_test_device_mutex );
+	ret = __mmc_test_get_device( kdev );
+	up( &mmc_test_device_mutex );
+
+	return ret;
+}
+
+static inline void mmc_test_put_device( mmc_test_device_t dev )
+{
+	if ( dev ) {
+		down( &mmc_test_device_mutex );
+		__mmc_test_put_device( dev );
+		if ( !dev->usage ) {
+			if ( dev->card ) {
+				if ( dev->card->usage ) {
+					MMC_DEBUG( MMC_DEBUG_LEVEL0, 
+						"broken card reference\n" );
+				}
+				memset( dev, 0, sizeof( mmc_test_device_rec_t ) );
+			}
+		}
+		up( &mmc_test_device_mutex );
+	}
+}
+
+static inline int mmc_test_set_transfer_mode( mmc_test_device_t dev, mmc_transfer_mode_t mode )
+{
+	int ret = -1;
+	
+	if ( dev ) {
+		down( &mmc_test_device_mutex );
+		dev->transfer_mode = mode;
+		ret = 0;
+		up( &mmc_test_device_mutex );
+	}
+	return ret;
+}
+
+static inline mmc_transfer_mode_t mmc_test_get_transfer_mode( mmc_test_device_t dev )
+{
+	mmc_transfer_mode_t ret = MMC_TRANSFER_MODE_UNDEFINED;
+	
+	if ( dev ) {
+		down( &mmc_test_device_mutex );
+		ret = dev->transfer_mode;
+		up( &mmc_test_device_mutex );
+	}
+	return ret;
+}
+
+static int mmc_test_open( struct inode *inode, struct file *file )
+{
+	int ret = -ENODEV;
+	mmc_test_device_t dev = NULL;
+	
+	MOD_INC_USE_COUNT;
+	
+	__ENTER0( );	
+	dev = mmc_test_get_device( inode->i_rdev );
+	if ( !dev || !dev->card ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to acquire device\n" );
+		goto error;
+	}
+	
+	if ( dev->card->usage > 1 ) {
+		ret = -EBUSY;
+		goto error;
+	}
+	
+	dev->transfer_mode = MMC_TEST_TRANSFER_MODE_DEFAULT; /* FIXME: should check card CCC */
+	file->private_data = dev;
+	
+	__LEAVE0( );
+	return 0;
+error:
+	MOD_DEC_USE_COUNT;
+	mmc_test_put_device( dev );
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static int mmc_test_release( struct inode *inode, struct file *file )
+{
+	int ret = -ENODEV;
+	mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
+	
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
+		goto error;
+	}
+
+	__ENTER( "host=%d, card=%d", dev->card->ctrlr->slot, dev->card->slot );
+	
+	file->private_data = NULL;
+	
+	mmc_test_put_device( dev );
+	MOD_DEC_USE_COUNT;
+	
+	ret = 0;
+error:	
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static ssize_t mmc_test_read( struct file *file, char *buf, size_t size, loff_t *ppos )
+{
+	ssize_t ret = -ENODEV;
+	ssize_t retsize = 0;
+	mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
+
+	__ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size );
+	
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
+		goto error;
+	}
+	
+	switch ( dev->transfer_mode ) {
+		char *mbuf;
+		
+		case MMC_TRANSFER_MODE_BLOCK_SINGLE:
+			mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual read_bl_len or ctrlr->block_size_max whichever is less ), GFP_KERNEL */
+			if ( !mbuf ) { 
+				ret = -ENOMEM; 
+				goto error; 
+			}
+			
+			while( size > 0 ) {
+				int lsize = (size > 512) ? 512 : size; 
+		
+				MMC_DEBUG( MMC_DEBUG_LEVEL4, 
+						"before mmc_read mbuf=0x%x "
+						"lsize=%d ppos=0x%x *ppos=%d\n",
+						mbuf, lsize, ppos, *ppos );
+				ret = mmc_read( dev->card, 
+						MMC_TRANSFER_MODE_BLOCK_SINGLE,
+						mbuf, lsize, ppos );
+				if ( ret <= 0 )
+					break;
+				
+				/* Copy to user */
+				if ( copy_to_user( buf, mbuf, ret ) ) {
+					ret = -EFAULT;
+					break;
+				}
+				retsize += ret;
+				buf += ret;
+				size -= ret;
+			}
+			
+			if ( retsize > 0 )
+				ret = retsize;
+			kfree(mbuf);
+			break;
+			
+		case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
+			mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */
+			if ( !mbuf ) { 
+				ret = -ENOMEM; 
+				goto error; 
+			}
+			
+			while( size > 0 ) {
+				int lsize = (size > 1024) ? 1024 : size; 
+		
+				MMC_DEBUG( MMC_DEBUG_LEVEL4, 
+						"before mmc_read mbuf=0x%x "
+						"lsize=%d ppos=0x%x *ppos=%d\n",
+						mbuf, lsize, ppos, *ppos );
+				ret = mmc_read( dev->card, 
+					MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
+					mbuf, lsize, ppos );
+				if ( ret <= 0 )
+					break;
+				
+				/* Copy to user */
+				if ( copy_to_user( buf, mbuf, ret ) ) {
+					ret = -EFAULT;
+					break;
+				}
+				retsize += ret;
+				buf += ret;
+				size -= ret;
+			}
+			
+			if ( retsize > 0 )
+				ret = retsize;
+			kfree(mbuf);
+			break;
+			
+		case MMC_TRANSFER_MODE_STREAM:
+			ret = mmc_read( dev->card, dev->transfer_mode,
+					buf, size, ppos );
+			break;
+			
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" );
+	}
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static ssize_t mmc_test_write( struct file *file, const char *buf, size_t size, loff_t *ppos )
+{
+	ssize_t ret = -ENODEV;
+	mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
+	int retsize=0;
+
+	__ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size );
+	
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
+		goto error;
+	}
+	
+	switch ( dev->transfer_mode ) {
+		char *mbuf;
+		
+		case MMC_TRANSFER_MODE_BLOCK_SINGLE:
+			mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual write_bl_len or ctrlr->block_size_max whichever is less, GFP_KERNEL */
+			if ( !mbuf ) { 
+				ret = -ENOMEM; 
+				goto error; 
+			}
+	
+			while ( size > 0 ) {
+				int lsize = ( size > 512 ) ? 512 : size;
+		
+				/* Copy from user */
+				if ( copy_from_user( mbuf, buf, lsize ) ) {
+					ret = -EFAULT;
+					break;
+				}
+				
+				ret = mmc_write( dev->card,
+					MMC_TRANSFER_MODE_BLOCK_SINGLE, 
+					mbuf, lsize, ppos );
+				if( ret <= 0 )
+					break;
+	
+				retsize += ret;
+				buf += ret;
+				size -= ret;
+			}
+			
+			if ( retsize > 0 )
+				ret = retsize;
+			
+			kfree( mbuf );
+			break; 
+			
+		case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
+			mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */
+			if ( !mbuf ) { 
+				ret = -ENOMEM; 
+				goto error; 
+			}
+			
+			while( size > 0 ) {
+				int lsize = (size > 1024) ? 1024 : size; 
+		
+				MMC_DEBUG( MMC_DEBUG_LEVEL4, 
+						"before mmc_read mbuf=0x%x "
+						"lsize=%d ppos=0x%x *ppos=%d\n",
+						mbuf, lsize, ppos, *ppos );
+				ret = mmc_write( dev->card, 
+					MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
+					mbuf, lsize, ppos );
+				if ( ret <= 0 )
+					break;
+				
+				/* Copy to user */
+				if ( copy_to_user( (char *)buf, mbuf, ret ) ) {
+					ret = -EFAULT;
+					break;
+				}
+				retsize += ret;
+				buf += ret;
+				size -= ret;
+			}
+			
+			if ( retsize > 0 )
+				ret = retsize;
+			kfree(mbuf);
+			break;
+		case MMC_TRANSFER_MODE_STREAM:
+			ret = mmc_write( dev->card, dev->transfer_mode,
+					buf, size, ppos );
+			break;
+			
+		default:
+			MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" );
+	}
+error:
+	__LEAVE( "ret=%d", ret );
+	return ret;
+}
+
+static loff_t mmc_test_llseek( struct file *file, loff_t offset, int origin )
+{
+	loff_t ret = -ESPIPE;
+	mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
+	mmc_card_t card;
+	
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
+		ret = -ENODEV;
+		goto error;
+	}
+	
+	__ENTER( "host=%d, card=%d, off=%ld, orig=%d", dev->card->ctrlr->slot, dev->card->slot, (long)offset, origin );
+	
+	card = dev->card;
+	
+	switch ( origin ) {
+		case SEEK_CUR:
+			file->f_pos += offset;
+			break;
+	
+		case SEEK_END:
+			file->f_pos = card->info.capacity + offset;
+			break;
+		
+		case SEEK_SET:
+			file->f_pos = offset;
+			break;
+			
+		default:
+			ret = -EINVAL;
+			goto error;
+	}
+	
+	ret = file->f_pos;
+error:	
+	__LEAVE( "ret=%ld", (long)ret );
+	return ret;
+}
+
+static int mmc_test_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg )
+{
+	int ret = -ENODEV;
+	mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
+
+	if ( !dev ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
+		goto error;
+	}
+	
+	switch ( cmd ) {
+		case IOCMMCSTRNSMODE:
+			if ( get_user( ret, (int *)arg ) ) {
+				ret = -EFAULT;
+				goto error;
+			}
+			ret = mmc_test_set_transfer_mode( dev, ret );
+			break;
+			
+		case IOCMMCGTRNSMODE:
+			ret = mmc_test_get_transfer_mode( dev );
+			if ( put_user( ret, (int *)arg ) ) 
+				ret = -EFAULT;
+			break;
+		
+		default:
+			ret = mmc_ioctl( dev->card, cmd, arg );
+	}
+	
+error:
+	return ret;
+}
+
+struct file_operations mmc_test_fops = {
+	owner:		THIS_MODULE,
+	open:		mmc_test_open,
+	release:	mmc_test_release,
+	read:		mmc_test_read,
+	write:		mmc_test_write,
+	ioctl:		mmc_test_ioctl,
+	llseek:		mmc_test_llseek
+};
+
+#ifdef CONFIG_DEVFS_FS
+static int mmc_test_add_card( mmc_card_t card ) /* TODO */
+{
+	int ret = -1;
+	__ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot );
+/* TODO: make kdev; register with devfs */
+	__LEAVE0( );
+	return ret;
+}
+
+static int mmc_test_remove_card( mmc_card_t card ) /* TODO */
+{
+	int ret = -1;
+	__ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot );
+/* TODO: make kdev; unregister with devfs */
+	__LEAVE0( );
+	return ret;
+}
+
+static mmc_notifier_rec_t mmc_test_notifier = {
+	add:	mmc_test_add_card,
+	remove: mmc_test_remove_card
+};
+#endif /* CONFIG_DEVFS_FS */
+
+static int __init mmc_test_module_init( void )
+{
+	int ret = -ENODEV;
+
+#ifdef CONFIG_DEVFS_FS
+	if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_test_notifier, 0 ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );
+		goto error;
+	}
+#else
+	mmc_register( MMC_REG_TYPE_USER, NULL, 0 );
+	if ( register_chrdev( MMC_TEST_MAJOR, "mmc_test", &mmc_test_fops ) ) {
+		MMC_DEBUG( MMC_DEBUG_LEVEL0, 
+				"failed to request device major number\n" );
+		mmc_unregister( MMC_REG_TYPE_USER, NULL );
+		goto error;
+	}
+#endif
+	
+	memset( mmc_test_device, 0, sizeof( mmc_test_device ) );
+	
+	ret = 0;
+error:
+	return ret;
+}
+
+static void __exit mmc_test_module_cleanup( void )
+{
+#ifdef CONFIG_DEVFS_FS
+	mmc_unregister( MMC_REG_TYPE_USER, &mmc_test_notifier );
+#else
+	mmc_unregister( MMC_REG_TYPE_USER, NULL );
+	unregister_chrdev( MMC_TEST_MAJOR, "mmc_test" );
+#endif
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init( mmc_test_module_init );
+module_exit( mmc_test_module_cleanup );
+
+MODULE_LICENSE("GPL");
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/pm_test.c	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,29 @@
+/* Power Managment Test Module.  RTSoft Co. 2002 */ 
+
+/* The necessary header files */
+
+/* Standard in kernel modules */
+#include <linux/kernel.h>   /* We're doing kernel work */
+#include <linux/module.h>   /* Specifically, a module */
+#define CONFIG_PM
+#include <linux/pm.h>
+
+
+static int pmdata = -1;
+
+/* Initialize the module - register the proc file  */
+
+int init_module()
+{
+  pm_send_all(PM_SUSPEND,&pmdata);    
+  return(0);
+}
+
+
+/* Cleanup - unregister our file from /proc */
+void cleanup_module()
+{
+  pm_send_all(PM_RESUME,NULL);
+}
+
+MODULE_LICENSE( "GPL" );
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/mmc/types.h	2004-03-31 17:15:11.000000000 +0200
@@ -0,0 +1,59 @@
+/*
+ *  linux/drivers/mmc/types.h
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  $Id: types.h,v 0.5 2002/08/13 17:34:02 ted Exp ted $
+ *
+ *  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 __MMC_TYPES_P_H__
+#define __MMC_TYPES_P_H__
+
+#ifdef __KERNEL__
+#include <linux/kdev_t.h>
+
+typedef enum _mmc_reg_type mmc_reg_type_t;
+typedef enum _mmc_response mmc_response_fmt_t;
+
+/* MMC card private description */
+typedef struct _mmc_card_rec mmc_card_rec_t;
+typedef struct _mmc_card_rec *mmc_card_t;
+typedef enum _mmc_dir mmc_dir_t;
+typedef enum _mmc_buftype mmc_buftype_t;
+
+/* notifier declarations */
+typedef struct _mmc_notifier_rec mmc_notifier_rec_t;
+typedef struct _mmc_notifier_rec *mmc_notifier_t;
+
+typedef int (*mmc_notifier_fn_t) ( mmc_card_t );
+
+/* MMC card stack */
+typedef struct _mmc_card_stack_rec mmc_card_stack_rec_t;
+typedef struct _mmc_card_stack_rec *mmc_card_stack_t;
+
+typedef struct _mmc_data_transfer_req_rec mmc_data_transfer_req_rec_t;
+typedef struct _mmc_data_transfer_req_rec *mmc_data_transfer_req_t;
+
+/* MMC controller */
+typedef struct _mmc_controller_tmpl_rec mmc_controller_tmpl_rec_t;
+typedef struct _mmc_controller_tmpl_rec *mmc_controller_tmpl_t;
+
+typedef enum _mmc_controller_state mmc_controller_state_t;
+typedef struct _mmc_controller_rec mmc_controller_rec_t;
+typedef struct _mmc_controller_rec *mmc_controller_t;
+
+/* various kernel types */
+typedef struct semaphore semaphore_t;
+typedef struct rw_semaphore rwsemaphore_t;
+typedef struct proc_dir_entry proc_dir_entry_rec_t;
+typedef struct proc_dir_entry *proc_dir_entry_t;
+typedef struct gendisk gendisk_rec_t;
+typedef struct gendisk *gendisk_t;
+#endif /* __KERNEL__ */
+
+#endif /* __MMC_TYPES_P_H__ */
+
--- linux-2.4.25/drivers/net/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/net/Config.in	2004-03-31 17:15:11.000000000 +0200
@@ -125,6 +125,7 @@
       dep_tristate '    SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA
       dep_tristate '    SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA
       dep_tristate '    SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA
+      tristate     '    SMC 91C9x/91C1xx support' CONFIG_SMC91X
    fi
    bool '  Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL
    if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then
--- linux-2.4.25/drivers/net/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/net/Makefile	2004-03-31 17:15:11.000000000 +0200
@@ -137,6 +137,7 @@
 obj-$(CONFIG_SK_G16) += sk_g16.o
 obj-$(CONFIG_HP100) += hp100.o
 obj-$(CONFIG_SMC9194) += smc9194.o
+obj-$(CONFIG_SMC91X) += smc91x.o
 obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
 obj-$(CONFIG_ARM_ETHERH) += 8390.o
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
--- linux-2.4.25/drivers/net/cirrus.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/net/cirrus.c	2004-03-31 17:15:11.000000000 +0200
@@ -67,6 +67,9 @@
 #elif CONFIG_ARCH_CDB89712
 #	define CIRRUS_DEFAULT_IO ETHER_BASE + 0x300
 #	define CIRRUS_DEFAULT_IRQ IRQ_EINT3
+#elif CONFIG_ARCH_CSB226
+#	define CIRRUS_DEFAULT_IO 0xF8000000
+#	define CIRRUS_DEFAULT_IRQ IRQ_GPIO(14) 
 #else
 #	define CIRRUS_DEFAULT_IO	0
 #	define CIRRUS_DEFAULT_IRQ	0
--- linux-2.4.25/drivers/net/irda/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/net/irda/Config.in	2004-03-31 17:15:11.000000000 +0200
@@ -42,5 +42,7 @@
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
 fi
-
+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
+   dep_tristate 'Intel PXA2xx Internal IR' CONFIG_PXA_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL        
+fi
 endmenu
--- linux-2.4.25/drivers/net/irda/Makefile~2.4.25-vrs2-pxa1.patch	2004-02-18 14:36:31.000000000 +0100
+++ linux-2.4.25/drivers/net/irda/Makefile	2004-03-31 17:15:12.000000000 +0200
@@ -16,6 +16,7 @@
 obj-$(CONFIG_USB_IRDA)		+= irda-usb.o
 obj-$(CONFIG_NSC_FIR)		+= nsc-ircc.o
 obj-$(CONFIG_WINBOND_FIR)	+= w83977af_ir.o
+obj-$(CONFIG_PXA_FIR)		+= pxa_ir.o
 obj-$(CONFIG_SA1100_FIR)	+= sa1100_ir.o
 obj-$(CONFIG_TOSHIBA_OLD)	+= toshoboe.o
 obj-$(CONFIG_TOSHIBA_FIR)	+= donauboe.o
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/net/irda/pxa_ir.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,1545 @@
+/*
+ *  linux/drivers/net/irda/pxa_ir.c
+ *
+ *  Author:
+ *  Alexey Lugovskoy RTSoft. 
+ *	lugovskoy@rtsoft.msk.ru
+ *
+ *  Dmitrij Frasenyak RTSoft. 
+ *      sed@mipt.sw.ru
+ *
+ * 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.
+ *
+ *  Infra-red SIR and FIR driver for the PXA 210/250 embedded microprocessors
+ *  Based on linux/drivers/net/irda/sa1100_ir.c
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+
+#include <linux/pm.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/lubbock.h>
+
+
+static int rx_count = 0;
+static int tx_count = 0;
+
+/*
+ * Our netdevice.  There is only ever one of these.
+ */
+ 
+static struct net_device *netdev;
+
+struct pxa250_irda {
+	
+	unsigned char		open;
+
+	int			speed;
+	int			newspeed;
+
+	struct sk_buff		*txskb;
+	struct sk_buff		*rxskb;
+	
+
+	/* => FIR */
+	unsigned int		fir_irq;
+	int			txdma_ch;
+	int			rxdma_ch;
+	dma_addr_t		txbuf_dma;
+	dma_addr_t		rxbuf_dma;
+	void* 			txbuf_dma_virt;
+	void* 			rxbuf_dma_virt;
+	/* <= FIR*/
+	struct net_device_stats	stats;
+	struct irlap_cb		*irlap;
+	struct pm_dev		*pmdev;
+	struct qos_info		qos;
+
+	/* => SIR */
+	iobuff_t		tx_buff;
+	iobuff_t		rx_buff;
+	/* <= SIR */
+};
+
+#define IS_FIR(si)		((si)->speed >= 4000000)
+
+#define HPSIR_MAX_RXLEN		2050
+#define HPSIR_MAX_TXLEN		2050
+#define TXBUFF_MAX_SIZE		HPSIR_MAX_TXLEN
+#define SET_SIR_MODE            STISR = STISR_RCVEIR | STISR_XMITIR | STISR_XMODE
+
+/*
+ * If you want to disable debug information
+ * please uncomment line bellow
+ */
+
+#define PXA_FIR_DUMP_ENABLE
+#undef PXA_FIR_DUMP_ENABLE     
+
+
+#define PXA_FIR_DEBUG_ENABLE
+#undef PXA_FIR_DEBUG_ENABLE              
+
+#define PXA_FIR_IRQ_DEBUG_ENABLE
+#undef PXA_FIR_IRQ_DEBUG_ENABLE               
+
+#ifdef PXA_FIR_DEBUG_ENABLE
+#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__);
+#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__);
+#define DBG(args...) printk(KERN_ERR __FUNCTION__"():"args);
+#else
+#define __ECHO_IN
+#define __ECHO_OUT
+#define DBG(args...)
+#endif
+
+#ifdef PXA_FIR_IRQ_DEBUG_ENABLE
+#define DBG_IRQ(args...) printk(KERN_ERR __FUNCTION__"():"args);
+#else
+#define DBG_IRQ(args...)
+#endif
+
+
+static int pxa250_irda_set_speed(struct net_device *dev,int speed);
+static void pxa250_start_rx_dma(struct net_device *dev);
+
+
+
+/**************************************************************************
+ *			Misc FIR/SIR functions				  *
+ **************************************************************************/
+/*
+ * Allocate the receive buffer, unless it is already allocated.
+ */
+
+static int pxa250_irda_rx_alloc(struct pxa250_irda *si)
+{
+   __ECHO_IN;
+   
+   if (si->rxskb)
+      return 0;
+
+   si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
+
+   if (!si->rxskb) {
+      printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");
+      return -ENOMEM;
+   }
+
+   /*
+    * Align any IP headers that may be contained
+    * within the frame.
+    */
+   skb_reserve(si->rxskb, 1);
+
+   __ECHO_OUT;
+
+   return 0;
+}
+
+
+
+/**************************************************************************
+ *			FIR						  *
+ **************************************************************************/
+
+
+
+
+static inline void pxa250_dma_stop(int ch)
+{
+   __ECHO_IN;
+
+   DCSR(ch) &= ~DCSR_RUN;
+
+   __ECHO_OUT;
+   
+}
+
+
+static void pxa250_ficp_rx_start(void)
+{
+   ICCR0 = 0;
+   ICCR2 =  1 << 2 | 0 << 3 ; 
+   ICCR0 = ICCR0_ITR ;
+   ICCR0 |= ICCR0_RIE |  ICCR0_RXE ; 
+}
+
+/*
+ * Change Alternative Function encoding
+ * Enable ICP unit
+ * Disabe STUART unit
+ * Enable IRQ unit clock;
+ * Configure direction of GPIO used by ICP
+ */
+
+
+static void pxa250_do_fir_GPIO_config(void)
+{
+   /*
+    * Modify GPIO 46 and 47 Alternate Function 
+    */
+
+   __ECHO_IN;
+
+   /*Switch AF*/
+   set_GPIO_mode (GPIO46_ICPRXD_MD);
+   set_GPIO_mode (GPIO47_ICPTXD_MD);
+
+   if (machine_is_lubbock())
+      LUB_MISC_WR |= 1 << 4;
+
+   /*init clock*/
+   CKEN |= CKEN13_FICP;
+
+   __ECHO_OUT;
+}
+
+/*
+ * Low level hardware configuration and startup.
+ */
+
+static int pxa250_fir_irda_startup(struct pxa250_irda *si)
+{
+
+	__ECHO_IN;
+
+	/*
+	 * Disable STUART
+	 */
+
+	STIER &= ~IER_UUE;
+
+	/*Disable STUART FIFO */
+	STFCR = 0;
+
+	/*
+	 * Do low level configuration for HW AF and clock
+	 */
+	pxa250_do_fir_GPIO_config();
+
+	__ECHO_OUT;
+	return 0;
+}
+
+
+/*
+ * Aieeeeee .. we should never get here :(
+ */
+static void pxa250_irda_rxdma_irq(int ch,void *id, struct pt_regs *regs)
+{
+   struct net_device *dev=id;
+   struct pxa250_irda *si=dev->priv;
+   u_int dcsr;
+
+
+   __ECHO_IN;
+
+   /* 
+    * Make sure that irq is our.
+    */
+
+   if ( ch != si->rxdma_ch )
+      /*just*/ return;
+
+   /*
+    * Check status 
+    */
+   dcsr = DCSR(ch);
+
+   DBG("DCSR=%x\n",dcsr);
+
+   if (dcsr &  DCSR_STOPSTATE )
+   {
+      DBG_IRQ("Chanel %d in stop state\n",ch);
+   }
+
+   if (dcsr &  DCSR_BUSERR )
+   {
+      /*
+       * BUS Error we must restart reception
+       */
+      
+      DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
+      DCSR(ch) |= DCSR_BUSERR;
+   }
+
+   if (dcsr &  DCSR_ENDINTR )
+   {
+      DBG("PXA IrDA: Normal end of dma channel %d - packet to big\n", ch);
+      DCSR(ch) |= DCSR_ENDINTR;
+   }
+
+   /* no mater what restart rx*/
+   pxa250_start_rx_dma(dev);
+   
+   return ;
+   
+}
+
+
+static void pxa250_irda_txdma_irq(int ch, void *id , struct pt_regs *regs)
+{
+   struct net_device *dev=id;
+   struct pxa250_irda *si=dev->priv;
+   struct sk_buff *skb = si->txskb;
+   u_int dcsr;
+
+
+   __ECHO_IN;
+   DBG_IRQ("transmit\n"); 
+   
+     
+   /* 
+    * Make sure that irq is our.
+    */
+
+   if ( ch != si->txdma_ch )
+      /*just*/ return;
+
+
+   /*
+    * Check status 
+    */
+   dcsr = DCSR(ch);
+
+   DBG("DCSR=%x",dcsr);
+
+   if (dcsr &  DCSR_STOPSTATE )
+   {
+      DBG("Chanel %d in stop state\n",ch);
+   }
+
+   if (dcsr &  DCSR_BUSERR )
+   {
+      DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
+      DCSR(ch) |= DCSR_BUSERR;
+      si->txskb = NULL;
+   }
+
+   if (dcsr &  DCSR_ENDINTR )
+   {
+      DBG("PXA IrDA: Normal end of dma channel %d\n", ch);
+      DCSR(ch) |= DCSR_ENDINTR;
+      si->txskb = NULL;
+   }
+
+   /*
+    * Account and free the packet.
+    */
+   if (skb)
+   {
+      si->stats.tx_packets ++;
+      si->stats.tx_bytes += skb->len;
+      dev_kfree_skb_irq(skb);
+   }
+
+	/*Disable transceiver and enable receiver*/
+
+	if (si->newspeed) {
+	   pxa250_irda_set_speed(dev, si->newspeed);
+	   si->newspeed = 0;
+	}
+
+	while (ICSR1 & ICSR1_TBY)
+	   udelay(1);
+	
+     	ICCR0 &= ~ICCR0_TXE;
+
+	
+	enable_irq(si->fir_irq);
+
+  	ICCR0 |= ICCR0_RXE; 
+
+	/*
+	 * Make sure that the TX queue is available for sending
+	 * (for retries).  TX has priority over RX at all times.
+	 */
+	netif_wake_queue(dev);
+	
+	__ECHO_OUT;
+}
+
+
+static void pxa250_start_rx_dma(struct net_device *dev)
+{
+   struct pxa250_irda *si = dev->priv;
+   int ch=si->rxdma_ch;
+
+   if (!si->rxskb) {
+      DBG("rx buffer went missing\n");
+/*        return; */
+   }
+
+   DCSR(ch)=0;
+   DCSR(ch)=DCSR_NODESC;
+   DSADR(ch) = __PREG(ICDR);
+   DTADR(ch) = si->rxbuf_dma; /* phisical address */;
+
+   /* We should never do END_IRQ.  !!!*/
+   DCMD(ch) = DCMD_ENDIRQEN| DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | HPSIR_MAX_RXLEN;
+
+   /*
+    * All right information will be available as soon as we set RXE flag
+    */
+   
+   DCSR(ch) = DCSR_ENDINTR | DCSR_BUSERR;
+   DCSR(ch) = DCSR_RUN | DCSR_NODESC ;
+
+}
+
+
+
+
+static int pxa250_get_rx_len(struct pxa250_irda *si)
+{
+   /*
+    * DMA have to be stoped here
+    */
+
+   if ( ! (DCSR(si->rxdma_ch) & DCSR_STOPSTATE) )
+      printk("warning dma have to be stoped befor counting len\n");
+   
+   return ( HPSIR_MAX_RXLEN - ( DCMD(si->rxdma_ch) & DCMD_LENGTH ) );
+   
+}
+
+static void pxa250_irda_fir_error(struct net_device *dev)
+{
+   struct pxa250_irda *si = dev->priv;
+   struct sk_buff *skb = si->rxskb;
+   int len;
+   int stat,data;
+
+   __ECHO_IN;
+   
+      if (!skb)
+      {
+	 printk("pxa250 fir_error: SKB is NULL!\n");
+	 return;
+      }
+
+      /*
+       * Get the current data position.
+       */
+
+      len=pxa250_get_rx_len(si);
+      DBG("RXLEN=%d\n",len);
+      memcpy(skb->data, si->rxbuf_dma_virt, len);
+
+      do {
+	 /*
+	  * Read Status, and then Data.
+	  */
+	   stat = ICSR1;
+	   rmb();
+	   data = ICDR;
+	   if (stat & (ICSR1_CRE | ICSR1_ROR)) {
+	      si->stats.rx_errors++;
+	      if (stat & ICSR1_CRE)
+		 si->stats.rx_crc_errors++;
+	      if (stat & ICSR1_ROR)
+		 si->stats.rx_frame_errors++;
+	   } else
+	      skb->data[len++] = data;
+
+		/*
+		 * If we hit the end of frame, there's
+		 * no point in continuing.
+		 */
+	   if (stat & ICSR1_EOF)
+	      break;
+	} while (ICSR0 & ICSR0_EIF);
+
+	if (stat & ICSR1_EOF) {
+	   si->rxskb = NULL;
+
+	   skb_put(skb, len);
+	   skb->dev = dev;
+	   skb->mac.raw = skb->data;
+	   skb->protocol = htons(ETH_P_IRDA);
+	   si->stats.rx_packets++;
+	   si->stats.rx_bytes += len;
+
+	   /*
+	    * Before we pass the buffer up, allocate a new one.
+	    */
+
+	   si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
+
+	   if (!si->rxskb) {
+	      printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");
+	      return;
+	   }
+
+	   /*
+	    * Align any IP headers that may be contained
+	    * within the frame.
+	    */
+	   skb_reserve(si->rxskb, 1);
+
+	   netif_rx(skb);
+	}
+}
+
+/*
+ * FIR format interrupt service routine.  We only have to
+ * handle RX events; transmit events go via the TX DMA irq handler.
+ *
+ * No matter what, we disable RX, process, and then restart RX.
+ */
+
+static void pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+   struct net_device *dev = dev_id;
+   struct pxa250_irda *si = dev->priv;
+   int status;
+   
+   /*
+    * Stop RX
+    */
+
+   __ECHO_IN;
+
+   pxa250_dma_stop(si->rxdma_ch);
+
+   
+   /*
+    * Framing error - we throw away the packet completely.
+    * Clearing RXE flushes the error conditions and data
+    * from the fifo.
+    */
+   status=ICSR0;
+   
+   if (status & (ICSR0_FRE | ICSR0_RAB)) {
+      DBG_IRQ("Framing error or RAB\n"); 
+      
+      si->stats.rx_errors++;
+
+      if (ICSR0 & ICSR0_FRE)
+	 si->stats.rx_frame_errors++;
+
+      /* Clear RX fifo
+       * DMA will be cleared when we restart RX
+       * Should we check RNE after that? 
+       */
+
+      ICCR0 &= ~ICCR0_RXE;
+      
+      /*
+       * Clear selected status bits now, so we
+       * don't miss them next time around.
+       */
+      ICSR0 = status & (ICSR0_FRE | ICSR0_RAB);
+   }
+
+   
+   /*
+    * Deal with any receive errors.  The any of the lowest
+    * 8 bytes in the FIFO may contain an error.  We must read
+    * them one by one.  The "error" could even be the end of
+    * packet!
+    */
+   if (ICSR0 & ICSR0_EIF)
+      pxa250_irda_fir_error(dev);
+
+   /*
+    * No matter what happens, we must restart reception.
+    */
+
+   ICCR0 = 0;
+   pxa250_start_rx_dma(dev);
+   pxa250_ficp_rx_start();
+   __ECHO_OUT;
+}
+
+
+
+
+
+/**************************************************************************
+ *			SIR 						  *
+ **************************************************************************/
+/*
+ * HP-SIR format interrupt service routines.
+ */
+static void pxa250_sir_transmit(struct net_device *dev)
+{
+   struct pxa250_irda *si = dev->priv;
+   
+   if (si->tx_buff.len) 
+   {
+	/* Disable receiver and  enable transmiter*/
+
+      
+      
+		STISR &= ~STISR_RCVEIR; 
+//	        STISR |= STISR_XMITIR;
+
+				
+		
+                disable_irq(dev->irq);
+		
+		do 
+		{
+
+		   if (STLSR & LSR_TDRQ)
+		   {
+		      STTHR = *si->tx_buff.data++;
+		      si->tx_buff.len -= 1;
+ 
+		      tx_count++;
+		   }
+		   
+				         
+		} while (si->tx_buff.len);
+
+				
+		if (si->tx_buff.len == 0) 
+		{
+		   
+		   
+			si->stats.tx_packets++;
+			si->stats.tx_bytes += si->tx_buff.data -
+					      si->tx_buff.head;
+
+			/*
+			 * We need to ensure that the transmitter has
+			 * finished.
+			 */
+			
+		        do
+			{
+			   udelay(1);
+			   
+            		}				
+			while ( ! (STLSR & LSR_TEMT) );
+                       
+						
+			/*
+
+			 * Ok, we've finished transmitting.  Now enable
+			 * the receiver.  Sometimes we get a receive IRQ
+			 * immediately after a transmit...
+			 */
+
+			if (si->newspeed)
+			{
+				pxa250_irda_set_speed(dev, si->newspeed);
+				si->newspeed = 0;
+			}
+
+			/* I'm hungry! */
+			netif_wake_queue(dev);
+		}
+		
+		enable_irq (dev->irq);
+                STIER = (IER_RAVIE | IER_UUE | IER_RTIOE);
+
+		STISR |= STISR_RCVEIR;
+//		STISR &= ~STISR_XMITIR;
+   }
+}
+
+static void pxa250_irda_hpsir_irq(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+
+	/*
+	 * Deal with any receive errors first.  The bytes in error may be
+	 * the only bytes in the receive FIFO, so we do this first.
+	 */
+  	__ECHO_IN; 
+	
+	while (STLSR & LSR_FIFOE)
+	{
+		int stat, data;
+
+		stat = STLSR; 
+		data = STRBR;
+               
+		
+                if (stat & (LSR_FE | LSR_OE | LSR_PE)) 
+		
+		{
+		        si->stats.rx_errors++;
+			if (stat & LSR_FE) 
+				si->stats.rx_frame_errors++;
+			if (stat & LSR_OE) 
+				si->stats.rx_fifo_errors++;
+			
+		} else
+		{
+		   rx_count++;
+		   async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+                }
+		
+	}
+
+	/*
+	 * We must clear certain bits.
+	 */
+	 
+	if (STLSR & (LSR_DR)) 
+	{
+		/*
+		 * Fifo contains at least 1 character.
+		 */
+		do
+		{
+		   int data;
+		   
+		   data = STRBR;
+		   
+		   async_unwrap_char(dev, &si->stats, &si->rx_buff,
+					  data); /* was Ser2UTDR); Clo */
+		   rx_count++;
+		   
+		} while (STLSR & LSR_DR); 
+		
+		dev->last_rx = jiffies;
+	}
+
+  	__ECHO_OUT; 
+}
+
+static void pxa250_sir_irda_shutdown(struct pxa250_irda *si)
+{
+
+   STIER = 0;
+   STFCR = 0;
+   STISR = 0;
+   CKEN &= ~CKEN5_STUART; 
+}
+
+
+/************************************************************************************/
+
+/*Low level init/uninstall function PM control and IrDA protocol stack registration */
+
+/*
+ * Set the IrDA communications speed.
+ * Interrupt have to be disabled here.
+ */
+
+static int pxa250_irda_startup(struct net_device *dev)
+{
+   
+
+   __ECHO_IN;
+
+   /*
+    * Ensure that the ports for this device are setup correctly.
+    */
+
+
+   set_GPIO_mode (GPIO46_STRXD_MD);
+   set_GPIO_mode (GPIO47_STTXD_MD);
+
+   STMCR = MCR_OUT2;
+   STLCR = LCR_WLS1 | LCR_WLS0;
+
+   SET_SIR_MODE;
+   CKEN |= CKEN5_STUART;
+   /* enable irq from stuart */
+   ICMR |= ( 1 << 20 );
+	
+   /*reset FIFO*/
+		
+/*	STFCR = FCR_TRFIFOE |  FCR_RESETTF | FCR_RESETRF;// | FCR_ITL_16;
+
+	STIER = IER_UUE | IER_RAVIE | IER_RTOIE;
+*/	
+   __ECHO_OUT;
+
+   return 0;
+	
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * Suspend the IrDA interface.
+ */
+
+static int pxa250_irda_shutdown(struct pxa250_irda *si)
+{
+
+   pxa250_sir_irda_shutdown(si);
+   return 0;
+   
+}
+
+
+static int pxa250_irda_suspend(struct net_device *dev, int state)
+{
+	struct pxa250_irda *si = dev->priv;
+
+	if (si && si->open) {
+	   /*
+	    * Stop the transmit queue
+	    */
+	   if (IS_FIR(si))
+	      return -1;
+
+	   netif_stop_queue(dev);
+	   disable_irq(dev->irq);
+	   disable_irq(si->fir_irq);
+	   pxa250_sir_irda_shutdown(si);
+	}
+
+	return 0;
+}
+
+/*
+ * Resume the IrDA interface.
+ */
+
+static int pxa250_irda_resume(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+
+	__ECHO_IN;
+	
+	if (si && si->open) {
+		/*
+		 * If we missed a speed change, initialise at the new speed
+		 * directly.  It is debatable whether this is actually
+		 * required, but in the interests of continuing from where
+		 * we left off it is desireable.  The converse argument is
+		 * that we should re-negotiate at 9600 baud again.
+		 */
+		if (si->newspeed) {
+			si->speed = si->newspeed;
+			si->newspeed = 0;
+		}
+
+		pxa250_irda_startup(dev);
+		enable_irq(dev->irq);
+
+		/*
+		 * This automatically wakes up the queue
+		 */
+		netif_wake_queue(dev);
+		pxa250_irda_set_speed(dev,si->speed = 9600);
+		
+	}
+
+	__ECHO_OUT;
+	return 0;
+}
+
+static int pxa250_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	int ret;
+
+	
+	if (!dev->data)
+		return -EINVAL;
+
+
+	switch (rqst) {
+	case PM_SUSPEND:
+		ret = pxa250_irda_suspend((struct net_device *)dev->data,
+					  (int)data);
+		break;
+
+	case PM_RESUME:
+		ret = pxa250_irda_resume((struct net_device *)dev->data);
+		break;
+
+	default:
+
+	   ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+#endif
+
+
+
+
+static void pxa250_irda_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	
+	pxa250_irda_hpsir_irq(dev);
+	
+}
+
+
+static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+	int speed = irda_get_next_speed(skb);
+	int mtt;
+	
+  	__ECHO_IN; 
+
+	/*
+	 * Does this packet contain a request to change the interface
+	 * speed?  If so, remember it until we complete the transmission
+	 * of this frame.
+	 */
+	if (speed != si->speed && speed != -1)
+		si->newspeed = speed;
+
+	/*
+	 * If this is an empty frame, we can bypass a lot.
+	 */
+	if (skb->len == 0) {
+		if (si->newspeed) {
+			si->newspeed = 0;
+			pxa250_irda_set_speed(dev, speed);
+		}
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+
+  	DBG("stop queue\n"); 
+	netif_stop_queue(dev);
+
+	if(!IS_FIR(si))
+	{
+	   
+	   si->tx_buff.data = si->tx_buff.head;
+	   si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data,
+						  si->tx_buff.truesize);
+
+        
+	   pxa250_sir_transmit(dev);
+
+	
+	
+	   dev_kfree_skb(skb);
+
+	   dev->trans_start = jiffies;
+
+	   return 0;
+	}
+	else /* FIR */
+	{
+	   DBG("Enter FIR transmit\n");
+	   /*
+	    * We must not be transmitting...
+	    */
+	   if (si->txskb)
+	      BUG();
+
+      	   disable_irq(si->fir_irq); 
+	   
+	   netif_stop_queue(dev);
+	   DBG("queue stoped\n");
+	   si->txskb = skb;
+
+	   /* we could not just map so we'll need some triks */
+	   /* skb->data may be not DMA capable -Sed- */
+
+
+	   if (skb->len > TXBUFF_MAX_SIZE)
+	   {
+	      printk (KERN_ERR "skb data too large\n");
+	      printk (KERN_ERR "len=%d",skb->len);
+	      BUG();
+	   }
+		
+
+	   DBG("gonna copy %d bytes to txbuf\n",skb->len);
+
+	   memcpy (si->txbuf_dma_virt, skb->data , skb->len);
+	   
+	   /* Actual sending ;must not be receiving !!! */
+	   /* Write data and source address */
+
+	   DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 );
+
+	   /*Disable receiver and enable transifer */
+  	   ICCR0 &= ~ICCR0_RXE;      
+	   
+	   if (ICSR1 & ICSR1_TBY)
+	      BUG();
+
+    	   ICCR0 |= ICCR0_TXE;  
+		
+	   DBG("FICP status %x\n",ICSR0);
+
+	   if (0){
+	      int i;
+		   
+	      DBG("sending packet\n");
+	      for (i=0;i<skb->len;i++)
+		 (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ;
+	      DBG(" done\n");
+   
+	   }
+	   /*
+	    * If we have a mean turn-around time, impose the specified
+	    * specified delay.  We could shorten this by timing from
+	    * the point we received the packet.
+	    */
+	   
+	   mtt = irda_get_mtt(skb); 
+	   if(mtt)    
+	      udelay(mtt);    
+	   
+	   DCSR(si->txdma_ch)=0;
+	   DCSR(si->txdma_ch)=DCSR_NODESC;
+	   DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */
+	   DTADR(si->txdma_ch) = __PREG(ICDR);
+		
+	   DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len;
+
+	   DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR;
+	   DCSR(si->txdma_ch) = DCSR_RUN | DCSR_NODESC ;
+
+	   DBG("FICP status %x\n",ICSR0);
+
+	   return 0;
+	}
+	
+}
+
+static int
+pxa250_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+	struct pxa250_irda *si = dev->priv;
+	int ret = -EOPNOTSUPP;
+
+	__ECHO_IN;
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH:
+		if (capable(CAP_NET_ADMIN)) {
+			/*
+			 * We are unable to set the speed if the
+			 * device is not running.
+			 */
+			if (si->open) {
+				ret = pxa250_irda_set_speed(dev,
+						rq->ifr_baudrate);
+			} else {
+				printk("pxa250_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");
+				ret = 0;
+			}
+		}
+		break;
+
+	case SIOCSMEDIABUSY:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			irda_device_set_media_busy(dev, TRUE);
+			ret = 0;
+		}
+		break;
+
+	case SIOCGRECEIVING:
+		rq->ifr_receiving = IS_FIR(si) ? 0
+					: si->rx_buff.state != OUTSIDE_FRAME;
+		break;
+
+	default:
+		break;
+	}
+
+	__ECHO_OUT;
+
+	return ret;
+}
+
+static struct net_device_stats *pxa250_irda_stats(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+	return &si->stats;
+}
+
+static int pxa250_irda_start(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+	int err;
+	unsigned int flags;
+	
+
+	MOD_INC_USE_COUNT;
+
+	__ECHO_IN;
+	si->speed = 9600;
+
+	local_irq_save(flags);
+	
+	err = request_irq(si->fir_irq, pxa250_irda_fir_irq, 0,  dev->name, dev);
+	if (err)
+		goto err_fir_irq;
+
+	err = request_irq(dev->irq, pxa250_irda_irq, 0, dev->name, dev);
+	if (err)
+		goto err_irq;
+
+	/*
+	 * The interrupt must remain disabled for now.
+	 */
+	
+	disable_irq(dev->irq);
+  	disable_irq(si->fir_irq);
+
+	local_irq_restore(flags);
+
+
+	/* Allocate DMA channel for receiver (not used) */
+	err = pxa_request_dma("IrDA receive", DMA_PRIO_LOW, pxa250_irda_rxdma_irq, dev);
+	if (err < 0 )
+	   goto err_rx_dma;
+	si->rxdma_ch=err;
+
+	DRCMRRXICDR = DRCMR_MAPVLD | si->rxdma_ch;
+	
+
+	/* Allocate DMA channel for transmit */
+	err = pxa_request_dma("IrDA transmit", DMA_PRIO_LOW, pxa250_irda_txdma_irq , dev);
+	if (err < 0 )
+	   goto err_tx_dma;
+
+	si->txdma_ch=err;
+
+	/*
+	 * Make sure that ICP will be able 
+	 * to assert the transmit dma request bit
+	 * through the peripherals request bus (PREQ)
+	 */
+	
+	DRCMRTXICDR = DRCMR_MAPVLD | si->txdma_ch;
+
+	DBG("rx(not used) channel=%d tx channel=%d\n",si->rxdma_ch,si->txdma_ch);
+	
+	/* allocate consistent buffers for dma access
+	 * buffers have to be aligned and situated in dma capable memory region;
+	 */
+	si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma);
+	if (! si->rxbuf_dma_virt )
+		goto err_rxbuf_dma;
+
+	si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN,  &si->txbuf_dma); 
+	if (! si->txbuf_dma_virt )
+		goto err_txbuf_dma;
+
+	/* Alocate skb for receiver */
+	err=pxa250_irda_rx_alloc(si);
+	if (err)
+	   goto err_rx_alloc;
+	
+	/*
+	 * Setup the serial port for the specified config.
+	 */
+	err = pxa250_irda_startup(dev);
+	if (err)
+		goto err_startup;
+
+	pxa250_irda_set_speed(dev,si->speed = 9600);
+
+
+	/*
+	 * Open a new IrLAP layer instance.
+	 */
+	si->irlap = irlap_open(dev, &si->qos, "pxa250");
+	err = -ENOMEM;
+	if (!si->irlap)
+		goto err_irlap;
+
+	/*
+	 * Now enable the interrupt and start the queue
+	 */
+	si->open = 1;
+	enable_irq(dev->irq);
+	netif_start_queue(dev);
+	return 0;
+
+err_irlap:
+	si->open = 0;
+	pxa250_sir_irda_shutdown(si);
+err_startup:
+	dev_kfree_skb(si->rxskb);
+err_rx_alloc:	
+	consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
+err_txbuf_dma:
+	consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
+err_rxbuf_dma:
+	pxa_free_dma(si->txdma_ch);
+err_tx_dma:
+	pxa_free_dma(si->rxdma_ch);
+err_rx_dma:
+	free_irq(dev->irq, dev);
+err_irq:
+	free_irq(si->fir_irq, dev);
+err_fir_irq:	
+	MOD_DEC_USE_COUNT;
+	return err;
+}
+
+static int pxa250_irda_stop(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+	
+	printk(KERN_ERR "Irda stop... RX = %d TX = %d\n",rx_count,tx_count);
+
+	disable_irq(dev->irq);
+  	disable_irq(si->fir_irq); 
+/*  	pxa250_irda_shutdown(si); */
+
+	/*
+	 * If we have been doing DMA receive, make sure we
+	 * tidy that up cleanly.
+	 */
+	if (si->rxskb) {
+	        dev_kfree_skb(si->rxskb);
+		si->rxskb = NULL;
+	}
+
+	/* Stop IrLAP */
+	if (si->irlap) {
+		irlap_close(si->irlap);
+		si->irlap = NULL;
+	}
+
+	consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
+	consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
+	pxa_free_dma(si->txdma_ch);
+	pxa_free_dma(si->rxdma_ch);
+
+	netif_stop_queue(dev);
+	si->open = 0;
+
+	/*
+	 * Free resources
+	 */
+	free_irq(dev->irq, dev);
+	free_irq(si->fir_irq, dev);
+
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static int pxa250_irda_init_iobuf(iobuff_t *io, int size)
+{
+	io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
+	if (io->head != NULL) {
+		io->truesize = size;
+		io->in_frame = FALSE;
+		io->state    = OUTSIDE_FRAME;
+		io->data     = io->head;
+	}
+	return io->head ? 0 : -ENOMEM;
+}
+
+
+
+
+static int pxa250_stop_fir(struct net_device *dev)
+{
+   struct pxa250_irda *si = dev->priv;
+   unsigned int flag;
+
+   save_flags(flag);
+   cli();
+   
+   pxa250_dma_stop(si->txdma_ch);
+   pxa250_dma_stop(si->rxdma_ch);
+
+   if (si->txskb)
+      dev_kfree_skb_irq(si->txskb);
+
+   ICCR0 &= ~(ICCR0_RXE | ICCR0_TXE );
+   disable_irq(si->fir_irq);
+   CKEN &= ~CKEN13_FICP;
+
+   restore_flags(flag);
+
+   return 0;
+}
+
+
+
+static int pxa250_irda_set_speed(struct net_device *dev, int speed)
+{
+   struct pxa250_irda *si = dev->priv;
+   int brd, ret = -EINVAL;
+   static int last_fir_speed=0;
+
+   __ECHO_IN;
+   
+
+
+   switch (speed) {
+      case 9600:	case 19200:	case 38400:
+      case 57600:	case 115200:
+	   
+	 /* Baud rate fixed - Clo */
+
+	 /*
+	  * FIXME
+	  */
+	 if (last_fir_speed) 
+	 {
+
+	    pxa250_stop_fir(dev);
+	    set_GPIO_mode (GPIO46_STRXD_MD);
+	    set_GPIO_mode (GPIO47_STTXD_MD);
+   
+	    enable_irq(dev->irq);
+	    netif_wake_queue(dev);
+	    last_fir_speed=0;
+	 }
+	 
+
+	 LUB_MISC_WR &= ~(1 << 4);
+
+	 brd = 14745600 / (16 * speed); 
+
+	 STLCR |= LCR_DLAB;
+
+	 STDLH = brd >> 8; /* Clo: set Divisor Latch High */
+	 STDLL = brd & 0xFF; /* Clo: set Devisor Latch Low */
+		
+	 STLCR &= ~LCR_DLAB; /* Clo: clear DLAB bit */ 
+
+	 STMCR = MCR_OUT2;
+
+	 CKEN |= CKEN5_STUART;
+
+	 ICMR |= ( 1 << 20 );
+		
+	 STLCR = LCR_WLS1 | LCR_WLS0;
+
+	 SET_SIR_MODE;
+		
+	 STFCR = FCR_TRFIFOE |  FCR_RESETTF | FCR_RESETRF | FCR_ITL_1 ;// | FCR_ITL_16;
+
+	 STIER = IER_UUE | IER_RAVIE | IER_RTIOE;
+
+	 si->speed = speed;
+
+	 ret = 0;
+	 break;
+
+      case 4000000:
+
+	 if (last_fir_speed)
+	    goto speed_out;
+	 
+	 disable_irq(dev->irq);
+
+	 pxa250_sir_irda_shutdown(si);
+	 pxa250_fir_irda_startup(si);
+	 pxa250_irda_rx_alloc(si);
+	 ICCR0=0;
+	 pxa250_start_rx_dma(dev);
+	 pxa250_ficp_rx_start();
+	 
+	 enable_irq(si->fir_irq);
+	 DBG("enable FIR \n");
+	 si->speed = speed;
+
+	 netif_wake_queue(dev);
+	 last_fir_speed=1;
+speed_out:
+	 
+	 ret=0;
+	 
+	 break;
+
+      default:
+	 break;
+   }
+   __ECHO_OUT;
+
+   return ret;
+}
+
+
+static int pxa250_irda_net_init(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+	unsigned int baudrate_mask;
+	int err = -ENOMEM;
+
+	si = kmalloc(sizeof(struct pxa250_irda), GFP_KERNEL);
+	if (!si)
+		goto out;
+
+	memset(si, 0, sizeof(*si));
+
+	/*
+	 * Initialise the HP-SIR buffers
+	 */
+
+	err = pxa250_irda_init_iobuf(&si->rx_buff, 14384);
+	if (err)
+		goto out;
+	err = pxa250_irda_init_iobuf(&si->tx_buff, 4000);
+	if (err)
+		goto out_free_rx;
+
+	si->fir_irq		= IRQ_ICP;
+	dev->priv = si;
+	dev->hard_start_xmit	= pxa250_irda_hard_xmit;
+	dev->open		= pxa250_irda_start;
+	dev->stop		= pxa250_irda_stop;
+	dev->do_ioctl		= pxa250_irda_ioctl;
+	dev->get_stats		= pxa250_irda_stats;
+
+	irda_device_setup(dev);
+	irda_init_max_qos_capabilies(&si->qos);
+
+	/*
+	 * We support original IRDA up to 115k2. (we don't currently
+	 * support 4Mbps).  Min Turn Time set to 1ms or greater.
+	 */
+	baudrate_mask = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+  	baudrate_mask |= IR_4000000 << 8; 
+	si->qos.baud_rate.bits &= baudrate_mask;
+	si->qos.min_turn_time.bits = 7;
+
+	irda_qos_bits_to_value(&si->qos);
+
+#ifdef CONFIG_PM
+	/*
+	 * Power-Management is optional.
+	 */
+	si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, pxa250_irda_pmproc);
+	if (si->pmdev)
+		si->pmdev->data = dev;
+#endif
+
+	return 0;
+
+	kfree(si->tx_buff.head);
+out_free_rx:
+	kfree(si->rx_buff.head);
+out:
+	kfree(si);
+
+	return err;
+}
+
+/*
+ * Remove all traces of this driver module from the kernel, so we can't be
+ * called.  Note that the device has already been stopped, so we don't have
+ * to worry about interrupts or dma.
+ */
+static void pxa250_irda_net_uninit(struct net_device *dev)
+{
+	struct pxa250_irda *si = dev->priv;
+
+	dev->hard_start_xmit	= NULL;
+	dev->open		= NULL;
+	dev->stop		= NULL;
+	dev->do_ioctl		= NULL;
+	dev->get_stats		= NULL;
+	dev->priv		= NULL;
+
+	pm_unregister(si->pmdev);
+
+	kfree(si->tx_buff.head);
+	kfree(si->rx_buff.head);
+	kfree(si);
+}
+
+static int __init pxa250_irda_init(void)
+{
+	struct net_device *dev;
+	int err;
+
+	/* STUART */
+	err = request_mem_region(__PREG(STRBR), 0x24, "IrDA") ? 0 : -EBUSY;
+	if (err)
+		goto err_mem_1;
+
+	/* FIR */
+	err = request_mem_region(__PREG(ICCR0), 0x1c, "IrDA") ? 0 : -EBUSY;
+	if (err)
+		goto err_mem_2;
+
+
+	rtnl_lock();
+	dev = dev_alloc("irda%d", &err);
+	if (dev) {
+		dev->irq    = IRQ_STUART;
+		dev->init   = pxa250_irda_net_init;
+		dev->uninit = pxa250_irda_net_uninit;
+
+		err = register_netdevice(dev);
+
+		if (err)
+			kfree(dev);
+		else
+			netdev = dev;
+	}
+	rtnl_unlock();
+
+	if (err) {
+		release_mem_region(__PREG(ICCR0), 0x1c);
+err_mem_2:
+		release_mem_region(__PREG(STRBR), 0x24);
+	}
+err_mem_1:
+	return err;
+}
+
+static void __exit pxa250_irda_exit(void)
+{
+	struct net_device *dev = netdev;
+
+	netdev = NULL;
+	if (dev) {
+		rtnl_lock();
+		unregister_netdevice(dev);
+		rtnl_unlock();
+	}
+
+        release_mem_region(__PREG(ICCR0), 0x1c);
+
+	release_mem_region(__PREG(STRBR), 0x24);
+
+	/*
+	 * We now know that the netdevice is no longer in use, and all
+	 * references to our driver have been removed.  The only structure
+	 * which may still be present is the netdevice, which will get
+	 * cleaned up by net/core/dev.c
+	 */
+}
+
+module_init(pxa250_irda_init);
+module_exit(pxa250_irda_exit);
+
+MODULE_AUTHOR("Alexey Lugovskoy Frasenyak Dmitrij");
+MODULE_DESCRIPTION("PXA250 SIR/FIR");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/net/smc91x.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,2123 @@
+/*------------------------------------------------------------------------
+ . smc91x.c
+ . This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices.
+ .
+ . Copyright (C) 1996 by Erik Stahlman
+ . Copyright (C) 2001 Standard Microsystems Corporation
+ .	Developed by Simple Network Magic Corporation
+ . Copyright (C) 2003 Monta Vista Software, Inc.
+ .	Unified SMC91x driver by Nicolas Pitre
+ .
+ . 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
+ .
+ . Arguments:
+ . 	io	= for the base address
+ .	irq	= for the IRQ
+ .	nowait	= 0 for normal wait states, 1 eliminates additional wait states
+ .
+ . original author:
+ . 	Erik Stahlman <erik@vt.edu>
+ .
+ . hardware multicast code:
+ .    Peter Cammaert <pc@denkart.be>
+ .
+ . contributors:
+ . 	Daris A Nevil <dnevil@snmc.com>
+ .      Nicolas Pitre <nico@cam.org>
+ .
+ . History:
+ .   08/20/00  Arnaldo Melo       fix kfree(skb) in smc_hardware_send_packet
+ .   12/15/00  Christian Jullien  fix "Warning: kfree_skb on hard IRQ"
+ .   03/16/01  Daris A Nevil      modified smc9194.c for use with LAN91C111
+ .   08/22/01  Scott Anderson     merge changes from smc9194 to smc91111
+ .   08/21/01  Pramod B Bhardwaj  added support for RevB of LAN91C111
+ .   12/20/01  Jeff Sutherland    initial port to Xscale PXA with DMA support
+ .   04/07/03  Nicolas Pitre      unified SMC91x driver, killed irq races,
+ .                                more bus abstraction, big cleanup, etc.
+ ----------------------------------------------------------------------------*/
+
+static const char version[] =
+	"smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
+
+/* Debugging level */
+#ifndef SMC_DEBUG
+#define SMC_DEBUG		0
+#endif
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include "smc91x.h"
+
+
+#ifdef CONFIG_ISA
+/*
+ . the LAN91C111 can be at any of the following port addresses.  To change,
+ . for a slightly different card, you can add it to the array.  Keep in
+ . mind that the array must end in zero.
+*/
+static unsigned int smc_portlist[] __initdata = {
+	0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+	0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
+};
+#endif  /* CONFIG_ISA */
+
+#ifndef SMC_IOADDR
+# define SMC_IOADDR		-1
+#endif
+static int io = SMC_IOADDR;
+
+#ifndef SMC_IRQ
+# define SMC_IRQ		-1
+#endif
+static int irq = SMC_IRQ;
+
+#ifndef SMC_NOWAIT
+# define SMC_NOWAIT		0
+#endif
+static int nowait = SMC_NOWAIT;
+
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+MODULE_PARM(nowait, "i");
+MODULE_PARM_DESC(io, "I/O base address");
+MODULE_PARM_DESC(irq, "IRQ number");
+MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
+
+
+/*------------------------------------------------------------------------
+ .
+ . The internal workings of the driver.  If you are changing anything
+ . here with the SMC stuff, you should have the datasheet and know
+ . what you are doing.
+ .
+ -------------------------------------------------------------------------*/
+#define CARDNAME "LAN91x"
+
+// Use power-down feature of the chip
+#define POWER_DOWN		1
+
+/*
+ . Wait time for memory to be free.  This probably shouldn't be
+ . tuned that much, as waiting for this means nothing else happens
+ . in the system
+*/
+#define MEMORY_WAIT_TIME	16
+
+/*
+ . This selects whether TX packets are sent one by one to the SMC91x internal
+ . memory ans throttled until transmission completes.  This may prevent
+ . RX overruns a litle by keeping much of the memory free for RX packets
+ . but to the expense of reduced TX throughput and increased IRQ overhead.
+ . Note this is not a cure for a too slow data bus or too high IRQ latency.
+ */
+#define THROTTLE_TX_PKTS	0
+
+
+/* store this information for the driver.. */
+struct smc_local {
+
+	// If I have to wait until memory is available to send
+	// a packet, I will store the skbuff here, until I get the
+	// desired memory.  Then, I'll send it out and free it.
+	struct sk_buff *saved_skb;
+
+ 	// these are things that the kernel wants me to keep, so users
+	// can find out semi-useless statistics of how well the card is
+	// performing
+	struct net_device_stats stats;
+
+	// version/revision of the SMC91x chip
+	int version;
+
+	// Set to true during the auto-negotiation sequence
+	int autoneg_active;
+
+	// Address of our PHY port
+	int	phyaddr;
+
+	// Type of PHY
+	int	phytype;
+
+	// Last contents of PHY Register 18
+	int	lastPhy18;
+
+	// Contains the current active transmission mode
+	int	tcr_cur_mode;
+
+	// Contains the current active receive mode
+	int	rcr_cur_mode;
+
+	// Contains the current active receive/phy mode
+	int	rpc_cur_mode;
+	int	ctl_autoneg;
+	int	ctl_rfduplx;
+	int	ctl_rspeed;
+
+#ifdef CONFIG_PM
+	struct	pm_dev* pm;
+#endif
+
+};
+
+
+#if SMC_DEBUG > 2
+#define PRINTK3(args...)  printk(args)
+#else
+#define PRINTK3(args...)  do { } while(0)
+#endif
+
+#if SMC_DEBUG > 1
+#define PRINTK2(args...)  printk(args)
+#else
+#define PRINTK2(args...)  do { } while(0)
+#endif
+
+#if SMC_DEBUG > 0
+#define PRINTK1(args...)  printk(args)
+#define PRINTK(args...)   printk(args)
+#else
+#define PRINTK1(args...)  do { } while(0)
+#define PRINTK(args...)   printk(KERN_DEBUG args)
+#endif
+
+#if SMC_DEBUG > 3
+static void PRINT_PKT(u_char *buf, int length)
+{
+	int i;
+	int remainder;
+	int lines;
+
+	lines = length / 16;
+	remainder = length % 16;
+
+	for (i = 0; i < lines ; i ++) {
+		int cur;
+		for (cur = 0; cur < 8; cur++) {
+			u_char a, b;
+			a = *buf++;
+			b = *buf++;
+			printk("%02x%02x ", a, b);
+		}
+		printk("\n");
+	}
+	for (i = 0; i < remainder/2 ; i++) {
+		u_char a, b;
+		a = *buf++;
+		b = *buf++;
+		printk("%02x%02x ", a, b );
+	}
+	printk("\n");
+}
+#else
+#define PRINT_PKT(x...)  do { } while(0)
+#endif
+
+
+/* this enables an interrupt in the interrupt mask register */
+#define SMC_ENABLE_INT(x) do {						\
+	unsigned long flags;						\
+	unsigned char mask;						\
+	local_irq_save(flags);						\
+	mask = SMC_GET_INT_MASK();					\
+	mask |= (x);							\
+	SMC_SET_INT_MASK(mask);						\
+	local_irq_restore(flags);					\
+} while (0)
+
+/* this disables an interrupt from the interrupt mask register */
+#define SMC_DISABLE_INT(x) do {						\
+	unsigned long flags;						\
+	unsigned char mask;						\
+	local_irq_save(flags);						\
+	mask = SMC_GET_INT_MASK();					\
+	mask &= ~(x);							\
+	SMC_SET_INT_MASK(mask);						\
+	local_irq_restore(flags);					\
+} while (0)
+
+/* wait while MMU is busy */
+#define SMC_WAIT_MMU_BUSY() do {					\
+	if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) {				\
+		unsigned long timeout = jiffies + 2;			\
+		while (SMC_GET_MMU_CMD() & MC_BUSY) {			\
+			if (time_after(jiffies, timeout)) {		\
+				printk("%s: timeout %s line %d\n",	\
+					dev->name, __FILE__, __LINE__);	\
+				break;					\
+			}						\
+		}							\
+	}								\
+} while (0)
+
+
+/* this does a soft reset on the device */
+static void
+smc_reset(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int phyaddr = lp->phyaddr;
+	int status;
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	/* This resets the registers mostly to defaults, but doesn't
+	   affect EEPROM.  That seems unnecessary */
+	SMC_SELECT_BANK( 0 );
+	SMC_SET_RCR( RCR_SOFTRST );
+
+	/* Setup the Configuration Register */
+	/* This is necessary because the CONFIG_REG is not affected */
+	/* by a soft reset */
+	SMC_SELECT_BANK( 1 );
+	SMC_SET_CONFIG( CONFIG_DEFAULT );
+
+	/* Setup for fast accesses if requested */
+	/* If the card/system can't handle it then there will */
+	/* be no recovery except for a hard reset or power cycle */
+	if (nowait)
+		SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT );
+
+#ifdef POWER_DOWN
+	/* Release from possible power-down state */
+	/* Configuration register is not affected by Soft Reset */
+	SMC_SELECT_BANK( 1 );
+	SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN );
+	status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
+	status &= ~PHY_CNTL_PDN;
+	smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
+#endif
+
+	/* this should pause enough for the chip to be happy */
+	udelay(1);
+
+	/* Disable transmit and receive functionality */
+	SMC_SELECT_BANK( 0 );
+	SMC_SET_RCR( RCR_CLEAR );
+	SMC_SET_TCR( TCR_CLEAR );
+
+	/* set the control register to automatically
+	   release successfully transmitted packets, to make the best
+	   use out of our limited memory */
+	SMC_SELECT_BANK( 1 );
+#if ! THROTTLE_TX_PKTS
+	SMC_SET_CTL( SMC_GET_CTL() | CTL_AUTO_RELEASE );
+#else
+	SMC_SET_CTL( SMC_GET_CTL() & ~CTL_AUTO_RELEASE );
+#endif
+
+	/* Disable all interrupts */
+	SMC_SELECT_BANK( 2 );
+	SMC_SET_INT_MASK( 0 );
+
+	/* Reset the MMU */
+	SMC_SET_MMU_CMD( MC_RESET );
+	SMC_WAIT_MMU_BUSY();
+}
+
+/* Enable Interrupts, Receive, and Transmit */
+static void
+smc_enable(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int mask;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	/* see the header file for options in TCR/RCR DEFAULT*/
+	SMC_SELECT_BANK( 0 );
+	SMC_SET_TCR( lp->tcr_cur_mode );
+	SMC_SET_RCR( lp->rcr_cur_mode );
+
+	/* now, enable interrupts */
+	mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
+	if (lp->version >= 0x70)
+		mask |= IM_MDINT;
+	SMC_SELECT_BANK( 2 );
+	SMC_SET_INT_MASK( mask );
+}
+
+/* this puts the device in an inactive state */
+static void
+smc_shutdown(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int phyaddr = lp->phyaddr;
+	int status;
+
+	PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
+
+	/* no more interrupts for me */
+	SMC_SELECT_BANK( 2 );
+	SMC_SET_INT_MASK( 0 );
+
+	/* and tell the card to stay away from that nasty outside world */
+	SMC_SELECT_BANK( 0 );
+	SMC_SET_RCR( RCR_CLEAR );
+	SMC_SET_TCR( TCR_CLEAR );
+
+#ifdef POWER_DOWN
+	status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
+	status |= PHY_CNTL_PDN;
+	smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
+
+	/* finally, shut the chip down */
+	SMC_SELECT_BANK( 1 );
+	SMC_SET_CONFIG( SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN );
+#endif
+}
+
+/* This is the procedure to handle the receipt of a packet. */
+static inline void 
+smc_rcv(struct net_device *dev)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int packet_number, status, packet_len;
+
+	PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
+
+	packet_number = SMC_GET_RXFIFO();
+	if (unlikely(packet_number & RXFIFO_REMPTY)) {
+		PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
+		return;
+	}
+
+	/* read from start of packet */
+	SMC_SET_PTR( PTR_READ | PTR_RCV | PTR_AUTOINC );
+
+	/* First two words are status and packet length */
+	SMC_GET_PKT_HDR(status, packet_len);
+	packet_len &= 0x07ff;  /* mask off top bits */
+	PRINTK2("%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
+		dev->name, packet_number, status,
+		packet_len, packet_len);
+
+	if (unlikely(status & RS_ERRORS)) {
+		lp->stats.rx_errors++;
+		if (status & RS_ALGNERR)
+			lp->stats.rx_frame_errors++;
+		if (status & (RS_TOOSHORT | RS_TOOLONG))
+			lp->stats.rx_length_errors++;
+		if (status & RS_BADCRC)
+			lp->stats.rx_crc_errors++;
+	} else {
+		struct sk_buff *skb;
+		unsigned char *data;
+		unsigned int data_len;
+
+		/* set multicast stats */
+		if (status & RS_MULTICAST)
+			lp->stats.multicast++;
+
+		/*
+		 * Actual payload is packet_len - 4 (or 3 if odd byte).
+		 * We want skb_reserve(2) and the final ctrl word
+		 * (2 bytes, possibly containing the payload odd byte).
+		 * Ence packet_len - 4 + 2 + 2.
+		 */
+		skb = dev_alloc_skb(packet_len);
+		if (unlikely(skb == NULL)) {
+			printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
+				dev->name);
+			lp->stats.rx_dropped++;
+			goto done;
+		}
+
+		/* Align IP header to 32 bits */
+		skb_reserve(skb, 2);
+
+		/* BUG: the LAN91C111 rev A never sets this bit. Force it. */
+		if (lp->version == 0x90)
+			status |= RS_ODDFRAME;
+
+		/*
+		 * If odd length: packet_len - 3,
+		 * otherwise packet_len - 4.
+		 */
+		data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4);
+		data = skb_put(skb, data_len);
+		SMC_PULL_DATA(data, packet_len - 2);
+
+		PRINT_PKT(data, packet_len - 2);
+
+		dev->last_rx = jiffies;
+		skb->dev = dev;
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		lp->stats.rx_packets++;
+		lp->stats.rx_bytes += data_len;
+	}
+
+done:
+	SMC_WAIT_MMU_BUSY();
+	SMC_SET_MMU_CMD( MC_RELEASE );
+}
+
+/*
+ * This is called to actually send a packet to the chip.
+ * Returns non-zero when successful.
+ */
+static void
+smc_hardware_send_packet(struct net_device *dev)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	struct sk_buff *skb = lp->saved_skb;
+	unsigned int packet_no, len;
+	unsigned char *buf;
+
+	PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
+
+	if (unlikely(!skb)) {
+		printk ("%s: In XMIT with no packet to send\n", dev->name);
+		return;
+	}
+
+	packet_no = SMC_GET_AR();
+	if (unlikely(packet_no & AR_FAILED)) {
+		printk("%s: Memory allocation failed.\n", dev->name);
+		lp->saved_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_fifo_errors++;
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	/* point to the beginning of the packet */
+	SMC_SET_PN( packet_no );
+	SMC_SET_PTR( PTR_AUTOINC );
+
+	buf = skb->data;
+	len = skb->len;
+	PRINTK2("%s: TX PNR 0x%x lENGTH 0x%04x (%d) BUF 9x%p\n",
+		dev->name, packet_no, len, len, buf);
+	PRINT_PKT(buf, len);
+
+	/*
+	 * Send the packet length ( +6 for status words, length, and ctl.
+	 * The card will pad to 64 bytes with zeroes if packet is too small.
+	 */
+	SMC_PUT_PKT_HDR(0, len + 6);
+
+	/* send the actual data */
+	SMC_PUSH_DATA(buf, len & ~1);
+
+	/* Send final ctl word with the last byte if there is one */
+	SMC_outw( ((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG );
+
+	/* and let the chipset deal with it */
+	SMC_SET_MMU_CMD( MC_ENQUEUE );
+	SMC_ACK_INT( IM_TX_EMPTY_INT );
+
+	dev->trans_start = jiffies;
+	dev_kfree_skb_any(skb);
+	lp->saved_skb = NULL;
+	lp->stats.tx_packets++;
+	lp->stats.tx_bytes += len;
+}
+
+/*
+ . Since I am not sure if I will have enough room in the chip's ram
+ . to store the packet, I call this routine which either sends it
+ . now, or set the card to generates an interrupt when ready
+ . for the packet.
+ */
+static int
+smc_hard_start_xmit( struct sk_buff * skb, struct net_device * dev )
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int numPages, poll_count, status, saved_bank;
+
+	PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
+
+	if (unlikely(lp->saved_skb != NULL)) {
+		/* THIS SHOULD NEVER HAPPEN. */
+		printk( KERN_CRIT
+			"%s: Bad Craziness - sent packet while busy.\n",
+			dev->name );
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+		return 1;
+	}
+	lp->saved_skb = skb;
+
+	/*
+	** The MMU wants the number of pages to be the number of 256 bytes
+	** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
+	**
+	** The 91C111 ignores the size bits, but the code is left intact
+	** for backwards and future compatibility.
+	**
+	** Pkt size for allocating is data length +6 (for additional status
+	** words, length and ctl!)
+	**
+	** If odd size then last byte is included in ctl word.
+	*/
+	numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
+	if (unlikely(numPages > 7)) {
+		printk("%s: Far too big packet error.\n", dev->name);
+		lp->saved_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* now, try to allocate the memory */
+	saved_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK( 2 );
+	SMC_SET_MMU_CMD( MC_ALLOC | numPages );
+
+	/*
+	 * Poll the chip for a short amount of time in case the
+	 * allocation succeeds quickly.
+	 */
+	poll_count = MEMORY_WAIT_TIME;
+	do {
+		status = SMC_GET_INT();
+		if (status & IM_ALLOC_INT) {
+			SMC_ACK_INT( IM_ALLOC_INT );
+  			break;
+		}
+   	} while (--poll_count);
+
+   	if (!poll_count) {
+		/* oh well, wait until the chip finds memory later */
+		netif_stop_queue(dev);
+		PRINTK2("%s: TX memory allocation deferred.\n", dev->name);
+		SMC_ENABLE_INT( IM_ALLOC_INT );
+   	} else {
+		/* Send current packet immediately.. */
+#if THROTTLE_TX_PKTS
+		netif_stop_queue(dev);
+#endif
+		smc_hardware_send_packet(dev);
+		SMC_ENABLE_INT( IM_TX_INT | IM_TX_EMPTY_INT );
+	}
+
+	SMC_SELECT_BANK( saved_bank );
+	return 0;
+}
+
+/*
+ . This handles a TX interrupt, which is only called when an error
+ . relating to a packet is sent or CTL_AUTO_RELEASE is not set.
+*/
+static void
+smc_tx(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned int saved_packet, packet_no, tx_status, pkt_len;
+
+	PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
+
+	/* If the TX FIFO is empty then nothing to do */
+	packet_no = SMC_GET_TXFIFO();
+	if (unlikely(packet_no & TXFIFO_TEMPTY)) {
+		PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
+		return;
+	}
+
+	/* select packet to read from */
+	saved_packet = SMC_GET_PN();
+	SMC_SET_PN( packet_no );
+
+	/* read the first word (status word) from this packet */
+	SMC_SET_PTR( PTR_AUTOINC | PTR_READ );
+	SMC_GET_PKT_HDR(tx_status, pkt_len);
+	PRINTK2("%s: TX STATUS 0x%04x PNR 0x%02x\n",
+		dev->name, tx_status, packet_no);
+
+	if (!(tx_status & TS_SUCCESS))
+		lp->stats.tx_errors++;
+	if (tx_status & TS_LOSTCAR)
+		lp->stats.tx_carrier_errors++;
+	if (tx_status & TS_LATCOL) {
+		printk( KERN_DEBUG
+			"%s: Late collision occurred on last xmit.\n",
+			dev->name);
+		lp->stats.tx_window_errors++;
+	}
+
+	/* kill the packet */
+	SMC_WAIT_MMU_BUSY();
+	SMC_SET_MMU_CMD( MC_FREEPKT );
+
+	/* Don't restore Packet Number Reg until busy bit is cleared */
+	SMC_WAIT_MMU_BUSY();
+	SMC_SET_PN( saved_packet );
+
+	/* re-enable transmit */
+	SMC_SELECT_BANK( 0 );
+	SMC_SET_TCR( lp->tcr_cur_mode );
+	SMC_SELECT_BANK( 2 );
+}
+
+
+//---PHY CONTROL AND CONFIGURATION-----------------------------------------
+
+/*------------------------------------------------------------
+ . Debugging function for viewing MII Management serial bitstream
+ .-------------------------------------------------------------*/
+#if SMC_DEBUG > 3
+static void
+PRINT_MII_STREAM(u_char *bits, int size)
+{
+	int i;
+
+	printk("BIT#:");
+	for (i = 0; i < size; ++i)
+		printk("%d", i%10);
+
+	printk("\nMDOE:");
+	for (i = 0; i < size; ++i) {
+		if (bits[i] & MII_MDOE)
+			printk("1");
+		else
+			printk("0");
+	}
+
+	printk("\nMDO :");
+	for (i = 0; i < size; ++i) {
+		if (bits[i] & MII_MDO)
+			printk("1");
+		else
+			printk("0");
+	}
+
+	printk("\nMDI :");
+	for (i = 0; i < size; ++i) {
+		if (bits[i] & MII_MDI)
+			printk("1");
+		else
+			printk("0");
+	}
+
+	printk("\n");
+}
+#else
+#define PRINT_MII_STREAM(x...)
+#endif
+
+/*------------------------------------------------------------
+ . Reads a register from the MII Management serial interface
+ .-------------------------------------------------------------*/
+static int
+smc_read_phy_register(unsigned long ioaddr, int phyaddr, int phyreg)
+{
+	int oldBank;
+	int i, mask, mii_reg;
+	u_char bits[64];
+	int input_idx, phydata;
+	int clk_idx = 0;
+
+	// 32 consecutive ones on MDO to establish sync
+	for (i = 0; i < 32; ++i)
+		bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+	// Start code <01>
+	bits[clk_idx++] = MII_MDOE;
+	bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+	// Read command <10>
+	bits[clk_idx++] = MII_MDOE | MII_MDO;
+	bits[clk_idx++] = MII_MDOE;
+
+	// Output the PHY address, msb first
+	mask = 0x10;
+	for (i = 0; i < 5; ++i) {
+		if (phyaddr & mask)
+			bits[clk_idx++] = MII_MDOE | MII_MDO;
+		else
+			bits[clk_idx++] = MII_MDOE;
+
+		// Shift to next lowest bit
+		mask >>= 1;
+	}
+
+	// Output the phy register number, msb first
+	mask = 0x10;
+	for (i = 0; i < 5; ++i) {
+		if (phyreg & mask)
+			bits[clk_idx++] = MII_MDOE | MII_MDO;
+		else
+			bits[clk_idx++] = MII_MDOE;
+
+		// Shift to next lowest bit
+		mask >>= 1;
+	}
+
+	// Tristate and turnaround (2 bit times)
+	bits[clk_idx++] = 0;
+	//bits[clk_idx++] = 0;
+
+	// Input starts at this bit time
+	input_idx = clk_idx;
+
+	// Will input 16 bits
+	for (i = 0; i < 16; ++i)
+		bits[clk_idx++] = 0;
+
+	// Final clock bit
+	bits[clk_idx++] = 0;
+
+	// Save the current bank
+	oldBank = SMC_CURRENT_BANK();
+
+	// Select bank 3
+	SMC_SELECT_BANK( 3 );
+
+	// Get the current MII register value
+	mii_reg = SMC_GET_MII();
+
+	// Turn off all MII Interface bits
+	mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
+
+	// Clock all 64 cycles
+	for (i = 0; i < sizeof bits; ++i) {
+		// Clock Low - output data
+		SMC_SET_MII( mii_reg | bits[i] );
+		udelay(50);
+
+		// Clock Hi - input data
+		SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
+		udelay(50);
+		bits[i] |= SMC_GET_MII() & MII_MDI;
+	}
+
+	// Return to idle state
+	// Set clock to low, data to low, and output tristated
+	SMC_SET_MII( mii_reg );
+	udelay(50);
+
+	// Restore original bank select
+	SMC_SELECT_BANK( oldBank );
+
+	// Recover input data
+	phydata = 0;
+	for (i = 0; i < 16; ++i) {
+		phydata <<= 1;
+
+		if (bits[input_idx++] & MII_MDI)
+			phydata |= 0x0001;
+	}
+
+	PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+		__FUNCTION__, phyaddr, phyreg, phydata);
+	PRINT_MII_STREAM(bits, sizeof(bits));
+
+	return phydata;
+}
+
+/*------------------------------------------------------------
+ . Writes a register to the MII Management serial interface
+ .-------------------------------------------------------------*/
+static void
+smc_write_phy_register( unsigned long ioaddr, int phyaddr,
+			int phyreg, int phydata )
+{
+	int oldBank;
+	int i, mask, mii_reg;
+	u_char bits[65];
+	int clk_idx = 0;
+
+	// 32 consecutive ones on MDO to establish sync
+	for (i = 0; i < 32; ++i)
+		bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+	// Start code <01>
+	bits[clk_idx++] = MII_MDOE;
+	bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+	// Write command <01>
+	bits[clk_idx++] = MII_MDOE;
+	bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+	// Output the PHY address, msb first
+	mask = 0x10;
+	for (i = 0; i < 5; ++i) {
+		if (phyaddr & mask)
+			bits[clk_idx++] = MII_MDOE | MII_MDO;
+		else
+			bits[clk_idx++] = MII_MDOE;
+
+		// Shift to next lowest bit
+		mask >>= 1;
+	}
+
+	// Output the phy register number, msb first
+	mask = 0x10;
+	for (i = 0; i < 5; ++i) {
+		if (phyreg & mask)
+			bits[clk_idx++] = MII_MDOE | MII_MDO;
+		else
+			bits[clk_idx++] = MII_MDOE;
+
+		// Shift to next lowest bit
+		mask >>= 1;
+	}
+
+	// Tristate and turnaround (2 bit times)
+	bits[clk_idx++] = 0;
+	bits[clk_idx++] = 0;
+
+	// Write out 16 bits of data, msb first
+	mask = 0x8000;
+	for (i = 0; i < 16; ++i) {
+		if (phydata & mask)
+			bits[clk_idx++] = MII_MDOE | MII_MDO;
+		else
+			bits[clk_idx++] = MII_MDOE;
+
+		// Shift to next lowest bit
+		mask >>= 1;
+	}
+
+	// Final clock bit (tristate)
+	bits[clk_idx++] = 0;
+
+	// Save the current bank
+	oldBank = SMC_CURRENT_BANK();
+
+	// Select bank 3
+	SMC_SELECT_BANK( 3 );
+
+	// Get the current MII register value
+	mii_reg = SMC_GET_MII();
+
+	// Turn off all MII Interface bits
+	mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
+
+	// Clock all cycles
+	for (i = 0; i < sizeof bits; ++i) {
+		// Clock Low - output data
+		SMC_SET_MII( mii_reg | bits[i] );
+		udelay(50);
+
+		// Clock Hi - input data
+		SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
+		udelay(50);
+		bits[i] |= SMC_GET_MII() & MII_MDI;
+	}
+
+	// Return to idle state
+	// Set clock to low, data to low, and output tristated
+	SMC_SET_MII( mii_reg );
+	udelay(50);
+
+	// Restore original bank select
+	SMC_SELECT_BANK( oldBank );
+
+	PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+		__FUNCTION__, phyaddr, phyreg, phydata);
+	PRINT_MII_STREAM(bits, sizeof(bits));
+}
+
+
+/*------------------------------------------------------------
+ . Finds and reports the PHY address
+ .-------------------------------------------------------------*/
+static int smc_detect_phy(struct net_device* dev)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	int phy_id1, phy_id2;
+	int phyaddr;
+	int found = 0;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	// Scan all 32 PHY addresses if necessary
+	for (phyaddr = 0; phyaddr < 32; ++phyaddr) {
+		// Read the PHY identifiers
+		phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
+		phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
+
+		PRINTK3("%s: phy_id1=0x%x, phy_id2=0x%x\n",
+			dev->name, phy_id1, phy_id2);
+
+		// Make sure it is a valid identifier
+		if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
+		    (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) {
+			if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) {
+				// Save the PHY's address
+				lp->phyaddr = phyaddr;
+				found = 1;
+				break;
+			}
+		}
+	}
+
+	if (!found) {
+		PRINTK("%s: No PHY found\n", dev->name);
+		return(0);
+	}
+
+	// Set the PHY type
+	if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) {
+		lp->phytype = PHY_LAN83C183;
+		PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name);
+	}
+
+	if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) {
+		lp->phytype = PHY_LAN83C180;
+		PRINTK("%s: PHY=LAN83C180\n", dev->name);
+	}
+
+	return 1;
+}
+
+/*------------------------------------------------------------
+ . Waits the specified number of milliseconds - kernel friendly
+ .-------------------------------------------------------------*/
+static void
+smc_wait_ms(unsigned int ms)
+{
+	if (!in_interrupt()) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1 + ms * HZ / 1000);
+	} else {
+		/* if this happens it must be fixed */
+		printk( KERN_WARNING "%s: busy wait while in interrupt!\n",
+			__FUNCTION__);
+		mdelay(ms);
+	}
+}
+
+/*------------------------------------------------------------
+ . Sets the PHY to a configuration as determined by the user
+ .-------------------------------------------------------------*/
+static int
+smc_phy_fixed(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int phyaddr = lp->phyaddr;
+	int my_fixed_caps, cfg1;
+
+	PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
+
+	// Enter Link Disable state
+	cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG);
+	cfg1 |= PHY_CFG1_LNKDIS;
+	smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1);
+
+	// Set our fixed capabilities
+	// Disable auto-negotiation
+	my_fixed_caps = 0;
+
+	if (lp->ctl_rfduplx)
+		my_fixed_caps |= PHY_CNTL_DPLX;
+
+	if (lp->ctl_rspeed == 100)
+		my_fixed_caps |= PHY_CNTL_SPEED;
+
+	// Write our capabilities to the phy control register
+	smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps);
+
+	// Re-Configure the Receive/Phy Control register
+	SMC_SET_RPC( lp->rpc_cur_mode );
+
+	// Success
+	return(1);
+}
+
+/*------------------------------------------------------------
+ . Configures the specified PHY through the MII management interface
+ . using Autonegotiation.
+ . Calls smc_phy_fixed() if the user has requested a certain config.
+ .-------------------------------------------------------------*/
+static void
+smc_phy_configure(struct net_device* dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int timeout;
+	int phyaddr;
+	int my_phy_caps; // My PHY capabilities
+	int my_ad_caps; // My Advertised capabilities
+	int status;
+
+	PRINTK3("%s:smc_program_phy()\n", dev->name);
+
+	// Set the blocking flag
+	lp->autoneg_active = 1;
+
+	// Find the address and type of our phy
+	if (!smc_detect_phy(dev))
+		goto smc_phy_configure_exit;
+
+	// Get the detected phy address
+	phyaddr = lp->phyaddr;
+
+	// Reset the PHY, setting all other bits to zero
+	smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
+
+	// Wait for the reset to complete, or time out
+	timeout = 6; // Wait up to 3 seconds
+	while (timeout--) {
+		if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
+		    & PHY_CNTL_RST))
+			// reset complete
+			break;
+		smc_wait_ms(500); // wait 500 millisecs
+		if (signal_pending(current)) { // Exit anyway if signaled
+			PRINTK("%s: PHY reset interrupted by signal\n",
+				dev->name);
+			timeout = 0;
+			break;
+		}
+	}
+
+	if (timeout < 1) {
+		printk("%s: PHY reset timed out\n", dev->name);
+		goto smc_phy_configure_exit;
+	}
+
+	// Read PHY Register 18, Status Output
+	lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
+
+	// Enable PHY Interrupts (for register 18)
+	// Interrupts listed here are disabled
+	smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
+		PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
+		PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
+		PHY_INT_SPDDET | PHY_INT_DPLXDET);
+
+	/* Configure the Receive/Phy Control register */
+	SMC_SELECT_BANK( 0 );
+	SMC_SET_RPC( lp->rpc_cur_mode );
+
+	// Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
+	my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+
+	// If the user requested no auto neg, then go set his request
+	if (!(lp->ctl_autoneg)) {
+		smc_phy_fixed(dev);
+		goto smc_phy_configure_exit;
+	}
+
+	if( !( my_phy_caps & PHY_STAT_CAP_ANEG))
+	{
+		printk(KERN_INFO "Auto negotiation NOT supported\n");
+		smc_phy_fixed(dev);
+		goto smc_phy_configure_exit;
+	}
+
+	my_ad_caps  = PHY_AD_CSMA; // I am CSMA capable
+
+	if (my_phy_caps & PHY_STAT_CAP_T4)
+		my_ad_caps |= PHY_AD_T4;
+
+	if (my_phy_caps & PHY_STAT_CAP_TXF)
+		my_ad_caps |= PHY_AD_TX_FDX;
+
+	if (my_phy_caps & PHY_STAT_CAP_TXH)
+		my_ad_caps |= PHY_AD_TX_HDX;
+
+	if (my_phy_caps & PHY_STAT_CAP_TF)
+		my_ad_caps |= PHY_AD_10_FDX;
+
+	if (my_phy_caps & PHY_STAT_CAP_TH)
+		my_ad_caps |= PHY_AD_10_HDX;
+
+	// Disable capabilities not selected by our user
+	if (lp->ctl_rspeed != 100)
+		my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX);
+
+	if (!lp->ctl_rfduplx)
+		my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX);
+
+	// Update our Auto-Neg Advertisement Register
+	smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
+
+	// Read the register back.  Without this, it appears that when
+	// auto-negotiation is restarted, sometimes it isn't ready and
+	// the link does not come up.
+	status = smc_read_phy_register(ioaddr, phyaddr, PHY_AD_REG);
+
+	PRINTK2("%s: phy caps=%x\n", dev->name, my_phy_caps);
+	PRINTK2("%s: phy advertised caps=%x\n", dev->name, my_ad_caps);
+
+	// Restart auto-negotiation process in order to advertise my caps
+	smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
+		PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
+
+	// Wait for the auto-negotiation to complete.  This may take from
+	// 2 to 3 seconds.
+	// Wait for the reset to complete, or time out
+	timeout = 20; // Wait up to 10 seconds
+	while (timeout--) {
+		status = smc_read_phy_register(ioaddr, phyaddr, PHY_RMT_REG);
+		if (status & PHY_AD_ACK)
+			// auto-negotiate complete
+			break;
+
+		smc_wait_ms(500); // wait 500 millisecs
+		if (signal_pending(current)) { // Exit anyway if signaled
+			printk(KERN_DEBUG
+				"%s: PHY auto-negotiate interrupted by signal\n",
+				dev->name);
+			timeout = 0;
+			break;
+		}
+	}
+	status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+
+	if (timeout < 1) {
+		PRINTK("%s: PHY auto-negotiate timed out\n", dev->name);
+	}
+
+	// Fail if we detected an auto-negotiate remote fault
+	if (status & PHY_STAT_REM_FLT) {
+		PRINTK("%s: PHY remote fault detected\n", dev->name);
+	}
+
+	// Wait for link. Once the link is up, phy18 should be up to date
+        timeout = 200;
+        do              
+        {
+                udelay(100);
+                status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+        } while ( ((status & PHY_STAT_LINK)==0) && --timeout);
+
+        if (status & PHY_STAT_LINK)        
+        {                                      
+                PRINTK("%s: Ethernet Link Detected\n", dev->name); 
+        }       
+
+	// The smc_phy_interrupt() routine will be called to update lastPhy18
+
+	// Set our sysctl parameters to match auto-negotiation results
+	if ( lp->lastPhy18 & PHY_INT_SPDDET ) {
+		PRINTK("%s: PHY 100BaseT\n", dev->name);
+		lp->rpc_cur_mode |= RPC_SPEED;
+	} else {
+		PRINTK("%s: PHY 10BaseT\n", dev->name);
+		lp->rpc_cur_mode &= ~RPC_SPEED;
+	}
+
+	if ( lp->lastPhy18 & PHY_INT_DPLXDET ) {
+		PRINTK("%s: PHY Full Duplex\n", dev->name);
+		lp->rpc_cur_mode |= RPC_DPLX;
+		lp->tcr_cur_mode |= TCR_SWFDUP;
+	} else {
+		PRINTK("%s: PHY Half Duplex\n", dev->name);
+		lp->rpc_cur_mode &= ~RPC_DPLX;
+		lp->tcr_cur_mode &= ~TCR_SWFDUP;
+	}
+
+	// Re-Configure the Receive/Phy Control register and TCR
+	SMC_SET_RPC( lp->rpc_cur_mode );
+	SMC_SET_TCR( lp->tcr_cur_mode );
+
+smc_phy_configure_exit:
+	// Exit auto-negotiation
+	lp->autoneg_active = 0;
+}
+
+/*************************************************************************
+ . smc_phy_interrupt
+ .
+ . Purpose:  Handle interrupts relating to PHY register 18. This is
+ .  called from the "hard" interrupt handler.
+ .
+ ************************************************************************/
+static void
+smc_phy_interrupt(struct net_device* dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int phyaddr = lp->phyaddr;
+	int phy18;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	for(;;) {
+		// Read PHY Register 18, Status Output
+		phy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
+
+		// Exit if not more changes
+		if (phy18 == lp->lastPhy18)
+			break;
+
+#if SMC_DEBUG > 1
+		PRINTK2("%s:     phy18=0x%04x\n", dev->name, phy18);
+		PRINTK2("%s: lastPhy18=0x%04x\n", dev->name, lp->lastPhy18);
+
+		// Handle events
+		if ((phy18 & PHY_INT_LNKFAIL) !=
+				(lp->lastPhy18 & PHY_INT_LNKFAIL))
+			PRINTK2("%s: PHY Link Fail=%x\n", dev->name,
+					phy18 & PHY_INT_LNKFAIL);
+
+		if ((phy18 & PHY_INT_LOSSSYNC) !=
+				(lp->lastPhy18 & PHY_INT_LOSSSYNC))
+			PRINTK2("%s: PHY LOSS SYNC=%x\n", dev->name,
+					phy18 & PHY_INT_LOSSSYNC);
+
+		if ((phy18 & PHY_INT_CWRD) != (lp->lastPhy18 & PHY_INT_CWRD))
+			PRINTK2("%s: PHY INVALID 4B5B code=%x\n", dev->name,
+					phy18 & PHY_INT_CWRD);
+
+		if ((phy18 & PHY_INT_SSD) != (lp->lastPhy18 & PHY_INT_SSD))
+			PRINTK2("%s: PHY No Start Of Stream=%x\n", dev->name,
+					phy18 & PHY_INT_SSD);
+
+		if ((phy18 & PHY_INT_ESD) != (lp->lastPhy18 & PHY_INT_ESD))
+
+			PRINTK2("%s: PHY No End Of Stream=%x\n", dev->name,
+					phy18 & PHY_INT_ESD);
+
+		if ((phy18 & PHY_INT_RPOL) != (lp->lastPhy18 & PHY_INT_RPOL))
+			PRINTK2("%s: PHY Reverse Polarity Detected=%x\n",
+					dev->name, phy18 & PHY_INT_RPOL);
+
+		if ((phy18 & PHY_INT_JAB) != (lp->lastPhy18 & PHY_INT_JAB))
+			PRINTK2("%s: PHY Jabber Detected=%x\n", dev->name,
+					phy18 & PHY_INT_JAB);
+
+		if ((phy18 & PHY_INT_SPDDET) !=
+				(lp->lastPhy18 & PHY_INT_SPDDET))
+			PRINTK2("%s: PHY Speed Detect=%x\n", dev->name,
+					phy18 & PHY_INT_SPDDET);
+
+		if ((phy18 & PHY_INT_DPLXDET) !=
+				(lp->lastPhy18 & PHY_INT_DPLXDET))
+			PRINTK2("%s: PHY Duplex Detect=%x\n", dev->name,
+					phy18 & PHY_INT_DPLXDET);
+#endif
+		// Update the last phy 18 variable
+		lp->lastPhy18 = phy18;
+	}
+}
+
+//--- END PHY CONTROL AND CONFIGURATION-------------------------------------
+
+
+/*
+ * This is the main routine of the driver, to handle the device when
+ * it needs some attention.
+ */
+static void
+smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	int status, mask, timeout, card_stats;
+	int saved_bank, saved_pointer;
+
+	PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
+
+	saved_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(2);
+	saved_pointer = SMC_GET_PTR();
+	mask = SMC_GET_INT_MASK();
+	SMC_SET_INT_MASK( 0 );
+
+	/* set a timeout value, so I don't stay here forever */
+	timeout = 8;
+
+	do {
+		status = SMC_GET_INT();
+
+		PRINTK2("%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
+			dev->name, status, mask,
+			({ int meminfo; SMC_SELECT_BANK(0);
+			   meminfo = SMC_GET_MIR();
+			   SMC_SELECT_BANK(2); meminfo; }),
+			SMC_GET_FIFO());
+
+		status &= mask;
+		if (!status)
+			break;
+
+		if (status & IM_RCV_INT) {
+			PRINTK3("%s: RX irq\n", dev->name);
+			smc_rcv(dev);
+		} else if (status & IM_TX_INT) {
+			PRINTK3("%s: TX int\n", dev->name);
+			smc_tx(dev);
+			SMC_ACK_INT( IM_TX_INT );
+#if THROTTLE_TX_PKTS
+			netif_wake_queue(dev);
+#endif
+		} else if (status & IM_ALLOC_INT) {
+			PRINTK3("%s: Allocation irq\n", dev->name);
+			smc_hardware_send_packet(dev);
+			mask |= (IM_TX_INT | IM_TX_EMPTY_INT);
+			mask &= ~IM_ALLOC_INT;
+#if ! THROTTLE_TX_PKTS
+			netif_wake_queue(dev);
+#endif
+		} else if (status & IM_TX_EMPTY_INT) {
+			PRINTK3("%s: TX empty\n", dev->name);
+			mask &= ~IM_TX_EMPTY_INT;
+
+			/* update stats */
+			SMC_SELECT_BANK( 0 );
+			card_stats = SMC_GET_COUNTER();
+			SMC_SELECT_BANK( 2 );
+
+			/* single collisions */
+			lp->stats.collisions += card_stats & 0xF;
+			card_stats >>= 4;
+
+			/* multiple collisions */
+			lp->stats.collisions += card_stats & 0xF;
+		} else if (status & IM_RX_OVRN_INT) {
+			PRINTK1( "%s: RX overrun\n", dev->name);
+			SMC_ACK_INT( IM_RX_OVRN_INT );
+			lp->stats.rx_errors++;
+			lp->stats.rx_fifo_errors++;
+		} else if (status & IM_EPH_INT) {
+			PRINTK("%s: UNSUPPORTED: EPH INTERRUPT\n", dev->name);
+		} else if (status & IM_MDINT) {
+			SMC_ACK_INT( IM_MDINT );
+			smc_phy_interrupt(dev);
+		} else if (status & IM_ERCV_INT ) {
+			SMC_ACK_INT( IM_ERCV_INT );
+			PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
+		}
+	} while (--timeout);
+
+	/* restore register states */
+	SMC_SET_INT_MASK( mask );
+	SMC_SET_PTR( saved_pointer );
+	SMC_SELECT_BANK( saved_bank );
+
+	PRINTK3("%s: Interrupt done\n", dev->name);
+}
+
+/* Our watchdog timed out. Called by the networking layer */
+static void
+smc_timeout(struct net_device *dev)
+{
+	struct smc_local *lp 	= (struct smc_local *)dev->priv;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	smc_reset(dev);
+	smc_enable(dev);
+
+#if 0
+	/* Reconfiguring the PHY doesn't seem like a bad idea here, but
+	 * it introduced a problem.  Now that this is a timeout routine,
+	 * we are getting called from within an interrupt context.
+	 * smc_phy_configure() calls smc_wait_ms() which calls
+	 * schedule_timeout() which calls schedule().  When schedule()
+	 * is called from an interrupt context, it prints out
+	 * "Scheduling in interrupt" and then calls BUG().  This is
+	 * obviously not desirable.  This was worked around by removing
+	 * the call to smc_phy_configure() here because it didn't seem
+	 * absolutely necessary.  Ultimately, if smc_wait_ms() is
+	 * supposed to be usable from an interrupt context (which it
+	 * looks like it thinks it should handle), it should be fixed.
+	 */
+	/* Reconfigure the PHY */
+	smc_phy_configure(dev);
+#endif
+
+	/* clear anything saved */
+	if (lp->saved_skb != NULL) {
+		dev_kfree_skb (lp->saved_skb);
+		lp->saved_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+	}
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+}
+
+/*
+ * Finds the CRC32 of a set of bytes.
+ * (from Peter Cammaert's code)
+ */
+static int
+crc32(char *s, int length)
+{
+	/* indices */
+	int perByte;
+	int perBit;
+	/* crc polynomial for Ethernet */
+	const unsigned long poly = 0xedb88320;
+	/* crc value - preinitialized to all 1's */
+	unsigned long crc_value = 0xffffffff;
+
+	for ( perByte = 0; perByte < length; perByte ++ ) {
+		unsigned char	c;
+
+		c = *(s++);
+		for ( perBit = 0; perBit < 8; perBit++ ) {
+			crc_value = (crc_value>>1)^
+				(((crc_value^c)&0x01)?poly:0);
+			c >>= 1;
+		}
+	}
+	return	crc_value;
+}
+
+/*
+ .    This sets the internal hardware table to filter out unwanted multicast
+ .    packets before they take up memory.
+ .
+ .    The SMC chip uses a hash table where the high 6 bits of the CRC of
+ .    address are the offset into the table.  If that bit is 1, then the
+ .    multicast packet is accepted.  Otherwise, it's dropped silently.
+ .
+ .    To use the 6 bits as an offset into the table, the high 3 bits are the
+ .    number of the 8 bit register, while the low 3 bits are the bit within
+ .    that register.
+ .
+ .    This routine is based very heavily on the one provided by Peter Cammaert.
+*/
+static void
+smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs)
+{
+	int			i;
+	unsigned char		multicast_table[ 8 ];
+	struct dev_mc_list	*cur_addr;
+
+	/* table for flipping the order of 3 bits */
+	static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+
+	/* start with a table of all zeros: reject all */
+	memset( multicast_table, 0, sizeof( multicast_table ) );
+
+	cur_addr = addrs;
+	for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next  ) {
+		int position;
+
+		/* do we have a pointer here? */
+		if ( !cur_addr )
+			break;
+		/* make sure this is a multicast address - shouldn't this
+		   be a given if we have it here ? */
+		if ( !( *cur_addr->dmi_addr & 1 ) )
+			continue;
+
+		/* only use the low order bits */
+		position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f;
+
+		/* do some messy swapping to put the bit in the right spot */
+		multicast_table[invert3[position&7]] |=
+					(1<<invert3[(position>>3)&7]);
+
+	}
+	/* now, the table can be loaded into the chipset */
+	SMC_SELECT_BANK( 3 );
+	SMC_SET_MCAST( multicast_table );
+}
+
+/*
+ . This routine will, depending on the values passed to it,
+ . either make it accept multicast packets, go into
+ . promiscuous mode ( for TCPDUMP and cousins ) or accept
+ . a select set of multicast packets
+*/
+static void smc_set_multicast_list(struct net_device *dev)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	SMC_SELECT_BANK(0);
+	if ( dev->flags & IFF_PROMISC ) {
+		PRINTK2("%s: RCR_PRMS\n", dev->name);
+		lp->rcr_cur_mode |= RCR_PRMS;
+		SMC_SET_RCR( lp->rcr_cur_mode );
+	}
+
+/* BUG?  I never disable promiscuous mode if multicasting was turned on.
+   Now, I turn off promiscuous mode, but I don't do anything to multicasting
+   when promiscuous mode is turned on.
+*/
+
+	/* Here, I am setting this to accept all multicast packets.
+	   I don't need to zero the multicast table, because the flag is
+	   checked before the table is
+	*/
+	else if (dev->flags & IFF_ALLMULTI) {
+		lp->rcr_cur_mode |= RCR_ALMUL;
+		SMC_SET_RCR( lp->rcr_cur_mode );
+		PRINTK2("%s: RCR_ALMUL\n", dev->name);
+	}
+
+	/* We just get all multicast packets even if we only want them
+	 . from one source.  This will be changed at some future
+	 . point. */
+	else if (dev->mc_count )  {
+		/* support hardware multicasting */
+
+		/* be sure I get rid of flags I might have set */
+		lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
+		SMC_SET_RCR( lp->rcr_cur_mode );
+		/* NOTE: this has to set the bank, so make sure it is the
+		   last thing called.  The bank is set to zero at the top */
+		smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
+	} else  {
+		PRINTK2("%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name);
+		lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
+		SMC_SET_RCR( lp->rcr_cur_mode );
+
+		/*
+		  since I'm disabling all multicast entirely, I need to
+		  clear the multicast list
+		*/
+		SMC_SELECT_BANK( 3 );
+		SMC_CLEAR_MCAST();
+	}
+}
+
+
+/*
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc ..
+ */
+static int
+smc_open(struct net_device *dev)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	/* clear out all the junk that was put here before... */
+	memset(dev->priv, 0, sizeof(struct smc_local));
+
+	// Setup the default Register Modes
+	lp->tcr_cur_mode = TCR_DEFAULT;
+	lp->rcr_cur_mode = RCR_DEFAULT;
+	lp->rpc_cur_mode = RPC_DEFAULT;
+
+	/* Set default parameters */
+#ifdef CONFIG_ARCH_RAMSES
+	lp->ctl_autoneg = 0;
+	lp->ctl_rfduplx = 0;
+	lp->ctl_rspeed = 10;
+#else
+	lp->ctl_autoneg = 1;
+	lp->ctl_rfduplx = 1;
+	lp->ctl_rspeed = 100;
+#endif
+
+	SMC_SELECT_BANK(3);
+	lp->version = SMC_GET_REV() & 0xff;
+
+	/* reset the hardware */
+	smc_reset(dev);
+	smc_enable(dev);
+
+	SMC_SELECT_BANK( 1 );
+	SMC_SET_MAC_ADDR(dev->dev_addr);
+
+	/* Configure the PHY */
+	if (lp->version >= 0x70)
+		smc_phy_configure(dev);
+
+	netif_start_queue(dev);
+	return 0;
+}
+
+/*----------------------------------------------------
+ . smc_close
+ .
+ . this makes the board clean up everything that it can
+ . and not talk to the outside world.   Caused by
+ . an 'ifconfig ethX down'
+ .
+ -----------------------------------------------------*/
+static int
+smc_close(struct net_device *dev)
+{
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	netif_stop_queue(dev);
+
+	/* clear everything */
+	smc_shutdown(dev);
+
+	return 0;
+}
+
+/*------------------------------------------------------------
+ . Get the current statistics.
+ . This may be called with the card open or closed.
+ .-------------------------------------------------------------*/
+static struct net_device_stats *
+smc_query_statistics(struct net_device *dev)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+
+	PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
+
+	return &lp->stats;
+}
+
+/*----------------------------------------------------------------------
+ . smc_findirq
+ .
+ . This routine has a simple purpose -- make the SMC chip generate an
+ . interrupt, so an auto-detect routine can detect it, and find the IRQ,
+ ------------------------------------------------------------------------
+*/
+int __init
+smc_findirq( unsigned long ioaddr )
+{
+	int timeout = 20;
+	unsigned long cookie;
+
+	PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
+
+	cookie = probe_irq_on();
+
+	/*
+	 * What I try to do here is trigger an ALLOC_INT. This is done
+	 * by allocating a small chunk of memory, which will give an interrupt
+	 * when done.
+	 */
+
+	/* enable ALLOCation interrupts ONLY */
+	SMC_SELECT_BANK(2);
+	SMC_SET_INT_MASK( IM_ALLOC_INT );
+
+	/*
+ 	 . Allocate 512 bytes of memory.  Note that the chip was just
+	 . reset so all the memory is available
+	*/
+	SMC_SET_MMU_CMD( MC_ALLOC | 1 );
+
+	/*
+	 . Wait until positive that the interrupt has been generated
+	*/
+	do {
+		int int_status;
+		udelay(10);
+		int_status = SMC_GET_INT();
+		if (int_status & IM_ALLOC_INT)
+			break;		/* got the interrupt */
+	} while (--timeout);
+
+	/* there is really nothing that I can do here if timeout fails,
+	   as autoirq_report will return a 0 anyway, which is what I
+	   want in this case.   Plus, the clean up is needed in both
+	   cases.  */
+
+	/* and disable all interrupts again */
+	SMC_SET_INT_MASK( 0 );
+
+	/* and return what I found */
+	return probe_irq_off(cookie);
+}
+
+/*----------------------------------------------------------------------
+ . Function: smc_probe( unsigned long ioaddr )
+ .
+ . Purpose:
+ .	Tests to see if a given ioaddr points to an SMC91x chip.
+ .	Returns a 0 on success
+ .
+ . Algorithm:
+ .	(1) see if the high byte of BANK_SELECT is 0x33
+ . 	(2) compare the ioaddr with the base register's address
+ .	(3) see if I recognize the chip ID in the appropriate register
+ .
+ .---------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------
+ . Here I do typical initialization tasks.
+ .
+ . o  Initialize the structure if needed
+ . o  print out my vanity message if not done so already
+ . o  print out what type of hardware is detected
+ . o  print out the ethernet address
+ . o  find the IRQ
+ . o  set up my private data
+ . o  configure the dev structure with my subroutines
+ . o  actually GRAB the irq.
+ . o  GRAB the region
+ .-----------------------------------------------------------------
+*/
+static int __init
+smc_probe(struct net_device *dev, unsigned long ioaddr)
+{
+	struct smc_local *lp = (struct smc_local *)dev->priv;
+	static int version_printed = 0;
+	int i, retval;
+	unsigned int val, revision_register;
+	const char *version_string;
+
+	PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
+
+	/* Grab the region so that no one else tries to probe our ioports. */
+	if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
+		return -EBUSY;
+
+	/* First, see if the high byte is 0x33 */
+	val = SMC_CURRENT_BANK();
+	PRINTK2("%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
+	if ( (val & 0xFF00) != 0x3300 ) {
+		if ( (val & 0xFF) == 0x33 ) {
+			printk( KERN_WARNING
+				"%s: Detected possible byte-swapped interface"
+				" at IOADDR 0x%lx\n", CARDNAME, ioaddr);
+		}
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/* The above MIGHT indicate a device, but I need to write to further
+ 	 	test this.  */
+	SMC_SELECT_BANK(0);
+	val = SMC_CURRENT_BANK();
+	if ( (val & 0xFF00 ) != 0x3300 ) {
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/* well, we've already written once, so hopefully another time won't
+ 	   hurt.  This time, I need to switch the bank register to bank 1,
+	   so I can access the base address register */
+	SMC_SELECT_BANK(1);
+	val = SMC_GET_BASE();
+	val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
+	if ( (ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val ) {
+		printk( "%s: IOADDR %lx doesn't match configuration (%x).\n",
+			CARDNAME, ioaddr, val );
+	}
+
+	/*  check if the revision register is something that I recognize.
+	    These might need to be added to later, as future revisions
+	    could be added.  */
+	SMC_SELECT_BANK(3);
+	revision_register = SMC_GET_REV();
+	PRINTK2("%s: revision = 0x%04x\n", CARDNAME, revision_register);
+	version_string = chip_ids[ (revision_register >> 4) & 0xF];
+	if (!version_string || (revision_register & 0xff00) != 0x3300) {
+		/* I don't recognize this chip, so... */
+		printk( "%s: IO 0x%lx: Unrecognized revision register 0x%04x"
+			", Contact author.\n", CARDNAME,
+			ioaddr, revision_register);
+
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/* At this point I'll assume that the chip is an SMC91x. */
+	if (version_printed++ == 0)
+		printk("%s", version);
+
+	/* set the private data to zero by default */
+	memset(lp, 0, sizeof(struct smc_local));
+
+	/* fill in some of the fields */
+	dev->base_addr = ioaddr;
+	lp->version = revision_register & 0xff;
+
+	/* Get the MAC address */
+	SMC_SELECT_BANK( 1 );
+	SMC_GET_MAC_ADDR(dev->dev_addr);
+
+	/* now, reset the chip, and put it into a known state */
+	smc_reset( dev );
+
+	/*
+	 . If dev->irq is 0, then the device has to be banged on to see
+	 . what the IRQ is.
+ 	 .
+	 . This banging doesn't always detect the IRQ, for unknown reasons.
+	 . a workaround is to reset the chip and try again.
+	 .
+	 . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
+	 . be what is requested on the command line.   I don't do that, mostly
+	 . because the card that I have uses a non-standard method of accessing
+	 . the IRQs, and because this _should_ work in most configurations.
+	 .
+	 . Specifying an IRQ is done with the assumption that the user knows
+	 . what (s)he is doing.  No checking is done!!!!
+ 	 .
+	*/
+	if ( dev->irq < 1 ) {
+		int	trials;
+
+		trials = 3;
+		while ( trials-- ) {
+			dev->irq = smc_findirq( ioaddr );
+			if ( dev->irq )
+				break;
+			/* kick the card and try again */
+			smc_reset( dev );
+		}
+	}
+	if (dev->irq == 0 ) {
+		printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
+			dev->name);
+		retval = -ENODEV;
+		goto err_out;
+	}
+	dev->irq = irq_cannonicalize(dev->irq);
+
+	/* now, print out the card info, in a short format.. */
+	printk( "%s: %s (rev %d) at %#lx IRQ %d%s%s\n",
+		dev->name, version_string, revision_register & 0x0f,
+		ioaddr, dev->irq, nowait ? " [nowait]" : "",
+		THROTTLE_TX_PKTS ? " [throttle_tx]" : "" );
+
+	/* Print the Ethernet address */
+	printk("%s: Ethernet addr: ", dev->name);
+	for (i = 0; i < 5; i++)
+		printk("%2.2x:", dev->dev_addr[i] );
+	printk("%2.2x\n", dev->dev_addr[5] );
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(dev);
+
+	/* Grab the IRQ */
+      	retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
+      	if (retval) {
+  	  	goto err_out;
+      	}
+
+	dev->open		        = smc_open;
+	dev->stop		        = smc_close;
+	dev->hard_start_xmit    	= smc_hard_start_xmit;
+	dev->tx_timeout		    	= smc_timeout;
+	dev->watchdog_timeo		= HZ/10;
+	dev->get_stats			= smc_query_statistics;
+	dev->set_multicast_list 	= smc_set_multicast_list;
+
+	return 0;
+
+err_out:
+	release_region(ioaddr, SMC_IO_EXTENT);
+	return retval;
+}
+
+/*-------------------------------------------------------------------------
+ |
+ | smc_init( void )
+ |   Input parameters:
+ |	dev->base_addr == 0, try to find all possible locations
+ |	dev->base_addr > 0x1ff, this is the address to check
+ |	dev->base_addr == <anything else>, return failure code
+ |
+ |   Output:
+ |	0 --> there is a device
+ |	anything else, error
+ |
+ ---------------------------------------------------------------------------
+*/
+static struct net_device *global_dev = NULL;  /* needs to be fixed */
+
+#ifdef CONFIG_PM
+
+static int smc_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	unsigned long ioaddr = global_dev->base_addr;
+	struct smc_local *lp = (struct smc_local *)global_dev->priv;
+
+	switch (rqst) {
+	case PM_SUSPEND:
+		smc_shutdown(global_dev);
+		break;
+	case PM_RESUME:
+		smc_reset(global_dev);
+		smc_enable(global_dev);
+		SMC_SELECT_BANK( 1 );
+	        SMC_SET_MAC_ADDR(global_dev->dev_addr);
+	        if (lp->version >= 0x70)
+        	        smc_phy_configure(global_dev);
+		break;
+	}
+	return 0;
+}
+
+#endif
+
+static int __init
+smc_init(void)
+{
+	int ret;
+
+	PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
+
+#ifdef MODULE
+	if (io == -1)
+		printk( KERN_WARNING 
+			"%s: You shouldn't use auto-probing with insmod!\n",
+			CARDNAME );
+#endif
+
+	if (global_dev) {
+		printk("%s: already initialized.\n", CARDNAME);
+		return -EBUSY;
+	}
+
+	global_dev = init_etherdev(0, sizeof(struct smc_local));
+	if (!global_dev) {
+		printk("%s: could not allocate device.\n", CARDNAME);
+		return -ENOMEM;
+	}
+	SET_MODULE_OWNER(global_dev);
+
+	/* copy the parameters from insmod into the device structure */
+	if (io != -1)
+		global_dev->base_addr	= io;
+	if (irq != -1)
+		global_dev->irq	= irq;
+
+#ifdef CONFIG_ISA
+	/*  try a specific location */
+	if (global_dev->base_addr > 0x1ff)
+		ret = smc_probe(global_dev, global_dev->base_addr);
+	else if (global_dev->base_addr != 0)
+		ret = -ENXIO;
+	else {
+		int i;
+
+		/* check every ethernet address */
+		for (i = 0; smc_portlist[i]; i++) {
+			ret = smc_probe(global_dev, smc_portlist[i]);
+			if (ret == 0)
+				break;
+		}
+	}
+#elif defined(CONFIG_ARCH_LUBBOCK)
+	{
+		int ioaddr = LUBBOCK_ETH_VIRT + (0x300 << 2);
+		volatile int *attaddr = (int *)(LUBBOCK_ETH_VIRT + 0x100000);
+		unsigned long flags;
+
+		/* first reset, then enable the device. Sequence is critical */
+		local_irq_save(flags);
+		attaddr[ECOR] |= ECOR_RESET;
+		udelay(100);
+		attaddr[ECOR] &= ~ECOR_RESET;
+		attaddr[ECOR] |= ECOR_ENABLE;
+
+		/* force 16-bit mode */
+		attaddr[ECSR] &= ~ECSR_IOIS8;
+		mdelay(1);
+		local_irq_restore(flags);
+
+		global_dev->irq = LUBBOCK_ETH_IRQ;
+		ret = smc_probe(global_dev, ioaddr);
+	}
+#elif defined(CONFIG_ARCH_PXA_IDP)
+	{
+		int ioaddr = IDP_ETH_BASE + 0x300;
+		global_dev->irq = SMC_IRQ;
+		ret = smc_probe(global_dev, ioaddr);
+	}
+#elif defined(CONFIG_ARCH_RAMSES)
+	{
+		int ioaddr = RAMSES_ETH_BASE + 0x300;
+		global_dev->irq = SMC_IRQ;
+		ret = smc_probe(global_dev, ioaddr);
+	}
+#else
+	if (global_dev->base_addr == -1) {
+		printk(KERN_WARNING"%s: SMC91X_BASE_ADDR not set!\n", CARDNAME);
+		ret = -ENXIO;
+	} else {
+		void *ioaddr = ioremap(global_dev->base_addr, SMC_IO_EXTENT);
+		ret = smc_probe(global_dev, (unsigned long)ioaddr);
+		if (ret != 0)
+			iounmap(ioaddr);
+	}
+#endif
+
+#ifdef SMC_USE_PXA_DMA
+	if (ret == 0) {
+		int dma = pxa_request_dma(global_dev->name, DMA_PRIO_LOW,
+					  smc_pxa_dma_irq, NULL);
+		if (dma >= 0) {
+			global_dev->dma = dma;
+			PRINTK("%s: using DMA channel %d\n", global_dev->name, dma);
+		} else {
+			global_dev->dma = -1;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PM
+	if (ret == 0) {
+		struct smc_local *lp = (struct smc_local *)global_dev->priv;
+		lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback);
+	}
+#endif
+
+	if (ret != 0) {
+		printk("%s: not found.\n", CARDNAME);
+		kfree(global_dev->priv);
+		unregister_netdev(global_dev);
+		kfree(global_dev);
+	}
+
+	return ret;
+}
+
+static void __exit
+smc_cleanup(void)
+{
+	unregister_netdev(global_dev);
+#ifdef CONFIG_PM
+	{
+		struct smc_local *lp = (struct smc_local *)global_dev->priv;
+		pm_unregister(lp->pm);
+	}
+#endif
+	free_irq(global_dev->irq, global_dev);
+	release_region(global_dev->base_addr, SMC_IO_EXTENT);
+
+#ifndef CONFIG_ISA
+	iounmap((void *)global_dev->base_addr);
+#endif
+
+	kfree(global_dev);
+	global_dev = NULL;
+}
+
+module_init(smc_init);
+module_exit(smc_cleanup);
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/net/smc91x.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,835 @@
+/*------------------------------------------------------------------------
+ . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device.
+ .
+ . Copyright (C) 1996 by Erik Stahlman
+ . Copyright (C) 2001 Standard Microsystems Corporation
+ .	Developed by Simple Network Magic Corporation
+ . Copyright (C) 2003 Monta Vista Software, Inc.
+ .	Unified SMC91x driver by Nicolas Pitre
+ .
+ . 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
+ .
+ . Information contained in this file was obtained from the LAN91C111
+ . manual from SMC.  To get a copy, if you really want one, you can find
+ . information under www.smsc.com.
+ .
+ . Authors
+ .	Erik Stahlman		<erik@vt.edu>
+ .	Daris A Nevil		<dnevil@snmc.com>
+ .	Nicolas Pitre 		<nico@cam.org>
+ .
+ ---------------------------------------------------------------------------*/
+#ifndef _SMC91X_H_
+#define _SMC91X_H_
+
+
+/*
+ * Define your architecture specific configuration parameters here.
+ */
+
+#if	defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
+	defined(CONFIG_SA1100_PFS168) || \
+	defined(CONFIG_SA1100_FLEXANET) || \
+	defined(CONFIG_SA1100_GRAPHICSMASTER) || \
+	defined(CONFIG_ARCH_LUBBOCK)
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+#define SMC_NOWAIT		1
+
+/* The first two address lines aren't connected... */
+#define SMC_IO_SHIFT		2
+
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
+
+#ifdef CONFIG_ARCH_LUBBOCK
+#define SMC_IOADDR		LUBBOCK_ETH_PHYS
+#endif
+
+#elif	defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_ARCH_PXA_IDP) || defined(CONFIG_ARCH_RAMSES)
+
+#ifdef CONFIG_ARCH_MAINSTONE
+#include <asm/arch/mainstone.h>
+#define SMC_IOADDR		(MST_ETH_PHYS + 0x300)
+#define SMC_IRQ			MAINSTONE_IRQ(3)
+
+#elif CONFIG_ARCH_PXA_IDP
+#include <asm/arch/idp.h>
+#define SMC_IOADDR		(IDP_ETH_PHYS + 0x300)
+#define SMC_IRQ			ETHERNET_IRQ
+	
+#elif CONFIG_ARCH_RAMSES
+#include <asm/arch/ramses.h>
+#define SMC_IOADDR		(RAMSES_ETH_PHYS + 0x300)
+#define SMC_IRQ			ETHERNET_IRQ
+#endif
+	
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	1
+#define SMC_IO_SHIFT		0
+#define SMC_NOWAIT		1
+#define SMC_USE_PXA_DMA		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)	insl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)	outsl((a) + (r), p, l)
+
+/* We actually can't write halfwords properly if not word aligned */
+static inline void
+SMC_outw(u16 val, unsigned long ioaddr, int reg)
+{
+	if (reg & 2) {
+		unsigned int v = val << 16;
+		v |= readl(ioaddr + (reg & ~2)) & 0xffff;
+		writel(v, ioaddr + (reg & ~2));
+	} else {
+		writew(val, ioaddr + reg);
+	}
+}
+
+#elif	defined(CONFIG_ISA)
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+
+#define SMC_inb(a, r)		inb((a) + (r))
+#define SMC_inw(a, r)		inw((a) + (r))
+#define SMC_outb(v, a, r)	outb(v, (a) + (r))
+#define SMC_outw(v, a, r)	outw(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
+
+#endif
+
+
+#ifdef SMC_USE_PXA_DMA
+/*
+ * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
+ * always happening in irq context so no need to worry about races.  TX is
+ * different and probably not worth it for that reason, and not as critical
+ * as RX which can overrun memory and lose packets.
+ */
+#include <linux/pci.h>
+#include <asm/dma.h>
+
+#ifdef SMC_insl
+#undef SMC_insl
+#define SMC_insl(a, r, p, l)	smc_pxa_dma_insl(a, r, dev->dma, p, l)
+static inline void
+smc_pxa_dma_insl(u_long ioaddr, int reg, int dma, u_char *buf, int len)
+{
+	dma_addr_t dmabuf;
+
+	/* fallback if no DMA available */
+	if (dma == -1) {
+		insl(ioaddr + reg, buf, len);
+		return;
+	}
+
+	/* 64 bit alignment is required for memory to memory DMA */
+	if ((long)buf & 4) {
+		*((u32 *)buf)++ = SMC_inl(ioaddr, reg);
+		len--;
+	}
+
+	len *= 4;
+	dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
+	DCSR(dma) = DCSR_NODESC;
+	DTADR(dma) = dmabuf;
+	DSADR(dma) = SMC_IOADDR + reg;
+	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+		     DCMD_WIDTH4 | (DCMD_LENGTH & len));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+	while (!(DCSR(dma) & DCSR_STOPSTATE));
+	DCSR(dma) = 0;
+	pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE);
+}
+#endif
+
+#ifdef SMC_insw
+#undef SMC_insw
+#define SMC_insw(a, r, p, l)	smc_pxa_dma_insw(a, r, dev->dma, p, l)
+static inline void
+smc_pxa_dma_insw(u_long ioaddr, int reg, int dma, u_char *buf, int len)
+{
+	dma_addr_t dmabuf;
+
+	/* fallback if no DMA available */
+	if (dma == -1) {
+		insw(ioaddr + reg, buf, len);
+		return;
+	}
+
+	/* 64 bit alignment is required for memory to memory DMA */
+	while ((long)buf & 6) {
+		*((u16 *)buf)++ = SMC_inw(ioaddr, reg);
+		len--;
+	}
+
+	len *= 2;
+	dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
+	DCSR(dma) = DCSR_NODESC;
+	DTADR(dma) = dmabuf;
+	DSADR(dma) = SMC_IOADDR + reg;
+	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+		     DCMD_WIDTH2 | (DCMD_LENGTH & len));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+	while (!(DCSR(dma) & DCSR_STOPSTATE));
+	DCSR(dma) = 0;
+	pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE);
+}
+#endif
+
+static void
+smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
+{
+	DCSR(dma) = 0;
+}
+#endif  /* SMC_USE_PXA_DMA */
+
+
+/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */
+#ifndef SMC_IO_SHIFT
+#define SMC_IO_SHIFT	0
+#endif
+#define SMC_IO_EXTENT	(16 << SMC_IO_SHIFT)
+
+
+/*
+ . Bank Select Register:
+ .
+ .		yyyy yyyy 0000 00xx
+ .		xx 		= bank number
+ .		yyyy yyyy	= 0x33, for identification purposes.
+*/
+#define BANK_SELECT		(14 << SMC_IO_SHIFT)
+
+
+// Transmit Control Register
+/* BANK 0  */
+#define TCR_REG 	SMC_REG(0x0000, 0)
+#define TCR_ENABLE	0x0001	// When 1 we can transmit
+#define TCR_LOOP	0x0002	// Controls output pin LBK
+#define TCR_FORCOL	0x0004	// When 1 will force a collision
+#define TCR_PAD_EN	0x0080	// When 1 will pad tx frames < 64 bytes w/0
+#define TCR_NOCRC	0x0100	// When 1 will not append CRC to tx frames
+#define TCR_MON_CSN	0x0400	// When 1 tx monitors carrier
+#define TCR_FDUPLX    	0x0800  // When 1 enables full duplex operation
+#define TCR_STP_SQET	0x1000	// When 1 stops tx if Signal Quality Error
+#define TCR_EPH_LOOP	0x2000	// When 1 enables EPH block loopback
+#define TCR_SWFDUP	0x8000	// When 1 enables Switched Full Duplex mode
+
+#define TCR_CLEAR	0	/* do NOTHING */
+/* the default settings for the TCR register : */
+#define TCR_DEFAULT	(TCR_ENABLE | TCR_PAD_EN)
+
+
+// EPH Status Register
+/* BANK 0  */
+#define EPH_STATUS_REG	SMC_REG(0x0002, 0)
+#define ES_TX_SUC	0x0001	// Last TX was successful
+#define ES_SNGL_COL	0x0002	// Single collision detected for last tx
+#define ES_MUL_COL	0x0004	// Multiple collisions detected for last tx
+#define ES_LTX_MULT	0x0008	// Last tx was a multicast
+#define ES_16COL	0x0010	// 16 Collisions Reached
+#define ES_SQET		0x0020	// Signal Quality Error Test
+#define ES_LTXBRD	0x0040	// Last tx was a broadcast
+#define ES_TXDEFR	0x0080	// Transmit Deferred
+#define ES_LATCOL	0x0200	// Late collision detected on last tx
+#define ES_LOSTCARR	0x0400	// Lost Carrier Sense
+#define ES_EXC_DEF	0x0800	// Excessive Deferral
+#define ES_CTR_ROL	0x1000	// Counter Roll Over indication
+#define ES_LINK_OK	0x4000	// Driven by inverted value of nLNK pin
+#define ES_TXUNRN	0x8000	// Tx Underrun
+
+
+// Receive Control Register
+/* BANK 0  */
+#define RCR_REG		SMC_REG(0x0004, 0)
+#define RCR_RX_ABORT	0x0001	// Set if a rx frame was aborted
+#define RCR_PRMS	0x0002	// Enable promiscuous mode
+#define RCR_ALMUL	0x0004	// When set accepts all multicast frames
+#define RCR_RXEN	0x0100	// IFF this is set, we can receive packets
+#define RCR_STRIP_CRC	0x0200	// When set strips CRC from rx packets
+#define RCR_ABORT_ENB	0x0200	// When set will abort rx on collision
+#define RCR_FILT_CAR	0x0400	// When set filters leading 12 bit s of carrier
+#define RCR_SOFTRST	0x8000 	// resets the chip
+
+/* the normal settings for the RCR register : */
+#define RCR_DEFAULT	(RCR_STRIP_CRC | RCR_RXEN)
+#define RCR_CLEAR	0x0	// set it to a base state
+
+
+// Counter Register
+/* BANK 0  */
+#define COUNTER_REG	SMC_REG(0x0006, 0)
+
+
+// Memory Information Register
+/* BANK 0  */
+#define MIR_REG		SMC_REG(0x0008, 0)
+
+
+// Receive/Phy Control Register
+/* BANK 0  */
+#define RPC_REG		SMC_REG(0x000A, 0)
+#define RPC_SPEED	0x2000	// When 1 PHY is in 100Mbps mode.
+#define RPC_DPLX	0x1000	// When 1 PHY is in Full-Duplex Mode
+#define RPC_ANEG	0x0800	// When 1 PHY is in Auto-Negotiate Mode
+#define RPC_LSXA_SHFT	5	// Bits to shift LS2A,LS1A,LS0A to lsb
+#define RPC_LSXB_SHFT	2	// Bits to get LS2B,LS1B,LS0B to lsb
+#define RPC_LED_100_10	(0x00)	// LED = 100Mbps OR's with 10Mbps link detect
+#define RPC_LED_RES	(0x01)	// LED = Reserved
+#define RPC_LED_10	(0x02)	// LED = 10Mbps link detect
+#define RPC_LED_FD	(0x03)	// LED = Full Duplex Mode
+#define RPC_LED_TX_RX	(0x04)	// LED = TX or RX packet occurred
+#define RPC_LED_100	(0x05)	// LED = 100Mbps link dectect
+#define RPC_LED_TX	(0x06)	// LED = TX packet occurred
+#define RPC_LED_RX	(0x07)	// LED = RX packet occurred
+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+
+
+/* Bank 0 0x0C is reserved */
+
+// Bank Select Register
+/* All Banks */
+#define BSR_REG		0x000E
+
+
+// Configuration Reg
+/* BANK 1 */
+#define CONFIG_REG	SMC_REG(0x0000,	1)
+#define CONFIG_EXT_PHY	0x0200	// 1=external MII, 0=internal Phy
+#define CONFIG_GPCNTRL	0x0400	// Inverse value drives pin nCNTRL
+#define CONFIG_NO_WAIT	0x1000	// When 1 no extra wait states on ISA bus
+#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode.
+
+// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
+#define CONFIG_DEFAULT	(CONFIG_EPH_POWER_EN)
+
+
+// Base Address Register
+/* BANK 1 */
+#define BASE_REG	SMC_REG(0x0002, 1)
+
+
+// Individual Address Registers
+/* BANK 1 */
+#define ADDR0_REG	SMC_REG(0x0004, 1)
+#define ADDR1_REG	SMC_REG(0x0006, 1)
+#define ADDR2_REG	SMC_REG(0x0008, 1)
+
+
+// General Purpose Register
+/* BANK 1 */
+#define GP_REG		SMC_REG(0x000A, 1)
+
+
+// Control Register
+/* BANK 1 */
+#define CTL_REG		SMC_REG(0x000C, 1)
+#define CTL_RCV_BAD	0x4000 // When 1 bad CRC packets are received
+#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
+#define CTL_LE_ENABLE	0x0080 // When 1 enables Link Error interrupt
+#define CTL_CR_ENABLE	0x0040 // When 1 enables Counter Rollover interrupt
+#define CTL_TE_ENABLE	0x0020 // When 1 enables Transmit Error interrupt
+#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store
+#define CTL_RELOAD	0x0002 // When set reads EEPROM into registers
+#define CTL_STORE	0x0001 // When set stores registers into EEPROM
+
+
+// MMU Command Register
+/* BANK 2 */
+#define MMU_CMD_REG	SMC_REG(0x0000, 2)
+#define MC_BUSY		1	// When 1 the last release has not completed
+#define MC_NOP		(0<<5)	// No Op
+#define MC_ALLOC	(1<<5) 	// OR with number of 256 byte packets
+#define MC_RESET	(2<<5)	// Reset MMU to initial state
+#define MC_REMOVE	(3<<5) 	// Remove the current rx packet
+#define MC_RELEASE  	(4<<5) 	// Remove and release the current rx packet
+#define MC_FREEPKT  	(5<<5) 	// Release packet in PNR register
+#define MC_ENQUEUE	(6<<5)	// Enqueue the packet for transmit
+#define MC_RSTTXFIFO	(7<<5)	// Reset the TX FIFOs
+
+
+// Packet Number Register
+/* BANK 2 */
+#define PN_REG		SMC_REG(0x0002, 2)
+
+
+// Allocation Result Register
+/* BANK 2 */
+#define AR_REG		SMC_REG(0x0003, 2)
+#define AR_FAILED	0x80	// Alocation Failed
+
+
+// TX FIFO Ports Register
+/* BANK 2 */
+#define TXFIFO_REG	SMC_REG(0x0004, 2)
+#define TXFIFO_TEMPTY	0x80	// TX FIFO Empty
+
+// RX FIFO Ports Register
+/* BANK 2 */
+#define RXFIFO_REG	SMC_REG(0x0005, 2)
+#define RXFIFO_REMPTY	0x80	// RX FIFO Empty
+
+#define FIFO_REG	SMC_REG(0x0004, 2)
+
+// Pointer Register
+/* BANK 2 */
+#define PTR_REG		SMC_REG(0x0006, 2)
+#define PTR_RCV		0x8000 // 1=Receive area, 0=Transmit area
+#define PTR_AUTOINC 	0x4000 // Auto increment the pointer on each access
+#define PTR_READ	0x2000 // When 1 the operation is a read
+
+
+// Data Register
+/* BANK 2 */
+#define DATA_REG	SMC_REG(0x0008, 2)
+
+
+// Interrupt Status/Acknowledge Register
+/* BANK 2 */
+#define INT_REG		SMC_REG(0x000C, 2)
+
+
+// Interrupt Mask Register
+/* BANK 2 */
+#define IM_REG		SMC_REG(0x000D, 2)
+#define IM_MDINT	0x80 // PHY MI Register 18 Interrupt
+#define IM_ERCV_INT	0x40 // Early Receive Interrupt
+#define IM_EPH_INT	0x20 // Set by Ethernet Protocol Handler section
+#define IM_RX_OVRN_INT	0x10 // Set by Receiver Overruns
+#define IM_ALLOC_INT	0x08 // Set when allocation request is completed
+#define IM_TX_EMPTY_INT	0x04 // Set if the TX FIFO goes empty
+#define IM_TX_INT	0x02 // Transmit Interrupt
+#define IM_RCV_INT	0x01 // Receive Interrupt
+
+
+// Multicast Table Registers
+/* BANK 3 */
+#define MCAST_REG1	SMC_REG(0x0000, 3)
+#define MCAST_REG2	SMC_REG(0x0002, 3)
+#define MCAST_REG3	SMC_REG(0x0004, 3)
+#define MCAST_REG4	SMC_REG(0x0006, 3)
+
+
+// Management Interface Register (MII)
+/* BANK 3 */
+#define MII_REG		SMC_REG(0x0008, 3)
+#define MII_MSK_CRS100	0x4000 // Disables CRS100 detection during tx half dup
+#define MII_MDOE	0x0008 // MII Output Enable
+#define MII_MCLK	0x0004 // MII Clock, pin MDCLK
+#define MII_MDI		0x0002 // MII Input, pin MDI
+#define MII_MDO		0x0001 // MII Output, pin MDO
+
+
+// Revision Register
+/* BANK 3 */
+/* ( hi: chip id   low: rev # ) */
+#define REV_REG		SMC_REG(0x000A, 3)
+
+
+// Early RCV Register
+/* BANK 3 */
+/* this is NOT on SMC9192 */
+#define ERCV_REG	SMC_REG(0x000C, 3)
+#define ERCV_RCV_DISCRD	0x0080 // When 1 discards a packet being received
+#define ERCV_THRESHOLD	0x001F // ERCV Threshold Mask
+
+
+// External Register
+/* BANK 7 */
+#define EXT_REG		SMC_REG(0x0000, 7)
+
+
+#define CHIP_9192	3
+#define CHIP_9194	4
+#define CHIP_9195	5
+#define CHIP_9196	6
+#define CHIP_91100	7
+#define CHIP_91100FD	8
+#define CHIP_91111FD	9
+
+static const char * chip_ids[ 16 ] =  {
+	NULL, NULL, NULL,
+	/* 3 */ "SMC91C90/91C92",
+	/* 4 */ "SMC91C94",
+	/* 5 */ "SMC91C95",
+	/* 6 */ "SMC91C96",
+	/* 7 */ "SMC91C100",
+	/* 8 */ "SMC91C100FD",
+	/* 9 */ "SMC91C11xFD",
+	NULL, NULL, NULL,
+	NULL, NULL, NULL};
+
+
+/*
+ . Transmit status bits
+*/
+#define TS_SUCCESS 0x0001
+#define TS_LOSTCAR 0x0400
+#define TS_LATCOL  0x0200
+#define TS_16COL   0x0010
+
+/*
+ . Receive status bits
+*/
+#define RS_ALGNERR	0x8000
+#define RS_BRODCAST	0x4000
+#define RS_BADCRC	0x2000
+#define RS_ODDFRAME	0x1000
+#define RS_TOOLONG	0x0800
+#define RS_TOOSHORT	0x0400
+#define RS_MULTICAST	0x0001
+#define RS_ERRORS	(RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
+
+
+// PHY Types
+enum {
+	PHY_LAN83C183 = 1,	// LAN91C111 Internal PHY
+	PHY_LAN83C180
+};
+
+
+// PHY Register Addresses (LAN91C111 Internal PHY)
+
+// PHY Control Register
+#define PHY_CNTL_REG		0x00
+#define PHY_CNTL_RST		0x8000	// 1=PHY Reset
+#define PHY_CNTL_LPBK		0x4000	// 1=PHY Loopback
+#define PHY_CNTL_SPEED		0x2000	// 1=100Mbps, 0=10Mpbs
+#define PHY_CNTL_ANEG_EN	0x1000	// 1=Enable Auto negotiation
+#define PHY_CNTL_PDN		0x0800	// 1=PHY Power Down mode
+#define PHY_CNTL_MII_DIS	0x0400	// 1=MII 4 bit interface disabled
+#define PHY_CNTL_ANEG_RST	0x0200	// 1=Reset Auto negotiate
+#define PHY_CNTL_DPLX		0x0100	// 1=Full Duplex, 0=Half Duplex
+#define PHY_CNTL_COLTST		0x0080	// 1= MII Colision Test
+
+// PHY Status Register
+#define PHY_STAT_REG		0x01
+#define PHY_STAT_CAP_T4		0x8000	// 1=100Base-T4 capable
+#define PHY_STAT_CAP_TXF	0x4000	// 1=100Base-X full duplex capable
+#define PHY_STAT_CAP_TXH	0x2000	// 1=100Base-X half duplex capable
+#define PHY_STAT_CAP_TF		0x1000	// 1=10Mbps full duplex capable
+#define PHY_STAT_CAP_TH		0x0800	// 1=10Mbps half duplex capable
+#define PHY_STAT_CAP_SUPR	0x0040	// 1=recv mgmt frames with not preamble
+#define PHY_STAT_ANEG_ACK	0x0020	// 1=ANEG has completed
+#define PHY_STAT_REM_FLT	0x0010	// 1=Remote Fault detected
+#define PHY_STAT_CAP_ANEG	0x0008	// 1=Auto negotiate capable
+#define PHY_STAT_LINK		0x0004	// 1=valid link
+#define PHY_STAT_JAB		0x0002	// 1=10Mbps jabber condition
+#define PHY_STAT_EXREG		0x0001	// 1=extended registers implemented
+
+// PHY Identifier Registers
+#define PHY_ID1_REG		0x02	// PHY Identifier 1
+#define PHY_ID2_REG		0x03	// PHY Identifier 2
+
+// PHY Auto-Negotiation Advertisement Register
+#define PHY_AD_REG		0x04
+#define PHY_AD_NP		0x8000	// 1=PHY requests exchange of Next Page
+#define PHY_AD_ACK		0x4000	// 1=got link code word from remote
+#define PHY_AD_RF		0x2000	// 1=advertise remote fault
+#define PHY_AD_T4		0x0200	// 1=PHY is capable of 100Base-T4
+#define PHY_AD_TX_FDX		0x0100	// 1=PHY is capable of 100Base-TX FDPLX
+#define PHY_AD_TX_HDX		0x0080	// 1=PHY is capable of 100Base-TX HDPLX
+#define PHY_AD_10_FDX		0x0040	// 1=PHY is capable of 10Base-T FDPLX
+#define PHY_AD_10_HDX		0x0020	// 1=PHY is capable of 10Base-T HDPLX
+#define PHY_AD_CSMA		0x0001	// 1=PHY is capable of 802.3 CMSA
+
+// PHY Auto-negotiation Remote End Capability Register
+#define PHY_RMT_REG		0x05
+// Uses same bit definitions as PHY_AD_REG
+
+// PHY Configuration Register 1
+#define PHY_CFG1_REG		0x10
+#define PHY_CFG1_LNKDIS		0x8000	// 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS		0x4000	// 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN		0x2000	// 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR		0x0400	// 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS		0x0200	// 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR		0x0100	// 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE		0x0080	// 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0		0x0040	// 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT	2	// Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK	0x003C
+#define PHY_CFG1_TRF_MASK	0x0003	// Transmitter Rise/Fall time
+
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG		0x11
+#define PHY_CFG2_APOLDIS	0x0020	// 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS		0x0010	// 1=Jabber disabled
+#define PHY_CFG2_MREG		0x0008	// 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO	0x0004	// 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG		0x12	// Status Output (Interrupt Status)
+#define PHY_INT_INT		0x8000	// 1=bits have changed since last read
+#define PHY_INT_LNKFAIL		0x4000	// 1=Link Not detected
+#define PHY_INT_LOSSSYNC	0x2000	// 1=Descrambler has lost sync
+#define PHY_INT_CWRD		0x1000	// 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD		0x0800	// 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD		0x0400	// 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL		0x0200	// 1=Reverse Polarity detected
+#define PHY_INT_JAB		0x0100	// 1=Jabber detected
+#define PHY_INT_SPDDET		0x0080	// 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET		0x0040	// 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG		0x13	// Interrupt Mask
+// Uses the same bit definitions as PHY_INT_REG
+
+
+/*
+ * SMC91C96 ethernet config and status registers.
+ * These are in the "attribute" space.
+ */
+#define ECOR			0x8000
+#define ECOR_RESET		0x80
+#define ECOR_LEVEL_IRQ		0x40
+#define ECOR_WR_ATTRIB		0x04
+#define ECOR_ENABLE		0x01
+
+#define ECSR			0x8002
+#define ECSR_IOIS8		0x20
+#define ECSR_PWRDWN		0x04
+#define ECSR_INT		0x02
+
+
+/*
+ * Macros to abstract register access according to the data bus
+ * capabilities.  Please try to use those and not the in/out primitives.
+ * Note: the following macros do *not* select the bank -- this must
+ * be done separately as needed in the main code.  The SMC_REG() macro
+ * only uses the bank argument for debugging purposes.
+ */
+
+#if SMC_DEBUG > 0
+#define SMC_REG(reg, bank)						\
+	({								\
+		int __b = SMC_CURRENT_BANK();				\
+		if ((__b & ~0xf0) != (0x3300 | bank)) {			\
+			printk( "%s: bank reg screwed (0x%04x)\n",	\
+				CARDNAME, __b );			\
+			BUG();						\
+		}							\
+		reg<<SMC_IO_SHIFT;					\
+	})
+#else
+#define SMC_REG(reg, bank)	(reg<<SMC_IO_SHIFT)
+#endif
+
+#if SMC_CAN_USE_8BIT
+#define SMC_GET_PN()		SMC_inb( ioaddr, PN_REG )
+#define SMC_SET_PN(x)		SMC_outb( x, ioaddr, PN_REG )
+#define SMC_GET_AR()		SMC_inb( ioaddr, AR_REG )
+#define SMC_GET_TXFIFO()	SMC_inb( ioaddr, TXFIFO_REG )
+#define SMC_GET_RXFIFO()	SMC_inb( ioaddr, RXFIFO_REG )
+#define SMC_GET_INT()		SMC_inb( ioaddr, INT_REG )
+#define SMC_ACK_INT(x)		SMC_outb( x, ioaddr, INT_REG )
+#define SMC_GET_INT_MASK()	SMC_inb( ioaddr, IM_REG )
+#define SMC_SET_INT_MASK(x)	SMC_outb( x, ioaddr, IM_REG )
+#else
+#define SMC_GET_PN()		(SMC_inw( ioaddr, PN_REG ) & 0xFF)
+#define SMC_SET_PN(x)		SMC_outw( x, ioaddr, PN_REG )
+#define SMC_GET_AR()		(SMC_inw( ioaddr, PN_REG ) >> 8)
+#define SMC_GET_TXFIFO()	(SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF)
+#define SMC_GET_RXFIFO()	(SMC_inw( ioaddr, TXFIFO_REG ) >> 8)
+#define SMC_GET_INT()		(SMC_inw( ioaddr, INT_REG ) & 0xFF)
+#define SMC_ACK_INT(x)							\
+	do {								\
+		unsigned long __flags;					\
+		int __mask;						\
+		local_irq_save(__flags);				\
+		__mask = SMC_inw( ioaddr, INT_REG ) & ~0xff;		\
+		SMC_outw( __mask | (x), ioaddr, INT_REG );		\
+		local_irq_restore(__flags);				\
+	} while (0)
+#define SMC_GET_INT_MASK()	(SMC_inw( ioaddr, INT_REG ) >> 8)
+#define SMC_SET_INT_MASK(x)	SMC_outw( (x) << 8, ioaddr, INT_REG )
+#endif
+
+#define SMC_CURRENT_BANK()	SMC_inw( ioaddr, BANK_SELECT )
+#define SMC_SELECT_BANK(x)	SMC_outw( x, ioaddr, BANK_SELECT )
+#define SMC_GET_BASE()		SMC_inw( ioaddr, BASE_REG )
+#define SMC_SET_BASE(x)		SMC_outw( x, ioaddr, BASE_REG )
+#define SMC_GET_CONFIG()	SMC_inw( ioaddr, CONFIG_REG )
+#define SMC_SET_CONFIG(x)	SMC_outw( x, ioaddr, CONFIG_REG )
+#define SMC_GET_COUNTER()	SMC_inw( ioaddr, COUNTER_REG )
+#define SMC_GET_CTL()		SMC_inw( ioaddr, CTL_REG )
+#define SMC_SET_CTL(x)		SMC_outw( x, ioaddr, CTL_REG )
+#define SMC_GET_MII()		SMC_inw( ioaddr, MII_REG )
+#define SMC_SET_MII(x)		SMC_outw( x, ioaddr, MII_REG )
+#define SMC_GET_MIR()		SMC_inw( ioaddr, MIR_REG )
+#define SMC_SET_MIR(x)		SMC_outw( x, ioaddr, MIR_REG )
+#define SMC_GET_MMU_CMD()	SMC_inw( ioaddr, MMU_CMD_REG )
+#define SMC_SET_MMU_CMD(x)	SMC_outw( x, ioaddr, MMU_CMD_REG )
+#define SMC_GET_FIFO()		SMC_inw( ioaddr, FIFO_REG )
+#define SMC_GET_PTR()		SMC_inw( ioaddr, PTR_REG )
+#define SMC_SET_PTR(x)		SMC_outw( x, ioaddr, PTR_REG )
+#define SMC_GET_RCR()		SMC_inw( ioaddr, RCR_REG )
+#define SMC_SET_RCR(x)		SMC_outw( x, ioaddr, RCR_REG )
+#define SMC_GET_REV()		SMC_inw( ioaddr, REV_REG )
+#define SMC_GET_RPC()		SMC_inw( ioaddr, RPC_REG )
+#define SMC_SET_RPC(x)		SMC_outw( x, ioaddr, RPC_REG )
+#define SMC_GET_TCR()		SMC_inw( ioaddr, TCR_REG )
+#define SMC_SET_TCR(x)		SMC_outw( x, ioaddr, TCR_REG )
+
+#ifndef SMC_GET_MAC_ADDR
+#define SMC_GET_MAC_ADDR(addr)						\
+	do {								\
+		unsigned int __v;					\
+		__v = SMC_inw( ioaddr, ADDR0_REG );			\
+		addr[0] = __v; addr[1] = __v >> 8;			\
+		__v = SMC_inw( ioaddr, ADDR1_REG );			\
+		addr[2] = __v; addr[3] = __v >> 8;			\
+		__v = SMC_inw( ioaddr, ADDR2_REG );			\
+		addr[4] = __v; addr[5] = __v >> 8;			\
+	} while (0)
+#endif
+
+#define SMC_SET_MAC_ADDR(addr)						\
+	do {								\
+		SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG );	\
+		SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG );	\
+		SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG );	\
+	} while (0)
+
+#define SMC_CLEAR_MCAST()						\
+	do {								\
+		SMC_outw( 0, ioaddr, MCAST_REG1 );			\
+		SMC_outw( 0, ioaddr, MCAST_REG2 );			\
+		SMC_outw( 0, ioaddr, MCAST_REG3 );			\
+		SMC_outw( 0, ioaddr, MCAST_REG4 );			\
+	} while (0)
+#define SMC_SET_MCAST(x)						\
+	do {								\
+		unsigned char *mt = (x);				\
+		SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 );	\
+		SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 );	\
+		SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 );	\
+		SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 );	\
+	} while (0)
+
+#if SMC_CAN_USE_32BIT
+/*
+ * Some setups just can't write 8 or 16 bits reliably when not aligned
+ * to a 32 bit boundary.  I tell you that exists!
+ * We do the ones that can have their low parts written to 0 here.
+ */
+#undef SMC_SELECT_BANK
+#define SMC_SELECT_BANK(x)	SMC_outl( (x)<<16, ioaddr, 12<<SMC_IO_SHIFT )
+#undef SMC_SET_RPC
+#define SMC_SET_RPC(x)		SMC_outl( (x)<<16, ioaddr, SMC_REG(8, 0) )
+#undef SMC_SET_PN
+#define SMC_SET_PN(x)		SMC_outl( (x)<<16, ioaddr, SMC_REG(0, 2) )
+#undef SMC_SET_PTR
+#define SMC_SET_PTR(x)		SMC_outl( (x)<<16, ioaddr, SMC_REG(4, 2) )
+#endif
+
+#if SMC_CAN_USE_32BIT
+#define SMC_PUT_PKT_HDR(status, length)					\
+	SMC_outl( (status) | (length) << 16, ioaddr, DATA_REG )
+#define SMC_GET_PKT_HDR(status, length)					\
+	do {								\
+		unsigned int __val = SMC_inl( ioaddr, DATA_REG );	\
+		(status) = __val & 0xffff;				\
+		(length) = __val >> 16;					\
+	} while (0)
+#else
+#define SMC_PUT_PKT_HDR(status, length)					\
+	do {								\
+		SMC_outw( status, ioaddr, DATA_REG );			\
+		SMC_outw( length, ioaddr, DATA_REG );			\
+	} while (0)
+#define SMC_GET_PKT_HDR(status, length)					\
+	do {								\
+		(status) = SMC_inw( ioaddr, DATA_REG );			\
+		(length) = SMC_inw( ioaddr, DATA_REG );			\
+	} while (0)
+#endif
+
+#if SMC_CAN_USE_32BIT
+#define SMC_PUSH_DATA(p, l)						\
+	do {								\
+		char *__ptr = (p);					\
+		int __len = (l);					\
+		if (__len >= 2 && (long)__ptr & 2) {			\
+			__len -= 2;					\
+			SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
+		}							\
+		SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2);	\
+		if (__len & 2) {					\
+			__ptr += (__len & ~3);				\
+			SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );	\
+		}							\
+	} while (0)
+#define SMC_PULL_DATA(p, l)						\
+	do {								\
+		char *__ptr = (p);					\
+		int __len = (l);					\
+		if ((long)__ptr & 2) {					\
+			/*						\
+			 * We want 32bit alignment here.		\
+			 * Since some buses perform a full 32bit	\
+			 * fetch even for 16bit data we can't use	\
+			 * SMC_inw() here.  Back both source (on chip	\
+			 * and destination) pointers of 2 bytes.	\
+			 */						\
+			(long)__ptr &= ~2;				\
+			__len += 2;					\
+			SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );	\
+		}							\
+		__len += 2;						\
+		SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2);		\
+	} while (0)
+#elif SMC_CAN_USE_16BIT
+#define SMC_PUSH_DATA(p, l)	SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define SMC_PULL_DATA(p, l)	SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#elif SMC_CAN_USE_8BIT
+#define SMC_PUSH_DATA(p, l)	SMC_outsb( ioaddr, DATA_REG, p, l )
+#define SMC_PULL_DATA(p, l)	SMC_insb ( ioaddr, DATA_REG, p, l )
+#endif
+
+#if ! SMC_CAN_USE_16BIT
+#define SMC_outw(x, ioaddr, reg)					\
+	do {								\
+		unsigned int __val16 = (x);				\
+		SMC_outb( __val16, ioaddr, reg );			\
+		SMC_outb( __val16 >> 8, ioaddr, reg + 1 );		\
+	} while (0)
+#define SMC_inw(ioaddr, reg)						\
+	({								\
+		unsigned int __val16;					\
+		__val16 =  SMC_inb( ioaddr, reg );			\
+		__val16 |= SMC_inb( ioaddr, reg + 1 ) << 8;		\
+		__val16;						\
+	})
+#endif
+
+
+#endif  /* _SMC91X_H_ */
--- linux-2.4.25/drivers/pcmcia/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/Config.in	2004-03-31 17:15:12.000000000 +0200
@@ -45,6 +45,7 @@
 if [ "$CONFIG_ARM" = "y" ]; then
    dep_tristate '  CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
    dep_tristate '  SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
+   dep_tristate '  PXA250/210 support' CONFIG_PCMCIA_PXA $CONFIG_ARCH_PXA $CONFIG_PCMCIA
 fi
 
 endmenu
--- linux-2.4.25/drivers/pcmcia/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/Makefile	2004-03-31 17:15:12.000000000 +0200
@@ -94,6 +94,11 @@
 
 obj-$(CONFIG_PCMCIA_VRC4173)	+= vrc4173_cardu.o
 
+subdir-$(CONFIG_PCMCIA_PXA)			+= pxa
+ifeq ($(CONFIG_PCMCIA_PXA),y)
+  obj-y 					+= pxa/pxa_cs.o
+endif
+
 include $(TOPDIR)/Rules.make
 
 pcmcia_core.o:  $(pcmcia_core-objs)
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/pxa/Makefile	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,18 @@
+#
+# Makefile for the Intel PXA250/210 PCMCIA driver
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+O_TARGET			:= pxa_cs.o
+
+obj-y				:= pxa.o
+obj-$(CONFIG_ARCH_LUBBOCK)	+= lubbock.o
+obj-$(CONFIG_ARCH_PXA_IDP)	+= pxa_idp.o
+obj-$(CONFIG_ARCH_TRIZEPS2)	+= trizeps2.o
+obj-$(CONFIG_ARCH_PXA_CERF)	+= ../sa1100_cerf.o
+
+obj-m				:= $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/pxa/lubbock.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,329 @@
+/*
+ * linux/drivers/pcmcia/pxa/lubbock.c
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software 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.
+ *
+ * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
+ *
+ * Lubbock PCMCIA specific routines.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+#include <asm/hardware/sa1111.h>
+
+/*
+ * I'd really like to move the INTPOL stuff to arch/arm/mach-sa1100/sa1111.c
+ * ... and maybe even arch/arm/mach-pxa/sa1111.c now too!  : )
+ */
+#define SA1111_IRQMASK_LO(x)	(1 << (x - IRQ_SA1111_START))
+#define SA1111_IRQMASK_HI(x)	(1 << (x - IRQ_SA1111_START - 32))
+
+static int lubbock_pcmcia_init(struct pcmcia_init *init){
+  int return_val=0;
+
+  /* Set PCMCIA Socket 0 power to standby mode.
+   */
+  PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
+
+  /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller.
+   * Note that this is done only after first initializing GPIO_A<3:0>
+   * output state above to be certain that we drive signals to the same
+   * state as the pull-downs connected to these lines. The pull-downs are
+   * req'd to make sure PCMCIA power is OFF until we can get around to
+   * setting up the GPIO_A<3:0> state and direction.
+   */
+  PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
+
+  /* Set CF Socket 1 power to standby mode. */
+  LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14));
+
+  INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
+	     SA1111_IRQMASK_HI(S1_READY_NINT) |
+	     SA1111_IRQMASK_HI(S0_CD_VALID) |
+	     SA1111_IRQMASK_HI(S1_CD_VALID) |
+	     SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
+	     SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
+
+#warning what if a request_irq fails?
+  return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+			  "Lubbock PCMCIA (0) CD", NULL);
+  return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+			  "Lubbock CF (1) CD", NULL);
+  return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+			  "Lubbock PCMCIA (0) BVD1", NULL);
+  return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+			  "Lubbock CF (1) BVD1", NULL);
+
+  return (return_val<0) ? -1 : 2;
+}
+
+static int lubbock_pcmcia_shutdown(void){
+
+  free_irq(S0_CD_VALID, NULL);
+  free_irq(S1_CD_VALID, NULL);
+  free_irq(S0_BVD1_STSCHG, NULL);
+  free_irq(S1_BVD1_STSCHG, NULL);
+
+  INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) |
+	       SA1111_IRQMASK_HI(S1_CD_VALID) |
+	       SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
+	       SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
+
+  return 0;
+}
+
+static int lubbock_pcmcia_socket_state(struct pcmcia_state_array
+					*state_array){
+  unsigned long status;
+  int return_val=1;
+
+  if(state_array->size<2) return -1;
+
+  memset(state_array->state, 0, 
+	 (state_array->size)*sizeof(struct pcmcia_state));
+
+  status=PCSR;
+
+  state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+
+  state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+
+  state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+
+  state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+
+  state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+
+  state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+
+  state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+
+  state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+
+  state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+
+  state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+
+  state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+
+  state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+
+  state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+
+  state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+
+  return return_val;
+}
+
+static int lubbock_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+  switch(info->sock){
+  case 0:
+    info->irq=S0_READY_NINT;
+    break;
+
+  case 1:
+    info->irq=S1_READY_NINT;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+static int
+lubbock_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
+{
+  unsigned long flags, pccr, gpio, misc_wr, status;
+  int ret=1;
+
+  local_irq_save(flags);
+
+  pccr=PCCR;
+  gpio=PA_DWR;
+  misc_wr = LUB_MISC_WR;
+
+  /* Lubbock uses the Maxim MAX1602, with the following connections:
+   *
+   * Socket 0 (PCMCIA):
+   *	MAX1602	Lubbock		Register
+   *	Pin	Signal
+   *	-----	-------		----------------------
+   *	A0VPP	S0_PWR0		SA-1111 GPIO A<0>
+   *	A1VPP	S0_PWR1		SA-1111 GPIO A<1>
+   *	A0VCC	S0_PWR2		SA-1111 GPIO A<2>
+   *	A1VCC	S0_PWR3		SA-1111 GPIO A<3>
+   *	VX	VCC
+   *	VY	+3.3V
+   *	12IN	+12V
+   *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
+   *
+   * Socket 1 (CF):
+   *	MAX1602	Lubbock		Register
+   *	Pin	Signal
+   *	-----	-------		----------------------
+   *	A0VPP	GND		VPP is not connected
+   *	A1VPP	GND		VPP is not connected
+   *	A0VCC	S1_PWR0		MISC_WR<14>
+   *	A1VCC	S1_PWR0		MISC_WR<15>
+   *	VX	VCC
+   *	VY	+3.3V
+   *	12IN	GND		VPP is not connected
+   *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
+   *
+   */
+
+again:
+  switch(sock){
+  case 0:
+
+    switch(state->Vcc){
+    case 0:
+      pccr = (pccr & ~PCCR_S0_FLT);
+      gpio &= ~(GPIO_bit(2) | GPIO_bit(3));
+      break;
+
+    case 33:
+      pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
+      gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3);
+      break;
+
+    case 50:
+      pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
+      gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
+      break;
+
+    default:
+      printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
+      ret = -1;
+      break;
+    }
+
+    switch(state->Vpp){
+    case 0:
+      gpio &= ~(GPIO_bit(0) | GPIO_bit(1));
+      break;
+
+    case 120:
+      gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1);
+      break;
+
+    default:
+      /* REVISIT: I'm not sure about this? Is this correct?
+         Is it always safe or do we have potential problems
+         with bogus combinations of Vcc and Vpp settings? */
+      if(state->Vpp == state->Vcc)
+        gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0);
+      else {
+	printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp);
+	ret = -1;
+	break;
+      }
+    }
+
+    pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S0_RST) : (pccr&~PCCR_S0_RST);
+
+    break;
+
+  case 1:
+    switch(state->Vcc){
+    case 0:
+      pccr = (pccr & ~PCCR_S1_FLT);
+      misc_wr &= ~((1 << 15) | (1 << 14));
+      break;
+
+    case 33:
+      pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
+      misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
+      gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
+      break;
+
+    case 50:
+      pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
+      misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
+      break;
+
+    default:
+      printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
+      ret = -1;
+      break;
+    }
+
+    if(state->Vpp!=state->Vcc && state->Vpp!=0){
+      printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp);
+      ret = -1;
+      break;
+    }
+
+    pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S1_RST) : (pccr&~PCCR_S1_RST);
+
+    break;
+
+  default:
+    ret = -1;
+  }
+
+  if (ret >= 0) {
+    PCCR = pccr;
+    LUB_MISC_WR = misc_wr;
+    PA_DWR = gpio;
+  }
+
+  if (ret > 0) {
+    ret = 0;
+    /* 
+     * HACK ALERT: 
+     * We can't sense the voltage properly on Lubbock before actually
+     * applying some power to the socket (catch 22).
+     * Resense the socket Voltage Sense pins after applying socket power.
+     */
+    if (sock == 0)
+      status = PCSR & (PCSR_S0_VS1 | PCSR_S0_VS2);
+    else
+      status = PCSR & (PCSR_S1_VS1 | PCSR_S1_VS2);
+
+    if ((status == (PCSR_S0_VS1 | PCSR_S0_VS2)) && (state->Vcc == 33)) {
+      /* Switch to 5V,  Configure socket 0  with 5V voltage */
+      PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
+      PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
+      state->Vcc = 50;
+      state->Vpp = 50;
+      goto again;
+    }
+    if ((status == (PCSR_S1_VS1 | PCSR_S1_VS2)) && (state->Vcc == 33)) {
+      /* Switch to 5V, Configure socket 1 with 5V voltage */
+      LUB_MISC_WR &= ~((1 << 15) | (1 << 14));
+      state->Vcc = 50;
+      state->Vpp = 50;
+      goto again;
+    }
+  }
+
+  local_irq_restore(flags);
+  return ret;
+}
+
+struct pcmcia_low_level lubbock_pcmcia_ops = { 
+  lubbock_pcmcia_init,
+  lubbock_pcmcia_shutdown,
+  lubbock_pcmcia_socket_state,
+  lubbock_pcmcia_get_irq_info,
+  lubbock_pcmcia_configure_socket
+};
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/pxa/pxa.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,1247 @@
+/*
+ * linux/drivers/pcmcia/pxa/pxa.c
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software 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.
+ *
+ * Originally based upon linux/drivers/pcmcia/sa1100_generic.c
+ *
+ */
+
+/*======================================================================
+
+    Device driver for the PCMCIA control functionality of Intel
+    PXA250/210 microprocessors.
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is John G. Dorsey
+    <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
+    Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    and other provisions required by the GPL.  If you do not delete
+    the provisions above, a recipient may use your version of this
+    file under either the MPL or the GPL.
+    
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/tqueue.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/proc_fs.h>
+#include <linux/version.h>
+#include <linux/cpufreq.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bus_ops.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/arch/lubbock.h>
+
+#include "pxa.h"
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug;
+#endif
+
+MODULE_AUTHOR("George Davis <davis_g@mvista.com>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA250/210 Socket Controller");
+
+/* This structure maintains housekeeping state for each socket, such
+ * as the last known values of the card detect pins, or the Card Services
+ * callback value associated with the socket:
+ */
+static struct pxa_pcmcia_socket 
+pxa_pcmcia_socket[PXA_PCMCIA_MAX_SOCK];
+
+static int pxa_pcmcia_socket_count;
+
+
+/* Returned by the low-level PCMCIA interface: */
+static struct pcmcia_low_level *pcmcia_low_level;
+
+/* Event poll timer structure */
+static struct timer_list poll_timer;
+
+
+/* Prototypes for routines which are used internally: */
+
+static int  pxa_pcmcia_driver_init(void);
+static void pxa_pcmcia_driver_shutdown(void);
+static void pxa_pcmcia_task_handler(void *data);
+static void pxa_pcmcia_poll_event(unsigned long data);
+static void pxa_pcmcia_interrupt(int irq, void *dev,
+				    struct pt_regs *regs);
+static struct tq_struct pxa_pcmcia_task;
+
+#ifdef CONFIG_PROC_FS
+static int  pxa_pcmcia_proc_status(char *buf, char **start, off_t pos,
+				      int count, int *eof, void *data);
+#endif
+
+
+/* Prototypes for operations which are exported to the
+ * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core:
+ */
+
+static int pxa_pcmcia_init(unsigned int sock);
+static int pxa_pcmcia_suspend(unsigned int sock);
+static int pxa_pcmcia_register_callback(unsigned int sock,
+					   void (*handler)(void *, 
+							   unsigned int),
+					   void *info);
+static int pxa_pcmcia_inquire_socket(unsigned int sock, 
+					socket_cap_t *cap);
+static int pxa_pcmcia_get_status(unsigned int sock, u_int *value);
+static int pxa_pcmcia_get_socket(unsigned int sock, 
+				    socket_state_t *state);
+static int pxa_pcmcia_set_socket(unsigned int sock,
+				    socket_state_t *state);
+static int pxa_pcmcia_get_io_map(unsigned int sock,
+				    struct pccard_io_map *io);
+static int pxa_pcmcia_set_io_map(unsigned int sock,
+				    struct pccard_io_map *io);
+static int pxa_pcmcia_get_mem_map(unsigned int sock,
+				     struct pccard_mem_map *mem);
+static int pxa_pcmcia_set_mem_map(unsigned int sock,
+				     struct pccard_mem_map *mem);
+#ifdef CONFIG_PROC_FS
+static void pxa_pcmcia_proc_setup(unsigned int sock,
+				     struct proc_dir_entry *base);
+#endif
+
+static struct pccard_operations pxa_pcmcia_operations = {
+  pxa_pcmcia_init,
+  pxa_pcmcia_suspend,
+  pxa_pcmcia_register_callback,
+  pxa_pcmcia_inquire_socket,
+  pxa_pcmcia_get_status,
+  pxa_pcmcia_get_socket,
+  pxa_pcmcia_set_socket,
+  pxa_pcmcia_get_io_map,
+  pxa_pcmcia_set_io_map,
+  pxa_pcmcia_get_mem_map,
+  pxa_pcmcia_set_mem_map,
+#ifdef CONFIG_PROC_FS
+  pxa_pcmcia_proc_setup
+#endif
+};
+
+#ifdef CONFIG_CPU_FREQ
+/* forward declaration */
+static struct notifier_block pxa_pcmcia_notifier_block;
+#endif
+
+
+/* pxa_pcmcia_driver_init()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * This routine performs a basic sanity check to ensure that this
+ * kernel has been built with the appropriate board-specific low-level
+ * PCMCIA support, performs low-level PCMCIA initialization, registers
+ * this socket driver with Card Services, and then spawns the daemon
+ * thread which is the real workhorse of the socket driver.
+ *
+ * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
+ * on the low-level kernel interface.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int __init pxa_pcmcia_driver_init(void){
+  servinfo_t info;
+  struct pcmcia_init pcmcia_init;
+  struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
+  struct pcmcia_state_array state_array;
+  unsigned int i, clock;
+  unsigned long mecr;
+
+  printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE);
+
+  CardServices(GetCardServicesInfo, &info);
+
+  if(info.Revision!=CS_RELEASE_CODE){
+    printk(KERN_ERR "Card Services release codes do not match\n");
+    return -1;
+  }
+
+  /* Setup GPIOs for PCMCIA/CF alternate function mode.
+   *
+   * It would be nice if set_GPIO_mode included support
+   * for driving GPIO outputs to default high/low state
+   * before programming GPIOs as outputs. Setting GPIO
+   * outputs to default high/low state via GPSR/GPCR
+   * before defining them as outputs should reduce
+   * the possibility of glitching outputs during GPIO
+   * setup. This of course assumes external terminators
+   * are present to hold GPIOs in a defined state.
+   *
+   * In the meantime, setup default state of GPIO
+   * outputs before we enable them as outputs.
+   */
+
+  GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
+                      GPIO_bit(GPIO49_nPWE) |
+                      GPIO_bit(GPIO50_nPIOR) |
+                      GPIO_bit(GPIO51_nPIOW) |
+                      GPIO_bit(GPIO52_nPCE_1) |
+                      GPIO_bit(GPIO53_nPCE_2);
+
+  set_GPIO_mode(GPIO48_nPOE_MD);
+  set_GPIO_mode(GPIO49_nPWE_MD);
+  set_GPIO_mode(GPIO50_nPIOR_MD);
+  set_GPIO_mode(GPIO51_nPIOW_MD);
+  set_GPIO_mode(GPIO52_nPCE_1_MD);
+  set_GPIO_mode(GPIO53_nPCE_2_MD);
+  set_GPIO_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
+  set_GPIO_mode(GPIO55_nPREG_MD);
+  set_GPIO_mode(GPIO56_nPWAIT_MD);
+  set_GPIO_mode(GPIO57_nIOIS16_MD);
+
+
+  if(machine_is_lubbock()){
+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_CSB226)
+    pcmcia_low_level=&lubbock_pcmcia_ops;
+#endif
+  } else if (machine_is_pxa_idp()) {
+    pcmcia_low_level=&pxa_idp_pcmcia_ops;
+  } else if( machine_is_pxa_cerf()){
+    pcmcia_low_level=&cerf_pcmcia_ops;
+  } else if (machine_is_trizeps2()){
+#ifdef CONFIG_ARCH_TRIZEPS2
+    pcmcia_low_level=&trizeps2_pcmcia_ops;
+#endif
+  }
+
+  if (!pcmcia_low_level) {
+    printk(KERN_ERR "This hardware is not supported by the PXA250/210 Card Service driver\n");
+    return -ENODEV;
+  }
+
+  pcmcia_init.handler=pxa_pcmcia_interrupt;
+
+  if((pxa_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){
+    printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n");
+    return -EIO;
+  }
+
+  state_array.size=pxa_pcmcia_socket_count;
+  state_array.state=state;
+
+  /* Configure MECR based on the number of sockets present. */
+  if (pxa_pcmcia_socket_count == 2) {
+    MECR |= GPIO_bit(0);
+  } else {
+    MECR &= ~GPIO_bit(0);
+  }
+
+  if(pcmcia_low_level->socket_state(&state_array)<0){
+    printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
+    return -EIO;
+  }
+
+  /* Well, it looks good to go. So we can now enable the PCMCIA
+   * controller.
+   */
+  MECR |= GPIO_bit(1);
+
+  /* We need to initialize the MCXX registers to default values
+   * here because we're not guaranteed to see a SetIOMap operation
+   * at runtime.
+   */
+
+  clock = get_lclk_frequency_10khz();
+
+  for(i=0; i<pxa_pcmcia_socket_count; ++i){
+    pxa_pcmcia_socket[i].k_state=state[i];
+
+    /* This is an interim fix. Apparently, SetSocket is no longer
+     * called to initialize each socket (prior to the first detect
+     * event). For now, we'll just manually set up the mask.
+     */
+    pxa_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT;
+
+    pxa_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE;
+    pxa_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i);
+    pxa_pcmcia_socket[i].phys_mem=_PCMCIAMem(i);
+
+    /* REVISIT: cleanup these macros */
+    //MCIO_SET(i, PXA_PCMCIA_IO_ACCESS, clock);
+    //MCATTR_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock);
+    //MCMEM_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock);
+
+    pxa_pcmcia_socket[i].speed_io=PXA_PCMCIA_IO_ACCESS;
+    pxa_pcmcia_socket[i].speed_attr=PXA_PCMCIA_ATTR_MEM_ACCESS;
+    pxa_pcmcia_socket[i].speed_mem=PXA_PCMCIA_5V_MEM_ACCESS;
+  }
+
+/* REVISIT: cleanup these macros */
+MCMEM0 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+       | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+       | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+MCMEM1 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+       | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+       | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+       | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+       | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+       | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+       | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+MCIO0 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+       | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+       | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+MCIO1 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+       | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+       | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+
+#ifdef CONFIG_CPU_FREQ
+  if(cpufreq_register_notifier(&pxa_pcmcia_notifier_block) < 0){
+    printk(KERN_ERR "Unable to register CPU frequency change notifier\n");
+    return -ENXIO;
+  }
+#endif
+
+  /* Only advertise as many sockets as we can detect: */
+  if(register_ss_entry(pxa_pcmcia_socket_count, 
+		       &pxa_pcmcia_operations)<0){
+    printk(KERN_ERR "Unable to register socket service routine\n");
+    return -ENXIO;
+  }
+
+  /* Start the event poll timer.  It will reschedule by itself afterwards. */
+  pxa_pcmcia_poll_event(0);
+
+  DEBUG(1, "pxa_cs: initialization complete\n");
+
+  return 0;
+
+}  /* pxa_pcmcia_driver_init() */
+
+module_init(pxa_pcmcia_driver_init);
+
+
+/* pxa_pcmcia_driver_shutdown()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Invokes the low-level kernel service to free IRQs associated with this
+ * socket controller and reset GPIO edge detection.
+ */
+static void __exit pxa_pcmcia_driver_shutdown(void){
+
+  del_timer_sync(&poll_timer);
+  unregister_ss_entry(&pxa_pcmcia_operations);
+#ifdef CONFIG_CPU_FREQ
+  cpufreq_unregister_notifier(&pxa_pcmcia_notifier_block);
+#endif
+  pcmcia_low_level->shutdown();
+  flush_scheduled_tasks();
+
+  DEBUG(1, "pxa_cs: shutdown complete\n");
+}
+
+module_exit(pxa_pcmcia_driver_shutdown);
+
+
+/* pxa_pcmcia_init()
+ * ^^^^^^^^^^^^^^^^^^^^
+ * We perform all of the interesting initialization tasks in 
+ * pxa_pcmcia_driver_init().
+ *
+ * Returns: 0
+ */
+static int pxa_pcmcia_init(unsigned int sock){
+  
+  DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
+
+  return 0;
+}
+
+
+/* pxa_pcmcia_suspend()
+ * ^^^^^^^^^^^^^^^^^^^^^^^
+ * We don't currently perform any actions on a suspend.
+ *
+ * Returns: 0
+ */
+static int pxa_pcmcia_suspend(unsigned int sock)
+{
+  socket_state_t st;
+  int ret;
+
+  DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock);
+
+  st.Vcc = 0;
+  st.Vpp = 0;
+  st.flags = SS_RESET;
+
+  ret = pcmcia_low_level->configure_socket(sock, &st);
+
+  if (ret == 0)
+    pxa_pcmcia_socket[sock].cs_state = dead_socket;
+
+  return ret;
+}
+
+
+/* pxa_pcmcia_events()
+ * ^^^^^^^^^^^^^^^^^^^^^^
+ * Helper routine to generate a Card Services event mask based on
+ * state information obtained from the kernel low-level PCMCIA layer
+ * in a recent (and previous) sampling. Updates `prev_state'.
+ *
+ * Returns: an event mask for the given socket state.
+ */
+static inline unsigned pxa_pcmcia_events(struct pcmcia_state *state,
+					    struct pcmcia_state *prev_state,
+					    unsigned int mask,
+					    unsigned int flags){
+  unsigned int events=0;
+
+  if(state->detect!=prev_state->detect){
+
+    DEBUG(2, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
+
+    events|=mask&SS_DETECT;
+  }
+
+  if(state->ready!=prev_state->ready){
+
+    DEBUG(2, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
+
+    events|=mask&((flags&SS_IOCARD)?0:SS_READY);
+  }
+
+  if(state->bvd1!=prev_state->bvd1){
+
+    DEBUG(2, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
+
+    events|=mask&(flags&SS_IOCARD)?SS_STSCHG:SS_BATDEAD;
+  }
+
+  if(state->bvd2!=prev_state->bvd2){
+
+    DEBUG(2, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
+
+    events|=mask&(flags&SS_IOCARD)?0:SS_BATWARN;
+  }
+
+  DEBUG(2, "events: %s%s%s%s%s%s\n",
+	(events==0)?"<NONE>":"",
+	(events&SS_DETECT)?"DETECT ":"",
+	(events&SS_READY)?"READY ":"",
+	(events&SS_BATDEAD)?"BATDEAD ":"",
+	(events&SS_BATWARN)?"BATWARN ":"",
+	(events&SS_STSCHG)?"STSCHG ":"");
+
+  *prev_state=*state;
+
+  return events;
+
+}  /* pxa_pcmcia_events() */
+
+
+/* pxa_pcmcia_task_handler()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Processes serviceable socket events using the "eventd" thread context.
+ *
+ * Event processing (specifically, the invocation of the Card Services event
+ * callback) occurs in this thread rather than in the actual interrupt
+ * handler due to the use of scheduling operations in the PCMCIA core.
+ */
+static void pxa_pcmcia_task_handler(void *data) {
+  struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
+  struct pcmcia_state_array state_array;
+  int i, events, all_events, irq_status;
+
+  DEBUG(2, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
+
+  state_array.size=pxa_pcmcia_socket_count;
+  state_array.state=state;
+
+  do {
+
+    DEBUG(3, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__);
+
+    if((irq_status=pcmcia_low_level->socket_state(&state_array))<0)
+      printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n");
+
+    all_events=0;
+
+    if(irq_status>0){
+
+      for(i=0; i<state_array.size; ++i, all_events|=events)
+	if((events=
+	    pxa_pcmcia_events(&state[i],
+				 &pxa_pcmcia_socket[i].k_state,
+				 pxa_pcmcia_socket[i].cs_state.csc_mask,
+				 pxa_pcmcia_socket[i].cs_state.flags)))
+	  if(pxa_pcmcia_socket[i].handler!=NULL)
+	    pxa_pcmcia_socket[i].handler(pxa_pcmcia_socket[i].handler_info,
+					    events);
+    }
+
+  } while(all_events);
+}  /* pxa_pcmcia_task_handler() */
+
+static struct tq_struct pxa_pcmcia_task = {
+	routine: pxa_pcmcia_task_handler
+};
+
+
+/* pxa_pcmcia_poll_event()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Let's poll for events in addition to IRQs since IRQ only is unreliable...
+ */
+static void pxa_pcmcia_poll_event(unsigned long dummy)
+{
+  DEBUG(3, "%s(): polling for events\n", __FUNCTION__);
+  poll_timer.function = pxa_pcmcia_poll_event;
+  poll_timer.expires = jiffies + PXA_PCMCIA_POLL_PERIOD;
+  add_timer(&poll_timer);
+  schedule_task(&pxa_pcmcia_task);
+}
+
+
+/* pxa_pcmcia_interrupt()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Service routine for socket driver interrupts (requested by the
+ * low-level PCMCIA init() operation via pxa_pcmcia_thread()).
+ * The actual interrupt-servicing work is performed by
+ * pxa_pcmcia_thread(), largely because the Card Services event-
+ * handling code performs scheduling operations which cannot be
+ * executed from within an interrupt context.
+ */
+static void pxa_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs){
+  DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
+  schedule_task(&pxa_pcmcia_task);
+}
+
+
+/* pxa_pcmcia_register_callback()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the register_callback() operation for the in-kernel
+ * PCMCIA service (formerly SS_RegisterCallback in Card Services). If 
+ * the function pointer `handler' is not NULL, remember the callback 
+ * location in the state for `sock', and increment the usage counter 
+ * for the driver module. (The callback is invoked from the interrupt
+ * service routine, pxa_pcmcia_interrupt(), to notify Card Services
+ * of interesting events.) Otherwise, clear the callback pointer in the
+ * socket state and decrement the module usage count.
+ *
+ * Returns: 0
+ */
+static int pxa_pcmcia_register_callback(unsigned int sock,
+					   void (*handler)(void *,
+							   unsigned int),
+					   void *info){
+  if(handler==NULL){
+    pxa_pcmcia_socket[sock].handler=NULL;
+    MOD_DEC_USE_COUNT;
+  } else {
+    MOD_INC_USE_COUNT;
+    pxa_pcmcia_socket[sock].handler=handler;
+    pxa_pcmcia_socket[sock].handler_info=info;
+  }
+
+  return 0;
+}
+
+
+/* pxa_pcmcia_inquire_socket()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the inquire_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_InquireSocket in Card Services). Of note is
+ * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of
+ * `cap' to "trick" Card Services into tolerating large "I/O memory" 
+ * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory
+ * resource database check. (Mapped memory is set up within the socket
+ * driver itself.)
+ *
+ * In conjunction with the STATIC_MAP capability is a new field,
+ * `io_offset', recommended by David Hinds. Rather than go through
+ * the SetIOMap interface (which is not quite suited for communicating
+ * window locations up from the socket driver), we just pass up
+ * an offset which is applied to client-requested base I/O addresses
+ * in alloc_io_space().
+ *
+ * Returns: 0 on success, -1 if no pin has been configured for `sock'
+ */
+static int pxa_pcmcia_inquire_socket(unsigned int sock,
+					socket_cap_t *cap){
+  struct pcmcia_irq_info irq_info;
+
+  DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  if(sock>=pxa_pcmcia_socket_count){
+    printk(KERN_ERR "pxa_cs: socket %u not configured\n", sock);
+    return -1;
+  }
+
+  /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
+   *   force_low argument to validate_mem() in rsrc_mgr.c -- since in
+   *   general, the mapped * addresses of the PCMCIA memory regions
+   *   will not be within 0xffff, setting force_low would be
+   *   undesirable.
+   *
+   * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
+   *   resource database; we instead pass up physical address ranges
+   *   and allow other parts of Card Services to deal with remapping.
+   *
+   * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
+   *   not 32-bit CardBus devices.
+   */
+  cap->features=(SS_CAP_PAGE_REGS  | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
+
+  irq_info.sock=sock;
+  irq_info.irq=-1;
+
+  if(pcmcia_low_level->get_irq_info(&irq_info)<0){
+    printk(KERN_ERR "Error obtaining IRQ info from kernel for socket %u\n",
+	   sock);
+    return -1;
+  }
+
+  cap->irq_mask=0;
+  cap->map_size=PAGE_SIZE;
+  cap->pci_irq=irq_info.irq;
+  cap->io_offset=pxa_pcmcia_socket[sock].virt_io;
+
+  return 0;
+
+}  /* pxa_pcmcia_inquire_socket() */
+
+
+/* pxa_pcmcia_get_status()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_status() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetStatus in Card Services). Essentially just
+ * fills in bits in `status' according to internal driver state or
+ * the value of the voltage detect chipselect register.
+ *
+ * As a debugging note, during card startup, the PCMCIA core issues
+ * three set_socket() commands in a row the first with RESET deasserted,
+ * the second with RESET asserted, and the last with RESET deasserted
+ * again. Following the third set_socket(), a get_status() command will
+ * be issued. The kernel is looking for the SS_READY flag (see
+ * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
+ *
+ * Returns: 0
+ */
+static int pxa_pcmcia_get_status(unsigned int sock,
+				    unsigned int *status){
+  struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
+  struct pcmcia_state_array state_array;
+
+  DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  state_array.size=pxa_pcmcia_socket_count;
+  state_array.state=state;
+
+  if((pcmcia_low_level->socket_state(&state_array))<0){
+    printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
+    return -1;
+  }
+
+  pxa_pcmcia_socket[sock].k_state=state[sock];
+
+  *status=state[sock].detect?SS_DETECT:0;
+
+  *status|=state[sock].ready?SS_READY:0;
+
+  /* The power status of individual sockets is not available
+   * explicitly from the hardware, so we just remember the state
+   * and regurgitate it upon request:
+   */
+  *status|=pxa_pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0;
+
+  if(pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)
+    *status|=state[sock].bvd1?SS_STSCHG:0;
+  else {
+    if(state[sock].bvd1==0)
+      *status|=SS_BATDEAD;
+    else if(state[sock].bvd2==0)
+      *status|=SS_BATWARN;
+  }
+
+  *status|=state[sock].vs_3v?SS_3VCARD:0;
+
+  *status|=state[sock].vs_Xv?SS_XVCARD:0;
+
+  DEBUG(3, "\tstatus: %s%s%s%s%s%s%s%s\n",
+	(*status&SS_DETECT)?"DETECT ":"",
+	(*status&SS_READY)?"READY ":"", 
+	(*status&SS_BATDEAD)?"BATDEAD ":"",
+	(*status&SS_BATWARN)?"BATWARN ":"",
+	(*status&SS_POWERON)?"POWERON ":"",
+	(*status&SS_STSCHG)?"STSCHG ":"",
+	(*status&SS_3VCARD)?"3VCARD ":"",
+	(*status&SS_XVCARD)?"XVCARD ":"");
+
+  return 0;
+
+}  /* pxa_pcmcia_get_status() */
+
+
+/* pxa_pcmcia_get_socket()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetSocket in Card Services). Not a very 
+ * exciting routine.
+ *
+ * Returns: 0
+ */
+static int pxa_pcmcia_get_socket(unsigned int sock,
+				    socket_state_t *state){
+
+  DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  /* This information was given to us in an earlier call to set_socket(),
+   * so we're just regurgitating it here:
+   */
+  *state=pxa_pcmcia_socket[sock].cs_state;
+
+  return 0;
+}
+
+
+/* pxa_pcmcia_set_socket()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the set_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetSocket in Card Services). We more or
+ * less punt all of this work and let the kernel handle the details
+ * of power configuration, reset, &c. We also record the value of
+ * `state' in order to regurgitate it to the PCMCIA core later.
+ *
+ * Returns: 0
+ */
+static int pxa_pcmcia_set_socket(unsigned int sock,
+				    socket_state_t *state){
+
+  DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  DEBUG(3, "\tmask:  %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
+	"\tVcc %d  Vpp %d  irq %d\n",
+	(state->csc_mask==0)?"<NONE>":"",
+	(state->csc_mask&SS_DETECT)?"DETECT ":"",
+	(state->csc_mask&SS_READY)?"READY ":"",
+	(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
+	(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
+	(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
+	(state->flags==0)?"<NONE>":"",
+	(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
+	(state->flags&SS_IOCARD)?"IOCARD ":"",
+	(state->flags&SS_RESET)?"RESET ":"",
+	(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
+	(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+	state->Vcc, state->Vpp, state->io_irq);
+
+  if(pcmcia_low_level->configure_socket(sock, state)<0){
+    printk(KERN_ERR "Unable to configure socket %u\n", sock);
+    return -1;
+  }
+
+  pxa_pcmcia_socket[sock].cs_state=*state;
+  
+  return 0;
+
+}  /* pxa_pcmcia_set_socket() */
+
+
+/* pxa_pcmcia_get_io_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_io_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetIOMap in Card Services). Just returns an
+ * I/O map descriptor which was assigned earlier by a set_io_map().
+ *
+ * Returns: 0 on success, -1 if the map index was out of range
+ */
+static int pxa_pcmcia_get_io_map(unsigned int sock,
+				    struct pccard_io_map *map){
+
+  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  if(map->map>=MAX_IO_WIN){
+    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+	   map->map);
+    return -1;
+  }
+
+  *map=pxa_pcmcia_socket[sock].io_map[map->map];
+
+  return 0;
+}
+
+
+/* pxa_pcmcia_set_io_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the set_io_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetIOMap in Card Services). We configure
+ * the map speed as requested, but override the address ranges
+ * supplied by Card Services.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int pxa_pcmcia_set_io_map(unsigned int sock,
+				    struct pccard_io_map *map){
+  unsigned int clock, speed;
+  unsigned long mecr, start;
+
+  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  DEBUG(4, "\tmap %u  speed %u\n\tstart 0x%08lx  stop 0x%08lx\n"
+	"\tflags: %s%s%s%s%s%s%s%s\n",
+	map->map, map->speed, map->start, map->stop,
+	(map->flags==0)?"<NONE>":"",
+	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
+	(map->flags&MAP_16BIT)?"16BIT ":"",
+	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
+	(map->flags&MAP_0WS)?"0WS ":"",
+	(map->flags&MAP_WRPROT)?"WRPROT ":"",
+	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
+	(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+
+  if(map->map>=MAX_IO_WIN){
+    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+	   map->map);
+    return -1;
+  }
+
+  if(map->flags&MAP_ACTIVE){
+
+    speed=(map->speed>0)?map->speed:PXA_PCMCIA_IO_ACCESS;
+
+    clock = get_lclk_frequency_10khz();
+
+    pxa_pcmcia_socket[sock].speed_io=speed;
+
+    if (sock == 0) {
+      MCIO0 = ((pxa_mcxx_setup(speed, clock)
+			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+            | ((pxa_mcxx_asst(speed, clock)
+			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+            | ((pxa_mcxx_hold(speed, clock)
+			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+    } else {
+      MCIO1 = ((pxa_mcxx_setup(speed, clock)
+			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+            | ((pxa_mcxx_asst(speed, clock)
+			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+            | ((pxa_mcxx_hold(speed, clock)
+			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+    }
+
+    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
+	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
+	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
+	  sock, MECR_BSIO_GET(mecr, sock));
+
+  }
+
+  start=map->start;
+
+  if(map->stop==1)
+    map->stop=PAGE_SIZE-1;
+
+  map->start=pxa_pcmcia_socket[sock].virt_io;
+  map->stop=map->start+(map->stop-start);
+
+  pxa_pcmcia_socket[sock].io_map[map->map]=*map;
+
+  return 0;
+
+}  /* pxa_pcmcia_set_io_map() */
+
+
+/* pxa_pcmcia_get_mem_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_mem_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetMemMap in Card Services). Just returns a
+ *  memory map descriptor which was assigned earlier by a
+ *  set_mem_map() request.
+ *
+ * Returns: 0 on success, -1 if the map index was out of range
+ */
+static int pxa_pcmcia_get_mem_map(unsigned int sock,
+				     struct pccard_mem_map *map){
+
+  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  if(map->map>=MAX_WIN){
+    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+	   map->map);
+    return -1;
+  }
+
+  *map=pxa_pcmcia_socket[sock].mem_map[map->map];
+
+  return 0;
+}
+
+
+/* pxa_pcmcia_set_mem_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the set_mem_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetMemMap in Card Services). We configure
+ * the map speed as requested, but override the address ranges
+ * supplied by Card Services.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int pxa_pcmcia_set_mem_map(unsigned int sock,
+				     struct pccard_mem_map *map){
+  unsigned int clock, speed;
+  unsigned long mecr, start;
+
+  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  DEBUG(4, "\tmap %u  speed %u\n\tsys_start  %#lx\n"
+	"\tsys_stop   %#lx\n\tcard_start %#x\n"
+	"\tflags: %s%s%s%s%s%s%s%s\n",
+	map->map, map->speed, map->sys_start, map->sys_stop,
+	map->card_start, (map->flags==0)?"<NONE>":"",
+	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
+	(map->flags&MAP_16BIT)?"16BIT ":"",
+	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
+	(map->flags&MAP_0WS)?"0WS ":"",
+	(map->flags&MAP_WRPROT)?"WRPROT ":"",
+	(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
+	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+
+  if(map->map>=MAX_WIN){
+    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+	   map->map);
+    return -1;
+  }
+
+  if(map->flags&MAP_ACTIVE){
+    /* When clients issue RequestMap, the access speed is not always
+     * properly configured:
+     */
+    if(map->speed > 0)
+      speed = map->speed;
+    else
+      switch(pxa_pcmcia_socket[sock].cs_state.Vcc){
+      case 33:
+	speed = PXA_PCMCIA_3V_MEM_ACCESS;
+	break;
+      default:
+	speed = PXA_PCMCIA_5V_MEM_ACCESS;
+      }
+
+    clock = get_lclk_frequency_10khz();
+
+    if(map->flags&MAP_ATTRIB){
+      if (sock == 0) {
+        MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+               | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+               | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+      } else {
+        MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+               | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+               | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
+			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+      }
+      pxa_pcmcia_socket[sock].speed_attr=speed;
+    } else {
+      if (sock == 0) {
+        MCMEM0 = ((pxa_mcxx_setup(speed, clock)
+			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+               | ((pxa_mcxx_asst(speed, clock)
+			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+               | ((pxa_mcxx_hold(speed, clock)
+			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+      } else {
+        MCMEM1 = ((pxa_mcxx_setup(speed, clock)
+			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+               | ((pxa_mcxx_asst(speed, clock)
+			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+               | ((pxa_mcxx_hold(speed, clock)
+			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+      }
+      pxa_pcmcia_socket[sock].speed_mem=speed;
+    }
+    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
+	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
+	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
+	  sock, MECR_BSIO_GET(mecr, sock));
+  }
+
+  start=map->sys_start;
+
+  if(map->sys_stop==0)
+    map->sys_stop=PAGE_SIZE-1;
+
+  map->sys_start=(map->flags & MAP_ATTRIB)?\
+    pxa_pcmcia_socket[sock].phys_attr:\
+    pxa_pcmcia_socket[sock].phys_mem;
+
+  map->sys_stop=map->sys_start+(map->sys_stop-start);
+
+  pxa_pcmcia_socket[sock].mem_map[map->map]=*map;
+
+  return 0;
+
+}  /* pxa_pcmcia_set_mem_map() */
+
+
+#if defined(CONFIG_PROC_FS)
+
+/* pxa_pcmcia_proc_setup()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the proc_setup() operation for the in-kernel PCMCIA
+ * service (formerly SS_ProcSetup in Card Services).
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static void pxa_pcmcia_proc_setup(unsigned int sock,
+				     struct proc_dir_entry *base){
+  struct proc_dir_entry *entry;
+
+  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+  if((entry=create_proc_entry("status", 0, base))==NULL){
+    printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
+    return;
+  }
+
+  entry->read_proc=pxa_pcmcia_proc_status;
+  entry->data=(void *)sock;
+}
+
+
+/* pxa_pcmcia_proc_status()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the /proc/bus/pccard/??/status file.
+ *
+ * Returns: the number of characters added to the buffer
+ */
+static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos,
+				     int count, int *eof, void *data){
+  char *p=buf;
+  unsigned int sock=(unsigned int)data;
+  unsigned int clock = get_lclk_frequency_10khz();
+  unsigned long mecr = MECR;
+
+  p+=sprintf(p, "k_flags  : %s%s%s%s%s%s%s\n", 
+	     pxa_pcmcia_socket[sock].k_state.detect?"detect ":"",
+	     pxa_pcmcia_socket[sock].k_state.ready?"ready ":"",
+	     pxa_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"",
+	     pxa_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"",
+	     pxa_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"",
+	     pxa_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"",
+	     pxa_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":"");
+
+  p+=sprintf(p, "status   : %s%s%s%s%s%s%s%s%s\n",
+	     pxa_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"",
+	     pxa_pcmcia_socket[sock].k_state.ready?"SS_READY ":"",
+	     pxa_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"",
+	     pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
+	     "SS_IOCARD ":"",
+	     (pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD &&
+	      pxa_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"",
+	     ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
+	      (pxa_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"",
+	     ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
+	      (pxa_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"",
+	     pxa_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"",
+	     pxa_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":"");
+
+  p+=sprintf(p, "mask     : %s%s%s%s%s\n",
+	     pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\
+	     "SS_DETECT ":"",
+	     pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\
+	     "SS_READY ":"",
+	     pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\
+	     "SS_BATDEAD ":"",
+	     pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\
+	     "SS_BATWARN ":"",
+	     pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\
+	     "SS_STSCHG ":"");
+
+  p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
+	     pxa_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\
+	     "SS_PWR_AUTO ":"",
+	     pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
+	     "SS_IOCARD ":"",
+	     pxa_pcmcia_socket[sock].cs_state.flags&SS_RESET?\
+	     "SS_RESET ":"",
+	     pxa_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\
+	     "SS_SPKR_ENA ":"",
+	     pxa_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\
+	     "SS_OUTPUT_ENA ":"");
+
+  p+=sprintf(p, "Vcc      : %d\n", pxa_pcmcia_socket[sock].cs_state.Vcc);
+
+  p+=sprintf(p, "Vpp      : %d\n", pxa_pcmcia_socket[sock].cs_state.Vpp);
+
+  p+=sprintf(p, "irq      : %d\n", pxa_pcmcia_socket[sock].cs_state.io_irq);
+
+  p+=sprintf(p, "I/O      : %u (%u)\n", pxa_pcmcia_socket[sock].speed_io,
+             sock ?
+               pxa_pcmcia_cmd_time(clock,
+		((MCIO1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
+               pxa_pcmcia_cmd_time(clock,
+		((MCIO0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
+
+  p+=sprintf(p, "attribute: %u (%u)\n", pxa_pcmcia_socket[sock].speed_attr,
+             sock ?
+               pxa_pcmcia_cmd_time(clock,
+		((MCATT1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
+               pxa_pcmcia_cmd_time(clock,
+		((MCATT0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
+
+  p+=sprintf(p, "common   : %u (%u)\n", pxa_pcmcia_socket[sock].speed_mem,
+             sock ?
+               pxa_pcmcia_cmd_time(clock,
+		((MCMEM1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
+               pxa_pcmcia_cmd_time(clock,
+		((MCMEM0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
+
+  return p-buf;
+}
+
+#endif  /* defined(CONFIG_PROC_FS) */
+
+
+#ifdef CONFIG_CPU_FREQ
+
+/* pxa_pcmcia_update_mecr()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * When pxa_pcmcia_notifier() decides that a MECR adjustment (due
+ * to a core clock frequency change) is needed, this routine establishes
+ * new BS_xx values consistent with the clock speed `clock'.
+ */
+static void pxa_pcmcia_update_mecr(unsigned int clock){
+  unsigned int sock;
+
+  for(sock = 0; sock < PXA_PCMCIA_MAX_SOCK; ++sock){
+
+    // REVISIT: MCXX macros needed here
+    // MECR_BSIO_SET(mecr, sock,
+// 		  pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_io,
+// 					clock));
+    // MECR_BSA_SET(mecr, sock,
+// 		 pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_attr,
+// 				       clock));
+    // MECR_BSM_SET(mecr, sock,
+// 		 pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_mem,
+// 				       clock));
+  }
+}
+
+/* pxa_pcmcia_notifier()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
+ * When changing the processor core clock frequency, it is necessary
+ * to adjust the MECR timings accordingly. We've recorded the timings
+ * requested by Card Services, so this is just a matter of finding
+ * out what our current speed is, and then recomputing the new MECR
+ * values.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int pxa_pcmcia_notifier(struct notifier_block *nb,
+				  unsigned long val, void *data){
+  struct cpufreq_info *ci = data;
+
+  switch(val){
+  case CPUFREQ_MINMAX:
+
+    break;
+
+  case CPUFREQ_PRECHANGE:
+
+    if(ci->new_freq > ci->old_freq){
+      DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n",
+	    __FUNCTION__,
+	    ci->new_freq / 1000, (ci->new_freq / 100) % 10,
+	    ci->old_freq / 1000, (ci->old_freq / 100) % 10);
+      pxa_pcmcia_update_mecr(ci->new_freq);
+    }
+
+    break;
+
+  case CPUFREQ_POSTCHANGE:
+
+    if(ci->new_freq < ci->old_freq){
+      DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n",
+	    __FUNCTION__,
+	    ci->new_freq / 1000, (ci->new_freq / 100) % 10,
+	    ci->old_freq / 1000, (ci->old_freq / 100) % 10);
+      pxa_pcmcia_update_mecr(ci->new_freq);
+    }
+
+    break;
+
+  default:
+    printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__,
+	   val);
+    return -1;
+
+  }
+
+  return 0;
+
+}
+
+static struct notifier_block pxa_pcmcia_notifier_block = {
+  notifier_call: pxa_pcmcia_notifier
+};
+
+#endif
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/pxa/pxa.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,233 @@
+/*
+ * linux/drivers/pcmcia/pxa/pxa.h
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software 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.
+ *
+ * Originally based upon linux/drivers/pcmcia/sa1100_generic.h
+ *
+ */
+
+/*======================================================================
+
+    Device driver for the PCMCIA control functionality of Intel
+    PXA250/210 microprocessors.
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is John G. Dorsey
+    <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
+    Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    and other provisions required by the GPL.  If you do not delete
+    the provisions above, a recipient may use your version of this
+    file under either the MPL or the GPL.
+    
+======================================================================*/
+
+#if !defined(_PCMCIA_PXA_H)
+# define _PCMCIA_PXA_H
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "../cs_internal.h"
+
+#include <asm/arch/pcmcia.h>
+
+
+/* MECR: Expansion Memory Configuration Register
+ * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
+ *
+ * MECR layout is:  
+ *
+ *   FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
+ *
+ * (This layout is actually true only for the SA-1110; the FASTn bits are
+ * reserved on the SA-1100.)
+ */
+
+#define MCXX_SETUP_MASK     (0x7f)
+#define MCXX_ASST_MASK      (0x1f)
+#define MCXX_HOLD_MASK      (0x3f)
+#define MCXX_SETUP_SHIFT    (0)
+#define MCXX_ASST_SHIFT     (7)
+#define MCXX_HOLD_SHIFT     (14)
+
+
+#define MECR_SET(mecr, sock, shift, mask, bs) \
+((mecr)=((mecr)&~(((mask)<<(shift))<<\
+                  ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\
+        (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))
+
+#define MECR_GET(mecr, sock, shift, mask) \
+((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\
+ (shift))&(mask))
+
+#define MECR_BSIO_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSIO_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK)
+
+#define MECR_BSA_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSA_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK)
+
+#define MECR_BSM_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSM_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK)
+
+#define MECR_FAST_SET(mecr, sock, fast) \
+MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast))
+
+#define MECR_FAST_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK)
+
+
+/* This function implements the BS value calculation for setting the MECR
+ * using integer arithmetic:
+ */
+static inline unsigned int pxa_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
+						 unsigned int cpu_clock_khz){
+  unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000;
+  return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
+}
+
+static inline u_int pxa_mcxx_hold(u_int pcmcia_cycle_ns,
+					    u_int mem_clk_10khz){
+  u_int code = pcmcia_cycle_ns * mem_clk_10khz;
+  return (code / 300000) + ((code % 300000) ? 1 : 0);
+}
+
+static inline u_int pxa_mcxx_asst(u_int pcmcia_cycle_ns,
+					    u_int mem_clk_10khz){
+  u_int code = pcmcia_cycle_ns * mem_clk_10khz;
+  return (code / 300000) + ((code % 300000) ? 1 : 0);
+}
+
+static inline u_int pxa_mcxx_setup(u_int pcmcia_cycle_ns,
+					    u_int mem_clk_10khz){
+  u_int code = pcmcia_cycle_ns * mem_clk_10khz;
+  return (code / 100000) + ((code % 100000) ? 1 : 0) + 1;
+}
+
+/* This function returns the (approxmiate) command assertion period, in
+ * nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
+ */
+
+static inline u_int pxa_pcmcia_cmd_time(u_int mem_clk_10khz,
+					   u_int pcmcia_mcxx_asst){
+  return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
+}
+
+
+/* SA-1100 PCMCIA Memory and I/O timing
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * The SA-1110 Developer's Manual, section 10.2.5, says the following:
+ *
+ *  "To calculate the recommended BS_xx value for each address space:
+ *   divide the command width time (the greater of twIOWR and twIORD,
+ *   or the greater of twWE and twOE) by processor cycle time; divide
+ *   by 2; divide again by 3 (number of BCLK's per command assertion);
+ *   round up to the next whole number; and subtract 1."
+ *
+ * The PC Card Standard, Release 7, section 4.13.4, says that twIORD
+ * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has
+ * a minimum value of 165ns, as well. Section 4.7.2 (describing
+ * common and attribute memory write timing) says that twWE has a
+ * minimum value of 150ns for a 250ns cycle time (for 5V operation;
+ * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V
+ * operation, also section 4.7.4). Section 4.7.3 says that taOE
+ * has a maximum value of 150ns for a 300ns cycle time (for 5V
+ * operation), or 300ns for a 600ns cycle time (for 3.3V operation).
+ *
+ * When configuring memory maps, Card Services appears to adopt the policy
+ * that a memory access time of "0" means "use the default." The default
+ * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute
+ * and memory command width time is 150ns; the PCMCIA 3.3V attribute and
+ * memory command width time is 300ns.
+ */
+ 
+/* The PXA 250 and PXA 210 Application Processors Developer's Manual
+ * was used to determine correct PXA_PCMCIA_IO_ACCES time
+ */
+  
+#define PXA_PCMCIA_IO_ACCESS      (165) 
+
+/* Default PC Card Common Memory timings*/
+                                         
+#define PXA_PCMCIA_5V_MEM_ACCESS  (250)
+#define PXA_PCMCIA_3V_MEM_ACCESS  (250)
+
+/* Atrribute Memory timing - must be constant via PC Card standart*/
+ 
+#define PXA_PCMCIA_ATTR_MEM_ACCESS (300)
+
+
+/* The socket driver actually works nicely in interrupt-driven form,
+ * so the (relatively infrequent) polling is "just to be sure."
+ */
+#define PXA_PCMCIA_POLL_PERIOD    (2*HZ)
+
+
+/* This structure encapsulates per-socket state which we might need to
+ * use when responding to a Card Services query of some kind.
+ */
+struct pxa_pcmcia_socket {
+  socket_state_t        cs_state;
+  struct pcmcia_state   k_state;
+  unsigned int          irq;
+  void                  (*handler)(void *, unsigned int);
+  void                  *handler_info;
+  pccard_io_map         io_map[MAX_IO_WIN];
+  pccard_mem_map        mem_map[MAX_WIN];
+  ioaddr_t              virt_io, phys_attr, phys_mem;
+  unsigned short        speed_io, speed_attr, speed_mem;
+};
+
+
+/* I/O pins replacing memory pins
+ * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
+ *
+ * These signals change meaning when going from memory-only to 
+ * memory-or-I/O interface:
+ */
+#define iostschg bvd1
+#define iospkr   bvd2
+
+
+/*
+ * Declaration for all implementation specific low_level operations.
+ */
+extern struct pcmcia_low_level lubbock_pcmcia_ops;
+extern struct pcmcia_low_level pxa_idp_pcmcia_ops;
+extern struct pcmcia_low_level cerf_pcmcia_ops;
+extern struct pcmcia_low_level trizeps2_pcmcia_ops;
+
+#endif  /* !defined(_PCMCIA_PXA_H) */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/pxa/pxa_idp.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,297 @@
+/*
+ * linux/drivers/pcmcia/pxa/pxa_idp.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.
+ *
+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
+ * 
+ * Platform specific routines for the Accelent PXA250 IDP, based on those
+ * first done for the Lubbock.
+ *
+ * Version 1.0 2002-05-02  Jeff Sutherland <jeffs@accelent.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int 
+pxa_idp_pcmcia_init(struct pcmcia_init *init)
+{
+	int return_val = 0;
+
+  	/* Set PCMCIA Socket 0 power to standby mode.
+	*  PXA IDP has dedicated CPLD pins for all this stuff :-)
+   	*/
+	
+	/* both slots disabled, reset NOT active */
+	IDP_CPLD_PCCARD_EN = PCC0_ENABLE | PCC1_ENABLE;
+
+	IDP_CPLD_PCCARD_PWR = 0; //all power to both slots off
+
+	GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID)) &=
+	    ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID));
+	GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID)) &=
+	    ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID));
+
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID),
+			  GPIO_BOTH_EDGES);
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID),
+			  GPIO_BOTH_EDGES);
+
+	/* irq's for slots: */
+	GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT)) &=
+	    ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT));
+	GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT)) &=
+	    ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT));
+
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT),
+			  GPIO_FALLING_EDGE);
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT),
+			  GPIO_FALLING_EDGE);
+
+	return_val =
+	    request_irq(PCMCIA_S0_CD_VALID, init->handler, SA_INTERRUPT,
+			"PXA PCMCIA CD0", NULL);
+
+	if (return_val < 0)
+		return -1;
+	
+	return_val +=
+	    request_irq(PCMCIA_S1_CD_VALID, init->handler, SA_INTERRUPT,
+			"PXA PCMCIA CD1", NULL);
+	
+	if (return_val < 0) {
+		free_irq(PCMCIA_S0_CD_VALID, NULL);
+		return -1;
+	}
+
+	return 2;
+}
+
+static int
+pxa_idp_pcmcia_shutdown(void)
+{
+
+	free_irq(PCMCIA_S0_CD_VALID, NULL);
+	free_irq(PCMCIA_S1_CD_VALID, NULL);
+  
+	IDP_CPLD_PCCARD_EN = 0x03;	//disable slots
+	udelay(200);
+	IDP_CPLD_PCCARD_PWR = 0; //shut off all power
+
+	return 0;
+}
+
+static int
+pxa_idp_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+	unsigned long status;
+	int return_val = 1;
+	int i;
+	volatile unsigned long *stat_regs[2] = { &IDP_CPLD_PCCARD0_STATUS,
+		&IDP_CPLD_PCCARD1_STATUS
+	};
+
+	if (state_array->size < 2)
+		return -1;
+
+	memset(state_array->state, 0,
+	       (state_array->size) * sizeof (struct pcmcia_state));
+	
+	for (i = 0; i < 2; i++) {
+
+		status = *stat_regs[i];
+
+	      	/* this one is a gpio */
+		state_array->state[i].detect = (PCC_DETECT(i)) ? 0 : 1;
+		
+		state_array->state[i].ready =
+		    ((status & _PCC_IRQ) == 0) ? 0 : 1;
+		state_array->state[i].bvd1   = (status & PCC_BVD1) ? 0 : 1;
+		state_array->state[i].bvd2   = (status & PCC_BVD2) ? 0 : 1;
+		state_array->state[i].wrprot =
+		    (status & _PCC_WRPROT) ? 1 : 0;
+		state_array->state[i].vs_3v  = (status & PCC_VS1) ? 0 : 1;
+		state_array->state[i].vs_Xv  = (status & PCC_VS2) ? 0 : 1;
+	}
+
+	return return_val;
+}
+
+static int
+pxa_idp_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+	switch (info->sock) {
+	    case 0:
+		info->irq = PCMCIA_S0_RDYINT;
+		break;
+
+	    case 1:
+		info->irq = PCMCIA_S1_RDYINT;
+		break;
+
+	    default:
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+pxa_idp_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
+{
+  /* The PXA Idp uses the Maxim MAX1602, with the following connections:
+   *
+   * Socket 0 (PCMCIA):
+   *	MAX1602	PXA_IDP		Register
+   *	Pin	Signal  	IDP_CPLD_PCCARD_PWR:
+   *	-----	-------		----------------------
+   *	A0VPP	PCC0_PWR0	bit0
+   *	A1VPP	PCC0_PWR1	bit1	
+   *	A0VCC	PCC0_PWR2	bit2
+   *	A1VCC	PCC0_PWR3	bit3
+   *	VX	VCC
+   *	VY	+3.3V
+   *	12IN	+12V
+   *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
+   *
+   * Socket 1 (PCMCIA):
+   *	MAX1602	PXA_IDP		Register
+   *	Pin	Signal		IDP_CPLD_PCCARD_PWR:
+   *	-----	-------		----------------------
+   *	A0VPP	PCC1_PWR0	bit4
+   *	A1VPP	PCC1_PWR1	bit5
+   *	A0VCC	PCC1_PWR2	bit6
+   *	A1VCC	PCC1_PWR3	bit7
+   *	VX	VCC
+   *	VY	+3.3V
+   *	12IN	+12V		
+   *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
+   *
+   */
+
+	switch (sock) {
+	    case 0:
+		switch (state->Vcc) {
+		    case 0:
+			IDP_CPLD_PCCARD_EN |= PCC0_ENABLE; // disable socket
+			udelay(200);
+			IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
+			break;
+
+		    case 33:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
+			IDP_CPLD_PCCARD_PWR |= PCC0_PWR3;
+			IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE; //turn it on
+			break;
+
+		    case 50:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
+			IDP_CPLD_PCCARD_PWR |= PCC0_PWR2;
+			IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE;
+			break;
+
+		    default:
+			printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
+			       __FUNCTION__, state->Vcc);
+			return -1;
+		}
+
+		switch (state->Vpp) {
+		    case 0:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1);
+			break;
+
+		    case 120:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1);
+			IDP_CPLD_PCCARD_PWR |= PCC0_PWR1;
+			break;
+
+		    default:
+			if (state->Vpp == state->Vcc)
+				IDP_CPLD_PCCARD_PWR =
+				    (IDP_CPLD_PCCARD_PWR &
+				     ~(PCC0_PWR0 | PCC0_PWR1)) | PCC0_PWR0;
+			else {
+				printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
+				       __FUNCTION__, state->Vpp);
+			return -1;
+		}
+	    }
+
+		IDP_CPLD_PCCARD_EN =
+		    (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC0_RESET)
+		    : (IDP_CPLD_PCCARD_EN & ~PCC0_RESET);
+	    break;
+
+	case 1:
+		switch (state->Vcc) {
+		    case 0:
+			IDP_CPLD_PCCARD_EN |= PCC1_ENABLE; // disable socket
+			udelay(200);
+			IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
+			break;
+
+		    case 33:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
+			IDP_CPLD_PCCARD_PWR |= PCC1_PWR3;
+			IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE; //turn it on
+			break;
+
+		    case 50:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
+			IDP_CPLD_PCCARD_PWR |= PCC1_PWR2;
+			IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE;
+			break;
+
+		    default:
+			printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
+			       __FUNCTION__, state->Vcc);
+			return -1;
+		}
+
+		switch (state->Vpp) {
+		    case 0:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
+			break;
+
+		    case 120:
+			IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
+			IDP_CPLD_PCCARD_PWR |= PCC1_PWR1;
+			break;
+
+		    default:
+			if (state->Vpp == state->Vcc)
+				IDP_CPLD_PCCARD_PWR =
+				    (IDP_CPLD_PCCARD_PWR &
+				     ~(PCC1_PWR0 | PCC1_PWR1)) | PCC1_PWR0;
+			else {
+				printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
+				       __FUNCTION__, state->Vpp);
+				return -1;
+			}
+		}
+		IDP_CPLD_PCCARD_EN = (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC1_RESET)
+		    : (IDP_CPLD_PCCARD_EN & ~PCC1_RESET);
+	    break;
+	}
+	return 0;
+}
+
+struct pcmcia_low_level pxa_idp_pcmcia_ops = { 
+  pxa_idp_pcmcia_init,
+  pxa_idp_pcmcia_shutdown,
+  pxa_idp_pcmcia_socket_state,
+  pxa_idp_pcmcia_get_irq_info,
+  pxa_idp_pcmcia_configure_socket
+};
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/pxa/trizeps2.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,187 @@
+/*
+ * linux/drivers/pcmcia/pxa/trizeps2.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.
+ *
+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
+ * 
+ * Platform specific routines for the Keith-n-Koep Trizeps-II, based on IDP
+ *
+ * Copyright (c) 2003 Teradyne DS, Ltd.
+ * Port to Trizeps-2 MT6N board by Luc De Cock
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int trizeps2_pcmcia_init(struct pcmcia_init *init)
+{
+	int return_val = 0;
+	unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
+	unsigned short val;
+
+	/* reset the PCMCIA controller */
+	val = trizeps2_bcr_shadow | BCR_PCMCIA_RESET;
+	*bcr = val;
+	udelay(500);
+	/* un-reset it again */
+	trizeps2_bcr_shadow &= ~BCR_PCMCIA_RESET;
+	/* enable the PCMCIA buffer */
+	trizeps2_bcr_shadow &= ~(1 << 5);
+	*bcr = trizeps2_bcr_shadow;
+
+	GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID)) &=
+	       	~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID));
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID),
+				PCMCIA_S_CD_VALID_EDGE);
+	GPDR(IRQ_TO_GPIO(PCMCIA_S_RDYINT)) &=
+	       	~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S_RDYINT));
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO(PCMCIA_S_RDYINT),
+				PCMCIA_S_RDYINT_EDGE);
+
+	return_val = request_irq(PCMCIA_S_CD_VALID, init->handler, SA_INTERRUPT,
+			"PXA PCMCIA CD", NULL);
+	if (return_val < 0) {
+		return -1;
+	}
+	/* only 1 slot */
+	return 1;
+}
+
+static int trizeps2_pcmcia_shutdown(void)
+{
+	free_irq(PCMCIA_S_CD_VALID, NULL);
+
+	unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
+	trizeps2_bcr_shadow |= (1 << 5); /* pcmcia buffer off */
+	*bcr = trizeps2_bcr_shadow;
+	trizeps2_bcr_shadow &= 0xFFF0; /* pcmcia control logic grounded */
+	*bcr = trizeps2_bcr_shadow;
+
+	return 0;
+}
+
+static int trizeps2_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+	unsigned long status;
+	int return_val = 1;
+	volatile unsigned short *stat_regs[1] = {
+	       	&TRIZEPS2_PCCARD_STATUS
+	};
+
+	if (state_array->size < 1)
+		return -1;
+
+	memset(state_array->state, 0,
+	       (state_array->size) * sizeof (struct pcmcia_state));
+	
+	status = *stat_regs[0];
+
+      	/* this one is a gpio */
+	state_array->state[0].detect = (PCC_DETECT) ? 0 : 1;
+	state_array->state[0].ready =  (PCC_READY) ? 1 : 0;
+	state_array->state[0].bvd1   = (status & PCC_BVD1) ? 1 : 0;
+	state_array->state[0].bvd2   = (status & PCC_BVD2) ? 1 : 0;
+	state_array->state[0].wrprot = 0; /* r/w all the time */
+	state_array->state[0].vs_3v  = (status & PCC_VS1) ? 0 : 1;
+	state_array->state[0].vs_Xv  = (status & PCC_VS2) ? 0 : 1;
+
+	return return_val;
+}
+
+static int trizeps2_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+	switch (info->sock) {
+	    case 0:
+		info->irq = PCMCIA_S_RDYINT;
+		break;
+
+	    default:
+		return -1;
+	}
+
+	return 0;
+}
+
+static int trizeps2_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
+{
+	unsigned short cntr_logic = trizeps2_bcr_shadow & 0xF;
+	unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
+
+	/* configure Vcc and Vpp */
+	switch (sock) {
+	    case 0:
+		switch (state->Vcc) {
+		    case 0:
+			cntr_logic &= ~(PCC_3V | PCC_5V);
+			break;
+
+		    case 33:
+			cntr_logic &= ~(PCC_3V | PCC_5V);
+			cntr_logic |= PCC_3V;
+			break;
+
+		    case 50:
+			cntr_logic &= ~(PCC_3V | PCC_5V);
+			cntr_logic |= PCC_5V;
+			break;
+
+		    default:
+			printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
+			       __FUNCTION__, state->Vcc);
+			return -1;
+		}
+
+		switch (state->Vpp) {
+		    case 0:
+			cntr_logic &= ~(PCC_EN0 | PCC_EN1);
+			break;
+
+		    case 120:
+			cntr_logic &= ~(PCC_EN0 | PCC_EN1);
+			cntr_logic |= PCC_EN1;
+			break;
+
+		    default:
+			if (state->Vpp == state->Vcc) {
+				cntr_logic &= ~(PCC_EN0 | PCC_EN1);
+				cntr_logic |= PCC_EN0;
+			}
+			else {
+				printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
+				       __FUNCTION__, state->Vpp);
+				return -1;
+			}
+	    }
+	    trizeps2_bcr_shadow &= ~(PCC_EN0 | PCC_EN1 | PCC_3V | PCC_5V |
+			    		BCR_PCMCIA_RESET);
+	    trizeps2_bcr_shadow |= cntr_logic;
+	    *bcr = trizeps2_bcr_shadow;
+	    /* reset PCMCIA controller if requested */
+	    trizeps2_bcr_shadow |=
+	    	    (state->flags & SS_RESET) ? BCR_PCMCIA_RESET : 0;
+	    *bcr = trizeps2_bcr_shadow;
+	    udelay(500);
+	    break;
+	}
+	return 0;
+}
+
+struct pcmcia_low_level trizeps2_pcmcia_ops = { 
+  trizeps2_pcmcia_init,
+  trizeps2_pcmcia_shutdown,
+  trizeps2_pcmcia_socket_state,
+  trizeps2_pcmcia_get_irq_info,
+  trizeps2_pcmcia_configure_socket
+};
+
--- linux-2.4.25/drivers/pcmcia/sa1100_cerf.c~2.4.25-vrs2-pxa1.patch	2002-08-03 02:39:44.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/sa1100_cerf.c	2004-03-31 17:15:12.000000000 +0200
@@ -7,15 +7,25 @@
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
-#include "sa1100_generic.h"
 
-#ifdef CONFIG_SA1100_CERF_CPLD
-#define CERF_SOCKET	0
+#include <pcmcia/ss.h>
+#include <asm/arch/pcmcia.h>
+#include "sa1100_cerf.h"
+
+/*
+ * Set this to zero to remove all the debug statements via
+ * dead code elimination
+ */
+//#define DEBUGGING       1
+
+#if DEBUGGING
+static unsigned int pcmcia_debug = DEBUGGING;
 #else
-#define CERF_SOCKET	1
+#define pcmcia_debug 0     /* gcc will remove all the debug code for us */
 #endif
 
 static struct irqs {
@@ -23,122 +33,178 @@
 	unsigned int gpio;
 	const char *str;
 } irqs[] = {
-	{ IRQ_GPIO_CF_CD,   GPIO_CF_CD,   "CF_CD"   },
-	{ IRQ_GPIO_CF_BVD2, GPIO_CF_BVD2, "CF_BVD2" },
-	{ IRQ_GPIO_CF_BVD1, GPIO_CF_BVD1, "CF_BVD1" }
+	{ PCMCIA_IRQ_CF_CD,   PCMCIA_GPIO_CF_CD_EDGE,   "CF_CD"   },
+	{ PCMCIA_IRQ_CF_BVD2, PCMCIA_GPIO_CF_BVD2_EDGE, "CF_BVD2" },
+	{ PCMCIA_IRQ_CF_BVD1, PCMCIA_GPIO_CF_BVD1_EDGE, "CF_BVD1" }
 };
 
+static void cerf_pcmcia_reset( void)
+{
+	int i;
+
+	// Make sure SKTSEL is 0 (single slot)
+	set_GPIO_mode(54 | GPIO_OUT);
+	GPCR1 = GPIO_bit(54);
+	set_GPIO_mode(GPIO54_pSKTSEL_MD);
+
+	PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK;
+	mdelay(300);
+
+	PCMCIA_GPSR = PCMCIA_GPIO_CF_RESET_MASK;
+	udelay(20);
+
+	PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK;
+	mdelay(50);
+
+	for( i=0; i<10; i++)
+	{
+		if( cerf_pcmcia_level_ready()) break;
+		mdelay(100);
+	}
+}
+
 static int cerf_pcmcia_init(struct pcmcia_init *init)
 {
-  int i, res;
+	int i, res;
 
-  set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+	if( pcmcia_debug)
+		printk( KERN_INFO "cerf_pcmcia_init: enter\n");
 
-  for (i = 0; i < ARRAY_SIZE(irqs); i++) {
-    set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
-    res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-		      irqs[i].str, NULL);
-    if (res)
-      goto irq_err;
-  }
+	cerf_pcmcia_set_gpio_direction();
 
-  return 2;
+	set_GPIO_IRQ_edge( PCMCIA_GPIO_CF_IRQ_EDGE, GPIO_FALLING_EDGE );
 
- irq_err:
-  printk(KERN_ERR "%s: Request for IRQ%d failed\n", __FUNCTION__, irqs[i].irq);
+	for (i = 0; i < ARRAY_SIZE(irqs); i++) {
 
-  while (i--)
-    free_irq(irqs[i].irq, NULL);
+		set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
 
-  return -1;
+		res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+				irqs[i].str, NULL);
+		if (res)
+			goto irq_err;
+	}
+
+	printk( KERN_INFO "PCMCIA for Cerf: OK\n");
+
+	return CERF_SOCKET+1; /* last socket used +1 */
+
+irq_err:
+	printk(KERN_ERR "%s: Request for IRQ%d failed\n", 
+		__FUNCTION__, irqs[i].irq);
+
+	while (i--)
+		free_irq(irqs[i].irq, NULL);
+
+	return -1;
 }
 
 static int cerf_pcmcia_shutdown(void)
 {
-  int i;
+	int i;
+	if( pcmcia_debug)
+		printk( KERN_INFO "cerf_pcmcia_shutdown: enter\n");
 
-  for (i = 0; i < ARRAY_SIZE(irqs); i++)
-    free_irq(irqs[i].irq, NULL);
+	for (i = 0; i < ARRAY_SIZE(irqs); i++)
+		free_irq(irqs[i].irq, NULL);
 
-  return 0;
+	return 0;
 }
 
-static int cerf_pcmcia_socket_state(struct pcmcia_state_array
-				       *state_array){
-  unsigned long levels;
-  int i = CERF_SOCKET;
+static int cerf_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+	int i = CERF_SOCKET;
 
-  if(state_array->size<2) return -1;
+	if( pcmcia_debug > 3)
+		printk( KERN_INFO "cerf_pcmcia_socket_state: i=%d, size=%d\n",
+				i, state_array->size);
 
-  levels=GPLR;
+        memset(state_array->state, 0,
+                        (state_array->size)*sizeof(struct pcmcia_state));
 
-  state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0;
-  state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0;
-  state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0;
-  state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0;
-  state_array->state[i].wrprot=0;
-  state_array->state[i].vs_3v=1;
-  state_array->state[i].vs_Xv=0;
+	state_array->state[i].detect = cerf_pcmcia_level_detect();
+	state_array->state[i].ready  = cerf_pcmcia_level_ready();
+	state_array->state[i].bvd1   = cerf_pcmcia_level_bvd1();
+	state_array->state[i].bvd2   = cerf_pcmcia_level_bvd2();
+	state_array->state[i].wrprot=0;
+	state_array->state[i].vs_3v=1;
+	state_array->state[i].vs_Xv=0;
 
-  return 1;
+	if( pcmcia_debug > 3)
+		printk( KERN_INFO "cerf_pcmcia_socket_state: "
+			"detect=%d ready=%d bvd1=%d bvd2=%d\n", 
+			state_array->state[i].detect,
+			state_array->state[i].ready,
+			state_array->state[i].bvd1,
+			state_array->state[i].bvd2);
+
+	return 1;
 }
 
 static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
 
-  if(info->sock>1) return -1;
+	if( pcmcia_debug)
+		printk( KERN_INFO "cerf_pcmcia_get_irq_info: "
+				"sock=%d\n", info->sock);
 
-  if (info->sock == CERF_SOCKET)
-    info->irq=IRQ_GPIO_CF_IRQ;
+	if(info->sock>1) return -1;
 
-  return 0;
+	if (info->sock == CERF_SOCKET)
+		info->irq=PCMCIA_IRQ_CF_IRQ;
+
+	if( pcmcia_debug)
+		printk( KERN_INFO "cerf_pcmcia_get_irq_info: irq=%d\n",info->irq);
+
+	return 0;
 }
 
-static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
-					   *configure)
+static int cerf_pcmcia_configure_socket( unsigned int sock, socket_state_t *state)
 {
-  if(configure->sock>1)
-    return -1;
+	if( pcmcia_debug)
+		printk( KERN_INFO "cerf_pcmcia_configure_socket:"
+			"sock=%d vcc=%d flags=%x\n",
+			sock, state->Vcc, state->flags);
 
-  if (configure->sock != CERF_SOCKET)
-    return 0;
+	if(sock>1)
+		return -1;
 
-  switch(configure->vcc){
-  case 0:
-    break;
+	if (sock != CERF_SOCKET)
+		return 0;
 
-  case 50:
-  case 33:
-#ifdef CONFIG_SA1100_CERF_CPLD
-     GPCR = GPIO_PWR_SHUTDOWN;
+	switch(state->Vcc){
+		case 0:
+			break;
+
+		case 50:
+		case 33:
+#if defined(CONFIG_SA1100_CERF_CPLD)
+                        PCMCIA_GPDR |= PCMCIA_PWR_SHUTDOWN;
+                        PCMCIA_GPCR |= PCMCIA_PWR_SHUTDOWN;
 #endif
-     break;
+                        /* voltage selected automatically */
+			break;
 
-  default:
-    printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
-	   configure->vcc);
-    return -1;
-  }
+		default:
+			printk(KERN_ERR "%s(): unrecognized Vcc %u\n", 
+				__FUNCTION__, state->Vcc);
+			return -1;
+	}
 
-  if(configure->reset)
-  {
-#ifdef CONFIG_SA1100_CERF_CPLD
-    GPSR = GPIO_CF_RESET;
-#endif
-  }
-  else
-  {
-#ifdef CONFIG_SA1100_CERF_CPLD
-    GPCR = GPIO_CF_RESET;
-#endif
-  }
+	if(state->flags&SS_RESET)
+	{
+		cerf_pcmcia_reset();
+	}
 
-  return 0;
+	return 0;
 }
 
+#ifdef CONFIG_SA1100_CERF
 static int cerf_pcmcia_socket_init(int sock)
 {
   int i;
 
+  if( pcmcia_debug)
+      printk( KERN_INFO "cerf_pcmcia_socket_init: sock=%d\n",sock);
+
   if (sock == CERF_SOCKET)
     for (i = 0; i < ARRAY_SIZE(irqs); i++)
       set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
@@ -150,21 +216,26 @@
 {
   int i;
 
+  if( pcmcia_debug)
+      printk( KERN_INFO "cerf_pcmcia_socket_suspend: sock=%d\n",sock);
+
   if (sock == CERF_SOCKET)
     for (i = 0; i < ARRAY_SIZE(irqs); i++)
       set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
 
   return 0;
 }
+#endif
 
 struct pcmcia_low_level cerf_pcmcia_ops = { 
-  init:			cerf_pcmcia_init,
-  shutdown:		cerf_pcmcia_shutdown,
-  socket_state:		cerf_pcmcia_socket_state,
-  get_irq_info:		cerf_pcmcia_get_irq_info,
-  configure_socket:	cerf_pcmcia_configure_socket,
+init:			cerf_pcmcia_init,
+shutdown:		cerf_pcmcia_shutdown,
+socket_state:		cerf_pcmcia_socket_state,
+get_irq_info:		cerf_pcmcia_get_irq_info,
+configure_socket:	cerf_pcmcia_configure_socket,
 
-  socket_init:		cerf_pcmcia_socket_init,
-  socket_suspend:	cerf_pcmcia_socket_suspend,
+#ifdef CONFIG_SA1100_CERF
+socket_init:		cerf_pcmcia_socket_init,
+socket_suspend:		cerf_pcmcia_socket_suspend,
+#endif
 };
-
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/pcmcia/sa1100_cerf.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,138 @@
+/*
+ * drivers/pcmcia/cerf.h
+ *
+ * PCMCIA implementation routines for CerfBoard
+ * Based off the Assabet.
+ *
+ */
+#ifndef _LINUX_PCMCIA_CERF_H
+#define _LINUX_PCMCIA_CERF_H
+
+#include <linux/config.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+#ifdef CONFIG_PXA_CERF /* PXA */
+
+#define PCMCIA_GPCR GPCR0
+#define PCMCIA_GPSR GPSR0
+
+#define PCMCIA_GPIO_CF_CD    14
+#define PCMCIA_GPIO_CF_IRQ   13
+#define PCMCIA_GPIO_CF_RESET 12
+#ifdef CONFIG_PXA_CERF_PDA
+# define PCMCIA_GPIO_CF_BVD1  11
+# define PCMCIA_GPIO_CF_BVD2  10
+#elif defined( CONFIG_PXA_CERF_BOARD)
+# define PCMCIA_GPIO_CF_BVD1  32
+# define PCMCIA_GPIO_CF_BVD2  10
+#endif
+
+#define PCMCIA_GPIO_CF_CD_MASK    (GPIO_bit(PCMCIA_GPIO_CF_CD))
+#define PCMCIA_GPIO_CF_IRQ_MASK   (GPIO_bit(PCMCIA_GPIO_CF_IRQ))
+#define PCMCIA_GPIO_CF_RESET_MASK (GPIO_bit(PCMCIA_GPIO_CF_RESET))
+#define PCMCIA_GPIO_CF_BVD1_MASK  (GPIO_bit(PCMCIA_GPIO_CF_BVD1))
+#define PCMCIA_GPIO_CF_BVD2_MASK  (GPIO_bit(PCMCIA_GPIO_CF_BVD2))
+
+#define PCMCIA_GPIO_CF_CD_EDGE    PCMCIA_GPIO_CF_CD
+#define PCMCIA_GPIO_CF_IRQ_EDGE   PCMCIA_GPIO_CF_IRQ
+#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET
+#define PCMCIA_GPIO_CF_BVD1_EDGE  PCMCIA_GPIO_CF_BVD1
+#define PCMCIA_GPIO_CF_BVD2_EDGE  PCMCIA_GPIO_CF_BVD2
+
+#define PCMCIA_IRQ_CF_CD   IRQ_GPIO(PCMCIA_GPIO_CF_CD)
+#define PCMCIA_IRQ_CF_IRQ  IRQ_GPIO(PCMCIA_GPIO_CF_IRQ)
+#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO(PCMCIA_GPIO_CF_BVD1)
+#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO(PCMCIA_GPIO_CF_BVD2)
+
+#define PCMCIA_PWR_SHUTDOWN 0 /* not needed */
+#define CERF_SOCKET 0
+
+inline void cerf_pcmcia_set_gpio_direction(void)
+{
+	GPDR(PCMCIA_GPIO_CF_CD)   &= ~(PCMCIA_GPIO_CF_CD_MASK);
+	GPDR(PCMCIA_GPIO_CF_BVD1) &= ~(PCMCIA_GPIO_CF_BVD1_MASK);
+	GPDR(PCMCIA_GPIO_CF_BVD2) &= ~(PCMCIA_GPIO_CF_BVD2_MASK);
+	GPDR(PCMCIA_GPIO_CF_IRQ)  &= ~(PCMCIA_GPIO_CF_IRQ_MASK);
+	GPDR(PCMCIA_GPIO_CF_RESET)|=  (PCMCIA_GPIO_CF_RESET_MASK);
+}
+
+inline int cerf_pcmcia_level_detect( void)
+{
+	return ((GPLR(PCMCIA_GPIO_CF_CD)&PCMCIA_GPIO_CF_CD_MASK)==0)?1:0;
+}
+inline int cerf_pcmcia_level_ready( void)
+{
+	return (GPLR(PCMCIA_GPIO_CF_IRQ)&PCMCIA_GPIO_CF_IRQ_MASK)?1:0;
+}
+inline int cerf_pcmcia_level_bvd1( void)
+{
+	return (GPLR(PCMCIA_GPIO_CF_BVD1)&PCMCIA_GPIO_CF_BVD1_MASK)?1:0;
+}
+inline int cerf_pcmcia_level_bvd2( void)
+{
+	return (GPLR(PCMCIA_GPIO_CF_BVD2)&PCMCIA_GPIO_CF_BVD2_MASK)?1:0;
+}
+
+#elif defined(CONFIG_SA1100_CERF) /* SA1100 */
+
+#define PCMCIA_GPDR GPDR
+#define PCMCIA_GPCR GPCR
+#define PCMCIA_GPSR GPSR
+#define PCMCIA_GPLR GPLR
+
+#define PCMCIA_GPIO_CF_CD_MASK    GPIO_CF_CD
+#define PCMCIA_GPIO_CF_IRQ_MASK   GPIO_CF_IRQ
+#define PCMCIA_GPIO_CF_RESET_MASK GPIO_CF_RESET
+#define PCMCIA_GPIO_CF_BVD1_MASK  GPIO_CF_BVD1
+#define PCMCIA_GPIO_CF_BVD2_MASK  GPIO_CF_BVD2
+
+#define PCMCIA_GPIO_CF_CD_EDGE    PCMCIA_GPIO_CF_CD_MASK
+#define PCMCIA_GPIO_CF_IRQ_EDGE   PCMCIA_GPIO_CF_IRQ_MASK
+#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET_MASK
+#define PCMCIA_GPIO_CF_BVD1_EDGE  PCMCIA_GPIO_CF_BVD1_MASK
+#define PCMCIA_GPIO_CF_BVD2_EDGE  PCMCIA_GPIO_CF_BVD2_MASK
+
+#define PCMCIA_IRQ_CF_CD   IRQ_GPIO_CF_CD
+#define PCMCIA_IRQ_CF_IRQ  IRQ_GPIO_CF_IRQ
+#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO_CF_BVD1
+#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO_CF_BVD2
+
+#define PCMCIA_PWR_SHUTDOWN GPIO_PWR_SHUTDOWN
+
+#ifdef CONFIG_SA1100_CERF_CPLD
+#define CERF_SOCKET 0
+#else
+#define CERF_SOCKET 1
+#endif
+
+inline void cerf_pcmcia_set_gpio_direction(void)
+{
+	PCMCIA_GPDR &= ~(PCMCIA_GPIO_CF_CD_MASK |
+			 PCMCIA_GPIO_CF_BVD1_MASK |
+			 PCMCIA_GPIO_CF_BVD2_MASK |
+			 PCMCIA_GPIO_CF_IRQ_MASK);
+	PCMCIA_GPDR |=   PCMCIA_GPIO_CF_RESET_MASK;
+}
+
+inline int cerf_pcmcia_level_detect( void)
+{
+	return ((PCMCIA_GPLR & PCMCIA_GPIO_CF_CD_MASK)==0)?1:0;
+}
+inline int cerf_pcmcia_level_ready( void)
+{
+	return (PCMCIA_GPLR & PCMCIA_GPIO_CF_IRQ_MASK)?1:0;
+}
+inline int cerf_pcmcia_level_bvd1( void)
+{
+	return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD1_MASK)?1:0;
+}
+inline int cerf_pcmcia_level_bvd2( void)
+{
+	return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD2_MASK)?1:0;
+}
+
+#endif
+
+#endif
--- linux-2.4.25/drivers/sound/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/sound/Config.in	2004-03-31 17:15:12.000000000 +0200
@@ -239,6 +239,7 @@
       dep_tristate '    VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
    fi
    dep_tristate '    Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
+   dep_tristate '  Intel PXA250/210 AC97 audio' CONFIG_SOUND_PXA_AC97 $CONFIG_ARCH_PXA $CONFIG_SOUND
 fi
 
 dep_tristate '  TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
--- linux-2.4.25/drivers/sound/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/sound/Makefile	2004-03-31 17:15:12.000000000 +0200
@@ -11,7 +11,7 @@
 		    msnd.o opl3.o sb_common.o sequencer_syms.o \
 		    sound_core.o sound_syms.o uart401.o	\
 		    nm256_audio.o ac97.o ac97_codec.o aci.o \
-		    sa1100-audio.o
+		    sa1100-audio.o pxa-audio.o pxa-ac97.o
 
 # Each configuration option enables a list of files.
 
@@ -85,6 +85,7 @@
 obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
 obj-$(CONFIG_SOUND_SA1111_AC97)	+= sa1111-ac97.o ac97_codec.o
 obj-$(CONFIG_SOUND_SA1100SSP)	+= sa1100ssp.o
+obj-$(CONFIG_SOUND_PXA_AC97)+= pxa-ac97.o pxa-audio.o ac97_codec.o
 obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
 obj-$(CONFIG_SOUND_BCM_CS4297A)	+= swarm_cs4297a.o
 obj-$(CONFIG_SOUND_RME96XX)     += rme96xx.o
--- linux-2.4.25/drivers/sound/ac97_codec.c~2.4.25-vrs2-pxa1.patch	2003-11-28 19:26:20.000000000 +0100
+++ linux-2.4.25/drivers/sound/ac97_codec.c	2004-03-31 17:15:12.000000000 +0200
@@ -155,6 +155,7 @@
 	{0x45838308, "ESS Allegro ES1988",	&null_ops},
 	{0x49434511, "ICE1232",			&null_ops}, /* I hope --jk */
 	{0x4e534331, "National Semiconductor LM4549", &null_ops},
+	{0x50534304, "Philips UCB1400",		&default_ops},
 	{0x53494c22, "Silicon Laboratory Si3036", &null_ops},
 	{0x53494c23, "Silicon Laboratory Si3038", &null_ops},
 	{0x545200FF, "TriTech TR?????",		&tritech_m_ops},
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/sound/pxa-ac97.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,370 @@
+/*
+ *  linux/drivers/sound/pxa-ac97.c -- AC97 interface for the Cotula chip
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Aug 15, 2001
+ *  Copyright:	MontaVista Software 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.
+ *
+ *  AC97 GPIO Changes:-
+ *   In order to read/write codec GPIO bits using AC97 link slot 12,
+ *   all IO to AC97_GPIO_STATUS must be via the Xscale modem codec
+ *   address space. 
+ *     Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/ac97_codec.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/dma.h>
+
+#include "pxa-audio.h"
+
+static struct completion CAR_completion;
+static int waitingForMask;
+static DECLARE_MUTEX(CAR_mutex);
+
+static u16 pxa_ac97_read(struct ac97_codec *codec, u8 reg)
+{
+	u16 val = -1;
+
+	down(&CAR_mutex);
+	if (!(CAR & CAR_CAIP)) {
+		volatile u32 *reg_addr;
+		
+		// if we are reading the GPIO status then this is cached 
+		// in hardware so we don't need to read over the link.		
+		if (reg == AC97_GPIO_STATUS) {
+			reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1);
+			val = *reg_addr;
+			return val;
+		} 
+		
+		reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);
+
+		waitingForMask=GSR_SDONE;
+
+		init_completion(&CAR_completion);
+		(void)*reg_addr;			//start read access across the ac97 link
+		wait_for_completion(&CAR_completion);
+
+		if (GSR & GSR_RDCS) {
+			GSR |= GSR_RDCS;		//write a 1 to clear
+			printk(KERN_CRIT __FUNCTION__": read codec register timeout.\n");
+		}
+
+		init_completion(&CAR_completion);
+		val = *reg_addr;			//valid data now but we've just started another cycle...
+		wait_for_completion(&CAR_completion);
+
+	} else {
+		printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");
+	}
+	up(&CAR_mutex);
+	//printk("%s(0x%02x) = 0x%04x\n", __FUNCTION__, reg, val);
+	return val;
+}
+
+static void pxa_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
+{
+	down(&CAR_mutex);
+	if (!(CAR & CAR_CAIP)) {
+		volatile u32 *reg_addr;
+		
+		// if we are writing to the codec GPIO using slot 12 
+		// then we have to write to the modem register space		
+		if (reg == AC97_GPIO_STATUS) {
+			reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1);
+			*reg_addr = val;
+			return;
+		} 
+		
+		reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);
+
+		waitingForMask=GSR_CDONE;
+		init_completion(&CAR_completion);
+		*reg_addr = val;
+		wait_for_completion(&CAR_completion);
+	} else {
+		printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");
+	}
+	up(&CAR_mutex);
+	//printk("%s(0x%02x, 0x%04x)\n", __FUNCTION__, reg, val);
+}
+
+static void pxa_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int gsr = GSR;
+	GSR = gsr & (GSR_SDONE|GSR_CDONE);		//write a 1 to clear
+	if (gsr & waitingForMask)
+	{
+		complete(&CAR_completion);
+	}
+}
+
+static struct ac97_codec pxa_ac97_codec = {
+	codec_read:	pxa_ac97_read,
+	codec_write:	pxa_ac97_write,
+};
+
+static DECLARE_MUTEX(pxa_ac97_mutex);
+static int pxa_ac97_refcount;
+
+int pxa_ac97_get(struct ac97_codec **codec)
+{
+	int ret;
+
+	*codec = NULL;
+	down(&pxa_ac97_mutex);
+
+	if (!pxa_ac97_refcount) {
+		ret = request_irq(IRQ_AC97, pxa_ac97_irq, 0, "AC97", NULL);
+		if (ret)
+			return ret;
+
+		CKEN |= CKEN2_AC97; 
+		set_GPIO_mode(GPIO31_SYNC_AC97_MD);
+		set_GPIO_mode(GPIO30_SDATA_OUT_AC97_MD);
+		set_GPIO_mode(GPIO28_BITCLK_AC97_MD);
+		set_GPIO_mode(GPIO29_SDATA_IN_AC97_MD);
+
+		GCR = 0;
+		udelay(10);
+		GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE;
+		while (!(GSR & GSR_PCR)) {
+			schedule();
+		}
+
+		ret = ac97_probe_codec(&pxa_ac97_codec);
+		if (ret != 1) {
+			free_irq(IRQ_AC97, NULL);
+			GCR = GCR_ACLINK_OFF;
+			CKEN &= ~CKEN2_AC97; 
+			return ret;
+		}
+
+		// need little hack for UCB1400 (should be moved elsewhere)
+		pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1);
+		//pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x1ff7);
+		pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050);
+		pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030);
+	}
+
+	pxa_ac97_refcount++;
+	up(&pxa_ac97_mutex);
+	*codec = &pxa_ac97_codec;
+	return 0;
+}
+
+void pxa_ac97_put(void)
+{
+	down(&pxa_ac97_mutex);
+	pxa_ac97_refcount--;
+	if (!pxa_ac97_refcount) {
+		GCR = GCR_ACLINK_OFF;
+		CKEN &= ~CKEN2_AC97; 
+		free_irq(IRQ_AC97, NULL);
+	}
+	up(&pxa_ac97_mutex);
+}
+
+EXPORT_SYMBOL(pxa_ac97_get);
+EXPORT_SYMBOL(pxa_ac97_put);
+
+
+/*
+ * Audio Mixer stuff
+ */
+
+static audio_state_t ac97_audio_state;
+static audio_stream_t ac97_audio_in;
+
+static int mixer_ioctl( struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int ret, val;
+
+	ret = pxa_ac97_codec.mixer_ioctl(&pxa_ac97_codec, cmd, arg);
+	if (ret)
+		return ret;
+
+	/* We must snoop for some commands to provide our own extra processing */
+	switch (cmd) {
+	case SOUND_MIXER_WRITE_RECSRC:
+		/*
+		 * According to the PXA250 spec, mic-in should use different
+		 * DRCMR and different AC97 FIFO.
+		 * Unfortunately current UCB1400 versions (up to ver 2A) don't
+		 * produce slot 6 for the audio input frame, therefore the PXA
+		 * AC97 mic-in FIFO is always starved.
+		 */
+#if 0
+		ret = get_user(val, (int *)arg);
+		if (ret)
+			return ret;
+		pxa_audio_clear_buf(&ac97_audio_in);
+		*ac97_audio_in.drcmr = 0;
+		if (val & (1 << SOUND_MIXER_MIC)) {
+			ac97_audio_in.dcmd = DCMD_RXMCDR;
+			ac97_audio_in.drcmr = &DRCMRRXMCDR;
+			ac97_audio_in.dev_addr = __PREG(MCDR);
+		} else {
+			ac97_audio_in.dcmd = DCMD_RXPCDR;
+			ac97_audio_in.drcmr = &DRCMRRXPCDR;
+			ac97_audio_in.dev_addr = __PREG(PCDR);
+		}
+		if (ac97_audio_state.rd_ref)
+			*ac97_audio_in.drcmr =
+				ac97_audio_in.dma_ch | DRCMR_MAPVLD;
+#endif
+		break;
+	}
+	return 0;
+}
+
+static struct file_operations mixer_fops = {
+	ioctl:		mixer_ioctl,
+	llseek:		no_llseek,
+	owner:		THIS_MODULE
+};
+
+/*
+ * AC97 codec ioctls
+ */
+
+static int codec_adc_rate = 48000;
+static int codec_dac_rate = 48000;
+
+static int ac97_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	long val;
+
+	switch(cmd) {
+	case SNDCTL_DSP_STEREO:
+		ret = get_user(val, (int *) arg);
+		if (ret)
+			return ret;
+		/* FIXME: do we support mono? */
+		ret = (val == 0) ? -EINVAL : 1;
+		return put_user(ret, (int *) arg);
+
+	case SNDCTL_DSP_CHANNELS:
+	case SOUND_PCM_READ_CHANNELS:
+		/* FIXME: do we support mono? */
+		return put_user(2, (long *) arg);
+
+	case SNDCTL_DSP_SPEED:
+		ret = get_user(val, (long *) arg);
+		if (ret)
+			return ret;
+		if (file->f_mode & FMODE_READ)
+			codec_adc_rate = ac97_set_adc_rate(&pxa_ac97_codec, val);
+		if (file->f_mode & FMODE_WRITE)
+			codec_dac_rate = ac97_set_dac_rate(&pxa_ac97_codec, val);
+		/* fall through */
+
+	case SOUND_PCM_READ_RATE:
+		if (file->f_mode & FMODE_READ)
+			val = codec_adc_rate;
+		if (file->f_mode & FMODE_WRITE)
+			val = codec_dac_rate;
+		return put_user(val, (long *) arg);
+
+	case SNDCTL_DSP_SETFMT:
+	case SNDCTL_DSP_GETFMTS:
+		/* FIXME: can we do other fmts? */
+		return put_user(AFMT_S16_LE, (long *) arg);
+
+	default:
+		/* Maybe this is meant for the mixer (As per OSS Docs) */
+		return mixer_ioctl(inode, file, cmd, arg);
+	}
+	return 0;
+}
+
+
+/*
+ * Audio stuff
+ */
+
+static audio_stream_t ac97_audio_out = {
+	name:			"AC97 audio out",
+	dcmd:			DCMD_TXPCDR,
+	drcmr:			&DRCMRTXPCDR,
+	dev_addr:		__PREG(PCDR),
+};
+
+static audio_stream_t ac97_audio_in = {
+	name:			"AC97 audio in",
+	dcmd:			DCMD_RXPCDR,
+	drcmr:			&DRCMRRXPCDR,
+	dev_addr:		__PREG(PCDR),
+};
+
+static audio_state_t ac97_audio_state = {
+	output_stream:		&ac97_audio_out,
+	input_stream:		&ac97_audio_in,
+	client_ioctl:		ac97_ioctl,
+	sem:			__MUTEX_INITIALIZER(ac97_audio_state.sem),
+};
+
+static int ac97_audio_open(struct inode *inode, struct file *file)
+{
+	return pxa_audio_attach(inode, file, &ac97_audio_state);
+}
+
+/*
+ * Missing fields of this structure will be patched with the call
+ * to pxa_audio_attach().
+ */
+
+static struct file_operations ac97_audio_fops = {
+	open:		ac97_audio_open,
+	owner:		THIS_MODULE
+};
+
+
+static int __init pxa_ac97_init(void)
+{
+	int ret;
+	struct ac97_codec *dummy;
+
+	ret = pxa_ac97_get(&dummy);
+	if (ret)
+		return ret;
+
+	ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1);
+	pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1);
+
+	return 0;
+}
+
+static void __exit pxa_ac97_exit(void)
+{
+	unregister_sound_dsp(ac97_audio_state.dev_dsp);
+	unregister_sound_mixer(pxa_ac97_codec.dev_mixer);
+	pxa_ac97_put();
+}
+
+
+module_init(pxa_ac97_init);
+module_exit(pxa_ac97_exit);
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/sound/pxa-audio.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,853 @@
+/*
+ *  linux/drivers/sound/pxa-audio.c -- audio interface for the Cotula chip
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Aug 15, 2001
+ *  Copyright:	MontaVista Software 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/dma.h>
+
+#include "pxa-audio.h"
+
+
+#define AUDIO_NBFRAGS_DEFAULT	8
+#define AUDIO_FRAGSIZE_DEFAULT	8192
+
+#define MAX_DMA_SIZE		4096
+#define DMA_DESC_SIZE		sizeof(pxa_dma_desc)
+
+
+/*
+ * This function frees all buffers
+ */
+#define audio_clear_buf pxa_audio_clear_buf
+
+void pxa_audio_clear_buf(audio_stream_t * s)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int frag;
+
+	if (!s->buffers)
+		return;
+
+	/* Ensure DMA isn't running */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	add_wait_queue(&s->stop_wq, &wait);
+	DCSR(s->dma_ch) = DCSR_STOPIRQEN;
+	schedule();
+	remove_wait_queue(&s->stop_wq, &wait);
+
+	/* free DMA buffers */
+	for (frag = 0; frag < s->nbfrags; frag++) {
+		audio_buf_t *b = &s->buffers[frag];
+		if (!b->master)
+			continue;
+		consistent_free(b->data, b->master, b->dma_desc->dsadr);
+	}
+
+	/* free descriptor ring */
+	if (s->buffers->dma_desc)
+		consistent_free(s->buffers->dma_desc, 
+				s->nbfrags * s->descs_per_frag * DMA_DESC_SIZE,
+				s->dma_desc_phys);
+
+	/* free buffer structure array */
+	kfree(s->buffers);
+	s->buffers = NULL;
+}
+
+/*
+ * This function allocates the DMA descriptor array and buffer data space
+ * according to the current number of fragments and fragment size.
+ */
+static int audio_setup_buf(audio_stream_t * s)
+{
+	pxa_dma_desc *dma_desc;
+	dma_addr_t dma_desc_phys;
+	int nb_desc, frag, i, buf_size = 0;
+	char *dma_buf = NULL;
+	dma_addr_t dma_buf_phys = 0;
+
+	if (s->buffers)
+		return -EBUSY;
+
+	/* Our buffer structure array */
+	s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
+	if (!s->buffers)
+		goto err;
+	memzero(s->buffers, sizeof(audio_buf_t) * s->nbfrags);
+
+	/* 
+	 * Our DMA descriptor array:
+	 * for Each fragment we have one checkpoint descriptor plus one 
+	 * descriptor per MAX_DMA_SIZE byte data blocks.
+	 */
+	nb_desc = (1 + (s->fragsize + MAX_DMA_SIZE - 1)/MAX_DMA_SIZE) * s->nbfrags;
+	dma_desc = consistent_alloc(GFP_KERNEL,
+				    nb_desc * DMA_DESC_SIZE,
+				    &dma_desc_phys,
+				    0);
+	if (!dma_desc)
+		goto err;
+	s->descs_per_frag = nb_desc / s->nbfrags;
+	s->buffers->dma_desc = dma_desc;
+	s->dma_desc_phys = dma_desc_phys;
+	for (i = 0; i < nb_desc - 1; i++)
+		dma_desc[i].ddadr = dma_desc_phys + (i + 1) * DMA_DESC_SIZE;
+	dma_desc[i].ddadr = dma_desc_phys;
+
+	/* Our actual DMA buffers */
+	for (frag = 0; frag < s->nbfrags; frag++) {
+		audio_buf_t *b = &s->buffers[frag];
+
+		/*
+		 * Let's allocate non-cached memory for DMA buffers.
+		 * We try to allocate all memory at once.
+		 * If this fails (a common reason is memory fragmentation),
+		 * then we'll try allocating smaller buffers.
+		 */
+		if (!buf_size) {
+			buf_size = (s->nbfrags - frag) * s->fragsize;
+			do {
+				dma_buf = consistent_alloc(GFP_KERNEL,
+							   buf_size, 
+							   &dma_buf_phys,
+							   0);
+				if (!dma_buf)
+					buf_size -= s->fragsize;
+			} while (!dma_buf && buf_size);
+			if (!dma_buf)
+				goto err;
+			b->master = buf_size;
+			memzero(dma_buf, buf_size);
+		}
+
+		/* 
+		 * Set up our checkpoint descriptor.  Since the count 
+		 * is always zero, we'll abuse the dsadr and dtadr fields
+		 * just in case this one is picked up by the hardware
+		 * while processing SOUND_DSP_GETPTR.
+		 */
+		dma_desc->dsadr = dma_buf_phys;
+		dma_desc->dtadr = dma_buf_phys;
+		dma_desc->dcmd = DCMD_ENDIRQEN;
+		if (s->output && !s->mapped)
+			dma_desc->ddadr |= DDADR_STOP;
+		b->dma_desc = dma_desc++;
+
+		/* set up the actual data descriptors */
+		for (i = 0; (i * MAX_DMA_SIZE) < s->fragsize; i++) {
+			dma_desc[i].dsadr = (s->output) ?
+				(dma_buf_phys + i*MAX_DMA_SIZE) : s->dev_addr;
+			dma_desc[i].dtadr = (s->output) ?
+				s->dev_addr : (dma_buf_phys + i*MAX_DMA_SIZE);
+			dma_desc[i].dcmd = s->dcmd |
+				((s->fragsize < MAX_DMA_SIZE) ?
+					s->fragsize : MAX_DMA_SIZE);
+		}
+		dma_desc += i;
+
+		/* handle buffer pointers */
+		b->data = dma_buf;
+		dma_buf += s->fragsize;
+		dma_buf_phys += s->fragsize;
+		buf_size -= s->fragsize;
+	}
+
+	s->usr_frag = s->dma_frag = 0;
+	s->bytecount = 0;
+	s->fragcount = 0;
+	sema_init(&s->sem, (s->output) ? s->nbfrags : 0);
+	return 0;
+
+err:
+	printk("pxa-audio: unable to allocate audio memory\n ");
+	audio_clear_buf(s);
+	return -ENOMEM;
+}
+
+/*
+ * Our DMA interrupt handler
+ */
+static void audio_dma_irq(int ch, void *dev_id, struct pt_regs *regs)
+{
+	audio_stream_t *s = dev_id;
+	u_int dcsr;
+
+	dcsr = DCSR(ch);
+	DCSR(ch) = dcsr & ~DCSR_STOPIRQEN;
+
+	if (!s->buffers) {
+		printk("AC97 DMA: wow... received IRQ for channel %d but no buffer exists\n", ch);
+		return;
+	}
+
+	if (dcsr & DCSR_BUSERR)
+		printk("AC97 DMA: bus error interrupt on channel %d\n", ch);
+
+	if (dcsr & DCSR_ENDINTR) {
+		u_long cur_dma_desc;
+		u_int cur_dma_frag;
+
+		/* 
+		 * Find out which DMA desc is current.  Note that DDADR
+		 * points to the next desc, not the current one.
+		 */
+		cur_dma_desc = DDADR(ch) - s->dma_desc_phys - DMA_DESC_SIZE;
+
+		/*
+		 * Let the compiler nicely optimize constant divisors into
+		 * multiplications for the common cases which is much faster.
+		 * Common cases: x = 1 + (1 << y) for y = [0..3]
+		 */
+		switch (s->descs_per_frag) {
+		case 2:  cur_dma_frag = cur_dma_desc / (2*DMA_DESC_SIZE); break;
+		case 3:  cur_dma_frag = cur_dma_desc / (3*DMA_DESC_SIZE); break;
+		case 5:  cur_dma_frag = cur_dma_desc / (5*DMA_DESC_SIZE); break;
+		case 9:  cur_dma_frag = cur_dma_desc / (9*DMA_DESC_SIZE); break;
+		default: cur_dma_frag =
+			    cur_dma_desc / (s->descs_per_frag * DMA_DESC_SIZE);
+		}
+
+		/* Account for possible wrap back of cur_dma_desc above */
+		if (cur_dma_frag >= s->nbfrags)
+			cur_dma_frag = s->nbfrags - 1;
+
+		while (s->dma_frag != cur_dma_frag) {
+			if (!s->mapped) {
+				/* 
+				 * This fragment is done - set the checkpoint
+				 * descriptor to STOP until it is gets
+				 * processed by the read or write function.
+				 */
+				s->buffers[s->dma_frag].dma_desc->ddadr |= DDADR_STOP;
+				up(&s->sem);
+			}
+			if (++s->dma_frag >= s->nbfrags)
+				s->dma_frag = 0;
+
+			/* Accounting */
+			s->bytecount += s->fragsize;
+			s->fragcount++;
+		}
+
+		/* ... and for polling processes */
+		wake_up(&s->frag_wq);
+	}
+
+	if ((dcsr & DCSR_STOPIRQEN) && (dcsr & DCSR_STOPSTATE))
+		wake_up(&s->stop_wq);
+}
+
+/*
+ * Validate and sets up buffer fragments, etc.
+ */
+static int audio_set_fragments(audio_stream_t *s, int val)
+{
+	if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN)
+		return -EBUSY;
+	if (s->buffers)
+		audio_clear_buf(s);
+	s->nbfrags = (val >> 16) & 0x7FFF;
+	val &= 0xffff;
+	if (val < 5)
+		val = 5;
+	if (val > 15)
+		val = 15;
+	s->fragsize = 1 << val;
+	if (s->nbfrags < 2)
+		s->nbfrags = 2;
+	if (s->nbfrags * s->fragsize > 256 * 1024)
+		s->nbfrags = 256 * 1024 / s->fragsize;
+	if (audio_setup_buf(s))
+		return -ENOMEM;
+	return val|(s->nbfrags << 16);
+}
+
+
+/*
+ * The fops functions
+ */
+
+static int audio_write(struct file *file, const char *buffer,
+		       size_t count, loff_t * ppos)
+{
+	const char *buffer0 = buffer;
+	audio_state_t *state = (audio_state_t *)file->private_data;
+	audio_stream_t *s = state->output_stream;
+	int chunksize, ret = 0;
+
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->mapped)
+		return -ENXIO;
+	if (!s->buffers && audio_setup_buf(s))
+		return -ENOMEM;
+
+	while (count > 0) {
+		audio_buf_t *b = &s->buffers[s->usr_frag];
+
+		/* Grab a fragment */
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			if (down_trylock(&s->sem))
+				break;
+		} else {
+			ret = -ERESTARTSYS;
+			if (down_interruptible(&s->sem))
+				break;
+		}
+
+		/* Feed the current buffer */
+		chunksize = s->fragsize - b->offset;
+		if (chunksize > count)
+			chunksize = count;
+		if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
+			up(&s->sem);
+			return -EFAULT;
+		}
+		b->offset += chunksize;
+		buffer += chunksize;
+		count -= chunksize;
+		if (b->offset < s->fragsize) {
+			up(&s->sem);
+			break;
+		}
+
+		/* 
+		 * Activate DMA on current buffer.
+		 * We unlock this fragment's checkpoint descriptor and
+		 * kick DMA if it is idle.  Using checkpoint descriptors
+		 * allows for control operations without the need for 
+		 * stopping the DMA channel if it is already running.
+		 */
+		b->offset = 0;
+		b->dma_desc->ddadr &= ~DDADR_STOP;
+		if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
+			DDADR(s->dma_ch) = b->dma_desc->ddadr;
+			DCSR(s->dma_ch) = DCSR_RUN;
+		}
+
+		/* move the index to the next fragment */
+		if (++s->usr_frag >= s->nbfrags)
+			s->usr_frag = 0;
+	}
+
+	if ((buffer - buffer0))
+		ret = buffer - buffer0;
+	return ret;
+}
+
+
+static int audio_read(struct file *file, char *buffer,
+		      size_t count, loff_t * ppos)
+{
+	char *buffer0 = buffer;
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s = state->input_stream;
+	int chunksize, ret = 0;
+
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->mapped)
+		return -ENXIO;
+	if (!s->buffers && audio_setup_buf(s))
+		return -ENOMEM;
+
+	while (count > 0) {
+		audio_buf_t *b = &s->buffers[s->usr_frag];
+
+		/* prime DMA */
+		if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
+			DDADR(s->dma_ch) = 
+				s->buffers[s->dma_frag].dma_desc->ddadr;
+			DCSR(s->dma_ch) = DCSR_RUN;
+		}
+
+		/* Wait for a buffer to become full */
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			if (down_trylock(&s->sem))
+				break;
+		} else {
+			ret = -ERESTARTSYS;
+			if (down_interruptible(&s->sem))
+				break;
+		}
+
+		/* Grab data from current buffer */
+		chunksize = s->fragsize - b->offset;
+		if (chunksize > count)
+			chunksize = count;
+		if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
+			up(&s->sem);
+			return -EFAULT;
+		}
+		b->offset += chunksize;
+		buffer += chunksize;
+		count -= chunksize;
+		if (b->offset < s->fragsize) {
+			up(&s->sem);
+			break;
+		}
+
+		/* 
+		 * Make this buffer available for DMA again.
+		 * We unlock this fragment's checkpoint descriptor and
+		 * kick DMA if it is idle.  Using checkpoint descriptors
+		 * allows for control operations without the need for 
+		 * stopping the DMA channel if it is already running.
+		 */
+		b->offset = 0;
+		b->dma_desc->ddadr &= ~DDADR_STOP;
+
+		/* move the index to the next fragment */
+		if (++s->usr_frag >= s->nbfrags)
+			s->usr_frag = 0;
+	}
+
+	if ((buffer - buffer0))
+		ret = buffer - buffer0;
+	return ret;
+}
+
+
+static int audio_sync(struct file *file)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s = state->output_stream;
+	audio_buf_t *b;
+	pxa_dma_desc *final_desc;
+	u_long dcmd_save = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
+		return 0;
+
+	/*
+	 * Send current buffer if it contains data.  Be sure to send
+	 * a full sample count.
+	 */
+	final_desc = NULL;
+	b = &s->buffers[s->usr_frag];
+	if (b->offset &= ~3) {
+		final_desc = &b->dma_desc[1 + b->offset/MAX_DMA_SIZE];
+		b->offset &= (MAX_DMA_SIZE-1);
+		dcmd_save = final_desc->dcmd;
+		final_desc->dcmd = b->offset | s->dcmd | DCMD_ENDIRQEN; 
+		final_desc->ddadr |= DDADR_STOP;
+		b->offset = 0;
+		b->dma_desc->ddadr &= ~DDADR_STOP;
+		if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
+			DDADR(s->dma_ch) = b->dma_desc->ddadr;
+			DCSR(s->dma_ch) = DCSR_RUN;
+		}
+	}
+
+	/* Wait for DMA to complete. */
+	set_current_state(TASK_INTERRUPTIBLE);
+#if 0
+	/* 
+	 * The STOPSTATE IRQ never seem to occur if DCSR_STOPIRQEN is set
+	 * along wotj DCSR_RUN.  Silicon bug?
+	 */
+	add_wait_queue(&s->stop_wq, &wait);
+	DCSR(s->dma_ch) |= DCSR_STOPIRQEN;
+	schedule();
+#else 
+	add_wait_queue(&s->frag_wq, &wait);
+	while ((DCSR(s->dma_ch) & DCSR_RUN) && !signal_pending(current)) {
+		schedule();
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+#endif
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&s->frag_wq, &wait);
+
+	/* Restore the descriptor chain. */
+	if (final_desc) {
+		final_desc->dcmd = dcmd_save;
+		final_desc->ddadr &= ~DDADR_STOP;
+		b->dma_desc->ddadr |= DDADR_STOP;
+	}
+	return 0;
+}
+
+
+static unsigned int audio_poll(struct file *file,
+			       struct poll_table_struct *wait)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *is = state->input_stream;
+	audio_stream_t *os = state->output_stream;
+	unsigned int mask = 0;
+
+	if (file->f_mode & FMODE_READ) {
+		/* Start audio input if not already active */
+		if (!is->buffers && audio_setup_buf(is))
+			return -ENOMEM;
+		if (DCSR(is->dma_ch) & DCSR_STOPSTATE) {
+			DDADR(is->dma_ch) = 
+				is->buffers[is->dma_frag].dma_desc->ddadr;
+			DCSR(is->dma_ch) = DCSR_RUN;
+		}
+		poll_wait(file, &is->frag_wq, wait);
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (!os->buffers && audio_setup_buf(os))
+			return -ENOMEM;
+		poll_wait(file, &os->frag_wq, wait);
+	}
+
+	if (file->f_mode & FMODE_READ)
+		if (( is->mapped && is->bytecount > 0) ||
+		    (!is->mapped && atomic_read(&is->sem.count) > 0))
+			mask |= POLLIN | POLLRDNORM;
+
+	if (file->f_mode & FMODE_WRITE)
+		if (( os->mapped && os->bytecount > 0) ||
+		    (!os->mapped && atomic_read(&os->sem.count) > 0))
+			mask |= POLLOUT | POLLWRNORM;
+
+	return mask;
+}
+
+
+static int audio_ioctl( struct inode *inode, struct file *file,
+			uint cmd, ulong arg)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *os = state->output_stream;
+	audio_stream_t *is = state->input_stream;
+	long val;
+
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE)
+			return put_user(os->fragsize, (int *)arg);
+		else
+			return put_user(is->fragsize, (int *)arg);
+
+	case SNDCTL_DSP_GETCAPS:
+		val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
+		if (is && os)
+			val |= DSP_CAP_DUPLEX;
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (get_user(val, (long *) arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			int ret = audio_set_fragments(is, val);
+			if (ret < 0)
+				return ret;
+			ret = put_user(ret, (int *)arg);
+			if (ret)
+				return ret;
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			int ret = audio_set_fragments(os, val);
+			if (ret < 0)
+				return ret;
+			ret = put_user(ret, (int *)arg);
+			if (ret)
+				return ret;
+		}
+		return 0;
+
+	case SNDCTL_DSP_SYNC:
+		return audio_sync(file);
+
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_POST:
+		return 0;
+
+	case SNDCTL_DSP_GETTRIGGER:
+		val = 0;
+		if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN)
+			val |= PCM_ENABLE_INPUT;
+		if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN)
+			val |= PCM_ENABLE_OUTPUT;
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_SETTRIGGER:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			if (val & PCM_ENABLE_INPUT) {
+				if (!is->buffers && audio_setup_buf(is))
+					return -ENOMEM;
+				if (!(DCSR(is->dma_ch) & DCSR_RUN)) {
+					audio_buf_t *b = &is->buffers[is->dma_frag];
+					DDADR(is->dma_ch) = b->dma_desc->ddadr;
+					DCSR(is->dma_ch) = DCSR_RUN;
+				}
+			} else {
+				DCSR(is->dma_ch) = 0;
+			}
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			if (val & PCM_ENABLE_OUTPUT) {
+				if (!os->buffers && audio_setup_buf(os))
+					return -ENOMEM;
+				if (!(DCSR(os->dma_ch) & DCSR_RUN)) {
+					audio_buf_t *b = &os->buffers[os->dma_frag];
+					DDADR(os->dma_ch) = b->dma_desc->ddadr;
+					DCSR(os->dma_ch) = DCSR_RUN;
+				}
+			} else {
+				DCSR(os->dma_ch) = 0;
+			}
+		}
+		return 0;
+
+	case SNDCTL_DSP_GETOSPACE:
+	case SNDCTL_DSP_GETISPACE:
+	    {
+		audio_buf_info inf = { 0, };
+		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;
+
+		if ((s == is && !(file->f_mode & FMODE_READ)) ||
+		    (s == os && !(file->f_mode & FMODE_WRITE)))
+			return -EINVAL;
+		if (!s->buffers && audio_setup_buf(s))
+			return -ENOMEM;
+		inf.bytes = atomic_read(&s->sem.count) * s->fragsize;
+		inf.bytes -= s->buffers[s->usr_frag].offset;
+		inf.fragments = inf.bytes / s->fragsize;
+		inf.fragsize = s->fragsize;
+		inf.fragstotal = s->nbfrags;
+		return copy_to_user((void *)arg, &inf, sizeof(inf));
+	    }
+
+	case SNDCTL_DSP_GETOPTR:
+	case SNDCTL_DSP_GETIPTR:
+	    {
+		count_info inf = { 0, };
+		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
+		dma_addr_t ptr;
+		int bytecount, offset, flags;
+
+		if ((s == is && !(file->f_mode & FMODE_READ)) ||
+		    (s == os && !(file->f_mode & FMODE_WRITE)))
+			return -EINVAL;
+		if (DCSR(s->dma_ch) & DCSR_RUN) {
+			audio_buf_t *b;
+			save_flags_cli(flags);
+			ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch);
+			b = &s->buffers[s->dma_frag];
+			offset = ptr - b->dma_desc->dsadr;
+			if (offset >= s->fragsize)
+				offset = s->fragsize - 4;
+		} else {
+			save_flags(flags);
+			offset = 0;
+		}
+		inf.ptr = s->dma_frag * s->fragsize + offset;
+		bytecount = s->bytecount + offset;
+		s->bytecount = -offset;
+		inf.blocks = s->fragcount;
+		s->fragcount = 0;
+		restore_flags(flags);
+		if (bytecount < 0)
+			bytecount = 0;
+		inf.bytes = bytecount;
+		return copy_to_user((void *)arg, &inf, sizeof(inf));
+	    }
+
+	case SNDCTL_DSP_NONBLOCK:
+		file->f_flags |= O_NONBLOCK;
+		return 0;
+
+	case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_WRITE) 
+			audio_clear_buf(os);
+		if (file->f_mode & FMODE_READ)
+			audio_clear_buf(is);
+		return 0;
+
+	default:
+		return state->client_ioctl(inode, file, cmd, arg);
+	}
+
+	return 0;
+}
+
+
+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s;
+	unsigned long size, vma_addr;
+	int i, ret;
+
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+
+	if (vma->vm_flags & VM_WRITE) {
+		if (!state->wr_ref)
+			return -EINVAL;;
+		s = state->output_stream;
+	} else if (vma->vm_flags & VM_READ) {
+		if (!state->rd_ref)
+			return -EINVAL;
+		s = state->input_stream;
+	} else return -EINVAL;
+
+	if (s->mapped)
+		return -EINVAL;
+	size = vma->vm_end - vma->vm_start;
+	if (size != s->fragsize * s->nbfrags)
+		return -EINVAL;
+	if (!s->buffers && audio_setup_buf(s))
+		return -ENOMEM;
+	vma_addr = vma->vm_start;
+	for (i = 0; i < s->nbfrags; i++) {
+		audio_buf_t *buf = &s->buffers[i];
+		if (!buf->master)
+			continue;
+		ret = remap_page_range(vma_addr, buf->dma_desc->dsadr,
+				       buf->master, vma->vm_page_prot);
+		if (ret)
+			return ret;
+		vma_addr += buf->master;
+	}
+	for (i = 0; i < s->nbfrags; i++)
+		s->buffers[i].dma_desc->ddadr &= ~DDADR_STOP;
+	s->mapped = 1;
+	return 0;
+}
+
+
+static int audio_release(struct inode *inode, struct file *file)
+{
+	audio_state_t *state = file->private_data;
+
+	down(&state->sem);
+
+	if (file->f_mode & FMODE_READ) {
+		audio_clear_buf(state->input_stream);
+		*state->input_stream->drcmr = 0;
+		pxa_free_dma(state->input_stream->dma_ch);
+		state->rd_ref = 0;
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		audio_sync(file);
+		audio_clear_buf(state->output_stream);
+		*state->output_stream->drcmr = 0;
+		pxa_free_dma(state->output_stream->dma_ch);
+		state->wr_ref = 0;
+	}
+
+	up(&state->sem);
+	return 0;
+}
+
+
+int pxa_audio_attach(struct inode *inode, struct file *file,
+			 audio_state_t *state)
+{
+	audio_stream_t *is = state->input_stream;
+	audio_stream_t *os = state->output_stream;
+	int err;
+
+	down(&state->sem);
+
+	/* access control */
+	err = -ENODEV;
+	if ((file->f_mode & FMODE_WRITE) && !os)
+		goto out;
+	if ((file->f_mode & FMODE_READ) && !is)
+		goto out;
+	err = -EBUSY;
+	if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
+		goto out;
+	if ((file->f_mode & FMODE_READ) && state->rd_ref)
+		goto out;
+
+	/* request DMA channels */
+	if (file->f_mode & FMODE_WRITE) {
+		err = pxa_request_dma(os->name, DMA_PRIO_LOW, 
+					  audio_dma_irq, os);
+		if (err < 0)
+			goto out;
+		os->dma_ch = err;
+	}
+	if (file->f_mode & FMODE_READ) {
+		err = pxa_request_dma(is->name, DMA_PRIO_LOW,
+					  audio_dma_irq, is);
+		if (err < 0) {
+			if (file->f_mode & FMODE_WRITE) {
+				*os->drcmr = 0;
+				pxa_free_dma(os->dma_ch);
+			}
+			goto out;
+		}
+		is->dma_ch = err;
+	}
+
+	file->private_data	= state;
+	file->f_op->release	= audio_release;
+	file->f_op->write	= audio_write;
+	file->f_op->read	= audio_read;
+	file->f_op->mmap	= audio_mmap;
+	file->f_op->poll	= audio_poll;
+	file->f_op->ioctl	= audio_ioctl;
+	file->f_op->llseek	= no_llseek;
+
+	if ((file->f_mode & FMODE_WRITE)) {
+		state->wr_ref = 1;
+		os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
+		os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
+		os->output = 1;
+		os->mapped = 0;
+		init_waitqueue_head(&os->frag_wq);
+		init_waitqueue_head(&os->stop_wq);
+		*os->drcmr = os->dma_ch | DRCMR_MAPVLD;
+	}
+	if (file->f_mode & FMODE_READ) {
+		state->rd_ref = 1;
+		is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
+		is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
+		is->output = 0;
+		is->mapped = 0;
+		init_waitqueue_head(&is->frag_wq);
+		init_waitqueue_head(&is->stop_wq);
+		*is->drcmr = is->dma_ch | DRCMR_MAPVLD;
+	}
+
+	err = 0;
+
+out:
+	up(&state->sem);
+	return err;
+}
+
+EXPORT_SYMBOL(pxa_audio_attach);
+EXPORT_SYMBOL(pxa_audio_clear_buf);
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/sound/pxa-audio.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,55 @@
+/*
+ *  linux/drivers/sound/pxa-audio.h -- audio interface for the Cotula chip
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Aug 15, 2001
+ *  Copyright:	MontaVista Software 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.
+ */
+
+typedef struct {
+	int offset;			/* current buffer position */
+	char *data; 	           	/* actual buffer */
+	pxa_dma_desc *dma_desc;	/* pointer to the starting desc */
+	int master;             	/* owner for buffer allocation, contain size whn true */
+} audio_buf_t;
+
+typedef struct {
+	char *name;			/* stream identifier */
+	audio_buf_t *buffers;   	/* pointer to audio buffer array */
+	u_int usr_frag;			/* user fragment index */
+	u_int dma_frag;			/* DMA fragment index */
+	u_int fragsize;			/* fragment size */
+	u_int nbfrags;			/* number of fragments */
+	u_int dma_ch;			/* DMA channel number */
+	dma_addr_t dma_desc_phys;	/* phys addr of descriptor ring */
+	u_int descs_per_frag;		/* nbr descriptors per fragment */
+	int bytecount;			/* nbr of processed bytes */
+	int fragcount;			/* nbr of fragment transitions */
+	struct semaphore sem;		/* account for fragment usage */
+	wait_queue_head_t frag_wq;	/* for poll(), etc. */
+	wait_queue_head_t stop_wq;	/* for users of DCSR_STOPIRQEN */
+	u_long dcmd;			/* DMA descriptor dcmd field */
+	volatile u32 *drcmr;		/* the DMA request channel to use */
+	u_long dev_addr;		/* device physical address for DMA */
+	int mapped:1;			/* mmap()'ed buffers */
+	int output:1;			/* 0 for input, 1 for output */
+} audio_stream_t;
+	
+typedef struct {
+	audio_stream_t *output_stream;
+	audio_stream_t *input_stream;
+	int dev_dsp;			/* audio device handle */
+	int rd_ref:1;           /* open reference for recording */
+	int wr_ref:1;           /* open reference for playback */
+	int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
+	struct semaphore sem;		/* prevent races in attach/release */
+} audio_state_t;
+
+extern int pxa_audio_attach(struct inode *inode, struct file *file,
+				audio_state_t *state);
+extern void pxa_audio_clear_buf(audio_stream_t *s);
+
--- linux-2.4.25/drivers/sound/sa1100-audio.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/sound/sa1100-audio.c	2004-03-31 17:15:12.000000000 +0200
@@ -148,7 +148,8 @@
 			do {
 			  	dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
 							  dmasize,
-							  &dmaphys);
+							  &dmaphys,
+							  0);
 				if (!dmabuf)
 					dmasize -= s->fragsize;
 			} while (!dmabuf && dmasize);
--- linux-2.4.25/drivers/video/Config.in~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/video/Config.in	2004-03-31 17:15:12.000000000 +0200
@@ -50,6 +50,15 @@
      if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
        bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
      fi
+     tristate '  PXA LCD support' CONFIG_FB_PXA $CONFIG_ARCH_PXA
+     if [ "$CONFIG_FB_PXA" != "n" ]; then
+        choice 'LCD Bit Depth' \
+               "8-Bpp          CONFIG_FB_PXA_8BPP \
+                16-Bpp         CONFIG_FB_PXA_16BPP" Bit-Depth
+     fi
+     if [ "$CONFIG_FB_PXA" != "n" -a "$CONFIG_ARCH_LUBBOCK" = "y" ]; then
+	bool '  Lubbock QVGA LCD support instead of DSTN' CONFIG_FB_PXA_QVGA
+     fi
    fi
    dep_tristate '  CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
    if [ "$CONFIG_APOLLO" = "y" ]; then
@@ -295,7 +304,7 @@
       if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
 	   "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
 	   "$CONFIG_FB_TX3912" = "y"  -o "$CONFIG_FB_CLPS711X" = "y" -o \
-           "$CONFIG_FB_DBMX1" = "y" ]; then
+           "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then
 	 define_tristate CONFIG_FBCON_CFB2 y
 	 define_tristate CONFIG_FBCON_CFB4 y
       else
@@ -329,7 +338,7 @@
 	   "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
 	   "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
 	   "$CONFIG_FB_INTEL" = "y" -o \
-           "$CONFIG_FB_DBMX1" = "y" ]; then
+           "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then
 	 define_tristate CONFIG_FBCON_CFB8 y
       else
 	 if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -372,7 +381,7 @@
 	   "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
 	   "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
 	   "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
-	   "$CONFIG_FB_ANAKIN" = "y" -o \
+	   "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_PXA" = "y" -o \
            "$CONFIG_FB_DBMX1" = "y" ]; then
 	 define_tristate CONFIG_FBCON_CFB16 y
       else
--- linux-2.4.25/drivers/video/Makefile~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/video/Makefile	2004-03-31 17:15:12.000000000 +0200
@@ -14,7 +14,7 @@
 		  fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
 		  fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
 		  fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
-		  fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \
+		  fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o pxafb.o \
 		  cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o
 
 # Each configuration option enables a list of files.
@@ -129,6 +129,10 @@
 obj-$(CONFIG_FB_BWTWO)            += bwtwofb.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
+obj-$(CONFIG_FB_PXA)              += pxafb.o
+ifeq ($(CONFIG_PXA_CERF_PDA),y)
+   obj-$(CONFIG_FB_PXA)           += lcdctrl.o lcdctrl_cerf.o
+endif
 obj-$(CONFIG_FB_DBMX1)            += dbmx1fb.o
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o fbgen.o
--- linux-2.4.25/drivers/video/fbmem.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/video/fbmem.c	2004-03-31 17:15:12.000000000 +0200
@@ -109,6 +109,7 @@
 extern int chips_init(void);
 extern int g364fb_init(void);
 extern int sa1100fb_init(void);
+extern int pxafb_init(void);
 extern int fm2fb_init(void);
 extern int fm2fb_setup(char*);
 extern int q40fb_init(void);
@@ -305,6 +306,9 @@
 #ifdef CONFIG_FB_SA1100
 	{ "sa1100", sa1100fb_init, NULL },
 #endif
+#ifdef CONFIG_FB_PXA
+	{ "pxa", pxafb_init, NULL },
+#endif
 #ifdef CONFIG_FB_SUN3
 	{ "sun3", sun3fb_init, sun3fb_setup },
 #endif
@@ -675,13 +679,13 @@
 #elif defined(__i386__) || defined(__x86_64__)
 	if (boot_cpu_data.x86 > 3)
 		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#elif defined(__arm__) || defined(__mips__)
+#elif defined(__mips__)
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 #elif defined(__sh__)
 	pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
 #elif defined(__hppa__)
 	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-#elif defined(__ia64__)
+#elif defined(__ia64__) || defined(__arm__)
 	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 #elif defined(__hppa__)
 	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/video/lcdctrl.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,223 @@
+/*
+ *  lcdctrl.c
+ *
+ *  Generic LCD control for brightness, contrast, etc.
+ *  Device specific drivers implement a lcdctrl_device and
+ *  provides access to it via lcdctrl_device_get_ops().
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Mar 2002: Initial version [FB]
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include <video/lcdctrl.h>
+
+/*
+ * Set this to zero to remove all the debug statements via
+ * dead code elimination.
+ */
+#define DEBUGGING       0
+
+#if DEBUGGING
+static unsigned int lcd_debug = DEBUGGING;
+#else
+#define lcd_debug 	0
+#endif
+
+/* -- prototypes -- */
+
+static int lcdctrl_ioctl(struct inode * inode, struct file *filp,
+			 unsigned int cmd , unsigned long arg);
+static int lcdctrl_open(struct inode *inode, struct file *filp);
+static int lcdctrl_close(struct inode *inode, struct file *filp);
+
+/* -- variables -- */
+
+struct lcdctrl_device *lcd_device;
+
+static int intensity;
+static int brightness;
+static int contrast;
+
+static int enabled;
+static int sync_needed;
+static int chrdev_major;
+
+static struct file_operations lcdctrl_fops = {
+	ioctl:		lcdctrl_ioctl,
+	open:		lcdctrl_open,
+	release:	lcdctrl_close
+};
+
+/* -- ioctl -- */
+
+static int lcdctrl_ioctl(struct inode * inode, struct file *filp,
+                         unsigned int cmd , unsigned long arg)
+{
+	int ret;
+	ret = -EINVAL;
+
+	if( lcd_debug)
+	    printk(KERN_INFO "lcdctrl_ioctl: cmd=%d, arg=%ld\n", cmd, arg);
+
+	switch(cmd)
+	{
+		case _LCDCTRL_IOCTL_ON:
+			ret = lcdctrl_enable();
+			break;
+		case _LCDCTRL_IOCTL_OFF:
+			ret = lcdctrl_disable();  
+			break;
+		case _LCDCTRL_IOCTL_INTENSITY:
+			if ((arg >=0) && (arg <= 100))
+				ret = lcdctrl_set_intensity(arg);
+			break;
+		case _LCDCTRL_IOCTL_BRIGHTNESS:
+			if ((arg >=0) && (arg <= 100))
+				ret = lcdctrl_set_brightness(arg);
+			break;
+		case _LCDCTRL_IOCTL_CONTRAST:
+			if ((arg >=0) && (arg <= 100))
+				ret = lcdctrl_set_contrast(arg, LCD_NO_SYNC);
+			break;  
+		case _LCDCTRL_IOCTL_GET_BRIGHTNESS:
+			ret = brightness;
+			break;
+		case _LCDCTRL_IOCTL_GET_CONTRAST:
+			ret = contrast;
+			break;
+		case _LCDCTRL_IOCTL_GET_INTENSITY:
+			ret = intensity;
+			break;
+
+		default:
+			printk(KERN_ERR "lcdctrl_ioctl: invalid ioctl\n");
+			break;
+	}
+
+	return ret;
+}
+
+static int lcdctrl_open(struct inode *inode, struct file *filp)
+{
+//	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int lcdctrl_close(struct inode *inode, struct file *filp)
+{
+//	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/* -- -- */
+
+int lcdctrl_enable( void)
+{
+	int result;
+
+	if( enabled) return 0;
+
+	result = lcd_device->enable();
+
+	lcdctrl_set_intensity( intensity);
+	lcdctrl_set_brightness( brightness);
+	lcdctrl_set_contrast( contrast, sync_needed);
+        sync_needed = LCD_NO_SYNC;
+
+	enabled = 1;
+	return result;
+}
+
+int lcdctrl_disable( void)
+{
+	enabled = 0;
+	return lcd_device->disable();
+}
+
+int lcdctrl_set_intensity( int i)
+{
+	intensity = i;
+	return lcd_device->set_intensity( i);
+}
+
+int lcdctrl_set_brightness( int b)
+{
+	brightness = b;
+	return lcd_device->set_brightness( b);
+}
+
+int lcdctrl_set_contrast( int c, int sync)
+{
+	contrast = c;
+	return lcd_device->set_contrast( c, sync);
+}
+
+int lcdctrl_get_intensity( void)
+{
+	return intensity;
+}
+
+int lcdctrl_get_brightness( void)
+{
+	return brightness;
+}
+
+int lcdctrl_get_contrast( void)
+{
+	return contrast;
+}
+
+/* -- -- */
+
+/* the device specific driver should implement this */
+struct lcdctrl_device *lcdctrl_device_get_ops(void);
+
+int lcdctrl_init( void)
+{
+	int ret;
+
+	lcd_device = lcdctrl_device_get_ops();
+
+	if( !lcd_device)
+	{
+		printk(KERN_ERR "lcdctrl_init: No lcd_device registered.\n");
+		return -EINVAL;
+	}
+
+	ret = lcd_device->init( &intensity, &brightness, &contrast);
+
+        sync_needed = LCD_SYNC_NEEDED;
+
+	if( ret == 0)
+	{
+		chrdev_major = 
+			register_chrdev( 0,_LCD_CONTROL_NAME,&lcdctrl_fops);
+		if( lcd_debug)
+			printk(KERN_INFO "lcdctrl_init: OK\n");
+	}
+	return ret;
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/video/lcdctrl_cerf.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,175 @@
+/*
+ *  lcdctrl_cerf.c
+ *
+ *  Cerf LCD control for brightness and contrast.
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Mar 2002: Initial version [FB]
+ * 
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/arch/cerf_ucb1400gpio.h>
+
+#include <video/lcdctrl.h>
+
+/*
+ * Set this to zero to remove all the debug statements via
+ * dead code elimination.
+ */
+#define DEBUGGING       0
+
+#if DEBUGGING
+static unsigned int lcd_debug = DEBUGGING;
+#else
+#define lcd_debug       0
+#endif
+
+#define LCD_MAX_INTENSITY	 0
+#define LCD_MAX_BRIGHTNESS	15
+#define LCD_MAX_CONTRAST	100
+
+#define LCD_DEFAULT_INTENSITY	 0
+#define LCD_DEFAULT_BRIGHTNESS	14*100/(LCD_MAX_BRIGHTNESS)
+#define LCD_DEFAULT_CONTRAST	90*100/(LCD_MAX_CONTRAST)
+
+#define UP	1
+#define DOWN	0
+
+/* -- prototypes -- */
+
+static int cerf_lcdctrl_init( int *intensity, int *brightness, int *contrast);
+static int cerf_lcdctrl_enable(void);
+static int cerf_lcdctrl_disable(void);
+static int cerf_lcdctrl_set_intensity( int i);
+static int cerf_lcdctrl_set_brightness( int b);
+static int cerf_lcdctrl_set_contrast( int c, int sync);
+
+static void cerf_lcdctrl_contrast_step( int direction);
+
+/* -- variables -- */
+
+static int dev_contrast;
+
+/* -- -- */
+
+static struct lcdctrl_device cerf_dev = {
+	init: 		cerf_lcdctrl_init,
+	enable:		cerf_lcdctrl_enable,
+	disable:	cerf_lcdctrl_disable,
+	set_intensity:	cerf_lcdctrl_set_intensity,
+	set_brightness:	cerf_lcdctrl_set_brightness,
+	set_contrast:	cerf_lcdctrl_set_contrast
+}; 
+
+static int cerf_lcdctrl_enable( void)
+{
+	cerf_ucb1400gpio_lcd_enable();
+
+	return 0;
+}
+
+static int cerf_lcdctrl_disable( void)
+{
+	cerf_ucb1400gpio_lcd_disable();
+
+	return 0;
+}
+
+static int cerf_lcdctrl_set_intensity( int i)
+{
+	int dev_intensity = LCD_MAX_INTENSITY*i/100;
+	if( lcd_debug)
+		printk(KERN_INFO "cerf_lcdctrl_set_intensity: "
+			"dev_intensity = %d\n", dev_intensity);
+	return 0;
+}
+
+static int cerf_lcdctrl_set_brightness( int b)
+{
+	int dev_brightness = LCD_MAX_BRIGHTNESS*b/100;
+	outw( dev_brightness, CERF_PDA_CPLD+CERF_PDA_CPLD_BRIGHTNESS);
+	if( lcd_debug)
+		printk(KERN_INFO "cerf_lcdctrl_set_brightness: "
+			"dev_brightness = %d\n", dev_brightness);
+	return 0;
+}
+
+static int cerf_lcdctrl_set_contrast( int c, int sync)
+{
+	int new_dev_contrast = LCD_MAX_CONTRAST*c/100;
+	int i;
+	int count;
+	int direction = UP;
+	if( sync == LCD_SYNC_NEEDED)
+	{
+		/* In order to sync we step down to the lowest contrast level */
+		for( i=0; i<LCD_MAX_CONTRAST; i++)
+			cerf_lcdctrl_contrast_step(DOWN);
+		dev_contrast = 0;
+	}
+
+	count = new_dev_contrast - dev_contrast;
+	if( count < 0)
+	{
+		/* new contrast is lower then current setting */
+		direction = DOWN;
+		count = -count;
+	}
+
+	for( i=0; i<count; i++)
+		cerf_lcdctrl_contrast_step(direction);
+
+	if( lcd_debug)
+		printk(KERN_INFO "cerf_lcdctrl_set_contrast: "
+			"dev_contrast = %d\n", new_dev_contrast);
+	dev_contrast = new_dev_contrast;
+
+	return 0;
+}
+
+/* -- -- */
+
+static void cerf_lcdctrl_contrast_step( int direction)
+{
+	cerf_ucb1400gpio_lcd_contrast_step( direction);
+}
+
+/* -- -- */
+
+static int cerf_lcdctrl_init( int *intensity, int *brightness, int *contrast)
+{
+	*intensity = LCD_DEFAULT_INTENSITY;
+	*brightness = LCD_DEFAULT_BRIGHTNESS;
+	*contrast = LCD_DEFAULT_CONTRAST;
+
+	if( lcd_debug)
+		printk(KERN_INFO "cerf_lcdctrl_init: OK\n");
+	return 0;
+}
+
+/* this is the hook for lcdctrl to access to the device specifics */
+struct lcdctrl_device *lcdctrl_device_get_ops(void)
+{
+	return &cerf_dev;
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/video/pxafb.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,1410 @@
+/*
+ *  linux/drivers/video/pxafb.c
+ *
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *	        Intel PXA250/210 LCD Controller Frame Buffer Driver
+ *
+ * Please direct your questions and comments on this driver to the following
+ * email address:
+ *
+ *	linux-arm-kernel@lists.arm.linux.org.uk
+ *
+ *
+ * Code Status:
+ *
+ * 2001/08/03: <cbrake@accelent.com>
+ *      - Ported from SA1100 to PXA250
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/cpufreq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/lcdctrl.h> /* brightness, contrast, etc. control */
+
+/*
+ * debugging?
+ */
+#define DEBUG 0
+/*
+ * Complain if VAR is out of range.
+ */
+#define DEBUG_VAR 1
+
+#undef ASSABET_PAL_VIDEO
+
+#include "pxafb.h"
+
+void (*pxafb_blank_helper)(int blank);
+EXPORT_SYMBOL(pxafb_blank_helper);
+
+/*
+ * IMHO this looks wrong.  In 8BPP, length should be 8.
+ */
+static struct pxafb_rgb rgb_8 = {
+	red:	{ offset: 0,  length: 4, },
+	green:	{ offset: 0,  length: 4, },
+	blue:	{ offset: 0,  length: 4, },
+	transp:	{ offset: 0,  length: 0, },
+};
+
+static struct pxafb_rgb def_rgb_16 = {
+	red:	{ offset: 11, length: 5, },
+	green:	{ offset: 5,  length: 6, },
+	blue:	{ offset: 0,  length: 5, },
+	transp:	{ offset: 0,  length: 0, },
+};
+
+static struct pxafb_mach_info pxa_fb_info __initdata = {
+	pixclock:	LCD_PIXCLOCK,	/* clock period in ps */
+	bpp:		LCD_BPP,
+	xres:		LCD_XRES,
+	yres:		LCD_YRES,
+	hsync_len:	LCD_HORIZONTAL_SYNC_PULSE_WIDTH,
+	vsync_len:	LCD_VERTICAL_SYNC_PULSE_WIDTH,
+	left_margin:	LCD_BEGIN_OF_LINE_WAIT_COUNT,
+	upper_margin:	LCD_BEGIN_FRAME_WAIT_COUNT,
+	right_margin:	LCD_END_OF_LINE_WAIT_COUNT,
+	lower_margin:	LCD_END_OF_FRAME_WAIT_COUNT,
+	sync:		LCD_SYNC,
+	lccr0:		LCD_LCCR0,
+	lccr3:		LCD_LCCR3
+};
+
+static struct pxafb_mach_info * __init
+pxafb_get_machine_info(struct pxafb_info *fbi)
+{
+	return &pxa_fb_info;
+}
+
+static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
+
+static inline void pxafb_schedule_task(struct pxafb_info *fbi, u_int state)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/*
+	 * We need to handle two requests being made at the same time.
+	 * There are two important cases:
+	 *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
+	 *     We must perform the unblanking, which will do our REENABLE for us.
+	 *  2. When we are blanking, but immediately unblank before we have
+	 *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
+	 */
+	if (fbi->task_state == C_ENABLE && state == C_REENABLE)
+		state = (u_int) -1;
+	if (fbi->task_state == C_DISABLE && state == C_ENABLE)
+		state = C_REENABLE;
+
+	if (state != (u_int)-1) {
+		fbi->task_state = state;
+		schedule_task(&fbi->task);
+	}
+	local_irq_restore(flags);
+}
+
+/*
+ * Get the VAR structure pointer for the specified console
+ */
+static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;
+}
+
+/*
+ * Get the DISPLAY structure pointer for the specified console
+ */
+static inline struct display *get_con_display(struct fb_info *info, int con)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	return (con < 0) ? fbi->fb.disp : &fb_display[con];
+}
+
+/*
+ * Get the CMAP pointer for the specified console
+ */
+static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;
+}
+
+static inline u_int
+chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int
+pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+		       u_int trans, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	u_int val, ret = 1;
+
+	if (regno < fbi->palette_size) {
+		val = ((red >> 0) & 0xf800);
+		val |= ((green >> 5) & 0x07e0);
+		val |= ((blue >> 11) & 0x001f);
+
+		fbi->palette_cpu[regno] = val;
+		ret = 0;
+	}
+	return ret;
+}
+
+static int
+pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		   u_int trans, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	u_int val;
+	int ret = 1;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no mater what visual we are using.
+	 */
+	if (fbi->fb.var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (fbi->fb.disp->visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_DIRECTCOLOR:
+		/*
+		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno <= 16) {
+			u16 *pal = fbi->fb.pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ *  pxafb_decode_var():
+ *    Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *    if it's too big, return -EINVAL.
+ *
+ *    Suggestion: Round up in the following order: bits_per_pixel, xres,
+ *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+ *    bitfields, horizontal timing, vertical timing.
+ */
+static int pxafb_validate_var(struct fb_var_screeninfo *var,
+				 struct pxafb_info *fbi)
+{
+	int ret = -EINVAL;
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+	if (var->xres > fbi->max_xres)
+		var->xres = fbi->max_xres;
+	if (var->yres > fbi->max_yres)
+		var->yres = fbi->max_yres;
+	var->xres_virtual =
+	    var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
+	var->yres_virtual =
+	    var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
+
+	DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+	case 4:  ret = 0; break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:  ret = 0; break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 12:
+		/* make sure we are in passive mode */
+		if (!(fbi->lccr0 & LCCR0_PAS))
+			ret = 0;
+		break;
+
+	case 16:
+		/* 
+		 * 16 bits works apparemtly fine in passive mode for those,
+		 * so don't complain
+		 */
+		if (machine_is_lubbock() ||
+		    machine_is_pxa_cerf()) {
+			ret = 0;
+		} else
+			/* make sure we are in active mode */
+			if ((fbi->lccr0 & LCCR0_PAS))
+				ret = 0;
+		break;
+#endif
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static inline void pxafb_set_truecolor(u_int is_true_color)
+{
+	DPRINTK("true_color = %d\n", is_true_color);
+}
+
+static void
+pxafb_hw_set_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
+{
+
+	fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, &fbi->fb);
+
+	/* Set board control register to handle new color depth */
+	pxafb_set_truecolor(var->bits_per_pixel >= 16);
+
+	pxafb_activate_var(var, fbi);
+
+}
+
+/*
+ * pxafb_set_var():
+ *	Set the user defined part of the display for the specified console
+ */
+static int
+pxafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
+	struct display *display = get_con_display(&fbi->fb, con);
+	int err, chgvar = 0, rgbidx;
+
+	DPRINTK("set_var\n");
+
+	/*
+	 * Decode var contents into a par structure, adjusting any
+	 * out of range values.
+	 */
+	err = pxafb_validate_var(var, fbi);
+	if (err)
+		return err;
+
+	if (var->activate & FB_ACTIVATE_TEST)
+		return 0;
+
+	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+		return -EINVAL;
+
+	if (dvar->xres != var->xres)
+		chgvar = 1;
+	if (dvar->yres != var->yres)
+		chgvar = 1;
+	if (dvar->xres_virtual != var->xres_virtual)
+		chgvar = 1;
+	if (dvar->yres_virtual != var->yres_virtual)
+		chgvar = 1;
+	if (dvar->bits_per_pixel != var->bits_per_pixel)
+		chgvar = 1;
+	if (con < 0)
+		chgvar = 0;
+
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+	case 4:
+		if (fbi->cmap_static)
+			display->visual	= FB_VISUAL_STATIC_PSEUDOCOLOR;
+		else
+			display->visual	= FB_VISUAL_PSEUDOCOLOR;
+		display->line_length	= var->xres / 2;
+		display->dispsw		= &fbcon_cfb4;
+		rgbidx			= RGB_8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		if (fbi->cmap_static)
+			display->visual	= FB_VISUAL_STATIC_PSEUDOCOLOR;
+		else
+			display->visual	= FB_VISUAL_PSEUDOCOLOR;
+		display->line_length	= var->xres;
+		display->dispsw		= &fbcon_cfb8;
+		rgbidx			= RGB_8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 12:
+	case 16:
+		display->visual		= FB_VISUAL_TRUECOLOR;
+		display->line_length	= var->xres * 2;
+		display->dispsw		= &fbcon_cfb16;
+		display->dispsw_data	= fbi->fb.pseudo_palette;
+		rgbidx			= RGB_16;
+		break;
+#endif
+	default:
+		rgbidx = 0;
+		display->dispsw = &fbcon_dummy;
+		break;
+	}
+
+	display->screen_base	= fbi->screen_cpu;
+	display->next_line	= display->line_length;
+	display->type		= fbi->fb.fix.type;
+	display->type_aux	= fbi->fb.fix.type_aux;
+	display->ypanstep	= fbi->fb.fix.ypanstep;
+	display->ywrapstep	= fbi->fb.fix.ywrapstep;
+	display->can_soft_blank	= 1;
+	display->inverse	= 0;
+
+	*dvar			= *var;
+	dvar->activate		&= ~FB_ACTIVATE_ALL;
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	dvar->red		= fbi->rgb[rgbidx]->red;
+	dvar->green		= fbi->rgb[rgbidx]->green;
+	dvar->blue		= fbi->rgb[rgbidx]->blue;
+	dvar->transp		= fbi->rgb[rgbidx]->transp;
+
+	DPRINTK("RGBT length = %d:%d:%d:%d\n",
+		dvar->red.length, dvar->green.length, dvar->blue.length,
+		dvar->transp.length);
+
+	DPRINTK("RGBT offset = %d:%d:%d:%d\n",
+		dvar->red.offset, dvar->green.offset, dvar->blue.offset,
+		dvar->transp.offset);
+
+	/*
+	 * Update the old var.  The fbcon drivers still use this.
+	 * Once they are using fbi->fb.var, this can be dropped.
+	 */
+	display->var = *dvar;
+
+	/*
+	 * If we are setting all the virtual consoles, also set the
+	 * defaults used to create new consoles.
+	 */
+	if (var->activate & FB_ACTIVATE_ALL)
+		fbi->fb.disp->var = *dvar;
+
+	/*
+	 * If the console has changed and the console has defined
+	 * a changevar function, call that function.
+	 */
+	if (chgvar && info && fbi->fb.changevar)
+		fbi->fb.changevar(con);
+
+	/* If the current console is selected, activate the new var. */
+	if (con != fbi->currcon)
+		return 0;
+
+	pxafb_hw_set_var(dvar, fbi);
+
+	return 0;
+}
+
+static int
+__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+	      struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct fb_cmap *dcmap = get_con_cmap(info, con);
+	int err = 0;
+
+	if (con == -1)
+		con = fbi->currcon;
+
+	/* no colormap allocated? (we always have "this" colour map allocated) */
+	if (con >= 0)
+		err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
+
+	if (!err && con == fbi->currcon)
+		err = fb_set_cmap(cmap, kspc, pxafb_setcolreg, info);
+
+	if (!err)
+		fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
+
+	return err;
+}
+
+static int
+pxafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+		  struct fb_info *info)
+{
+	struct display *disp = get_con_display(info, con);
+
+	if (disp->visual == FB_VISUAL_TRUECOLOR)
+		return -EINVAL;
+
+	return __do_set_cmap(cmap, kspc, con, info);
+}
+
+static int
+pxafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	struct display *display = get_con_display(info, con);
+
+	*fix = info->fix;
+
+	fix->line_length = display->line_length;
+	fix->visual	 = display->visual;
+	return 0;
+}
+
+static int
+pxafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	*var = *get_con_var(info, con);
+	return 0;
+}
+
+static int
+pxafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+	struct fb_cmap *dcmap = get_con_cmap(info, con);
+	fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+static struct fb_ops pxafb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	pxafb_get_fix,
+	fb_get_var:	pxafb_get_var,
+	fb_set_var:	pxafb_set_var,
+	fb_get_cmap:	pxafb_get_cmap,
+	fb_set_cmap:	pxafb_set_cmap,
+};
+
+/*
+ *  pxafb_switch():       
+ *	Change to the specified console.  Palette and video mode
+ *      are changed to the console's stored parameters.
+ *
+ *	Uh oh, this can be called from a tasklet (IRQ)
+ */
+static int pxafb_switch(int con, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct display *disp;
+	struct fb_cmap *cmap;
+
+	DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);
+
+	if (con == fbi->currcon)
+		return 0;
+
+	if (fbi->currcon >= 0) {
+		disp = fb_display + fbi->currcon;
+
+		/*
+		 * Save the old colormap and video mode.
+		 */
+		disp->var = fbi->fb.var;
+
+		if (disp->cmap.len)
+			fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
+	}
+
+	fbi->currcon = con;
+	disp = fb_display + con;
+
+	/*
+	 * Make sure that our colourmap contains 256 entries.
+	 */
+	fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
+
+	if (disp->cmap.len)
+		cmap = &disp->cmap;
+	else
+		cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
+
+	fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
+
+	fbi->fb.var = disp->var;
+	fbi->fb.var.activate = FB_ACTIVATE_NOW;
+
+	pxafb_set_var(&fbi->fb.var, con, info);
+	return 0;
+}
+
+/*
+ * Formal definition of the VESA spec:
+ *  On
+ *  	This refers to the state of the display when it is in full operation
+ *  Stand-By
+ *  	This defines an optional operating state of minimal power reduction with
+ *  	the shortest recovery time
+ *  Suspend
+ *  	This refers to a level of power management in which substantial power
+ *  	reduction is achieved by the display.  The display can have a longer 
+ *  	recovery time from this state than from the Stand-by state
+ *  Off
+ *  	This indicates that the display is consuming the lowest level of power
+ *  	and is non-operational. Recovery from this state may optionally require
+ *  	the user to manually power on the monitor
+ *
+ *  Now, the fbdev driver adds an additional state, (blank), where they
+ *  turn off the video (maybe by colormap tricks), but don't mess with the
+ *  video itself: think of it semantically between on and Stand-By.
+ *
+ *  So here's what we should do in our fbdev blank routine:
+ *
+ *  	VESA_NO_BLANKING (mode 0)	Video on,  front/back light on
+ *  	VESA_VSYNC_SUSPEND (mode 1)  	Video on,  front/back light off
+ *  	VESA_HSYNC_SUSPEND (mode 2)  	Video on,  front/back light off
+ *  	VESA_POWERDOWN (mode 3)		Video off, front/back light off
+ *
+ *  This will match the matrox implementation.
+ */
+/*
+ * pxafb_blank():
+ *	Blank the display by setting all palette values to zero.  Note, the 
+ * 	12 and 16 bpp modes don't really use the palette, so this will not
+ *      blank the display in all modes.  
+ */
+static void pxafb_blank(int blank, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	int i;
+
+	DPRINTK("pxafb_blank: blank=%d info->modename=%s\n", blank,
+		fbi->fb.modename);
+
+	switch (blank) {
+	case VESA_POWERDOWN:
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+		if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
+		    fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			for (i = 0; i < fbi->palette_size; i++)
+				pxafb_setpalettereg(i, 0, 0, 0, 0, info);
+		pxafb_schedule_task(fbi, C_DISABLE);
+		if (pxafb_blank_helper)
+			pxafb_blank_helper(blank);
+		break;
+
+	case VESA_NO_BLANKING:
+		if (pxafb_blank_helper)
+			pxafb_blank_helper(blank);
+		if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
+		    fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, info);
+		pxafb_schedule_task(fbi, C_ENABLE);
+	}
+}
+
+static int pxafb_updatevar(int con, struct fb_info *info)
+{
+	DPRINTK("entered\n");
+	return 0;
+}
+
+/*
+ * Calculate the PCD value from the clock rate (in picoseconds).
+ * We take account of the PPCR clock setting.
+ */
+static inline int get_pcd(unsigned int pixclock)
+{
+	unsigned int pcd;
+
+	if (pixclock) {
+		pcd = get_lclk_frequency_10khz() * pixclock;
+		pcd /= 100000000;
+		pcd += 1;	/* make up for integer math truncations */
+	} else {
+		printk(KERN_WARNING "Please convert me to use the PCD calculations\n");
+		pcd = 0;
+	}
+	return pcd;
+}
+
+/*
+ * pxafb_activate_var():
+ *	Configures LCD Controller based on entries in var parameter.  Settings are      
+ *      only written to the controller if changes were made.  
+ */
+static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
+{
+	struct pxafb_lcd_reg new_regs;
+//	u_int pcd = get_pcd(var->pixclock);
+	u_long flags;
+
+	DPRINTK("Configuring PXA LCD\n");
+
+	DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
+		var->xres, var->hsync_len,
+		var->left_margin, var->right_margin);
+	DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
+		var->yres, var->vsync_len,
+		var->upper_margin, var->lower_margin);
+
+#if DEBUG_VAR
+	if (var->xres < 16        || var->xres > 1024)
+		printk(KERN_ERR "%s: invalid xres %d\n",
+			fbi->fb.fix.id, var->xres);
+	if (var->hsync_len < 1    || var->hsync_len > 64)
+		printk(KERN_ERR "%s: invalid hsync_len %d\n",
+			fbi->fb.fix.id, var->hsync_len);
+	if (var->left_margin < 1  || var->left_margin > 255)
+		printk(KERN_ERR "%s: invalid left_margin %d\n",
+			fbi->fb.fix.id, var->left_margin);
+	if (var->right_margin < 1 || var->right_margin > 255)
+		printk(KERN_ERR "%s: invalid right_margin %d\n",
+			fbi->fb.fix.id, var->right_margin);
+	if (var->yres < 1         || var->yres > 1024)
+		printk(KERN_ERR "%s: invalid yres %d\n",
+			fbi->fb.fix.id, var->yres);
+	if (var->vsync_len < 1    || var->vsync_len > 64)
+		printk(KERN_ERR "%s: invalid vsync_len %d\n",
+			fbi->fb.fix.id, var->vsync_len);
+	if (var->upper_margin < 0 || var->upper_margin > 255)
+		printk(KERN_ERR "%s: invalid upper_margin %d\n",
+			fbi->fb.fix.id, var->upper_margin);
+	if (var->lower_margin < 0 || var->lower_margin > 255)
+		printk(KERN_ERR "%s: invalid lower_margin %d\n",
+			fbi->fb.fix.id, var->lower_margin);
+#endif
+
+#if defined (CONFIG_PXA_CERF_PDA)
+	new_regs.lccr0 = fbi->lccr0;
+	new_regs.lccr1 =
+		LCCR1_DisWdth(var->xres) +
+		LCCR1_HorSnchWdth(var->hsync_len) +
+		LCCR1_BegLnDel(var->left_margin) +
+		LCCR1_EndLnDel(var->right_margin);
+		
+	new_regs.lccr2 =
+		LCCR2_DisHght(var->yres) +
+		LCCR2_VrtSnchWdth(var->vsync_len) +
+		LCCR2_BegFrmDel(var->upper_margin) +
+		LCCR2_EndFrmDel(var->lower_margin);
+
+	new_regs.lccr3 = fbi->lccr3
+		|
+		(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
+		(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
+#elif defined (CONFIG_FB_PXA_QVGA)
+	new_regs.lccr0 = fbi->lccr0;
+	new_regs.lccr1 =
+		LCCR1_DisWdth(var->xres) +
+		LCCR1_HorSnchWdth(var->hsync_len) +
+		LCCR1_BegLnDel(var->left_margin) +
+		LCCR1_EndLnDel(var->right_margin);
+	new_regs.lccr2 =
+		LCCR2_DisHght(var->yres) +
+		LCCR2_VrtSnchWdth(var->vsync_len) +
+		LCCR2_BegFrmDel(var->upper_margin) +
+		LCCR2_EndFrmDel(var->lower_margin);
+	new_regs.lccr3 = fbi->lccr3;
+#else
+	// FIXME using hardcoded values for now
+	new_regs.lccr0 = fbi->lccr0;
+//		|
+//		LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
+//		LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
+
+	new_regs.lccr1 = 0x3030A7F;
+//		LCCR1_DisWdth(var->xres) +
+//		LCCR1_HorSnchWdth(var->hsync_len) +
+//		LCCR1_BegLnDel(var->left_margin) +
+//		LCCR1_EndLnDel(var->right_margin);
+
+	new_regs.lccr2 = 0x4EF;
+//		LCCR2_DisHght(var->yres) +
+//		LCCR2_VrtSnchWdth(var->vsync_len) +
+//		LCCR2_BegFrmDel(var->upper_margin) +
+//		LCCR2_EndFrmDel(var->lower_margin);
+
+	new_regs.lccr3 = fbi->lccr3;
+//	|
+//		(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
+//		(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
+//		LCCR3_ACBsCntOff;
+#endif
+
+//	if (pcd)
+//		new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
+
+	DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
+	DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
+	DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
+	DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
+
+	/* Update shadow copy atomically */
+	local_irq_save(flags);
+
+	/* setup dma descriptors */
+	fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16);
+	fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16);
+	fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16);
+
+	fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16;
+	fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16;
+	fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16;
+
+	#define BYTES_PER_PANEL	((fbi->lccr0 & LCCR0_SDS) ? (var->xres * var->yres * var->bits_per_pixel / 8 / 2) : \
+			                                    (var->xres * var->yres * var->bits_per_pixel / 8))
+	
+	/* populate descriptors */
+	fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma;
+	fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL;
+	fbi->dmadesc_fblow_cpu->fidr  = 0;
+	fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL;
+
+	fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */
+		
+	fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
+	fbi->dmadesc_fbhigh_cpu->fidr = 0;
+	fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
+
+	fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
+	fbi->dmadesc_palette_cpu->fidr  = 0;
+	fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
+
+	if( var->bits_per_pixel < 12)
+	{
+		/* assume any mode with <12 bpp is palette driven */
+		fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
+		fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
+		fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
+	}
+	else
+	{
+		/* palette shouldn't be loaded in true-color mode */
+		fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
+		fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
+	}
+
+	DPRINTK("fbi->dmadesc_fblow_cpu = 0x%x\n", fbi->dmadesc_fblow_cpu);
+	DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%x\n", fbi->dmadesc_fbhigh_cpu);
+	DPRINTK("fbi->dmadesc_palette_cpu = 0x%x\n", fbi->dmadesc_palette_cpu);
+	DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
+	DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
+	DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
+
+	DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
+	DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
+	DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
+
+	DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
+	DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
+	DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
+
+	DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
+	DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
+	DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
+	
+	fbi->reg_lccr0 = new_regs.lccr0;
+	fbi->reg_lccr1 = new_regs.lccr1;
+	fbi->reg_lccr2 = new_regs.lccr2;
+	fbi->reg_lccr3 = new_regs.lccr3;
+	local_irq_restore(flags);
+
+	/*
+	 * Only update the registers if the controller is enabled
+	 * and something has changed.
+	 */
+	if ((LCCR0 != fbi->reg_lccr0)       || (LCCR1 != fbi->reg_lccr1) ||
+	    (LCCR2 != fbi->reg_lccr2)       || (LCCR3 != fbi->reg_lccr3) ||
+	    (FDADR0 != fbi->fdadr0) || (FDADR1 != fbi->fdadr1))
+		pxafb_schedule_task(fbi, C_REENABLE);
+
+	return 0;
+}
+
+/*
+ * NOTE!  The following functions are purely helpers for set_ctrlr_state.
+ * Do not call them directly; set_ctrlr_state does the correct serialisation
+ * to ensure that things happen in the right way 100% of time time.
+ *	-- rmk
+ */
+
+/*
+ * FIXME: move LCD power stuff into pxafb_power_up_lcd()
+ * Also, I'm expecting that the backlight stuff should
+ * be handled differently.
+ */
+static void pxafb_backlight_on(struct pxafb_info *fbi)
+{
+	DPRINTK("backlight on\n");
+
+#ifdef CONFIG_ARCH_PXA_IDP
+	if(machine_is_pxa_idp()) {	
+		FB_BACKLIGHT_ON();
+	}
+#endif
+}
+
+/*
+ * FIXME: move LCD power stuf into pxafb_power_down_lcd()
+ * Also, I'm expecting that the backlight stuff should
+ * be handled differently.
+ */
+static void pxafb_backlight_off(struct pxafb_info *fbi)
+{
+	DPRINTK("backlight off\n");
+
+#ifdef CONFIG_ARCH_PXA_IDP
+	if(machine_is_pxa_idp()) {
+		FB_BACKLIGHT_OFF();
+	}
+#endif
+	
+}
+
+static void pxafb_power_up_lcd(struct pxafb_info *fbi)
+{
+	DPRINTK("LCD power on\n");
+	CKEN |= CKEN16_LCD;
+
+	if(machine_is_pxa_cerf()) {
+		lcdctrl_enable();
+	}
+
+#if CONFIG_ARCH_PXA_IDP
+	/* set GPIOs, etc */
+	if(machine_is_pxa_idp()) {
+		// FIXME need to add proper delays
+		FB_PWR_ON();
+		FB_VLCD_ON();	// FIXME this should be after scanning starts
+	}
+#endif
+}
+
+static void pxafb_power_down_lcd(struct pxafb_info *fbi)
+{
+	DPRINTK("LCD power off\n");
+	CKEN &= ~CKEN16_LCD;
+
+	if(machine_is_pxa_cerf()) {
+		lcdctrl_disable();
+	}
+
+	/* set GPIOs, etc */
+#if CONFIG_ARCH_PXA_IDP
+	if(machine_is_pxa_idp()) {
+		// FIXME need to add proper delays
+		FB_PWR_OFF();
+		FB_VLCD_OFF();	// FIXME this should be before scanning stops
+	}
+#endif
+
+}
+
+static void pxafb_setup_gpio(struct pxafb_info *fbi)
+{
+	unsigned int lccr0;
+
+	/*
+	 * setup is based on type of panel supported
+	 */
+
+	lccr0 = fbi->lccr0;
+
+	/* 4 bit interface */
+	if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
+	{
+		// bits 58-61
+		GPDR1 |= (0xf << 26);
+		GAFR1_U = (GAFR1_U & ~(0xff << 20)) | (0xaa << 20);
+
+		// bits 74-77
+		GPDR2 |= (0xf << 10);
+                GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
+	}
+
+        /* 8 bit interface */
+        else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
+                 (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
+        {
+		// bits 58-65
+                GPDR1 |= (0x3f << 26);
+                GPDR2 |= (0x3);
+
+                GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
+                GAFR2_L = (GAFR2_L & ~0xf) | (0xa);
+
+                // bits 74-77
+                GPDR2 |= (0xf << 10);
+                GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
+        }
+
+        /* 16 bit interface */
+        else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
+        {
+		// bits 58-77
+                GPDR1 |= (0x3f << 26);
+                GPDR2 |= 0x00003fff;
+
+                GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
+                GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
+        }
+	else
+	{
+		printk( KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
+	}
+}
+
+static void pxafb_enable_controller(struct pxafb_info *fbi)
+{
+	DPRINTK("Enabling LCD controller\n");
+
+	/* Sequence from 11.7.10 */
+	LCCR3 = fbi->reg_lccr3;
+	LCCR2 = fbi->reg_lccr2;
+	LCCR1 = fbi->reg_lccr1;
+	LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB;
+
+	/* FIXME we used to have LCD power control here */
+
+	FDADR0 = fbi->fdadr0;
+	FDADR1 = fbi->fdadr1;
+	LCCR0 |= LCCR0_ENB;
+
+	DPRINTK("FDADR0 = 0x%08x\n", (unsigned int)FDADR0);
+	DPRINTK("FDADR1 = 0x%08x\n", (unsigned int)FDADR1);
+	DPRINTK("LCCR0 = 0x%08x\n", (unsigned int)LCCR0);
+	DPRINTK("LCCR1 = 0x%08x\n", (unsigned int)LCCR1);
+	DPRINTK("LCCR2 = 0x%08x\n", (unsigned int)LCCR2);
+	DPRINTK("LCCR3 = 0x%08x\n", (unsigned int)LCCR3);
+}
+
+static void pxafb_disable_controller(struct pxafb_info *fbi)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	DPRINTK("Disabling LCD controller\n");
+
+	/* FIXME add power down GPIO stuff here */
+
+	add_wait_queue(&fbi->ctrlr_wait, &wait);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+
+	LCSR = 0xffffffff;	/* Clear LCD Status Register */
+	LCCR0 &= ~LCCR0_LDM;	/* Enable LCD Disable Done Interrupt */
+	LCCR0 &= ~LCCR0_ENB;	/* Disable LCD Controller */
+
+	schedule_timeout(20 * HZ / 1000);
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&fbi->ctrlr_wait, &wait);
+}
+
+/*
+ *  pxafb_handle_irq: Handle 'LCD DONE' interrupts.
+ */
+static void pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pxafb_info *fbi = dev_id;
+	unsigned int lcsr = LCSR;
+
+	if (lcsr & LCSR_LDD) {
+		LCCR0 |= LCCR0_LDM;
+		wake_up(&fbi->ctrlr_wait);
+	}
+
+	LCSR = lcsr;
+}
+
+/*
+ * This function must be called from task context only, since it will
+ * sleep when disabling the LCD controller, or if we get two contending
+ * processes trying to alter state.
+ */
+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
+{
+	u_int old_state;
+
+	down(&fbi->ctrlr_sem);
+
+	old_state = fbi->state;
+
+	switch (state) {
+	case C_DISABLE_CLKCHANGE:
+		/*
+		 * Disable controller for clock change.  If the
+		 * controller is already disabled, then do nothing.
+		 */
+		if (old_state != C_DISABLE) {
+			fbi->state = state;
+			pxafb_disable_controller(fbi);
+		}
+		break;
+
+	case C_DISABLE:
+		/*
+		 * Disable controller
+		 */
+		if (old_state != C_DISABLE) {
+			fbi->state = state;
+
+			pxafb_backlight_off(fbi);
+			if (old_state != C_DISABLE_CLKCHANGE)
+				pxafb_disable_controller(fbi);
+			pxafb_power_down_lcd(fbi);
+		}
+		break;
+
+	case C_ENABLE_CLKCHANGE:
+		/*
+		 * Enable the controller after clock change.  Only
+		 * do this if we were disabled for the clock change.
+		 */
+		if (old_state == C_DISABLE_CLKCHANGE) {
+			fbi->state = C_ENABLE;
+			pxafb_enable_controller(fbi);
+		}
+		break;
+
+	case C_REENABLE:
+		/*
+		 * Re-enable the controller only if it was already
+		 * enabled.  This is so we reprogram the control
+		 * registers.
+		 */
+		if (old_state == C_ENABLE) {
+			pxafb_disable_controller(fbi);
+			pxafb_setup_gpio(fbi);
+			pxafb_enable_controller(fbi);
+		}
+		break;
+
+	case C_ENABLE:
+		/*
+		 * Power up the LCD screen, enable controller, and
+		 * turn on the backlight.
+		 */
+		if (old_state != C_ENABLE) {
+			fbi->state = C_ENABLE;
+			pxafb_setup_gpio(fbi);
+			pxafb_power_up_lcd(fbi);
+			pxafb_enable_controller(fbi);
+			pxafb_backlight_on(fbi);
+		}
+		break;
+	}
+	up(&fbi->ctrlr_sem);
+}
+
+/*
+ * Our LCD controller task (which is called when we blank or unblank)
+ * via keventd.
+ */
+static void pxafb_task(void *dummy)
+{
+	struct pxafb_info *fbi = dummy;
+	u_int state = xchg(&fbi->task_state, -1);
+
+	set_ctrlr_state(fbi, state);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ * CPU clock speed change handler.  We need to adjust the LCD timing
+ * parameters when the CPU clock is adjusted by the power management
+ * subsystem.
+ */
+static int
+pxafb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
+			 void *data)
+{
+	struct pxafb_info *fbi = TO_INF(nb, clockchg);
+	u_int pcd;
+
+	switch (val) {
+	case CPUFREQ_MINMAX:
+		/* todo: fill in min/max values */
+		break;
+
+	case CPUFREQ_PRECHANGE:
+		set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
+		break;
+
+	case CPUFREQ_POSTCHANGE:
+		pcd = get_pcd(fbi->fb.var.pixclock);
+		fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+		set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
+		break;
+	}
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+/*
+ * Power management hook.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int
+pxafb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
+{
+	struct pxafb_info *fbi = pm_dev->data;
+
+	DPRINTK("pm_callback: %d\n", req);
+
+	if (req == PM_SUSPEND || req == PM_RESUME) {
+		int state = (int)data;
+
+		if (state == 0) {
+			/* Enter D0. */
+			set_ctrlr_state(fbi, C_ENABLE);
+		} else {
+			/* Enter D1-D3.  Disable the LCD controller.  */
+			set_ctrlr_state(fbi, C_DISABLE);
+		}
+	}
+	DPRINTK("done\n");
+	return 0;
+}
+#endif
+
+/*
+ * pxafb_map_video_memory():
+ *      Allocates the DRAM memory for the frame buffer.  This buffer is  
+ *	remapped into a non-cached, non-buffered, memory region to  
+ *      allow palette and pixel writes to occur without flushing the 
+ *      cache.  Once this area is remapped, all virtual memory
+ *      access to the video memory should occur at the new region.
+ */
+static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
+{
+	u_long palette_mem_size;
+
+	/*
+	 * We reserve one page for the palette, plus the size
+	 * of the framebuffer.
+	 *
+	 * layout of stuff in memory
+	 *
+	 *                fblow descriptor
+	 *                fbhigh descriptor
+	 *                palette descriptor
+	 *                palette
+	 *   page boundary->
+	 *                frame buffer
+	 */
+	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
+	fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
+					&fbi->map_dma, PTE_BUFFERABLE);
+
+	if (fbi->map_cpu) {
+		fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
+		fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
+		fbi->fb.fix.smem_start = fbi->screen_dma;
+
+		fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
+
+		palette_mem_size = fbi->palette_size * sizeof(u16);
+
+		DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+
+		fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
+		fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
+
+	}
+
+	return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+/* Fake monspecs to fill in fbinfo structure */
+static struct fb_monspecs monspecs __initdata = {
+	30000, 70000, 50, 65, 0	/* Generic */
+};
+
+
+static struct pxafb_info * __init pxafb_init_fbinfo(void)
+{
+	struct pxafb_mach_info *inf;
+	struct pxafb_info *fbi;
+
+	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(struct display) +
+		      sizeof(u16) * 16, GFP_KERNEL);
+	if (!fbi)
+		return NULL;
+
+	memset(fbi, 0, sizeof(struct pxafb_info) + sizeof(struct display));
+
+	fbi->currcon		= -1;
+
+	strcpy(fbi->fb.fix.id, PXA_NAME);
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.type_aux	= 0;
+	fbi->fb.fix.xpanstep	= 0;
+	fbi->fb.fix.ypanstep	= 0;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.var.nonstd	= 0;
+	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
+	fbi->fb.var.height	= -1;
+	fbi->fb.var.width	= -1;
+	fbi->fb.var.accel_flags	= 0;
+	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
+
+	strcpy(fbi->fb.modename, PXA_NAME);
+	strcpy(fbi->fb.fontname, "Acorn8x8");
+
+	fbi->fb.fbops		= &pxafb_ops;
+	fbi->fb.changevar	= NULL;
+	fbi->fb.switch_con	= pxafb_switch;
+	fbi->fb.updatevar	= pxafb_updatevar;
+	fbi->fb.blank		= pxafb_blank;
+	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fbi->fb.node		= -1;
+	fbi->fb.monspecs	= monspecs;
+	fbi->fb.disp		= (struct display *)(fbi + 1);
+	fbi->fb.pseudo_palette	= (void *)(fbi->fb.disp + 1);
+
+	fbi->rgb[RGB_8]		= &rgb_8;
+	fbi->rgb[RGB_16]	= &def_rgb_16;
+
+	inf = pxafb_get_machine_info(fbi);
+
+	fbi->max_xres			= inf->xres;
+	fbi->fb.var.xres		= inf->xres;
+	fbi->fb.var.xres_virtual	= inf->xres;
+	fbi->max_yres			= inf->yres;
+	fbi->fb.var.yres		= inf->yres;
+	fbi->fb.var.yres_virtual	= inf->yres;
+	fbi->max_bpp			= inf->bpp;
+	fbi->fb.var.bits_per_pixel	= inf->bpp;
+	fbi->fb.var.pixclock		= inf->pixclock;
+	fbi->fb.var.hsync_len		= inf->hsync_len;
+	fbi->fb.var.left_margin		= inf->left_margin;
+	fbi->fb.var.right_margin	= inf->right_margin;
+	fbi->fb.var.vsync_len		= inf->vsync_len;
+	fbi->fb.var.upper_margin	= inf->upper_margin;
+	fbi->fb.var.lower_margin	= inf->lower_margin;
+	fbi->fb.var.sync		= inf->sync;
+	fbi->fb.var.grayscale		= inf->cmap_greyscale;
+	fbi->cmap_inverse		= inf->cmap_inverse;
+	fbi->cmap_static		= inf->cmap_static;
+	fbi->lccr0			= inf->lccr0;
+	fbi->lccr3			= inf->lccr3;
+	fbi->state			= C_DISABLE;
+	fbi->task_state			= (u_char)-1;
+	fbi->fb.fix.smem_len		= fbi->max_xres * fbi->max_yres *
+					  fbi->max_bpp / 8;
+
+	init_waitqueue_head(&fbi->ctrlr_wait);
+	INIT_TQUEUE(&fbi->task, pxafb_task, fbi);
+	init_MUTEX(&fbi->ctrlr_sem);
+
+	return fbi;
+}
+
+int __init pxafb_init(void)
+{
+	struct pxafb_info *fbi;
+	int ret;
+
+	fbi = pxafb_init_fbinfo();
+	ret = -ENOMEM;
+	if (!fbi)
+		goto failed;
+
+	if(machine_is_pxa_cerf()) {
+		// brightness&contrast is handled via lcdctrl.
+		lcdctrl_init();
+	}
+
+	/* Initialize video memory */
+	ret = pxafb_map_video_memory(fbi);
+	if (ret)
+		goto failed;
+
+	ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT,
+			  "LCD", fbi);
+	if (ret) {
+		printk(KERN_ERR "pxafb: failed in request_irq: %d\n", ret);
+		goto failed;
+	}
+
+	pxafb_set_var(&fbi->fb.var, -1, &fbi->fb);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0)
+		goto failed;
+
+#ifdef CONFIG_PM
+	/*
+	 * Note that the console registers this as well, but we want to
+	 * power down the display prior to sleeping.
+	 */
+	fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, pxafb_pm_callback);
+	if (fbi->pm)
+		fbi->pm->data = fbi;
+#endif
+#ifdef CONFIG_CPU_FREQ
+	fbi->clockchg.notifier_call = pxafb_clkchg_notifier;
+	cpufreq_register_notifier(&fbi->clockchg);
+#endif
+
+	/*
+	 * Ok, now enable the LCD controller
+	 */
+	set_ctrlr_state(fbi, C_ENABLE);
+
+	/* This driver cannot be unloaded at the moment */
+	MOD_INC_USE_COUNT;
+
+	return 0;
+
+failed:
+	if (fbi)
+		kfree(fbi);
+	return ret;
+}
+
+
+#ifdef MODULE
+module_init(pxafb_init);
+#endif
+
+MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
+MODULE_LICENSE("GPL");
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/drivers/video/pxafb.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,238 @@
+/*
+ * linux/drivers/video/pxafb.h
+ *    -- Intel PXA250/210 LCD Controller Frame Buffer Device
+ *
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ *  2001-08-03: Cliff Brake <cbrake@acclent.com>
+ *	 - ported SA1100 code to PXA
+ *  
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * These are the bitfields for each
+ * display depth that we support.
+ */
+struct pxafb_rgb {
+	struct fb_bitfield	red;
+	struct fb_bitfield	green;
+	struct fb_bitfield	blue;
+	struct fb_bitfield	transp;
+};
+
+/*
+ * This structure describes the machine which we are running on.
+ */
+struct pxafb_mach_info {
+	u_long		pixclock;
+
+	u_short		xres;
+	u_short		yres;
+
+	u_char		bpp;
+	u_char		hsync_len;
+	u_char		left_margin;
+	u_char		right_margin;
+
+	u_char		vsync_len;
+	u_char		upper_margin;
+	u_char		lower_margin;
+	u_char		sync;
+
+	u_int		cmap_greyscale:1,
+			cmap_inverse:1,
+			cmap_static:1,
+			unused:29;
+
+	u_int		lccr0;
+	u_int		lccr3;
+};
+
+/* Shadows for LCD controller registers */
+struct pxafb_lcd_reg {
+	unsigned int lccr0;
+	unsigned int lccr1;
+	unsigned int lccr2;
+	unsigned int lccr3;
+};
+
+/* PXA LCD DMA descriptor */
+struct pxafb_dma_descriptor {
+	unsigned int fdadr;
+	unsigned int fsadr;
+	unsigned int fidr;
+	unsigned int ldcmd;
+};
+
+#define RGB_8	(0)
+#define RGB_16	(1)
+#define NR_RGB	2
+
+struct pxafb_info {
+	struct fb_info		fb;
+	signed int		currcon;
+
+	struct pxafb_rgb	*rgb[NR_RGB];
+
+	u_int			max_bpp;
+	u_int			max_xres;
+	u_int			max_yres;
+
+	/*
+	 * These are the addresses we mapped
+	 * the framebuffer memory region to.
+	 */
+
+	/* raw memory addresses */
+	dma_addr_t		map_dma;	/* physical */
+	u_char *		map_cpu;	/* virtual */
+	u_int			map_size;
+
+	/* addresses of pieces placed in raw buffer */
+	u_char *		screen_cpu;	/* virtual address of frame buffer */
+	dma_addr_t		screen_dma;	/* physical address of frame buffer */
+	u16 *			palette_cpu;	/* virtual address of palette memory */
+	dma_addr_t		palette_dma;	/* physical address of palette memory */
+	u_int			palette_size;
+
+	/* DMA descriptors */
+	struct pxafb_dma_descriptor * 	dmadesc_fblow_cpu;
+	dma_addr_t				dmadesc_fblow_dma;
+	struct pxafb_dma_descriptor * 	dmadesc_fbhigh_cpu;
+	dma_addr_t				dmadesc_fbhigh_dma;
+	struct pxafb_dma_descriptor *	dmadesc_palette_cpu;
+	dma_addr_t				dmadesc_palette_dma;
+
+	dma_addr_t		fdadr0;
+	dma_addr_t		fdadr1;
+
+	u_int			lccr0;
+	u_int			lccr3;
+	u_int			cmap_inverse:1,
+				cmap_static:1,
+				unused:30;
+
+	u_int			reg_lccr0;
+	u_int			reg_lccr1;
+	u_int			reg_lccr2;
+	u_int			reg_lccr3;
+
+	volatile u_char		state;
+	volatile u_char		task_state;
+	struct semaphore	ctrlr_sem;
+	wait_queue_head_t	ctrlr_wait;
+	struct tq_struct	task;
+
+#ifdef CONFIG_PM
+	struct pm_dev		*pm;
+#endif
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	clockchg;
+#endif
+};
+
+#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
+
+#define TO_INF(ptr,member)	__type_entry(ptr,struct pxafb_info,member)
+
+/*
+ * These are the actions for set_ctrlr_state
+ */
+#define C_DISABLE		(0)
+#define C_ENABLE		(1)
+#define C_DISABLE_CLKCHANGE	(2)
+#define C_ENABLE_CLKCHANGE	(3)
+#define C_REENABLE		(4)
+
+#define PXA_NAME	"PXA"
+
+/*
+ *  Debug macros 
+ */
+#if DEBUG
+#  define DPRINTK(fmt, args...)	printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES	64
+#define MIN_YRES	64
+
+/*
+ * Are we configured for 8 or 16 bits per pixel?
+ */
+#ifdef CONFIG_FB_PXA_8BPP
+#  define PXAFB_BPP		8
+#  define PXAFB_BPP_BITS	0x03
+#elif CONFIG_FB_PXA_16BPP
+#  define PXAFB_BPP		16
+#  define PXAFB_BPP_BITS	0x04
+#endif
+
+#if defined(CONFIG_ARCH_LUBBOCK)
+#define LCD_PIXCLOCK			150000
+#define LCD_BPP				PXAFB_BPP
+#ifdef CONFIG_FB_PXA_QVGA
+#define LCD_XRES			320
+#define LCD_YRES			240
+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH	51
+#define LCD_VERTICAL_SYNC_PULSE_WIDTH	1
+#define LCD_BEGIN_OF_LINE_WAIT_COUNT	1
+#define LCD_BEGIN_FRAME_WAIT_COUNT 	8
+#define LCD_END_OF_LINE_WAIT_COUNT	1
+#define LCD_END_OF_FRAME_WAIT_COUNT	1
+#define LCD_SYNC			(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
+#define LCD_LCCR0			0x003008F8
+#define LCD_LCCR3 			(0x0040FF0C | (PXAFB_BPP_BITS << 24))
+#else
+#define LCD_XRES			640
+#define LCD_YRES			480
+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH	1
+#define LCD_VERTICAL_SYNC_PULSE_WIDTH	1
+#define LCD_BEGIN_OF_LINE_WAIT_COUNT	3
+#define LCD_BEGIN_FRAME_WAIT_COUNT 	0
+#define LCD_END_OF_LINE_WAIT_COUNT	3
+#define LCD_END_OF_FRAME_WAIT_COUNT	0
+#define LCD_SYNC			(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
+#define LCD_LCCR0			0x0030087C
+#define LCD_LCCR3 			(0x0040FF0C | (PXAFB_BPP_BITS << 24))
+#endif
+
+#elif defined (CONFIG_ARCH_PXA_IDP)
+#define LCD_PIXCLOCK			150000
+#define LCD_BPP				PXAFB_BPP
+#define LCD_XRES			640
+#define LCD_YRES			480
+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH	1
+#define LCD_VERTICAL_SYNC_PULSE_WIDTH	1
+#define LCD_BEGIN_OF_LINE_WAIT_COUNT	3
+#define LCD_BEGIN_FRAME_WAIT_COUNT 	0
+#define LCD_END_OF_LINE_WAIT_COUNT	3
+#define LCD_END_OF_FRAME_WAIT_COUNT	0
+#define LCD_SYNC			(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
+#define LCD_LCCR0			0x0030087C
+#define LCD_LCCR3 			(0x0040FF0C | (PXAFB_BPP_BITS << 24))
+
+#elif defined CONFIG_PXA_CERF_PDA
+#define LCD_PIXCLOCK			171521
+#define LCD_BPP				PXAFB_BPP
+#define LCD_XRES			240
+#define LCD_YRES			320
+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH	7
+#define LCD_VERTICAL_SYNC_PULSE_WIDTH	2
+#define LCD_BEGIN_OF_LINE_WAIT_COUNT	17
+#define LCD_BEGIN_FRAME_WAIT_COUNT 	0
+#define LCD_END_OF_LINE_WAIT_COUNT	17
+#define LCD_END_OF_FRAME_WAIT_COUNT	0
+#define LCD_SYNC			(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
+#define LCD_LCCR0			(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM  | LCCR0_OUM)
+#define LCD_LCCR3 			(LCCR3_PCP | LCCR3_PixClkDiv(0x12) | LCCR3_Bpp(PXAFB_BPP_BITS) | LCCR3_Acb(0x18))
+
+#endif
--- linux-2.4.25/drivers/video/sa1100fb.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/drivers/video/sa1100fb.c	2004-03-31 17:15:12.000000000 +0200
@@ -2175,7 +2175,7 @@
 	 */
 	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
 	fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
-					&fbi->map_dma);
+					&fbi->map_dma, PTE_BUFFERABLE);
 
 	if (fbi->map_cpu) {
 		fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
--- linux-2.4.25/fs/Config.in~2.4.25-vrs2-pxa1.patch	2004-02-18 14:36:31.000000000 +0100
+++ linux-2.4.25/fs/Config.in	2004-03-31 17:15:12.000000000 +0200
@@ -51,6 +51,9 @@
    int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
 fi
 tristate 'Compressed ROM file system support' CONFIG_CRAMFS
+dep_mbool '  Use linear addressing for cramfs' CONFIG_CRAMFS_LINEAR $CONFIG_CRAMFS
+dep_bool '    Support XIP on linear cramfs' CONFIG_CRAMFS_LINEAR_XIP $CONFIG_CRAMFS_LINEAR
+dep_bool '    Root file system on linear cramfs' CONFIG_ROOT_CRAMFS_LINEAR $CONFIG_CRAMFS_LINEAR
 bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
 define_bool CONFIG_RAMFS y
 
--- linux-2.4.25/fs/cramfs/inode.c~2.4.25-vrs2-pxa1.patch	2002-08-03 02:39:45.000000000 +0200
+++ linux-2.4.25/fs/cramfs/inode.c	2004-03-31 17:15:12.000000000 +0200
@@ -4,11 +4,29 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
- */
-
-/*
+ *
  * These are the VFS interfaces to the compressed rom filesystem.
  * The actual compression is based on zlib, see the other files.
+ *
+ * Linear Addressing code
+ * Copyright (C) 2000 Shane Nay.
+ *
+ *   Allows you to have a linearly addressed cramfs filesystem.
+ *   Saves the need for buffer, and the munging of the buffer.
+ *   Savings a bit over 32k with default PAGE_SIZE, BUFFER_SIZE
+ *   etc.  Usefull on embedded platform with ROM :-).
+ *
+ *   Downsides- Currently linear addressed cramfs partitions
+ *   don't co-exist with block cramfs partitions.
+ *
+ * 28-Dec-2000: XIP mode for linear cramfs
+ * Copyright (C) 2000 Robert Leslie <rob@mars.org>
+ *
+ * Dynamic allocation of linear cramfs space by Nicolas Pitre
+ * Copyright (C) 2003 Monta Vista Software, Inc.
+ *
+ *   Linear cramfs now requires that you pass the physaddr= parameter to
+ *   the mount process.  Allows for multiple linear cramfs partitions.
  */
 
 #include <linux/module.h>
@@ -16,10 +34,12 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/kernel.h>
 #include <linux/locks.h>
 #include <linux/blkdev.h>
 #include <linux/cramfs_fs.h>
 #include <asm/semaphore.h>
+#include <asm/io.h>
 
 #include <asm/uaccess.h>
 
@@ -28,6 +48,8 @@
 #define CRAMFS_SB_BLOCKS u.cramfs_sb.blocks
 #define CRAMFS_SB_FILES u.cramfs_sb.files
 #define CRAMFS_SB_FLAGS u.cramfs_sb.flags
+#define CRAMFS_SB_LINEAR_PHYS_ADDR u.cramfs_sb.linear_phys_addr
+#define CRAMFS_SB_LINEAR_VIRT_ADDR u.cramfs_sb.linear_virt_addr
 
 static struct super_operations cramfs_ops;
 static struct inode_operations cramfs_dir_inode_operations;
@@ -42,6 +64,74 @@
 #define CRAMINO(x)	((x)->offset?(x)->offset<<2:1)
 #define OFFSET(x)	((x)->i_ino)
 
+
+#ifdef CONFIG_CRAMFS_LINEAR_XIP
+
+static int cramfs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	unsigned long address, length;
+	struct inode *inode = file->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+
+	/* this is only used in the case of read-only maps for XIP */
+
+	if (vma->vm_flags & VM_WRITE)
+		return generic_file_mmap(file, vma);
+
+	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
+		return -EINVAL;
+
+	address  = PAGE_ALIGN(sb->CRAMFS_SB_LINEAR_PHYS_ADDR + OFFSET(inode));
+	address += vma->vm_pgoff << PAGE_SHIFT;
+
+	length = vma->vm_end - vma->vm_start;
+
+	if (length > inode->i_size)
+		length = inode->i_size;
+
+	length = PAGE_ALIGN(length);
+
+
+#if 0
+	/* Doing the following makes it slower and more broken.  bdl */
+	/*
+	 * Accessing memory above the top the kernel knows about or
+	 * through a file pointer that was marked O_SYNC will be
+	 * done non-cached.
+	 */
+	vma->vm_page_prot =
+		__pgprot((pgprot_val(vma->vm_page_prot) & ~_CACHE_MASK)
+			| _CACHE_UNCACHED);
+#endif
+
+	/*
+	 * Don't dump addresses that are not real memory to a core file.
+	 */
+	vma->vm_flags |= VM_IO;
+	flush_tlb_page(vma, address);
+	if (remap_page_range(vma->vm_start, address, length,
+			     vma->vm_page_prot))
+		return -EAGAIN;
+
+#ifdef DEBUG_CRAMFS_XIP
+	printk("cramfs_mmap: mapped %s at 0x%08lx, length %lu to vma 0x%08lx"
+		", page_prot 0x%08lx\n",
+		file->f_dentry->d_name.name, address, length,
+		vma->vm_start, pgprot_val(vma->vm_page_prot));
+#endif
+
+	return 0;
+}
+
+static struct file_operations cramfs_linear_xip_fops = {
+	read:	generic_file_read,
+	mmap:	cramfs_mmap,
+};
+
+#define CRAMFS_INODE_IS_XIP(x) ((x)->i_mode & S_ISVTX)
+
+#endif
+
 static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
 {
 	struct inode * inode = new_inode(sb);
@@ -60,7 +150,11 @@
 		   without -noleaf option. */
 		insert_inode_hash(inode);
 		if (S_ISREG(inode->i_mode)) {
+#ifdef CONFIG_CRAMFS_LINEAR_XIP
+			inode->i_fop = CRAMFS_INODE_IS_XIP(inode) ? &cramfs_linear_xip_fops : &generic_ro_fops;
+#else
 			inode->i_fop = &generic_ro_fops;
+#endif
 			inode->i_data.a_ops = &cramfs_aops;
 		} else if (S_ISDIR(inode->i_mode)) {
 			inode->i_op = &cramfs_dir_inode_operations;
@@ -76,6 +170,18 @@
 	return inode;
 }
 
+#ifdef CONFIG_CRAMFS_LINEAR
+/*
+ * Return a pointer to the block in the linearly addressed cramfs image.
+ */
+static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
+{
+	if (!len)
+		return NULL;
+	return (void*)(sb->CRAMFS_SB_LINEAR_VIRT_ADDR + offset);
+}
+
+#else /* Not linear addressing - aka regular block mode. */
 /*
  * We have our own block cache: don't fill up the buffer cache
  * with the rom-image, because the way the filesystem is set
@@ -186,23 +292,65 @@
 	}
 	return read_buffers[buffer] + offset;
 }
-
+#endif /* !CONFIG_CRAMFS_LINEAR */
 
 static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
 {
+#ifndef CONFIG_CRAMFS_LINEAR
 	int i;
+#else
+	char *p;
+#endif
 	struct cramfs_super super;
 	unsigned long root_offset;
 	struct super_block * retval = NULL;
 
-	set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 
+#ifndef CONFIG_CRAMFS_LINEAR
+
+	set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
+
 	/* Invalidate the read buffers on mount: think disk change.. */
 	for (i = 0; i < READ_BUFFERS; i++)
 		buffer_blocknr[i] = -1;
 
+#else
+
+	/*
+	 * The physical location of the cramfs image is specified as
+	 * a mount parameter.  This parameter is mandatory for obvious
+	 * reasons.  Some validation is made on the phys address but this
+	 * is not exhaustive and we count on the fact that someone using
+	 * this feature is supposed to know what he/she's doing.
+	 */
+	if (!data || !(p = strstr((char *)data, "physaddr="))) {
+		printk(KERN_ERR "cramfs: unknown physical address for linear cramfs image\n");
+		goto out;
+	}
+	sb->CRAMFS_SB_LINEAR_PHYS_ADDR = simple_strtoul(p + 9, NULL, 0);
+	if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR & (PAGE_SIZE-1)) {
+		printk(KERN_ERR "cramfs: physical address 0x%lx for linear cramfs isn't aligned to a page boundary\n",
+		       sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
+		goto out;
+	}
+	if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR == 0) {
+		printk(KERN_ERR "cramfs: physical address for linear cramfs image can't be 0\n");
+		goto out;
+	}
+	printk(KERN_INFO "cramfs: checking physical address 0x%lx for linear cramfs image\n",
+	       sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
+
+	/* Map only one page for now.  Will remap it when fs size is known. */
+	sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
+		ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, PAGE_SIZE);
+	if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
+		printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
+		goto out;
+	}
+#endif
+
 	down(&read_mutex);
 	/* Read the first block and get the superblock from it */
 	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
@@ -254,8 +402,26 @@
 	/* Set it all up.. */
 	sb->s_op = &cramfs_ops;
 	sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
+
+#ifdef CONFIG_CRAMFS_LINEAR
+	/* Remap the whole filesystem now */
+	iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
+	printk(KERN_INFO "cramfs: linear cramfs image appears to be %lu KB in size\n",
+	       sb->CRAMFS_SB_SIZE/1024);
+	sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
+		ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, sb->CRAMFS_SB_SIZE);
+	if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
+		printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
+		goto out;
+	}
+#endif
+
 	retval = sb;
 out:
+#ifdef CONFIG_CRAMFS_LINEAR
+	if (!retval && sb->CRAMFS_SB_LINEAR_VIRT_ADDR)
+		iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
+#endif
 	return retval;
 }
 
@@ -388,6 +554,18 @@
 
 	maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	bytes_filled = 0;
+#ifdef CONFIG_CRAMFS_LINEAR_XIP
+	if (page->index < maxblock && CRAMFS_INODE_IS_XIP(inode)) {
+		struct super_block *sb = inode->i_sb;
+		u32 blkptr_offset = PAGE_ALIGN(OFFSET(inode)) +
+				    page->index * PAGE_CACHE_SIZE;
+		memcpy( page_address(page),
+			(void*)(sb->CRAMFS_SB_LINEAR_VIRT_ADDR + blkptr_offset),
+			PAGE_CACHE_SIZE );
+		bytes_filled = PAGE_CACHE_SIZE;
+		pgdata = kmap(page);
+	} else
+#endif
 	if (page->index < maxblock) {
 		struct super_block *sb = inode->i_sb;
 		u32 blkptr_offset = OFFSET(inode) + page->index*4;
@@ -444,7 +622,11 @@
 	statfs:		cramfs_statfs,
 };
 
+#ifndef CONFIG_CRAMFS_LINEAR
 static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
+#else
+static DECLARE_FSTYPE(cramfs_fs_type, "cramfs", cramfs_read_super, 0);
+#endif
 
 static int __init init_cramfs_fs(void)
 {
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/fs/cramfs/mkcramfs.c	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,821 @@
+/*
+ * mkcramfs - make a cramfs file system, optionally with XIP files.
+ *
+ * Copyright (C) 1999-2001 Transmeta Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <getopt.h>
+#include <linux/cramfs_fs.h>
+#include <zlib.h>
+
+#define PAD_SIZE 512		/* only 0 and 512 supported by kernel */
+
+static const char *progname = "mkcramfs";
+
+/* N.B. If you change the disk format of cramfs, please update fs/cramfs/README. */
+
+/* Input status of 0 to print help and exit without an error. */
+static void usage(int status)
+{
+	FILE *stream = status ? stderr : stdout;
+
+	fprintf(stream, "usage: %s [-h] [-e edition] [-i file] [-n name] dirname outfile\n"
+		" -h         print this help\n"
+		" -E         make all warnings errors (non-zero exit status)\n"
+		" -e edition set edition number (part of fsid)\n"
+		" -i file    insert a file image into the filesystem (requires >= 2.4.0)\n"
+		" -n name    set name of cramfs filesystem\n"
+		" -p         pad by %d bytes for boot code\n"
+		" -s         sort directory entries (old option, ignored)\n"
+		" -x         make marked files eXecute In Place\n"
+		" -z         make explicit holes (requires >= 2.3.39)\n"
+		" dirname    root of the filesystem to be compressed\n"
+		" outfile    output file\n", progname, PAD_SIZE);
+
+	exit(status);
+}
+
+#define PAGE_SIZE (4096)
+#define PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
+#define ROM_OFFSET 0
+#define ROM_ALIGN(x) (PAGE_ALIGN((x) + ROM_OFFSET) - ROM_OFFSET)
+#define PAGE_CACHE_SIZE (4096)
+/* The kernel assumes PAGE_CACHE_SIZE as block size. */
+static unsigned int blksize = PAGE_CACHE_SIZE;
+static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */
+static int image_length = 0;
+
+/*
+ * If opt_holes is set, then mkcramfs can create explicit holes in the
+ * data, which saves 26 bytes per hole (which is a lot smaller a
+ * saving than most most filesystems).
+ *
+ * Note that kernels up to at least 2.3.39 don't support cramfs holes,
+ * which is why this is turned off by default.
+ */
+static int opt_edition = 0;
+static int opt_errors = 0;
+static int opt_holes = 0;
+static int opt_xip = 0;
+static int opt_pad = 0;
+static char *opt_image = NULL;
+static char *opt_name = NULL;
+
+static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid;
+
+#ifndef MIN
+# define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+/* In-core version of inode / directory entry. */
+struct entry {
+	/* stats */
+	char *name;
+	unsigned int mode, size, uid, gid;
+
+	/* FS data */
+	void *uncompressed;
+        /* points to other identical file */
+        struct entry *same;
+        unsigned int offset;            /* pointer to compressed data in archive */
+	unsigned int dir_offset;	/* Where in the archive is the directory entry? */
+
+	/* organization */
+	struct entry *child; /* null for non-directories and empty directories */
+	struct entry *next;
+};
+
+/*
+ * The longest file name component to allow for in the input directory tree.
+ * Ext2fs (and many others) allow up to 255 bytes.  A couple of filesystems
+ * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
+ * >255-byte names in the input directory tree given that such names get
+ * truncated to 255 bytes when written to cramfs.
+ */
+#define MAX_INPUT_NAMELEN 255
+
+static int find_identical_file(struct entry *orig,struct entry *newfile)
+{
+        if(orig==newfile) return 1;
+        if(!orig) return 0;
+        if(orig->size==newfile->size && orig->uncompressed && !memcmp(orig->uncompressed,newfile->uncompressed,orig->size)) {
+                newfile->same=orig;
+                return 1;
+        }
+        return find_identical_file(orig->child,newfile) ||
+                   find_identical_file(orig->next,newfile);
+}
+
+static void eliminate_doubles(struct entry *root,struct entry *orig) {
+        if(orig) {
+                if(orig->size && orig->uncompressed)
+			find_identical_file(root,orig);
+                eliminate_doubles(root,orig->child);
+                eliminate_doubles(root,orig->next);
+        }
+}
+
+/*
+ * We define our own sorting function instead of using alphasort which
+ * uses strcoll and changes ordering based on locale information.
+ */
+static int cramsort (const void *a, const void *b)
+{
+	return strcmp ((*(const struct dirent **) a)->d_name,
+		       (*(const struct dirent **) b)->d_name);
+}
+
+static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub)
+{
+	struct dirent **dirlist;
+	int totalsize = 0, dircount, dirindex;
+	char *path, *endpath;
+	size_t len = strlen(name);
+
+	/* Set up the path. */
+	/* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
+	path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1);
+	if (!path) {
+		perror(NULL);
+		exit(8);
+	}
+	memcpy(path, name, len);
+	endpath = path + len;
+	*endpath = '/';
+	endpath++;
+
+        /* read in the directory and sort */
+        dircount = scandir(name, &dirlist, 0, cramsort);
+
+	if (dircount < 0) {
+		perror(name);
+		exit(8);
+	}
+
+	/* process directory */
+	for (dirindex = 0; dirindex < dircount; dirindex++) {
+		struct dirent *dirent;
+		struct entry *entry;
+		struct stat st;
+		int size;
+		size_t namelen;
+
+		dirent = dirlist[dirindex];
+
+		/* Ignore "." and ".." - we won't be adding them to the archive */
+		if (dirent->d_name[0] == '.') {
+			if (dirent->d_name[1] == '\0')
+				continue;
+			if (dirent->d_name[1] == '.') {
+				if (dirent->d_name[2] == '\0')
+					continue;
+			}
+		}
+		namelen = strlen(dirent->d_name);
+		if (namelen > MAX_INPUT_NAMELEN) {
+			fprintf(stderr,
+				"Very long (%u bytes) filename `%s' found.\n"
+				" Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile.  Exiting.\n",
+				namelen, dirent->d_name);
+			exit(8);
+		}
+		memcpy(endpath, dirent->d_name, namelen + 1);
+
+		if (lstat(path, &st) < 0) {
+			perror(endpath);
+			warn_skip = 1;
+			continue;
+		}
+		entry = calloc(1, sizeof(struct entry));
+		if (!entry) {
+			perror(NULL);
+			exit(8);
+		}
+		entry->name = strdup(dirent->d_name);
+		if (!entry->name) {
+			perror(NULL);
+			exit(8);
+		}
+		if (namelen > 255) {
+			/* Can't happen when reading from ext2fs. */
+
+			/* TODO: we ought to avoid chopping in half
+			   multi-byte UTF8 characters. */
+			entry->name[namelen = 255] = '\0';
+			warn_namelen = 1;
+		}
+		entry->mode = st.st_mode;
+		entry->size = st.st_size;
+		entry->uid = st.st_uid;
+		if (entry->uid >= 1 << CRAMFS_UID_WIDTH)
+			warn_uid = 1;
+		entry->gid = st.st_gid;
+		if (entry->gid >= 1 << CRAMFS_GID_WIDTH)
+			/* TODO: We ought to replace with a default
+                           gid instead of truncating; otherwise there
+                           are security problems.  Maybe mode should
+                           be &= ~070.  Same goes for uid once Linux
+                           supports >16-bit uids. */
+			warn_gid = 1;
+		size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
+		*fslen_ub += size;
+		if (S_ISDIR(st.st_mode)) {
+			entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
+		} else if (S_ISREG(st.st_mode)) {
+			/* TODO: We ought to open files in do_compress, one
+			   at a time, instead of amassing all these memory
+			   maps during parse_directory (which don't get used
+			   until do_compress anyway).  As it is, we tend to
+			   get EMFILE errors (especially if mkcramfs is run
+			   by non-root).
+
+			   While we're at it, do analagously for symlinks
+			   (which would just save a little memory). */
+			int fd = open(path, O_RDONLY);
+			if (fd < 0) {
+				perror(path);
+				warn_skip = 1;
+				continue;
+			}
+			if (entry->size) {
+				if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) {
+					warn_size = 1;
+					entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
+				}
+
+				entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0);
+				if (-1 == (int) (long) entry->uncompressed) {
+					perror("mmap");
+					exit(8);
+				}
+			}
+			close(fd);
+		} else if (S_ISLNK(st.st_mode)) {
+			entry->uncompressed = malloc(entry->size);
+			if (!entry->uncompressed) {
+				perror(NULL);
+				exit(8);
+			}
+			if (readlink(path, entry->uncompressed, entry->size) < 0) {
+				perror(path);
+				warn_skip = 1;
+				continue;
+			}
+		} else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
+			/* maybe we should skip sockets */
+			entry->size = 0;
+		} else {
+			entry->size = st.st_rdev;
+			if (entry->size & -(1<<CRAMFS_SIZE_WIDTH))
+				warn_dev = 1;
+		}
+
+		if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
+			int blocks = ((entry->size - 1) / blksize + 1);
+
+			/* block pointers & data expansion allowance + data */
+			if(entry->size)
+				*fslen_ub += (4+26)*blocks + entry->size + 3;
+                }
+
+		if (opt_xip && entry->mode & S_ISVTX) {
+			/* worse case, depending on where the offsets falls,
+			 * a single XIP entry could expand the sizeof the
+			 * file system by 8k, since we're aligning the start
+			 * and end on page boundary.
+			 */
+			*fslen_ub += 2*PAGE_CACHE_SIZE;
+		}
+
+		/* Link it into the list */
+		*prev = entry;
+		prev = &entry->next;
+		totalsize += size;
+	}
+	free(path);
+	free(dirlist);		/* allocated by scandir() with malloc() */
+	return totalsize;
+}
+
+/* Returns sizeof(struct cramfs_super), which includes the root inode. */
+static unsigned int write_superblock(struct entry *root, char *base, int size)
+{
+	struct cramfs_super *super = (struct cramfs_super *) base;
+	unsigned int offset = sizeof(struct cramfs_super) + image_length;
+
+	if (opt_pad) {
+		offset += opt_pad;
+	}
+
+	super->magic = CRAMFS_MAGIC;
+	super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS;
+	if (opt_holes)
+		super->flags |= CRAMFS_FLAG_HOLES;
+	if (image_length > 0)
+		super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET;
+	super->size = size;
+	memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
+
+	super->fsid.crc = crc32(0L, Z_NULL, 0);
+	super->fsid.edition = opt_edition;
+	super->fsid.blocks = total_blocks;
+	super->fsid.files = total_nodes;
+
+	memset(super->name, 0x00, sizeof(super->name));
+	if (opt_name)
+		strncpy(super->name, opt_name, sizeof(super->name));
+	else
+		strncpy(super->name, "Compressed", sizeof(super->name));
+
+	super->root.mode = root->mode;
+	super->root.uid = root->uid;
+	super->root.gid = root->gid;
+	super->root.size = root->size;
+	super->root.offset = offset >> 2;
+
+	return offset;
+}
+
+static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
+{
+	struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
+#ifdef DEBUG
+	assert ((offset & 3) == 0);
+#endif /* DEBUG */
+	if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) {
+		fprintf(stderr, "filesystem too big.  Exiting.\n");
+		exit(8);
+	}
+	inode->offset = (offset >> 2);
+}
+
+
+/*
+ * We do a width-first printout of the directory
+ * entries, using a stack to remember the directories
+ * we've seen.
+ */
+#define MAXENTRIES (100)
+static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
+{
+	int stack_entries = 0;
+	struct entry *entry_stack[MAXENTRIES];
+
+	for (;;) {
+		int dir_start = stack_entries;
+		while (entry) {
+			struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset);
+			size_t len = strlen(entry->name);
+
+			entry->dir_offset = offset;
+
+			inode->mode = entry->mode;
+			inode->uid = entry->uid;
+			inode->gid = entry->gid;
+			inode->size = entry->size;
+			inode->offset = 0;
+			/* Non-empty directories, regfiles and symlinks will
+			   write over inode->offset later. */
+
+			offset += sizeof(struct cramfs_inode);
+			total_nodes++;	/* another node */
+			memcpy(base + offset, entry->name, len);
+			/* Pad up the name to a 4-byte boundary */
+			while (len & 3) {
+				*(base + offset + len) = '\0';
+				len++;
+			}
+			inode->namelen = len >> 2;
+			offset += len;
+
+			/* TODO: this may get it wrong for chars >= 0x80.
+			   Most filesystems use UTF8 encoding for filenames,
+			   whereas the console is a single-byte character
+			   set like iso-latin-1. */
+			printf("  %s\n", entry->name);
+			if (entry->child) {
+				if (stack_entries >= MAXENTRIES) {
+					fprintf(stderr, "Exceeded MAXENTRIES.  Raise this value in mkcramfs.c and recompile.  Exiting.\n");
+					exit(8);
+				}
+				entry_stack[stack_entries] = entry;
+				stack_entries++;
+			}
+			entry = entry->next;
+		}
+
+		/*
+		 * Reverse the order the stack entries pushed during
+                 * this directory, for a small optimization of disk
+                 * access in the created fs.  This change makes things
+                 * `ls -UR' order.
+		 */
+		{
+			struct entry **lo = entry_stack + dir_start;
+			struct entry **hi = entry_stack + stack_entries;
+			struct entry *tmp;
+
+			while (lo < --hi) {
+				tmp = *lo;
+				*lo++ = *hi;
+				*hi = tmp;
+			}
+		}
+
+		/* Pop a subdirectory entry from the stack, and recurse. */
+		if (!stack_entries)
+			break;
+		stack_entries--;
+		entry = entry_stack[stack_entries];
+
+		set_data_offset(entry, base, offset);
+		printf("'%s':\n", entry->name);
+		entry = entry->child;
+	}
+	return offset;
+}
+
+static int is_zero(char const *begin, unsigned len)
+{
+	if (opt_holes)
+		/* Returns non-zero iff the first LEN bytes from BEGIN are
+		   all NULs. */
+		return (len-- == 0 ||
+			(begin[0] == '\0' &&
+			 (len-- == 0 ||
+			  (begin[1] == '\0' &&
+			   (len-- == 0 ||
+			    (begin[2] == '\0' &&
+			     (len-- == 0 ||
+			      (begin[3] == '\0' &&
+			       memcmp(begin, begin + 4, len) == 0))))))));
+	else
+		/* Never create holes. */
+		return 0;
+}
+
+static unsigned int do_xip(char *base, unsigned int offset,
+			   char const *name, char *uncompressed,
+			   unsigned int size)
+{
+	unsigned int start, end;
+
+	/* align to page boundary */
+
+	start = ROM_ALIGN(offset);
+	memset(base + offset, 0, start - offset);
+
+	memcpy(base + start, uncompressed, size);
+
+	/* pad to page boundary */
+
+	end = ROM_ALIGN(start + size);
+	memset(base + start + size, 0, end - (start + size));
+
+	printf("XIP (%u+%u bytes)\toffset %u\t%s\n",
+	       size, (end - offset) - size, offset, name);
+
+	return end;
+}
+
+/*
+ * One 4-byte pointer per block and then the actual blocked
+ * output. The first block does not need an offset pointer,
+ * as it will start immediately after the pointer block;
+ * so the i'th pointer points to the end of the i'th block
+ * (i.e. the start of the (i+1)'th block or past EOF).
+ *
+ * Note that size > 0, as a zero-sized file wouldn't ever
+ * have gotten here in the first place.
+ */
+static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size)
+{
+	unsigned long original_size = size;
+	unsigned long original_offset = offset;
+	unsigned long new_size;
+	unsigned long blocks = (size - 1) / blksize + 1;
+	unsigned long curr = offset + 4 * blocks;
+	int change;
+
+	total_blocks += blocks;
+
+	do {
+		unsigned long len = 2 * blksize;
+		unsigned int input = size;
+		if (input > blksize)
+			input = blksize;
+		size -= input;
+		if (!is_zero (uncompressed, input)) {
+			compress(base + curr, &len, uncompressed, input);
+			curr += len;
+		}
+		uncompressed += input;
+
+		if (len > blksize*2) {
+			/* (I don't think this can happen with zlib.) */
+			printf("AIEEE: block \"compressed\" to > 2*blocklength (%ld)\n", len);
+			exit(8);
+		}
+
+		*(u32 *) (base + offset) = curr;
+		offset += 4;
+	} while (size);
+
+	curr = (curr + 3) & ~3;
+	new_size = curr - original_offset;
+	/* TODO: Arguably, original_size in these 2 lines should be
+	   st_blocks * 512.  But if you say that then perhaps
+	   administrative data should also be included in both. */
+	change = new_size - original_size;
+	printf("%6.2f%% (%+d bytes)\toffset %lu\t%s\n",
+	       (change * 100) / (double) original_size, change, original_offset, name);
+
+	return curr;
+}
+
+
+/*
+ * Traverse the entry tree, writing data for every item that has
+ * non-null entry->compressed (i.e. every symlink and non-empty
+ * regfile).
+ */
+static unsigned int write_data(struct entry *entry, char *base, unsigned int offset)
+{
+	do {
+		if (entry->uncompressed) {
+                        if(entry->same) {
+                                set_data_offset(entry, base, entry->same->offset);
+                                entry->offset=entry->same->offset;
+                        } else {
+                                set_data_offset(entry, base, offset);
+                                entry->offset=offset;
+				if (opt_xip && entry->mode & S_ISVTX)
+					offset = do_xip(base, offset, entry->name, entry->uncompressed, entry->size);
+				else
+                                offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size);
+                        }
+		}
+		else if (entry->child)
+			offset = write_data(entry->child, base, offset);
+                entry=entry->next;
+	} while (entry);
+	return offset;
+}
+
+static unsigned int write_file(char *file, char *base, unsigned int offset)
+{
+	int fd;
+	char *buf;
+
+	fd = open(file, O_RDONLY);
+	if (fd < 0) {
+		perror(file);
+		exit(8);
+	}
+	buf = mmap(NULL, image_length, PROT_READ, MAP_PRIVATE, fd, 0);
+	memcpy(base + offset, buf, image_length);
+	munmap(buf, image_length);
+	close (fd);
+	/* Pad up the image_length to a 4-byte boundary */
+	while (image_length & 3) {
+		*(base + offset + image_length) = '\0';
+		image_length++;
+	}
+	return (offset + image_length);
+}
+
+/*
+ * Maximum size fs you can create is roughly 256MB.  (The last file's
+ * data must begin within 256MB boundary but can extend beyond that.)
+ *
+ * Note that if you want it to fit in a ROM then you're limited to what the
+ * hardware and kernel can support (64MB?).
+ */
+#define MAXFSLEN ((((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */ \
+		  + (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */ \
+		  + (1 << CRAMFS_SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ )
+
+
+/*
+ * Usage:
+ *
+ *      mkcramfs directory-name outfile
+ *
+ * where "directory-name" is simply the root of the directory
+ * tree that we want to generate a compressed filesystem out
+ * of.
+ */
+int main(int argc, char **argv)
+{
+	struct stat st;		/* used twice... */
+	struct entry *root_entry;
+	char *rom_image;
+	ssize_t offset, written;
+	int fd;
+	/* initial guess (upper-bound) of required filesystem size */
+	loff_t fslen_ub = sizeof(struct cramfs_super);
+	char const *dirname, *outfile;
+	u32 crc = crc32(0L, Z_NULL, 0);
+	int c;			/* for getopt */
+
+	total_blocks = 0;
+
+	if (argc)
+		progname = argv[0];
+
+	/* command line options */
+	while ((c = getopt(argc, argv, "hEe:i:n:psxz")) != EOF) {
+		switch (c) {
+		case 'h':
+			usage(0);
+		case 'E':
+			opt_errors = 1;
+			break;
+		case 'e':
+			opt_edition = atoi(optarg);
+			break;
+		case 'i':
+			opt_image = optarg;
+			if (lstat(opt_image, &st) < 0) {
+				perror(opt_image);
+				exit(16);
+			}
+			image_length = st.st_size; /* may be padded later */
+			fslen_ub += (image_length + 3); /* 3 is for padding */
+			break;
+		case 'n':
+			opt_name = optarg;
+			break;
+		case 'p':
+			opt_pad = PAD_SIZE;
+			fslen_ub += PAD_SIZE;
+			break;
+		case 's':
+			/* old option, ignored */
+			break;
+		case 'x':
+			opt_xip = 1;
+			break;
+		case 'z':
+			opt_holes = 1;
+			break;
+		}
+	}
+
+	if ((argc - optind) != 2)
+		usage(16);
+	dirname = argv[optind];
+	outfile = argv[optind + 1];
+
+	if (stat(dirname, &st) < 0) {
+		perror(dirname);
+		exit(16);
+	}
+	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+	root_entry = calloc(1, sizeof(struct entry));
+	if (!root_entry) {
+		perror(NULL);
+		exit(8);
+	}
+	root_entry->mode = st.st_mode;
+	root_entry->uid = st.st_uid;
+	root_entry->gid = st.st_gid;
+
+	root_entry->size = parse_directory(root_entry, dirname, &root_entry->child, &fslen_ub);
+
+	/* always allocate a multiple of blksize bytes because that's
+           what we're going to write later on */
+	fslen_ub = ((fslen_ub - 1) | (blksize - 1)) + 1;
+
+	if (fslen_ub > MAXFSLEN) {
+		fprintf(stderr,
+			"warning: guestimate of required size (upper bound) is %LdMB, but maximum image size is %uMB.  We might die prematurely.\n",
+			fslen_ub >> 20,
+			MAXFSLEN >> 20);
+		fslen_ub = MAXFSLEN;
+	}
+
+        /* find duplicate files. TODO: uses the most inefficient algorithm
+           possible. */
+        eliminate_doubles(root_entry,root_entry);
+
+	/* TODO: Why do we use a private/anonymous mapping here
+           followed by a write below, instead of just a shared mapping
+           and a couple of ftruncate calls?  Is it just to save us
+           having to deal with removing the file afterwards?  If we
+           really need this huge anonymous mapping, we ought to mmap
+           in smaller chunks, so that the user doesn't need nn MB of
+           RAM free.  If the reason is to be able to write to
+           un-mmappable block devices, then we could try shared mmap
+           and revert to anonymous mmap if the shared mmap fails. */
+	rom_image = mmap(NULL, fslen_ub?fslen_ub:1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+	if (-1 == (int) (long) rom_image) {
+		perror("ROM image map");
+		exit(8);
+	}
+
+	/* Skip the first opt_pad bytes for boot loader code */
+	offset = opt_pad;
+	memset(rom_image, 0x00, opt_pad);
+
+	/* Skip the superblock and come back to write it later. */
+	offset += sizeof(struct cramfs_super);
+
+	/* Insert a file image. */
+	if (opt_image) {
+		printf("Including: %s\n", opt_image);
+		offset = write_file(opt_image, rom_image, offset);
+	}
+
+	offset = write_directory_structure(root_entry->child, rom_image, offset);
+	printf("Directory data: %d bytes\n", offset);
+
+	offset = write_data(root_entry, rom_image, offset);
+
+	/* We always write a multiple of blksize bytes, so that
+           losetup works. */
+	offset = ((offset - 1) | (blksize - 1)) + 1;
+	printf("Everything: %d kilobytes\n", offset >> 10);
+
+	/* Write the superblock now that we can fill in all of the fields. */
+	write_superblock(root_entry, rom_image+opt_pad, offset);
+	printf("Super block: %d bytes\n", sizeof(struct cramfs_super));
+
+	/* Put the checksum in. */
+	crc = crc32(crc, (rom_image+opt_pad), (offset-opt_pad));
+	((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc;
+	printf("CRC: %x\n", crc);
+
+	/* Check to make sure we allocated enough space. */
+	if (fslen_ub < offset) {
+		fprintf(stderr, "not enough space allocated for ROM image (%Ld allocated, %d used)\n",
+			fslen_ub, offset);
+		exit(8);
+	}
+
+	written = write(fd, rom_image, offset);
+	if (written < 0) {
+		perror("ROM image");
+		exit(8);
+	}
+	if (offset != written) {
+		fprintf(stderr, "ROM image write failed (%d %d)\n", written, offset);
+		exit(8);
+	}
+
+	/* (These warnings used to come at the start, but they scroll off the
+           screen too quickly.) */
+	if (warn_namelen) /* (can't happen when reading from ext2fs) */
+		fprintf(stderr, /* bytes, not chars: think UTF8. */
+			"warning: filenames truncated to 255 bytes.\n");
+	if (warn_skip)
+		fprintf(stderr, "warning: files were skipped due to errors.\n");
+	if (warn_size)
+		fprintf(stderr,
+			"warning: file sizes truncated to %luMB (minus 1 byte).\n",
+			1L << (CRAMFS_SIZE_WIDTH - 20));
+	if (warn_uid) /* (not possible with current Linux versions) */
+		fprintf(stderr,
+			"warning: uids truncated to %u bits.  (This may be a security concern.)\n",
+			CRAMFS_UID_WIDTH);
+	if (warn_gid)
+		fprintf(stderr,
+			"warning: gids truncated to %u bits.  (This may be a security concern.)\n",
+			CRAMFS_GID_WIDTH);
+	if (warn_dev)
+		fprintf(stderr,
+			"WARNING: device numbers truncated to %u bits.  This almost certainly means\n"
+			"that some device files will be wrong.\n",
+			CRAMFS_OFFSET_WIDTH);
+	if (opt_errors &&
+	    (warn_namelen||warn_skip||warn_size||warn_uid||warn_gid||warn_dev))
+		exit(8);
+	return 0;
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/bitfield.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,113 @@
+/*
+ *	FILE    	bitfield.h
+ *
+ *	Version 	1.1
+ *	Author  	Copyright (c) Marc A. Viredaz, 1998
+ *	        	DEC Western Research Laboratory, Palo Alto, CA
+ *	Date    	April 1998 (April 1997)
+ *	System  	Advanced RISC Machine (ARM)
+ *	Language	C or ARM Assembly
+ *	Purpose 	Definition of macros to operate on bit fields.
+ */
+
+
+
+#ifndef __BITFIELD_H
+#define __BITFIELD_H
+
+#ifndef __ASSEMBLY__
+#define UData(Data)	((unsigned long) (Data))
+#else
+#define UData(Data)	(Data)
+#endif
+
+
+/*
+ * MACRO: Fld
+ *
+ * Purpose
+ *    The macro "Fld" encodes a bit field, given its size and its shift value
+ *    with respect to bit 0.
+ *
+ * Note
+ *    A more intuitive way to encode bit fields would have been to use their
+ *    mask. However, extracting size and shift value information from a bit
+ *    field's mask is cumbersome and might break the assembler (255-character
+ *    line-size limit).
+ *
+ * Input
+ *    Size      	Size of the bit field, in number of bits.
+ *    Shft      	Shift value of the bit field with respect to bit 0.
+ *
+ * Output
+ *    Fld       	Encoded bit field.
+ */
+
+#define Fld(Size, Shft)	(((Size) << 16) + (Shft))
+
+
+/*
+ * MACROS: FSize, FShft, FMsk, FAlnMsk, F1stBit
+ *
+ * Purpose
+ *    The macros "FSize", "FShft", "FMsk", "FAlnMsk", and "F1stBit" return
+ *    the size, shift value, mask, aligned mask, and first bit of a
+ *    bit field.
+ *
+ * Input
+ *    Field     	Encoded bit field (using the macro "Fld").
+ *
+ * Output
+ *    FSize     	Size of the bit field, in number of bits.
+ *    FShft     	Shift value of the bit field with respect to bit 0.
+ *    FMsk      	Mask for the bit field.
+ *    FAlnMsk   	Mask for the bit field, aligned on bit 0.
+ *    F1stBit   	First bit of the bit field.
+ */
+
+#define FSize(Field)	((Field) >> 16)
+#define FShft(Field)	((Field) & 0x0000FFFF)
+#define FMsk(Field)	(((UData (1) << FSize (Field)) - 1) << FShft (Field))
+#define FAlnMsk(Field)	((UData (1) << FSize (Field)) - 1)
+#define F1stBit(Field)	(UData (1) << FShft (Field))
+
+
+/*
+ * MACRO: FInsrt
+ *
+ * Purpose
+ *    The macro "FInsrt" inserts a value into a bit field by shifting the
+ *    former appropriately.
+ *
+ * Input
+ *    Value     	Bit-field value.
+ *    Field     	Encoded bit field (using the macro "Fld").
+ *
+ * Output
+ *    FInsrt    	Bit-field value positioned appropriately.
+ */
+
+#define FInsrt(Value, Field) \
+                	(UData (Value) << FShft (Field))
+
+
+/*
+ * MACRO: FExtr
+ *
+ * Purpose
+ *    The macro "FExtr" extracts the value of a bit field by masking and
+ *    shifting it appropriately.
+ *
+ * Input
+ *    Data      	Data containing the bit-field to be extracted.
+ *    Field     	Encoded bit field (using the macro "Fld").
+ *
+ * Output
+ *    FExtr     	Bit-field value.
+ */
+
+#define FExtr(Data, Field) \
+                	((UData (Data) >> FShft (Field)) & FAlnMsk (Field))
+
+
+#endif /* __BITFIELD_H */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/cerf.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,177 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/cerf.h
+ *
+ *  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.
+ */
+
+/*
+ * Add CerfBoard Specifics here...
+ */
+
+/*
+ * Memory sizes
+ */
+
+#define CERF_RAM_BASE			0xa0000000
+
+#ifdef CONFIG_PXA_CERF_RAM_128MB
+#define CERF_RAM_SIZE			128*1024*1024
+
+#elif defined (CONFIG_PXA_CERF_RAM_64MB)
+#define CERF_RAM_SIZE			64*1024*1024
+
+#elif defined (CONFIG_PXA_CERF_RAM_32MB)
+#define CERF_RAM_SIZE			32*1024*1024
+
+#elif defined (CONFIG_PXA_CERF_RAM_16MB)
+#define CERF_RAM_SIZE			16*1024*1024
+#endif
+
+/*
+ * CS memory timing via Static Memory Control Register (MSC0-2)
+ */
+
+#define MSC_CS(cs,val) ((val)<<((cs&1)<<4))
+
+#define MSC_RBUFF_SHIFT 15 
+#define MSC_RBUFF_SLOW (0)
+#define MSC_RBUFF_FAST (1)
+#define MSC_RBUFF(x) ((x)<<MSC_RBUFF_SHIFT)
+
+#define MSC_RRR_SHIFT 12
+#define MSC_RRR(x) ((x)<<MSC_RRR_SHIFT)
+
+#define MSC_RDN_SHIFT 8
+#define MSC_RDN(x) ((x)<<MSC_RDN_SHIFT)
+
+#define MSC_RDF_SHIFT 4
+#define MSC_RDF(x) ((x)<<MSC_RDF_SHIFT)
+
+#define MSC_RBW_SHIFT 3
+#define MSC_RBW(x) ((x)<<MSC_RBW_SHIFT)
+
+#define MSC_RT_SHIFT  0
+#define MSC_RT(x) ((x)<<MSC_RT_SHIFT)
+
+/*
+ * IO Pins for devices
+ */
+
+#define CERF_FLASH_BASE			0xe8000000
+#define CERF_FLASH_SIZE			0x02000000
+#define CERF_FLASH_PHYS			PXA_CS0_PHYS
+
+#define CERF_ETH_BASE			0xf0000000
+#define CERF_ETH_SIZE			0x00100000
+#define CERF_ETH_PHYS			PXA_CS1_PHYS
+
+#define CERF_BT_BASE			0xf2000000
+#define CERF_BT_SIZE			0x00100000
+#define CERF_BT_PHYS			PXA_CS2_PHYS
+
+#define CERF_SERIAL_BASE		0xf3000000
+#define CERF_SERIAL_SIZE		0x00100000
+#define CERF_SERIAL_PHYS		PXA_CS3_PHYS
+
+#define CERF_CPLD_BASE			0xf1000000
+#define CERF_CPLD_SIZE			0x00100000
+#define CERF_CPLD_PHYS			PXA_CS4_PHYS
+
+#define CERF_PDA_CPLD_WRCLRINT		(0x0)
+#define CERF_PDA_CPLD_BRIGHTNESS	(0x2)
+#define CERF_PDA_CPLD_KEYPAD_A		(0x6)
+#define CERF_PDA_CPLD_BATTFAULT		(0x8)
+#define CERF_PDA_CPLD_KEYPAD_B		(0xa)
+#define CERF_PDA_CPLD_SOUND_ENA		(0xc)
+
+#define CERF_PDA_SOUND_ENABLE		0x1
+#define CERF_PDA_DEFAULT_BRIGHTNESS	0x9
+
+/*
+ * Access functions (registers are 4-bit wide)
+ */
+
+#define CERF_PDA_CPLD CERF_CPLD_BASE
+
+#define CERF_PDA_CPLD_Get(x, y)      (*((char*)(CERF_PDA_CPLD + (x))) & (y))
+#define CERF_PDA_CPLD_Set(x, y, z)   (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) | (y))
+#define CERF_PDA_CPLD_UnSet(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) & ~(y))
+
+/* 
+ * IO and IRQ settings for cs8900 ethernet chip
+ */
+#define CERF_ETH_IO		CERF_ETH_BASE
+#define CERF_ETH_IRQ 		GPIO_2_80_TO_IRQ(21)
+
+/*
+ * We only have one LED on the XScale CerfPDA so only the
+ * time or idle should ever be selected.
+ */
+#define CERF_HEARTBEAT_LED 0x1
+#define CERF_SYS_BUSY_LED  0x2
+
+#define CERF_HEARTBEAT_LED_GPIO	16 // GPIO 4
+#define CERF_SYS_BUSY_LED_GPIO	16 // GPIO 4
+
+#define CERF_HEARTBEAT_LED_ON  (GPSR0 = CERF_HEARTBEAT_LED_GPIO)
+#define CERF_HEARTBEAT_LED_OFF (GPCR0 = CERF_HEARTBEAT_LED_GPIO)
+#define CERF_SYS_BUSY_LED_ON  (GPSR0 = CERF_SYS_BUSY_LED_GPIO)
+#define CERF_SYS_BUSY_LED_OFF (GPCR0 = CERF_SYS_BUSY_LED_GPIO)
+
+/*
+ * UCB 1400 gpio
+ */
+
+#define CERF_GPIO_UCB1400_IRQ 32
+
+#define UCB_IO_0                (1 << 0)
+#define UCB_IO_1                (1 << 1)
+#define UCB_IO_2                (1 << 2)
+#define UCB_IO_3                (1 << 3)
+#define UCB_IO_4                (1 << 4)
+#define UCB_IO_5                (1 << 5)
+#define UCB_IO_6                (1 << 6)
+#define UCB_IO_7                (1 << 7)
+#define UCB_IO_8                (1 << 8)
+#define UCB_IO_9                (1 << 9)
+
+#define UCB1400_GPIO_CONT_CS      UCB_IO_0
+#define UCB1400_GPIO_CONT_DOWN    UCB_IO_1
+#define UCB1400_GPIO_CONT_INC     UCB_IO_2
+#define UCB1400_GPIO_CONT_ENA     UCB_IO_3
+#define UCB1400_GPIO_LCD_RESET    UCB_IO_4
+#define UCB1400_GPIO_IRDA_ENABLE  UCB_IO_5
+#define UCB1400_GPIO_BT_ENABLE    UCB_IO_6
+#define UCB1400_GPIO_TEST_P1      UCB_IO_7
+#define UCB1400_GPIO_TEST_P2      UCB_IO_8
+#define UCB1400_GPIO_TEST_P3      UCB_IO_9
+
+/*
+ * IRQ for devices
+ */
+#define UCB1400_IRQ(x)          (NR_IRQS + 1 + (x))
+
+#define IRQ_UCB1400_IO0         UCB1400_IRQ(0)
+#define IRQ_UCB1400_IO1         UCB1400_IRQ(1)
+#define IRQ_UCB1400_IO2         UCB1400_IRQ(2)
+#define IRQ_UCB1400_IO3         UCB1400_IRQ(3)
+#define IRQ_UCB1400_IO4         UCB1400_IRQ(4)
+#define IRQ_UCB1400_IO5         UCB1400_IRQ(5)
+#define IRQ_UCB1400_IO6         UCB1400_IRQ(6)
+#define IRQ_UCB1400_IO7         UCB1400_IRQ(7)
+#define IRQ_UCB1400_IO8         UCB1400_IRQ(8)
+#define IRQ_UCB1400_IO9         UCB1400_IRQ(9)
+
+#define IRQ_UCB1400_CONT_CS     IRQ_UCB1400_IO0
+#define IRQ_UCB1400_CONT_DOWN   IRQ_UCB1400_IO1
+#define IRQ_UCB1400_CONT_INC    IRQ_UCB1400_IO2
+#define IRQ_UCB1400_CONT_ENA    IRQ_UCB1400_IO3
+#define IRQ_UCB1400_LCD_RESET   IRQ_UCB1400_IO4
+#define IRQ_UCB1400_IRDA_ENABLE IRQ_UCB1400_IO5
+#define IRQ_UCB1400_BT_ENABLE   IRQ_UCB1400_IO6
+#define IRQ_UCB1400_TEST_P1     IRQ_UCB1400_IO7
+#define IRQ_UCB1400_TEST_P2     IRQ_UCB1400_IO8
+#define IRQ_UCB1400_TEST_P3     IRQ_UCB1400_IO9
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/cerf_ucb1400gpio.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,30 @@
+/*
+ *  cerf_ucb1400gpio.h
+ *
+ *  UCB1400 GPIO control stuff for the cerf.
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Mar 2002: Initial version [FB]
+ * 
+ */
+/* -- lcd -- */
+extern void cerf_ucb1400gpio_lcd_enable( void);
+extern void cerf_ucb1400gpio_lcd_disable( void);
+extern void cerf_ucb1400gpio_lcd_contrast_step( int direction);
+
+/* -- irda -- */
+extern void cerf_ucb1400gpio_irda_enable( void);
+extern void cerf_ucb1400gpio_irda_disable( void);
+
+/* -- bt -- */
+extern void cerf_ucb1400gpio_bt_enable( void);
+extern void cerf_ucb1400gpio_bt_disable( void);
+
+/* -- init -- */
+extern int cerf_ucb1400gpio_init(void);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/csb226.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,99 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/csb226.h
+ *
+ *  Author:	Robert Schwebel (stolen from lubbock.h)
+ *  Created:	Oct 30, 2002
+ *  Copyright:	Pengutronix
+ *  
+ * 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.
+ */
+
+#define CSB226_FPGA_PHYS	PXA_CS2_PHYS    
+
+#define CSB226_FPGA_VIRT	(0xf0000000)	/* phys 0x08000000 */
+#define CSB226_ETH_BASE		(0xf1000000)	/* phys 0x0c000000 */
+
+#define CSB226_P2V(x)		((x) - CSB226_FPGA_PHYS + CSB226_FPGA_VIRT)
+#define CSB226_V2P(x)		((x) - CSB226_FPGA_VIRT + CSB226_FPGA_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __CSB226_REG(x)	(*((volatile unsigned long *)CSB226_P2V(x)))
+#else
+#  define __CSB226_REG(x)	CSB226_P2V(x)
+#endif
+
+
+/* register physical addresses */
+#define _CSB226_MISC_WR		(CSB226_FPGA_PHYS + 0x080)
+#define _CSB226_MISC_RD		(CSB226_FPGA_PHYS + 0x090)
+#define _CSB226_IRQ_MASK_EN	(CSB226_FPGA_PHYS + 0x0C0)
+#define _CSB226_IRQ_SET_CLR	(CSB226_FPGA_PHYS + 0x0D0)
+#define _CSB226_GP		(CSB226_FPGA_PHYS + 0x100)
+
+
+
+/* register virtual addresses */
+
+#define CSB226_MISC_WR             __CSB226_REG(_CSB226_MISC_WR) 
+#define CSB226_MISC_RD             __CSB226_REG(_CSB226_MISC_RD)         
+#define CSB226_IRQ_MASK_EN         __CSB226_REG(_CSB226_IRQ_MASK_EN)
+#define CSB226_IRQ_SET_CLR         __CSB226_REG(_CSB226_IRQ_SET_CLR)             
+#define CSB226_GP                  __CSB226_REG(_CSB226_GP)      
+
+
+/* GPIOs */
+
+#define GPIO_CSB226_IRQ		0
+#define IRQ_GPIO_CSB226_IRQ	IRQ_GPIO0
+
+
+/*
+ * LED macros
+ */
+
+// #define LEDS_BASE LUB_DISC_BLNK_LED
+
+// 8 discrete leds available for general use:
+
+/*
+#define D28	0x1
+#define D27	0x2
+#define D26	0x4
+#define D25	0x8
+#define D24	0x10
+#define D23	0x20
+#define D22	0x40
+#define D21	0x80
+*/
+
+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
+*  be sure to not monkey with them here.
+*/
+
+/*
+#define HEARTBEAT_LED	D28
+#define SYS_BUSY_LED    D27
+#define HEXLEDS_BASE LUB_HEXLED
+
+#define HEARTBEAT_LED_ON  (LEDS_BASE &= ~HEARTBEAT_LED)
+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
+#define SYS_BUSY_LED_OFF  (LEDS_BASE |= SYS_BUSY_LED)
+#define SYS_BUSY_LED_ON   (LEDS_BASE &= ~SYS_BUSY_LED)
+
+// use x = D26-D21 for these, please...
+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
+*/
+
+#ifndef __ASSEMBLY__
+
+//extern int hexled_val = 0;
+
+#endif
+
+/*
+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
+*/
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/dma.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/dma.h
+ *  
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software, 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.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+/* No DMA as the rest of the world see it */
+#define MAX_DMA_CHANNELS	0
+
+/*
+ * Descriptor structure for PXA's DMA engine
+ * Note: this structure must always be aligned to a 16-byte boundary.
+ */
+
+typedef struct {
+	volatile u32 ddadr;	/* Points to the next descriptor + flags */
+	volatile u32 dsadr;	/* DSADR value for the current transfer */
+	volatile u32 dtadr;	/* DTADR value for the current transfer */
+	volatile u32 dcmd;	/* DCMD value for the current transfer */
+} pxa_dma_desc;
+
+/*
+ * DMA registration
+ */
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 4,
+	DMA_PRIO_LOW = 8
+} pxa_dma_prio;
+
+int pxa_request_dma (char *name,
+			 pxa_dma_prio prio,
+			 void (*irq_handler)(int, void *, struct pt_regs *),
+			 void *data);
+
+void pxa_free_dma (int dma_ch);
+
+#endif /* _ASM_ARCH_DMA_H */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/hardware.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,142 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/hardware.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * These are statically mapped PCMCIA IO space for designs using it as a
+ * generic IO bus, typically with ISA parts, hardwired IDE interfaces, etc.
+ * The actual PCMCIA code is mapping required IO region at run time.
+ */
+#define PCMCIA_IO_0_BASE	0xf6000000
+#define PCMCIA_IO_1_BASE	0xf7000000
+
+
+/*
+ * XIP kernel text mapping.
+ * Note: the exact virtual address is also specified in arch/arm/Makefile.
+ */
+#ifdef CONFIG_XIP_KERNEL
+#define KERNEL_XIP_BASE_PHYS	(CONFIG_XIP_PHYS_ADDR & 0xffe00000)
+#define KERNEL_XIP_BASE_VIRT	0xe8000000
+#endif
+
+
+/*
+ * We requires absolute addresses.
+ */
+#define PCIO_BASE		0
+
+/*
+ * Workarounds for at least 2 errata so far require this.
+ * The mapping is set in mach-pxa/generic.c.
+ */
+#define UNCACHED_PHYS_0		0xff000000
+#define UNCACHED_ADDR		UNCACHED_PHYS_0
+
+/*
+ * Intel PXA internal I/O mappings:
+ *
+ * 0x40000000 - 0x41ffffff <--> 0xf8000000 - 0xf9ffffff
+ * 0x44000000 - 0x45ffffff <--> 0xfa000000 - 0xfbffffff
+ * 0x48000000 - 0x49ffffff <--> 0xfc000000 - 0xfdffffff
+ */
+
+#define io_p2v(x)	( ((x) | 0xbe000000) ^ (~((x) >> 1) & 0x06000000) )
+#define io_v2p( x )	( ((x) & 0x41ffffff) ^ ( ((x) & 0x06000000) << 1) )
+
+#ifndef __ASSEMBLY__
+
+#if 0
+# define __REG(x)	(*((volatile u32 *)io_p2v(x)))
+#else
+/*
+ * This __REG() version gives the same results as the one above,  except
+ * that we are fooling gcc somehow so it generates far better and smaller
+ * assembly code for access to contigous registers.  It's a shame that gcc
+ * doesn't guess this by itself.
+ */
+#include <asm/types.h>
+typedef struct { volatile u32 offset[4096]; } __regbase;
+# define __REGP(x)	((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
+# define __REG(x)	__REGP(io_p2v(x))
+#endif
+
+/* Let's kick gcc's ass again... */
+# define __REG2(x,y)	\
+	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
+				  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+
+# define __PREG(x)	(io_v2p((u32)&(x)))
+
+#else
+
+# define __REG(x)	io_p2v(x)
+# define __PREG(x)	io_v2p(x)
+
+#endif
+
+#include "pxa-regs.h"
+
+#ifndef __ASSEMBLY__
+
+/*
+ * GPIO edge detection for IRQs:
+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+ * This must be called *before* the corresponding IRQ is registered.
+ * Use this instead of directly setting GRER/GFER.
+ */
+#define GPIO_FALLING_EDGE       1
+#define GPIO_RISING_EDGE        2
+#define GPIO_BOTH_EDGES         3
+extern void set_GPIO_IRQ_edge( int gpio_nr, int edge_mask );
+
+/*
+ * Handy routine to set GPIO alternate functions
+ */
+extern void set_GPIO_mode( int gpio_mode );
+
+/*
+ * return current lclk frequency in units of 10kHz
+ */
+extern unsigned int get_lclk_frequency_10khz(void);
+
+/*
+ * return current clk frequency in units of 1kHz
+ */
+extern unsigned int get_clk_frequency_khz( int info);
+
+#endif
+
+
+/*
+ * Implementation specifics
+ */
+
+//#ifdef CONFIG_ARCH_LUBBOCK
+#include "lubbock.h"
+//#endif
+
+//#ifdef CONFIG_ARCH_PXA_IDP
+#include "idp.h"
+//#endif
+
+//#ifdef CONFIG_ARCH_PXA_CERF
+#include "cerf.h"
+//#endif
+
+#endif  /* _ASM_ARCH_HARDWARE_H */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/ide.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,59 @@
+/*
+ * linux/include/asm-arm/arch-pxa/ide.h
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software 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.
+ *
+ *
+ * Originally based upon linux/include/asm-arm/arch-sa1100/ide.h
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
+{
+	ide_ioreg_t reg;
+
+	memset(hw, 0, sizeof(*hw));
+
+	reg = (ide_ioreg_t)data_port;
+
+	hw->io_ports[IDE_DATA_OFFSET] =  reg + 0;
+	hw->io_ports[IDE_ERROR_OFFSET] = reg + 1;
+	hw->io_ports[IDE_NSECTOR_OFFSET] = reg + 2;
+	hw->io_ports[IDE_SECTOR_OFFSET] = reg + 3;
+	hw->io_ports[IDE_LCYL_OFFSET] = reg + 4;
+	hw->io_ports[IDE_HCYL_OFFSET] = reg + 5;
+	hw->io_ports[IDE_SELECT_OFFSET] = reg + 6;
+	hw->io_ports[IDE_STATUS_OFFSET] = reg + 7;
+
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+
+	if (irq)
+		*irq = 0;
+}
+
+
+/*
+ * Register the standard ports for this architecture with the IDE driver.
+ */
+static __inline__ void
+ide_init_default_hwifs(void)
+{
+	/* Nothing to declare... */
+}
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/idp.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,468 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/idp.h
+ *
+ * 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.
+ *
+ * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
+ *
+ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
+ *             Initial code
+ * 
+ */
+
+
+/*
+ * Note: this file must be safe to include in assembly files
+ */
+
+/* comment out following if you have a rev01 board */
+#define PXA_IDP_REV02	1
+//#undef PXA_IDP_REV02
+
+#ifdef PXA_IDP_REV02
+
+//Use this as well for 0017-x004 and greater pcb's:
+#define PXA_IDP_REV04 1
+
+#define IDP_FLASH_PHYS		(PXA_CS0_PHYS)
+#define IDP_ALT_FLASH_PHYS	(PXA_CS1_PHYS)
+#define IDP_MEDIAQ_PHYS		(PXA_CS3_PHYS)
+#define IDP_IDE_PHYS		(PXA_CS5_PHYS + 0x03000000)
+#define IDP_ETH_PHYS		(PXA_CS5_PHYS + 0x03400000)
+#define IDP_COREVOLT_PHYS	(PXA_CS5_PHYS + 0x03800000)
+#define IDP_CPLD_PHYS		(PXA_CS5_PHYS + 0x03C00000)
+
+
+/*
+ * virtual memory map
+ */
+
+#define IDP_IDE_BASE		(0xf0000000)
+#define IDP_IDE_SIZE		(1*1024*1024)
+
+#define IDP_ETH_BASE		(IDP_IDE_BASE + IDP_IDE_SIZE)
+#define IDP_ETH_SIZE		(1*1024*1024)
+#define ETH_BASE		IDP_ETH_BASE //smc9194 driver compatibility issue
+
+#define IDP_COREVOLT_BASE	(IDP_ETH_BASE + IDP_ETH_SIZE)
+#define IDP_COREVOLT_SIZE	(1*1024*1024)
+
+#define IDP_CPLD_BASE		(IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
+#define IDP_CPLD_SIZE		(1*1024*1024)
+
+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
+#error Your custom IO space is getting a bit large !!
+#endif
+
+#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
+#define CPLD_V2P(x)		((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __CPLD_REG(x)		(*((volatile unsigned long *)CPLD_P2V(x)))
+#else
+#  define __CPLD_REG(x)		CPLD_P2V(x)
+#endif
+
+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+
+#define _IDP_CPLD_REV			(IDP_CPLD_PHYS + 0x00)
+#define _IDP_CPLD_PERIPH_PWR		(IDP_CPLD_PHYS + 0x04)
+#define _IDP_CPLD_LED_CONTROL		(IDP_CPLD_PHYS + 0x08)
+#define _IDP_CPLD_KB_COL_HIGH		(IDP_CPLD_PHYS + 0x0C)
+#define _IDP_CPLD_KB_COL_LOW		(IDP_CPLD_PHYS + 0x10)
+#define _IDP_CPLD_PCCARD_EN		(IDP_CPLD_PHYS + 0x14)
+#define _IDP_CPLD_GPIOH_DIR		(IDP_CPLD_PHYS + 0x18)
+#define _IDP_CPLD_GPIOH_VALUE		(IDP_CPLD_PHYS + 0x1C)
+#define _IDP_CPLD_GPIOL_DIR		(IDP_CPLD_PHYS + 0x20)
+#define _IDP_CPLD_GPIOL_VALUE		(IDP_CPLD_PHYS + 0x24)
+#define _IDP_CPLD_PCCARD_PWR		(IDP_CPLD_PHYS + 0x28)
+#define _IDP_CPLD_MISC_CTRL		(IDP_CPLD_PHYS + 0x2C)
+#define _IDP_CPLD_LCD			(IDP_CPLD_PHYS + 0x30)
+#define _IDP_CPLD_FLASH_WE		(IDP_CPLD_PHYS + 0x34)
+
+#define _IDP_CPLD_KB_ROW		(IDP_CPLD_PHYS + 0x50)
+#define _IDP_CPLD_PCCARD0_STATUS	(IDP_CPLD_PHYS + 0x54)
+#define _IDP_CPLD_PCCARD1_STATUS	(IDP_CPLD_PHYS + 0x58)
+#define _IDP_CPLD_MISC_STATUS		(IDP_CPLD_PHYS + 0x5C)
+
+/* FPGA register virtual addresses */
+
+#define IDP_CPLD_REV			__CPLD_REG(_IDP_CPLD_REV)
+#define IDP_CPLD_PERIPH_PWR		__CPLD_REG(_IDP_CPLD_PERIPH_PWR)
+#define IDP_CPLD_LED_CONTROL		__CPLD_REG(_IDP_CPLD_LED_CONTROL)		
+#define IDP_CPLD_KB_COL_HIGH		__CPLD_REG(_IDP_CPLD_KB_COL_HIGH)	
+#define IDP_CPLD_KB_COL_LOW		__CPLD_REG(_IDP_CPLD_KB_COL_LOW)	
+#define IDP_CPLD_PCCARD_EN		__CPLD_REG(_IDP_CPLD_PCCARD_EN)		
+#define IDP_CPLD_GPIOH_DIR		__CPLD_REG(_IDP_CPLD_GPIOH_DIR)		
+#define IDP_CPLD_GPIOH_VALUE		__CPLD_REG(_IDP_CPLD_GPIOH_VALUE)
+#define IDP_CPLD_GPIOL_DIR		__CPLD_REG(_IDP_CPLD_GPIOL_DIR)	
+#define IDP_CPLD_GPIOL_VALUE		__CPLD_REG(_IDP_CPLD_GPIOL_VALUE)
+#define IDP_CPLD_PCCARD_PWR		__CPLD_REG(_IDP_CPLD_PCCARD_PWR)	
+#define IDP_CPLD_MISC_CTRL		__CPLD_REG(_IDP_CPLD_MISC_CTRL)		
+#define IDP_CPLD_LCD			__CPLD_REG(_IDP_CPLD_LCD)		
+#define IDP_CPLD_FLASH_WE		__CPLD_REG(_IDP_CPLD_FLASH_WE)
+                                                                         
+#define IDP_CPLD_KB_ROW		        __CPLD_REG(_IDP_CPLD_KB_ROW)		
+#define IDP_CPLD_PCCARD0_STATUS	        __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)
+#define IDP_CPLD_PCCARD1_STATUS	        __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)	
+#define IDP_CPLD_MISC_STATUS		__CPLD_REG(_IDP_CPLD_MISC_STATUS)	
+
+
+/*
+ * Bit masks for various registers
+ */
+// IDP_CPLD_PCCARD_PWR
+#define PCC0_PWR0	(1 << 0)
+#define PCC0_PWR1	(1 << 1)
+#define PCC0_PWR2	(1 << 2)
+#define PCC0_PWR3	(1 << 3)
+#define PCC1_PWR0	(1 << 4)
+#define PCC1_PWR1	(1 << 5)
+#define PCC1_PWR2	(1 << 6)
+#define PCC1_PWR3	(1 << 7)
+
+// IDP_CPLD_PCCARD_EN
+#define PCC0_RESET	(1 << 6)
+#define PCC1_RESET	(1 << 7)
+#define PCC0_ENABLE	(1 << 0)
+#define PCC1_ENABLE	(1 << 1)
+
+// IDP_CPLD_PCCARDx_STATUS
+#define _PCC_WRPROT	(1 << 7) // 7-4 read as low true
+#define _PCC_RESET	(1 << 6)
+#define _PCC_IRQ	(1 << 5)
+#define _PCC_INPACK	(1 << 4)
+#define PCC_BVD2	(1 << 3)
+#define PCC_BVD1	(1 << 2)
+#define PCC_VS2		(1 << 1)
+#define PCC_VS1		(1 << 0)
+
+#define PCC_DETECT(x)	(GPLR(7 + (x)) & GPIO_bit(7 + (x)))
+
+/*
+ * Macros for LCD Driver
+ */
+
+#ifdef CONFIG_FB_PXA
+
+#define FB_BACKLIGHT_ON()	(IDP_CPLD_LCD |= (1<<1)) 
+#define FB_BACKLIGHT_OFF() 	(IDP_CPLD_LCD &= ~(1<<1))
+
+#define FB_PWR_ON() 		(IDP_CPLD_LCD |= (1<< 0))
+#define FB_PWR_OFF() 		(IDP_CPLD_LCD &= ~(1<<0))
+
+#define FB_VLCD_ON()		(IDP_CPLD_LCD |= (1<<2)) 
+#define FB_VLCD_OFF() 		(IDP_CPLD_LCD &= ~(1<<2))
+
+#endif
+
+/* A listing of interrupts used by external hardware devices */
+
+#ifdef PXA_IDP_REV04
+#define TOUCH_PANEL_IRQ			IRQ_GPIO(5)
+#define IDE_IRQ				IRQ_GPIO(21) 
+#else
+#define TOUCH_PANEL_IRQ			IRQ_GPIO(21)
+#define IDE_IRQ				IRQ_GPIO(5)
+#endif
+
+#define TOUCH_PANEL_IRQ_EDGE		GPIO_FALLING_EDGE
+
+#define IDE_IRQ_EDGE			GPIO_RISING_EDGE
+
+#define ETHERNET_IRQ			IRQ_GPIO(4)
+#define ETHERNET_IRQ_EDGE		GPIO_RISING_EDGE
+
+#define IDE_IRQ_EDGE			GPIO_RISING_EDGE
+
+#define PCMCIA_S0_CD_VALID		IRQ_GPIO(7)
+#define PCMCIA_S0_CD_VALID_EDGE		GPIO_BOTH_EDGES
+
+#define PCMCIA_S1_CD_VALID		IRQ_GPIO(8)
+#define PCMCIA_S1_CD_VALID_EDGE		GPIO_BOTH_EDGES
+
+#define PCMCIA_S0_RDYINT		IRQ_GPIO(19)
+#define PCMCIA_S1_RDYINT		IRQ_GPIO(22)
+
+/*
+ * Macros for LED Driver
+ */
+
+/* leds 0 = ON */
+#define IDP_HB_LED	(1<<5)	
+#define IDP_BUSY_LED	(1<<6)
+
+#define IDP_LEDS_MASK	(IDP_HB_LED | IDP_BUSY_LED)
+
+#define IDP_WRITE_LEDS(value)	(IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & (~(IDP_LEDS_MASK)) | value))
+
+/*
+ * macros for MTD driver
+ */
+
+#define FLASH_WRITE_PROTECT_DISABLE()	((IDP_CPLD_FLASH_WE) &= ~(0x1))
+#define FLASH_WRITE_PROTECT_ENABLE()	((IDP_CPLD_FLASH_WE) |= (0x1))
+
+/*
+ * macros for matrix keyboard driver
+ */
+
+#define KEYBD_MATRIX_NUMBER_INPUTS	7
+#define KEYBD_MATRIX_NUMBER_OUTPUTS	14
+
+#define KEYBD_MATRIX_INVERT_OUTPUT_LOGIC	FALSE
+#define KEYBD_MATRIX_INVERT_INPUT_LOGIC		FALSE
+
+#define KEYBD_MATRIX_SETTLING_TIME_US			100
+#define KEYBD_MATRIX_KEYSTATE_DEBOUNCE_CONSTANT		2
+
+#define KEYBD_MATRIX_SET_OUTPUTS(outputs) \
+{\
+	IDP_CPLD_KB_COL_LOW = outputs;\
+	IDP_CPLD_KB_COL_HIGH = outputs >> 7;\
+}
+
+#define KEYBD_MATRIX_GET_INPUTS(inputs) \
+{\
+	inputs = (IDP_CPLD_KB_ROW & 0x7f);\
+}
+
+//------------------------------------------------------------------------------
+
+#else  // must be rev 01
+
+/* -----------------------------------------------------------------------------
+ * following is for rev01 boards only
+ */
+
+#define IDP_FLASH_PHYS		(PXA_CS0_PHYS)
+#define IDP_ALT_FLASH_PHYS	(PXA_CS1_PHYS)
+#define IDP_MEDIAQ_PHYS		(PXA_CS3_PHYS)
+#define IDP_CTRL_PORT_PHYS	(PXA_CS5_PHYS + 0x02C00000)
+#define IDP_IDE_PHYS		(PXA_CS5_PHYS + 0x03000000)
+#define IDP_ETH_PHYS		(PXA_CS5_PHYS + 0x03400000)
+#define IDP_COREVOLT_PHYS	(PXA_CS5_PHYS + 0x03800000)
+#define IDP_CPLD_PHYS		(PXA_CS5_PHYS + 0x03C00000)
+
+
+/*
+ * virtual memory map
+ */
+
+#define IDP_CTRL_PORT_BASE	(0xf0000000)
+#define IDP_CTRL_PORT_SIZE	(1*1024*1024)
+
+#define IDP_IDE_BASE		(IDP_CTRL_PORT_BASE + IDP_CTRL_PORT_SIZE)
+#define IDP_IDE_SIZE		(1*1024*1024)
+
+#define IDP_ETH_BASE		(IDP_IDE_BASE + IDP_IDE_SIZE)
+#define IDP_ETH_SIZE		(1*1024*1024)
+
+#define IDP_COREVOLT_BASE	(IDP_ETH_BASE + IDP_ETH_SIZE)
+#define IDP_COREVOLT_SIZE	(1*1024*1024)
+
+#define IDP_CPLD_BASE		(IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
+#define IDP_CPLD_SIZE		(1*1024*1024)
+
+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
+#error Your custom IO space is getting a bit large !!
+#endif
+
+#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
+#define CPLD_V2P(x)		((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __CPLD_REG(x)		(*((volatile unsigned long *)CPLD_P2V(x)))
+#else
+#  define __CPLD_REG(x)		CPLD_P2V(x)
+#endif
+
+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+
+#define _IDP_CPLD_LED_CONTROL		(IDP_CPLD_PHYS + 0x00)
+#define _IDP_CPLD_PERIPH_PWR		(IDP_CPLD_PHYS + 0x04)
+#define _IDP_CPLD_CIR			(IDP_CPLD_PHYS + 0x08)
+#define _IDP_CPLD_KB_COL_HIGH		(IDP_CPLD_PHYS + 0x0C)
+#define _IDP_CPLD_KB_COL_LOW		(IDP_CPLD_PHYS + 0x10)
+#define _IDP_CPLD_PCCARD_EN		(IDP_CPLD_PHYS + 0x14)
+#define _IDP_CPLD_GPIOH_DIR		(IDP_CPLD_PHYS + 0x18)
+#define _IDP_CPLD_GPIOH_VALUE		(IDP_CPLD_PHYS + 0x1C)
+#define _IDP_CPLD_GPIOL_DIR		(IDP_CPLD_PHYS + 0x20)
+#define _IDP_CPLD_GPIOL_VALUE		(IDP_CPLD_PHYS + 0x24)
+#define _IDP_CPLD_MISC			(IDP_CPLD_PHYS + 0x28)
+#define _IDP_CPLD_PCCARD0_STATUS	(IDP_CPLD_PHYS + 0x2C)
+#define _IDP_CPLD_PCCARD1_STATUS	(IDP_CPLD_PHYS + 0x30)
+
+/* FPGA register virtual addresses */
+#define IDP_CPLD_LED_CONTROL		__CPLD_REG(_IDP_CPLD_LED_CONTROL)	/* write only */
+#define IDP_CPLD_PERIPH_PWR		__CPLD_REG(_IDP_CPLD_PERIPH_PWR)	/* write only */
+#define IDP_CPLD_CIR			__CPLD_REG(_IDP_CPLD_CIR)		/* write only */
+#define IDP_CPLD_KB_COL_HIGH		__CPLD_REG(_IDP_CPLD_KB_COL_HIGH)	/* write only */
+#define IDP_CPLD_KB_COL_LOW		__CPLD_REG(_IDP_CPLD_KB_COL_LOW)	/* write only */
+#define IDP_CPLD_PCCARD_EN		__CPLD_REG(_IDP_CPLD_PCCARD_EN)		/* write only */
+#define IDP_CPLD_GPIOH_DIR		__CPLD_REG(_IDP_CPLD_GPIOH_DIR)		/* write only */
+#define IDP_CPLD_GPIOH_VALUE		__CPLD_REG(_IDP_CPLD_GPIOH_VALUE)	/* write only */
+#define IDP_CPLD_GPIOL_DIR		__CPLD_REG(_IDP_CPLD_GPIOL_DIR)		/* write only */
+#define IDP_CPLD_GPIOL_VALUE		__CPLD_REG(_IDP_CPLD_GPIOL_VALUE)	/* write only */
+#define IDP_CPLD_MISC			__CPLD_REG(_IDP_CPLD_MISC)		/* read only */
+#define IDP_CPLD_PCCARD0_STATUS		__CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)	/* read only */
+#define IDP_CPLD_PCCARD1_STATUS		__CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)	/* read only */
+
+
+#ifndef __ASSEMBLY__
+
+/* shadow registers for write only registers */
+extern unsigned int idp_cpld_led_control_shadow;
+extern unsigned int idp_cpld_periph_pwr_shadow;
+extern unsigned int idp_cpld_cir_shadow;
+extern unsigned int idp_cpld_kb_col_high_shadow;
+extern unsigned int idp_cpld_kb_col_low_shadow;
+extern unsigned int idp_cpld_pccard_en_shadow;
+extern unsigned int idp_cpld_gpioh_dir_shadow;
+extern unsigned int idp_cpld_gpioh_value_shadow;
+extern unsigned int idp_cpld_gpiol_dir_shadow;
+extern unsigned int idp_cpld_gpiol_value_shadow;
+
+extern unsigned int idp_control_port_shadow;
+
+/* 
+ * macros to write to write only register
+ *
+ * none of these macros are protected from 
+ * multiple drivers using them in interrupt context.
+ */
+
+#define WRITE_IDP_CPLD_LED_CONTROL(value, mask) \
+{\
+	idp_cpld_led_control_shadow = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
+	IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
+}
+#define WRITE_IDP_CPLD_PERIPH_PWR(value, mask) \
+{\
+	idp_cpld_periph_pwr_shadow = ((value & mask) | (idp_cpld_periph_pwr_shadow & ~mask));\
+	IDP_CPLD_PERIPH_PWR = idp_cpld_periph_pwr_shadow;\
+}
+#define WRITE_IDP_CPLD_CIR(value, mask) \
+{\
+	idp_cpld_cir_shadow = ((value & mask) | (idp_cpld_cir_shadow & ~mask));\
+	IDP_CPLD_CIR = idp_cpld_cir_shadow;\
+}
+#define WRITE_IDP_CPLD_KB_COL_HIGH(value, mask) \
+{\
+	idp_cpld_kb_col_high_shadow = ((value & mask) | (idp_cpld_kb_col_high_shadow & ~mask));\
+	IDP_CPLD_KB_COL_HIGH = idp_cpld_kb_col_high_shadow;\
+}
+#define WRITE_IDP_CPLD_KB_COL_LOW(value, mask) \
+{\
+	idp_cpld_kb_col_low_shadow = ((value & mask) | (idp_cpld_kb_col_low_shadow & ~mask));\
+	IDP_CPLD_KB_COL_LOW = idp_cpld_kb_col_low_shadow;\
+}
+#define WRITE_IDP_CPLD_PCCARD_EN(value, mask) \
+{\
+	idp_cpld_ = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
+	IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOH_DIR(value, mask) \
+{\
+	idp_cpld_gpioh_dir_shadow = ((value & mask) | (idp_cpld_gpioh_dir_shadow & ~mask));\
+	IDP_CPLD_GPIOH_DIR = idp_cpld_gpioh_dir_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOH_VALUE(value, mask) \
+{\
+	idp_cpld_gpioh_value_shadow = ((value & mask) | (idp_cpld_gpioh_value_shadow & ~mask));\
+	IDP_CPLD_GPIOH_VALUE = idp_cpld_gpioh_value_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOL_DIR(value, mask) \
+{\
+	idp_cpld_gpiol_dir_shadow = ((value & mask) | (idp_cpld_gpiol_dir_shadow & ~mask));\
+	IDP_CPLD_GPIOL_DIR = idp_cpld_gpiol_dir_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOL_VALUE(value, mask) \
+{\
+	idp_cpld_gpiol_value_shadow = ((value & mask) | (idp_cpld_gpiol_value_shadow & ~mask));\
+	IDP_CPLD_GPIOL_VALUE = idp_cpld_gpiol_value_shadow;\
+}
+
+#define WRITE_IDP_CONTROL_PORT(value, mask) \
+{\
+	idp_control_port_shadow = ((value & mask) | (idp_control_port_shadow & ~mask));\
+	(*((volatile unsigned long *)IDP_CTRL_PORT_BASE)) = idp_control_port_shadow;\
+}
+
+#endif
+
+/* A listing of interrupts used by external hardware devices */
+
+#define TOUCH_PANEL_IRQ			IRQ_GPIO(21)
+#define TOUCH_PANEL_IRQ_EGDE		GPIO_FALLING_EDGE
+
+#define ETHERNET_IRQ			IRQ_GPIO(4)
+#define ETHERNET_IRQ_EDGE		GPIO_RISING_EDGE
+
+/*
+ * Bit masks for various registers
+ */
+
+
+/* control port */
+#define IDP_CONTROL_PORT_PCSLOT0_0	(1 << 0)
+#define IDP_CONTROL_PORT_PCSLOT0_1	(1 << 1)
+#define IDP_CONTROL_PORT_PCSLOT0_2	(1 << 2)
+#define IDP_CONTROL_PORT_PCSLOT0_3	(1 << 3)
+#define IDP_CONTROL_PORT_PCSLOT1_1	(1 << 4)
+#define IDP_CONTROL_PORT_PCSLOT1_2	(1 << 5)
+#define IDP_CONTROL_PORT_PCSLOT1_3	(1 << 6)
+#define IDP_CONTROL_PORT_PCSLOT1_4	(1 << 7)
+#define IDP_CONTROL_PORT_SERIAL1_EN	(1 << 9)
+#define IDP_CONTROL_PORT_SERIAL2_EN	(1 << 10)
+#define IDP_CONTROL_PORT_SERIAL3_EN	(1 << 11)
+#define IDP_CONTROL_PORT_IRDA_FIR	(1 << 12)
+#define IDP_CONTROL_PORT_IRDA_M0	(1 << 13)
+#define IDP_CONTROL_PORT_IRDA_M1	(1 << 14)
+#define IDP_CONTROL_PORT_I2S_PWR	(1 << 15)
+#define IDP_CONTROL_PORT_FLASH_WP	(1 << 19)
+#define IDP_CONTROL_PORT_MILL_EN	(1 << 20)
+#define IDP_CONTROL_PORT_LCD_PWR	(1 << 21)
+#define IDP_CONTROL_PORT_LCD_BKLEN	(1 << 22)
+#define IDP_CONTROL_PORT_LCD_ENAVLCD	(1 << 23)
+
+/*
+ * Macros for LCD Driver
+ */
+
+#ifdef CONFIG_FB_PXA
+
+#define FB_BACKLIGHT_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_BKLEN, IDP_CONTROL_PORT_LCD_BKLEN)
+#define FB_BACKLIGHT_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_BKLEN)
+
+#define FB_PWR_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_PWR, IDP_CONTROL_PORT_LCD_PWR)
+#define FB_PWR_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_PWR)
+
+#define FB_VLCD_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_ENAVLCD, IDP_CONTROL_PORT_LCD_ENAVLCD)
+#define FB_VLCD_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_ENAVLCD)
+
+#endif
+
+
+/*
+ * Macros for LED Driver
+ */
+
+/* leds 0 = ON */
+#define IDP_HB_LED	0x1
+#define IDP_BUSY_LED	0x2
+
+#define IDP_LEDS_MASK	(IDP_HB_LED | IDP_BUSY_LED)
+
+#define IDP_WRITE_LEDS(value) 	WRITE_IDP_CPLD_LED_CONTROL(value, IDP_LEDS_MASK)
+
+/*
+ * macros for MTD driver
+ */
+
+#define FLASH_WRITE_PROTECT_DISABLE()	WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_FLASH_WP)
+#define FLASH_WRITE_PROTECT_ENABLE()	WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_FLASH_WP, IDP_CONTROL_PORT_FLASH_WP)
+
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/innokom.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * linux/include/asm-arm/arch-pxa/innokom.h
+ *
+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ *
+ * 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
+ */
+
+/* 
+ * GPIOs 
+ */
+#define GPIO_INNOKOM_RESET	3
+#define GPIO_INNOKOM_SW_UPDATE	11
+#define GPIO_INNOKOM_ETH	59
+
+/* 
+ * ethernet chip (SMSC91C111) 
+ */
+#define INNOKOM_ETH_PHYS	PXA_CS5_PHYS
+#define INNOKOM_ETH_BASE	(0xf0000000)	/* phys 0x14000000 */
+#define INNOKOM_ETH_SIZE	(1*1024*1024)
+#define INNOKOM_ETH_IRQ		IRQ_GPIO(GPIO_INNOKOM_ETH)
+#define INNOKOM_ETH_IRQ_EDGE	GPIO_RISING_EDGE
+
+/*
+ * virtual to physical conversion macros
+ */
+#define INNOKOM_P2V(x)		((x) - INNOKOM_FPGA_PHYS + INNOKOM_FPGA_VIRT)
+#define INNOKOM_V2P(x)		((x) - INNOKOM_FPGA_VIRT + INNOKOM_FPGA_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __INNOKOM_REG(x)	(*((volatile unsigned long *)INNOKOM_P2V(x)))
+#else
+#  define __INNOKOM_REG(x)	INNOKOM_P2V(x)
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/io.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,34 @@
+/*
+ * linux/include/asm-arm/arch-pxa/io.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software 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.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many 
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)			(a)
+#define __mem_pci(a)		((unsigned long)(a))
+#define __mem_isa(a)		((unsigned long)(a))
+
+/*
+ * Generic virtual read/write
+ */
+#define __arch_getw(a)		(*(volatile unsigned short *)(a))
+#define __arch_putw(v,a)	(*(volatile unsigned short *)(a) = (v))
+
+#define iomem_valid_addr(iomem,sz)	(1)
+#define iomem_to_phys(iomem)		(iomem)
+
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/irq.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-pxa/irq.h
+ * 
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software 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.
+ */
+
+#define fixup_irq(x)	(x)
+
+/*
+ * This prototype is required for cascading of multiplexed interrupts.
+ * Since it doesn't exist elsewhere, we'll put it here for now.
+ */
+extern void do_IRQ(int irq, struct pt_regs *regs);
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/irqs.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,137 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/irqs.h
+ *  
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software 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.
+ */
+
+#define PXA_IRQ_SKIP	7	/* The first 7 IRQs are not yet used */
+#define PXA_IRQ(x)		((x) - PXA_IRQ_SKIP)
+
+#define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error */
+#define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
+#define	IRQ_GPIO1	PXA_IRQ(9)	/* GPIO1 Edge Detect */
+#define	IRQ_GPIO_2_80	PXA_IRQ(10)	/* GPIO[2-80] Edge Detect */
+#define	IRQ_USB		PXA_IRQ(11)	/* USB Service */
+#define	IRQ_PMU		PXA_IRQ(12)	/* Performance Monitoring Unit */
+#define	IRQ_I2S		PXA_IRQ(13)	/* I2S Interrupt */
+#define	IRQ_AC97	PXA_IRQ(14)	/* AC97 Interrupt */
+#define IRQ_ASSP	PXA_IRQ(15)	/* Audio SSP Service Request */
+#define IRQ_NSSP	PXA_IRQ(16)	/* Network SSP Service Request */
+#define	IRQ_LCD		PXA_IRQ(17)	/* LCD Controller Service Request */
+#define	IRQ_I2C		PXA_IRQ(18)	/* I2C Service Request */
+#define	IRQ_ICP		PXA_IRQ(19)	/* ICP Transmit/Receive/Error */
+#define	IRQ_STUART	PXA_IRQ(20)	/* STUART Transmit/Receive/Error */
+#define	IRQ_BTUART	PXA_IRQ(21)	/* BTUART Transmit/Receive/Error */
+#define	IRQ_FFUART	PXA_IRQ(22)	/* FFUART Transmit/Receive/Error*/
+#define	IRQ_MMC		PXA_IRQ(23)	/* MMC Status/Error Detection */
+#define	IRQ_SSP		PXA_IRQ(24)	/* SSP Service Request */
+#define	IRQ_DMA 	PXA_IRQ(25)	/* DMA Channel Service Request */
+#define	IRQ_OST0 	PXA_IRQ(26)	/* OS Timer match 0 */
+#define	IRQ_OST1 	PXA_IRQ(27)	/* OS Timer match 1 */
+#define	IRQ_OST2 	PXA_IRQ(28)	/* OS Timer match 2 */
+#define	IRQ_OST3 	PXA_IRQ(29)	/* OS Timer match 3 */
+#define	IRQ_RTC1Hz	PXA_IRQ(30)	/* RTC HZ Clock Tick */
+#define	IRQ_RTCAlrm	PXA_IRQ(31)	/* RTC Alarm */
+
+#define GPIO_2_80_TO_IRQ(x)	\
+			PXA_IRQ((x) - 2 + 32)
+#define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_80_TO_IRQ(x))
+
+#define IRQ_TO_GPIO_2_80(i)	\
+			((i) - PXA_IRQ(32) + 2)
+#define IRQ_TO_GPIO(i)	((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) - 2 : IRQ_GPIO(0)))
+
+#define	NR_IRQS		(IRQ_GPIO(80) + 1)
+
+#if defined(CONFIG_SA1111)
+
+#define IRQ_SA1111_START	(IRQ_GPIO(80) + 1)
+#define SA1111_IRQ(x)		(IRQ_SA1111_START + (x))
+
+#define IRQ_GPAIN0		SA1111_IRQ(0)
+#define IRQ_GPAIN1		SA1111_IRQ(1)
+#define IRQ_GPAIN2		SA1111_IRQ(2)
+#define IRQ_GPAIN3		SA1111_IRQ(3)
+#define IRQ_GPBIN0		SA1111_IRQ(4)
+#define IRQ_GPBIN1		SA1111_IRQ(5)
+#define IRQ_GPBIN2		SA1111_IRQ(6)
+#define IRQ_GPBIN3		SA1111_IRQ(7)
+#define IRQ_GPBIN4		SA1111_IRQ(8)
+#define IRQ_GPBIN5		SA1111_IRQ(9)
+#define IRQ_GPCIN0		SA1111_IRQ(10)
+#define IRQ_GPCIN1		SA1111_IRQ(11)
+#define IRQ_GPCIN2		SA1111_IRQ(12)
+#define IRQ_GPCIN3		SA1111_IRQ(13)
+#define IRQ_GPCIN4		SA1111_IRQ(14)
+#define IRQ_GPCIN5		SA1111_IRQ(15)
+#define IRQ_GPCIN6		SA1111_IRQ(16)
+#define IRQ_GPCIN7		SA1111_IRQ(17)
+#define IRQ_MSTXINT		SA1111_IRQ(18)
+#define IRQ_MSRXINT		SA1111_IRQ(19)
+#define IRQ_MSSTOPERRINT	SA1111_IRQ(20)
+#define IRQ_TPTXINT		SA1111_IRQ(21)
+#define IRQ_TPRXINT		SA1111_IRQ(22)
+#define IRQ_TPSTOPERRINT	SA1111_IRQ(23)
+#define SSPXMTINT	SA1111_IRQ(24)
+#define SSPRCVINT	SA1111_IRQ(25)
+#define SSPROR		SA1111_IRQ(26)
+#define AUDXMTDMADONEA	SA1111_IRQ(32)
+#define AUDRCVDMADONEA	SA1111_IRQ(33)
+#define AUDXMTDMADONEB	SA1111_IRQ(34)
+#define AUDRCVDMADONEB	SA1111_IRQ(35)
+#define AUDTFSR		SA1111_IRQ(36)
+#define AUDRFSR		SA1111_IRQ(37)
+#define AUDTUR		SA1111_IRQ(38)
+#define AUDROR		SA1111_IRQ(39)
+#define AUDDTS		SA1111_IRQ(40)
+#define AUDRDD		SA1111_IRQ(41)
+#define AUDSTO		SA1111_IRQ(42)
+#define USBPWR		SA1111_IRQ(43)
+#define NIRQHCIM	SA1111_IRQ(44)
+#define HCIBUFFACC	SA1111_IRQ(45)
+#define HCIRMTWKP	SA1111_IRQ(46)
+#define NHCIMFCIR	SA1111_IRQ(47)
+#define PORT_RESUME	SA1111_IRQ(48)
+#define S0_READY_NINT	SA1111_IRQ(49)
+#define S1_READY_NINT	SA1111_IRQ(50)
+#define S0_CD_VALID	SA1111_IRQ(51)
+#define S1_CD_VALID	SA1111_IRQ(52)
+#define S0_BVD1_STSCHG	SA1111_IRQ(53)
+#define S1_BVD1_STSCHG	SA1111_IRQ(54)
+
+#define SA1111_IRQ_MAX	SA1111_IRQ(54)
+
+#undef NR_IRQS
+#define NR_IRQS		(SA1111_IRQ_MAX + 1)
+
+#endif	// defined(CONFIG_SA1111)
+
+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_PXA_IDP) 
+#if CONFIG_SA1111
+#define LUBBOCK_IRQ(x)	(SA1111_IRQ_MAX + 1 + (x))
+#else
+#define LUBBOCK_IRQ(x)	(IRQ_GPIO(80) + 1 + (x))
+#endif
+
+#define LUBBOCK_SD_IRQ		LUBBOCK_IRQ(0)
+#define LUBBOCK_SA1111_IRQ	LUBBOCK_IRQ(1)
+#define LUBBOCK_USB_IRQ		LUBBOCK_IRQ(2)
+#define LUBBOCK_ETH_IRQ		LUBBOCK_IRQ(3)
+#define LUBBOCK_UCB1400_IRQ	LUBBOCK_IRQ(4)
+#define LUBBOCK_BB_IRQ		LUBBOCK_IRQ(5)
+#define LUBBOCK_USB_DISC_IRQ	LUBBOCK_IRQ(6)	/* usb disconnect */
+#define LUBBOCK_LAST_IRQ	LUBBOCK_IRQ(6)
+
+#undef NR_IRQS
+#define NR_IRQS		(LUBBOCK_LAST_IRQ + 1)
+
+#endif	// CONFIG_ARCH_LUBBOCK
+
+
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/keyboard.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,29 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/keyboard.h
+ *
+ *  This file contains the architecture specific keyboard definitions
+ */
+
+#ifndef _PXA_KEYBOARD_H
+#define _PXA_KEYBOARD_H
+
+#include <linux/config.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+extern struct kbd_ops_struct *kbd_ops;
+
+#define kbd_disable_irq()	do { } while(0);
+#define kbd_enable_irq()	do { } while(0);
+
+extern int sa1111_kbd_init_hw(void);
+
+static inline void kbd_init_hw(void)
+{
+	if (machine_is_lubbock())
+		sa1111_kbd_init_hw();
+}
+
+
+#endif  /* _PXA_KEYBOARD_H */
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/lubbock.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,113 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/lubbock.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software 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.
+ */
+
+#define LUBBOCK_FPGA_PHYS	PXA_CS2_PHYS
+#define LUBBOCK_FPGA_VIRT	(0xf0000000)	/* phys 0x08000000 */
+#define LUBBOCK_ETH_PHYS	PXA_CS3_PHYS
+#define LUBBOCK_ETH_VIRT	(0xf1000000)
+#define LUBBOCK_SA1111_BASE	(0xf4000000)	/* phys 0x10000000 */
+
+#define LUB_P2V(x)		((x) - LUBBOCK_FPGA_PHYS + LUBBOCK_FPGA_VIRT)
+#define LUB_V2P(x)		((x) - LUBBOCK_FPGA_VIRT + LUBBOCK_FPGA_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __LUB_REG(x)		(*((volatile unsigned long *)LUB_P2V(x)))
+#else
+#  define __LUB_REG(x)		LUB_P2V(x)
+#endif
+
+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+
+#define WHOAMI			0	// card ID's (see programmers manual)
+#define HEX_LED			0x10	// R/W access to 8 7 segment displays
+#define DISC_BLNK_LED		0x40 	// R/W [15-8] enables for hex leds, [7-0] discrete LEDs
+#define CONF_SWITCHES		0x50	// RO [1] flash wrt prot, [0] 0= boot from rom, 1= flash
+#define USER_SWITCHES		0x60	// RO [15-8] dip switches, [7-0] 2 hex encoding switches
+#define MISC_WR			0x80	// R/W various system controls -see manual
+#define MISC_RD			0x90	// RO various system status bits -see manual
+//#define LUB_IRQ_MASK_EN		0xC0    // R/W 0= mask, 1= enable of TS, codec, ethernet, USB, SA1111, and card det. irq's
+//#define LUB_IRQ_SET_CLR		0xD0	// R/W 1= set, 0 = clear IRQ's from TS, codec, etc...
+//#define LUB_GP			0x100	// R/W [15-0] 16 bits of general purpose I/o for hacking
+
+
+/* FPGA register physical addresses */
+#define _LUB_WHOAMI		(LUBBOCK_FPGA_PHYS + 0x000)
+#define _LUB_HEXLED		(LUBBOCK_FPGA_PHYS + 0x010)
+#define _LUB_DISC_BLNK_LED	(LUBBOCK_FPGA_PHYS + 0x040)
+#define _LUB_CONF_SWITCHES	(LUBBOCK_FPGA_PHYS + 0x050)
+#define _LUB_USER_SWITCHES	(LUBBOCK_FPGA_PHYS + 0x060)
+#define _LUB_MISC_WR		(LUBBOCK_FPGA_PHYS + 0x080)
+#define _LUB_MISC_RD		(LUBBOCK_FPGA_PHYS + 0x090)
+#define _LUB_IRQ_MASK_EN	(LUBBOCK_FPGA_PHYS + 0x0C0)
+#define _LUB_IRQ_SET_CLR	(LUBBOCK_FPGA_PHYS + 0x0D0)
+#define _LUB_GP			(LUBBOCK_FPGA_PHYS + 0x100)
+
+/* FPGA register virtual addresses */
+#define LUB_WHOAMI		__LUB_REG(_LUB_WHOAMI)
+#define LUB_HEXLED		__LUB_REG(_LUB_HEXLED)		
+#define LUB_DISC_BLNK_LED	__LUB_REG(_LUB_DISC_BLNK_LED)	
+#define LUB_CONF_SWITCHES	__LUB_REG(_LUB_CONF_SWITCHES)	
+#define LUB_USER_SWITCHES	__LUB_REG(_LUB_USER_SWITCHES)	
+#define LUB_MISC_WR		__LUB_REG(_LUB_MISC_WR)	
+#define LUB_MISC_RD		__LUB_REG(_LUB_MISC_RD)		
+#define LUB_IRQ_MASK_EN		__LUB_REG(_LUB_IRQ_MASK_EN)
+#define LUB_IRQ_SET_CLR		__LUB_REG(_LUB_IRQ_SET_CLR)		
+#define LUB_GP			__LUB_REG(_LUB_GP)	
+
+/* GPIOs */
+
+#define GPIO_LUBBOCK_IRQ	0
+#define IRQ_GPIO_LUBBOCK_IRQ	IRQ_GPIO0
+
+
+/*
+ * LED macros
+ */
+
+#define LEDS_BASE LUB_DISC_BLNK_LED
+
+// 8 discrete leds available for general use:
+
+#define D28	0x1
+#define D27	0x2
+#define D26	0x4
+#define D25	0x8
+#define D24	0x10
+#define D23	0x20
+#define D22	0x40
+#define D21	0x80
+
+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
+*  be sure to not monkey with them here.
+*/
+
+#define HEARTBEAT_LED	D28
+#define SYS_BUSY_LED    D27
+#define HEXLEDS_BASE LUB_HEXLED
+
+#define HEARTBEAT_LED_ON  (LEDS_BASE &= ~HEARTBEAT_LED)
+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
+#define SYS_BUSY_LED_OFF  (LEDS_BASE |= SYS_BUSY_LED)
+#define SYS_BUSY_LED_ON   (LEDS_BASE &= ~SYS_BUSY_LED)
+
+// use x = D26-D21 for these, please...
+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
+
+#ifndef __ASSEMBLY__
+
+//extern int hexled_val = 0;
+
+#endif
+
+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/memory.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,106 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/memory.h
+ * 
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE	(0xc0000000UL)
+#define TASK_SIZE_26	(0x04000000UL)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET	(0xc0000000UL)
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	(0xa0000000UL)
+
+/*
+ * physical vs virtual ram conversion
+ */
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *		address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *		to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __bus_to_virt__is_a_macro
+#define __virt_to_bus(x)	 __virt_to_phys(x)
+#define __bus_to_virt(x)	 __phys_to_virt(x)
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * The nodes are matched with the physical SDRAM banks as follows:
+ *
+ * 	node 0:  0xa0000000-0xa3ffffff	-->  0xc0000000-0xc3ffffff
+ * 	node 1:  0xa4000000-0xa7ffffff	-->  0xc4000000-0xc7ffffff
+ * 	node 2:  0xa8000000-0xabffffff	-->  0xc8000000-0xcbffffff
+ * 	node 3:  0xac000000-0xafffffff	-->  0xcc000000-0xcfffffff
+ */
+
+#define NR_NODES	4
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 26)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn)		(((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr)	NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn)	NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ * and returns the index corresponding to the appropriate page in the
+ * node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+	(((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
+
+#else
+
+#define PFN_TO_NID(addr)	(0)
+
+#endif
+
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/param.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,3 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/param.h
+ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/pcmcia.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,65 @@
+/*
+ * linux/include/asm-arm/arch-pxa/pcmcia.h
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software 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.
+ *
+ *
+ * Originally based upon linux/include/asm-arm/arch-sa1100/pcmcia.h
+ *
+ */
+
+#ifndef _ASM_ARCH_PCMCIA
+#define _ASM_ARCH_PCMCIA
+
+
+/* Ideally, we'd support up to MAX_SOCK sockets, but PXA250 only
+ * provides support for a maximum of two.
+ */
+#define PXA_PCMCIA_MAX_SOCK   (2)
+
+
+#ifndef __ASSEMBLY__
+
+struct pcmcia_init {
+  void (*handler)(int irq, void *dev, struct pt_regs *regs);
+};
+
+struct pcmcia_state {
+  unsigned detect: 1,
+            ready: 1,
+             bvd1: 1,
+             bvd2: 1,
+           wrprot: 1,
+            vs_3v: 1,
+            vs_Xv: 1;
+};
+
+struct pcmcia_state_array {
+  unsigned int size;
+  struct pcmcia_state *state;
+};
+
+struct pcmcia_irq_info {
+  unsigned int sock;
+  unsigned int irq;
+};
+
+struct pcmcia_low_level {
+  int (*init)(struct pcmcia_init *);
+  int (*shutdown)(void);
+  int (*socket_state)(struct pcmcia_state_array *);
+  int (*get_irq_info)(struct pcmcia_irq_info *);
+  int (*configure_socket)(unsigned int, socket_state_t *);
+};
+
+extern struct pcmcia_low_level *pcmcia_low_level;
+
+#endif  /* __ASSEMBLY__ */
+
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/pxa-regs.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,1327 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/pxa-regs.h
+ *  
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software 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.
+ */
+#ifndef _PXA_REGS_H_
+#define _PXA_REGS_H_
+
+#include "bitfield.h"
+
+
+// FIXME hack so that SA-1111.h will work [cb]
+
+#ifndef __ASSEMBLY__
+typedef unsigned short  Word16 ;
+typedef unsigned int    Word32 ;
+typedef Word32          Word ;
+typedef Word            Quad [4] ;
+typedef void            *Address ;
+typedef void            (*ExcpHndlr) (void) ;
+#endif
+
+/*
+ * PXA Chip selects
+ */
+
+#define PXA_CS0_PHYS	0x00000000
+#define PXA_CS1_PHYS	0x04000000
+#define PXA_CS2_PHYS	0x08000000
+#define PXA_CS3_PHYS	0x0C000000
+#define PXA_CS4_PHYS	0x10000000
+#define PXA_CS5_PHYS	0x14000000
+
+
+/*
+ * Personal Computer Memory Card International Association (PCMCIA) sockets
+ */
+
+#define PCMCIAPrtSp	0x04000000	/* PCMCIA Partition Space [byte]   */
+#define PCMCIASp	(4*PCMCIAPrtSp)	/* PCMCIA Space [byte]             */
+#define PCMCIAIOSp	PCMCIAPrtSp	/* PCMCIA I/O Space [byte]         */
+#define PCMCIAAttrSp	PCMCIAPrtSp	/* PCMCIA Attribute Space [byte]   */
+#define PCMCIAMemSp	PCMCIAPrtSp	/* PCMCIA Memory Space [byte]      */
+
+#define PCMCIA0Sp	PCMCIASp	/* PCMCIA 0 Space [byte]           */
+#define PCMCIA0IOSp	PCMCIAIOSp	/* PCMCIA 0 I/O Space [byte]       */
+#define PCMCIA0AttrSp	PCMCIAAttrSp	/* PCMCIA 0 Attribute Space [byte] */
+#define PCMCIA0MemSp	PCMCIAMemSp	/* PCMCIA 0 Memory Space [byte]    */
+
+#define PCMCIA1Sp	PCMCIASp	/* PCMCIA 1 Space [byte]           */
+#define PCMCIA1IOSp	PCMCIAIOSp	/* PCMCIA 1 I/O Space [byte]       */
+#define PCMCIA1AttrSp	PCMCIAAttrSp	/* PCMCIA 1 Attribute Space [byte] */
+#define PCMCIA1MemSp	PCMCIAMemSp	/* PCMCIA 1 Memory Space [byte]    */
+
+#define _PCMCIA(Nb)	        	/* PCMCIA [0..1]                   */ \
+                	(0x20000000 + (Nb)*PCMCIASp)
+#define _PCMCIAIO(Nb)	_PCMCIA (Nb)	/* PCMCIA I/O [0..1]               */
+#define _PCMCIAAttr(Nb)	        	/* PCMCIA Attribute [0..1]         */ \
+                	(_PCMCIA (Nb) + 2*PCMCIAPrtSp)
+#define _PCMCIAMem(Nb)	        	/* PCMCIA Memory [0..1]            */ \
+                	(_PCMCIA (Nb) + 3*PCMCIAPrtSp)
+
+#define _PCMCIA0	_PCMCIA (0)	/* PCMCIA 0                        */
+#define _PCMCIA0IO	_PCMCIAIO (0)	/* PCMCIA 0 I/O                    */
+#define _PCMCIA0Attr	_PCMCIAAttr (0)	/* PCMCIA 0 Attribute              */
+#define _PCMCIA0Mem	_PCMCIAMem (0)	/* PCMCIA 0 Memory                 */
+
+#define _PCMCIA1	_PCMCIA (1)	/* PCMCIA 1                        */
+#define _PCMCIA1IO	_PCMCIAIO (1)	/* PCMCIA 1 I/O                    */
+#define _PCMCIA1Attr	_PCMCIAAttr (1)	/* PCMCIA 1 Attribute              */
+#define _PCMCIA1Mem	_PCMCIAMem (1)	/* PCMCIA 1 Memory                 */
+
+
+
+/*
+ * DMA Controller
+ */
+
+#define DCSR0		__REG(0x40000000)  /* DMA Control / Status Register for Channel 0 */
+#define DCSR1		__REG(0x40000004)  /* DMA Control / Status Register for Channel 1 */
+#define DCSR2		__REG(0x40000008)  /* DMA Control / Status Register for Channel 2 */
+#define DCSR3		__REG(0x4000000c)  /* DMA Control / Status Register for Channel 3 */
+#define DCSR4		__REG(0x40000010)  /* DMA Control / Status Register for Channel 4 */
+#define DCSR5		__REG(0x40000014)  /* DMA Control / Status Register for Channel 5 */
+#define DCSR6		__REG(0x40000018)  /* DMA Control / Status Register for Channel 6 */
+#define DCSR7		__REG(0x4000001c)  /* DMA Control / Status Register for Channel 7 */
+#define DCSR8		__REG(0x40000020)  /* DMA Control / Status Register for Channel 8 */
+#define DCSR9		__REG(0x40000024)  /* DMA Control / Status Register for Channel 9 */
+#define DCSR10		__REG(0x40000028)  /* DMA Control / Status Register for Channel 10 */
+#define DCSR11		__REG(0x4000002c)  /* DMA Control / Status Register for Channel 11 */
+#define DCSR12		__REG(0x40000030)  /* DMA Control / Status Register for Channel 12 */
+#define DCSR13		__REG(0x40000034)  /* DMA Control / Status Register for Channel 13 */
+#define DCSR14		__REG(0x40000038)  /* DMA Control / Status Register for Channel 14 */
+#define DCSR15		__REG(0x4000003c)  /* DMA Control / Status Register for Channel 15 */
+
+#define DCSR(x)		__REG2(0x40000000, (x) << 2)
+
+#define DCSR_RUN	(1 << 31)	/* Run Bit (read / write) */
+#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch (read / write) */
+#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable (read / write) */
+#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
+#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
+#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt (read / write) */
+#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
+#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
+
+#define DINT		__REG(0x400000f0)  /* DMA Interrupt Register */
+
+#define DRCMR0		__REG(0x40000100)  /* Request to Channel Map Register for DREQ 0 */
+#define DRCMR1		__REG(0x40000104)  /* Request to Channel Map Register for DREQ 1 */
+#define DRCMR2		__REG(0x40000108)  /* Request to Channel Map Register for I2S receive Request */
+#define DRCMR3		__REG(0x4000010c)  /* Request to Channel Map Register for I2S transmit Request */
+#define DRCMR4		__REG(0x40000110)  /* Request to Channel Map Register for BTUART receive Request */
+#define DRCMR5		__REG(0x40000114)  /* Request to Channel Map Register for BTUART transmit Request. */
+#define DRCMR6		__REG(0x40000118)  /* Request to Channel Map Register for FFUART receive Request */
+#define DRCMR7		__REG(0x4000011c)  /* Request to Channel Map Register for FFUART transmit Request */
+#define DRCMR8		__REG(0x40000120)  /* Request to Channel Map Register for AC97 microphone Request */
+#define DRCMR9		__REG(0x40000124)  /* Request to Channel Map Register for AC97 modem receive Request */
+#define DRCMR10		__REG(0x40000128)  /* Request to Channel Map Register for AC97 modem transmit Request */
+#define DRCMR11		__REG(0x4000012c)  /* Request to Channel Map Register for AC97 audio receive Request */
+#define DRCMR12		__REG(0x40000130)  /* Request to Channel Map Register for AC97 audio transmit Request */
+#define DRCMR13		__REG(0x40000134)  /* Request to Channel Map Register for SSP receive Request */
+#define DRCMR14		__REG(0x40000138)  /* Request to Channel Map Register for SSP transmit Request */
+#define DRCMR15		__REG(0x4000013c)  /* Reserved */
+#define DRCMR16		__REG(0x40000140)  /* Reserved */
+#define DRCMR17		__REG(0x40000144)  /* Request to Channel Map Register for ICP receive Request */
+#define DRCMR18		__REG(0x40000148)  /* Request to Channel Map Register for ICP transmit Request */
+#define DRCMR19		__REG(0x4000014c)  /* Request to Channel Map Register for STUART receive Request */
+#define DRCMR20		__REG(0x40000150)  /* Request to Channel Map Register for STUART transmit Request */
+#define DRCMR21		__REG(0x40000154)  /* Request to Channel Map Register for MMC receive Request */
+#define DRCMR22		__REG(0x40000158)  /* Request to Channel Map Register for MMC transmit Request */
+#define DRCMR23		__REG(0x4000015c)  /* Reserved */
+#define DRCMR24		__REG(0x40000160)  /* Reserved */
+#define DRCMR25		__REG(0x40000164)  /* Request to Channel Map Register for USB endpoint 1 Request */
+#define DRCMR26		__REG(0x40000168)  /* Request to Channel Map Register for USB endpoint 2 Request */
+#define DRCMR27		__REG(0x4000016C)  /* Request to Channel Map Register for USB endpoint 3 Request */
+#define DRCMR28		__REG(0x40000170)  /* Request to Channel Map Register for USB endpoint 4 Request */
+#define DRCMR29		__REG(0x40000174)  /* Reserved */
+#define DRCMR30		__REG(0x40000178)  /* Request to Channel Map Register for USB endpoint 6 Request */
+#define DRCMR31		__REG(0x4000017C)  /* Request to Channel Map Register for USB endpoint 7 Request */
+#define DRCMR32		__REG(0x40000180)  /* Request to Channel Map Register for USB endpoint 8 Request */
+#define DRCMR33		__REG(0x40000184)  /* Request to Channel Map Register for USB endpoint 9 Request */
+#define DRCMR34		__REG(0x40000188)  /* Reserved */
+#define DRCMR35		__REG(0x4000018C)  /* Request to Channel Map Register for USB endpoint 11 Request */
+#define DRCMR36		__REG(0x40000190)  /* Request to Channel Map Register for USB endpoint 12 Request */
+#define DRCMR37		__REG(0x40000194)  /* Request to Channel Map Register for USB endpoint 13 Request */
+#define DRCMR38		__REG(0x40000198)  /* Request to Channel Map Register for USB endpoint 14 Request */
+#define DRCMR39		__REG(0x4000019C)  /* Reserved */
+
+#define DRCMRRXSADR	DRCMR2
+#define DRCMRTXSADR	DRCMR3
+#define DRCMRRXBTRBR	DRCMR4
+#define DRCMRTXBTTHR	DRCMR5
+#define DRCMRRXFFRBR	DRCMR6
+#define DRCMRTXFFTHR	DRCMR7
+#define DRCMRRXMCDR	DRCMR8
+#define DRCMRRXMODR	DRCMR9
+#define DRCMRTXMODR	DRCMR10
+#define DRCMRRXPCDR	DRCMR11
+#define DRCMRTXPCDR	DRCMR12
+#define DRCMRRXSSDR	DRCMR13
+#define DRCMRTXSSDR	DRCMR14
+#define DRCMRRXICDR	DRCMR17
+#define DRCMRTXICDR	DRCMR18
+#define DRCMRRXSTRBR	DRCMR19
+#define DRCMRTXSTTHR	DRCMR20
+#define DRCMRRXMMC	DRCMR21
+#define DRCMRTXMMC	DRCMR22
+
+#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid (read / write) */
+#define DRCMR_CHLNUM	0x0f		/* mask for Channel Number (read / write) */
+
+#define DDADR0		__REG(0x40000200)  /* DMA Descriptor Address Register Channel 0 */
+#define DSADR0		__REG(0x40000204)  /* DMA Source Address Register Channel 0 */
+#define DTADR0		__REG(0x40000208)  /* DMA Target Address Register Channel 0 */
+#define DCMD0		__REG(0x4000020c)  /* DMA Command Address Register Channel 0 */
+#define DDADR1		__REG(0x40000210)  /* DMA Descriptor Address Register Channel 1 */
+#define DSADR1		__REG(0x40000214)  /* DMA Source Address Register Channel 1 */
+#define DTADR1		__REG(0x40000218)  /* DMA Target Address Register Channel 1 */
+#define DCMD1		__REG(0x4000021c)  /* DMA Command Address Register Channel 1 */
+#define DDADR2		__REG(0x40000220)  /* DMA Descriptor Address Register Channel 2 */
+#define DSADR2		__REG(0x40000224)  /* DMA Source Address Register Channel 2 */
+#define DTADR2		__REG(0x40000228)  /* DMA Target Address Register Channel 2 */
+#define DCMD2		__REG(0x4000022c)  /* DMA Command Address Register Channel 2 */
+#define DDADR3		__REG(0x40000230)  /* DMA Descriptor Address Register Channel 3 */
+#define DSADR3		__REG(0x40000234)  /* DMA Source Address Register Channel 3 */
+#define DTADR3		__REG(0x40000238)  /* DMA Target Address Register Channel 3 */
+#define DCMD3		__REG(0x4000023c)  /* DMA Command Address Register Channel 3 */
+#define DDADR4		__REG(0x40000240)  /* DMA Descriptor Address Register Channel 4 */
+#define DSADR4		__REG(0x40000244)  /* DMA Source Address Register Channel 4 */
+#define DTADR4		__REG(0x40000248)  /* DMA Target Address Register Channel 4 */
+#define DCMD4		__REG(0x4000024c)  /* DMA Command Address Register Channel 4 */
+#define DDADR5		__REG(0x40000250)  /* DMA Descriptor Address Register Channel 5 */
+#define DSADR5		__REG(0x40000254)  /* DMA Source Address Register Channel 5 */
+#define DTADR5		__REG(0x40000258)  /* DMA Target Address Register Channel 5 */
+#define DCMD5		__REG(0x4000025c)  /* DMA Command Address Register Channel 5 */
+#define DDADR6		__REG(0x40000260)  /* DMA Descriptor Address Register Channel 6 */
+#define DSADR6		__REG(0x40000264)  /* DMA Source Address Register Channel 6 */
+#define DTADR6		__REG(0x40000268)  /* DMA Target Address Register Channel 6 */
+#define DCMD6		__REG(0x4000026c)  /* DMA Command Address Register Channel 6 */
+#define DDADR7		__REG(0x40000270)  /* DMA Descriptor Address Register Channel 7 */
+#define DSADR7		__REG(0x40000274)  /* DMA Source Address Register Channel 7 */
+#define DTADR7		__REG(0x40000278)  /* DMA Target Address Register Channel 7 */
+#define DCMD7		__REG(0x4000027c)  /* DMA Command Address Register Channel 7 */
+#define DDADR8		__REG(0x40000280)  /* DMA Descriptor Address Register Channel 8 */
+#define DSADR8		__REG(0x40000284)  /* DMA Source Address Register Channel 8 */
+#define DTADR8		__REG(0x40000288)  /* DMA Target Address Register Channel 8 */
+#define DCMD8		__REG(0x4000028c)  /* DMA Command Address Register Channel 8 */
+#define DDADR9		__REG(0x40000290)  /* DMA Descriptor Address Register Channel 9 */
+#define DSADR9		__REG(0x40000294)  /* DMA Source Address Register Channel 9 */
+#define DTADR9		__REG(0x40000298)  /* DMA Target Address Register Channel 9 */
+#define DCMD9		__REG(0x4000029c)  /* DMA Command Address Register Channel 9 */
+#define DDADR10		__REG(0x400002a0)  /* DMA Descriptor Address Register Channel 10 */
+#define DSADR10		__REG(0x400002a4)  /* DMA Source Address Register Channel 10 */
+#define DTADR10		__REG(0x400002a8)  /* DMA Target Address Register Channel 10 */
+#define DCMD10		__REG(0x400002ac)  /* DMA Command Address Register Channel 10 */
+#define DDADR11		__REG(0x400002b0)  /* DMA Descriptor Address Register Channel 11 */
+#define DSADR11		__REG(0x400002b4)  /* DMA Source Address Register Channel 11 */
+#define DTADR11		__REG(0x400002b8)  /* DMA Target Address Register Channel 11 */
+#define DCMD11		__REG(0x400002bc)  /* DMA Command Address Register Channel 11 */
+#define DDADR12		__REG(0x400002c0)  /* DMA Descriptor Address Register Channel 12 */
+#define DSADR12		__REG(0x400002c4)  /* DMA Source Address Register Channel 12 */
+#define DTADR12		__REG(0x400002c8)  /* DMA Target Address Register Channel 12 */
+#define DCMD12		__REG(0x400002cc)  /* DMA Command Address Register Channel 12 */
+#define DDADR13		__REG(0x400002d0)  /* DMA Descriptor Address Register Channel 13 */
+#define DSADR13		__REG(0x400002d4)  /* DMA Source Address Register Channel 13 */
+#define DTADR13		__REG(0x400002d8)  /* DMA Target Address Register Channel 13 */
+#define DCMD13		__REG(0x400002dc)  /* DMA Command Address Register Channel 13 */
+#define DDADR14		__REG(0x400002e0)  /* DMA Descriptor Address Register Channel 14 */
+#define DSADR14		__REG(0x400002e4)  /* DMA Source Address Register Channel 14 */
+#define DTADR14		__REG(0x400002e8)  /* DMA Target Address Register Channel 14 */
+#define DCMD14		__REG(0x400002ec)  /* DMA Command Address Register Channel 14 */
+#define DDADR15		__REG(0x400002f0)  /* DMA Descriptor Address Register Channel 15 */
+#define DSADR15		__REG(0x400002f4)  /* DMA Source Address Register Channel 15 */
+#define DTADR15		__REG(0x400002f8)  /* DMA Target Address Register Channel 15 */
+#define DCMD15		__REG(0x400002fc)  /* DMA Command Address Register Channel 15 */
+
+#define DDADR(x)	__REG2(0x40000200, (x) << 4)
+#define DSADR(x)	__REG2(0x40000204, (x) << 4)
+#define DTADR(x)	__REG2(0x40000208, (x) << 4)
+#define DCMD(x)		__REG2(0x4000020c, (x) << 4)
+
+#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor (mask) */
+#define DDADR_STOP	(1 << 0)	/* Stop (read / write) */
+
+#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
+#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
+#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
+#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
+#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
+#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
+#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
+#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
+#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
+#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
+#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
+#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
+#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+
+/* default combinations */
+#define DCMD_RXPCDR	(DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
+#define DCMD_RXMCDR	(DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
+#define DCMD_TXPCDR	(DCMD_INCSRCADDR|DCMD_FLOWTRG|DCMD_BURST32|DCMD_WIDTH4)
+
+
+/*
+ * UARTs
+ */
+
+/* Full Function UART (FFUART) */
+#define FFUART		FFRBR
+#define FFRBR		__REG(0x40100000)  /* Receive Buffer Register (read only) */
+#define FFTHR		__REG(0x40100000)  /* Transmit Holding Register (write only) */
+#define FFIER		__REG(0x40100004)  /* Interrupt Enable Register (read/write) */
+#define FFIIR		__REG(0x40100008)  /* Interrupt ID Register (read only) */
+#define FFFCR		__REG(0x40100008)  /* FIFO Control Register (write only) */
+#define FFLCR		__REG(0x4010000C)  /* Line Control Register (read/write) */
+#define FFMCR		__REG(0x40100010)  /* Modem Control Register (read/write) */
+#define FFLSR		__REG(0x40100014)  /* Line Status Register (read only) */
+#define FFMSR		__REG(0x40100018)  /* Modem Status Register (read only) */
+#define FFSPR		__REG(0x4010001C)  /* Scratch Pad Register (read/write) */
+#define FFISR		__REG(0x40100020)  /* Infrared Selection Register (read/write) */
+#define FFDLL		__REG(0x40100000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define FFDLH		__REG(0x40100004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
+/* Bluetooth UART (BTUART) */
+#define BTUART		BTRBR
+#define BTRBR		__REG(0x40200000)  /* Receive Buffer Register (read only) */
+#define BTTHR		__REG(0x40200000)  /* Transmit Holding Register (write only) */
+#define BTIER		__REG(0x40200004)  /* Interrupt Enable Register (read/write) */
+#define BTIIR		__REG(0x40200008)  /* Interrupt ID Register (read only) */
+#define BTFCR		__REG(0x40200008)  /* FIFO Control Register (write only) */
+#define BTLCR		__REG(0x4020000C)  /* Line Control Register (read/write) */
+#define BTMCR		__REG(0x40200010)  /* Modem Control Register (read/write) */
+#define BTLSR		__REG(0x40200014)  /* Line Status Register (read only) */
+#define BTMSR		__REG(0x40200018)  /* Modem Status Register (read only) */
+#define BTSPR		__REG(0x4020001C)  /* Scratch Pad Register (read/write) */
+#define BTISR		__REG(0x40200020)  /* Infrared Selection Register (read/write) */
+#define BTDLL		__REG(0x40200000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define BTDLH		__REG(0x40200004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
+/* Standard UART (STUART) */
+#define STUART		STRBR
+#define STRBR		__REG(0x40700000)  /* Receive Buffer Register (read only) */
+#define STTHR		__REG(0x40700000)  /* Transmit Holding Register (write only) */
+#define STIER		__REG(0x40700004)  /* Interrupt Enable Register (read/write) */
+#define STIIR		__REG(0x40700008)  /* Interrupt ID Register (read only) */
+#define STFCR		__REG(0x40700008)  /* FIFO Control Register (write only) */
+#define STLCR		__REG(0x4070000C)  /* Line Control Register (read/write) */
+#define STMCR		__REG(0x40700010)  /* Modem Control Register (read/write) */
+#define STLSR		__REG(0x40700014)  /* Line Status Register (read only) */
+#define STMSR		__REG(0x40700018)  /* Reserved */
+#define STSPR		__REG(0x4070001C)  /* Scratch Pad Register (read/write) */
+#define STISR		__REG(0x40700020)  /* Infrared Selection Register (read/write) */
+#define STDLL		__REG(0x40700000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define STDLH		__REG(0x40700004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
+#define IER_DMAE	(1 << 7)	/* DMA Requests Enable */
+#define IER_UUE		(1 << 6)	/* UART Unit Enable */
+#define IER_NRZE	(1 << 5)	/* NRZ coding Enable */
+#define IER_RTIOE	(1 << 4)	/* Receiver Time Out Interrupt Enable */
+#define IER_MIE		(1 << 3)	/* Modem Interrupt Enable */
+#define IER_RLSE	(1 << 2)	/* Receiver Line Status Interrupt Enable */
+#define IER_TIE		(1 << 1)	/* Transmit Data request Interrupt Enable */
+#define IER_RAVIE	(1 << 0)	/* Receiver Data Available Interrupt Enable */
+
+#define IIR_FIFOES1	(1 << 7)	/* FIFO Mode Enable Status */
+#define IIR_FIFOES0	(1 << 6)	/* FIFO Mode Enable Status */
+#define IIR_TOD		(1 << 3)	/* Time Out Detected */
+#define IIR_IID2	(1 << 2)	/* Interrupt Source Encoded */
+#define IIR_IID1	(1 << 1)	/* Interrupt Source Encoded */
+#define IIR_IP		(1 << 0)	/* Interrupt Pending (active low) */
+
+#define FCR_ITL2	(1 << 7)	/* Interrupt Trigger Level */
+#define FCR_ITL1	(1 << 6)	/* Interrupt Trigger Level */
+#define FCR_RESETTF	(1 << 2)	/* Reset Transmitter FIFO */
+#define FCR_RESETRF	(1 << 1)	/* Reset Receiver FIFO */
+#define FCR_TRFIFOE	(1 << 0)	/* Transmit and Receive FIFO Enable */
+#define FCR_ITL_1	(0)
+#define FCR_ITL_8	(FCR_ITL1)
+#define FCR_ITL_16	(FCR_ITL2)
+#define FCR_ITL_32	(FCR_ITL2|FCR_ITL1)
+
+#define LCR_DLAB	(1 << 7)	/* Divisor Latch Access Bit */
+#define LCR_SB		(1 << 6)	/* Set Break */
+#define LCR_STKYP	(1 << 5)	/* Sticky Parity */
+#define LCR_EPS		(1 << 4)	/* Even Parity Select */
+#define LCR_PEN		(1 << 3)	/* Parity Enable */
+#define LCR_STB		(1 << 2)	/* Stop Bit */
+#define LCR_WLS1	(1 << 1)	/* Word Length Select */
+#define LCR_WLS0	(1 << 0)	/* Word Length Select */
+
+#define LSR_FIFOE	(1 << 7)	/* FIFO Error Status */
+#define LSR_TEMT	(1 << 6)	/* Transmitter Empty */
+#define LSR_TDRQ	(1 << 5)	/* Transmit Data Request */
+#define LSR_BI		(1 << 4)	/* Break Interrupt */
+#define LSR_FE		(1 << 3)	/* Framing Error */
+#define LSR_PE		(1 << 2)	/* Parity Error */
+#define LSR_OE		(1 << 1)	/* Overrun Error */
+#define LSR_DR		(1 << 0)	/* Data Ready */
+
+#define MCR_LOOP	(1 << 4)	*/ 
+#define MCR_OUT2	(1 << 3)	/* force MSR_DCD in loopback mode */
+#define MCR_OUT1	(1 << 2)	/* force MSR_RI in loopback mode */
+#define MCR_RTS		(1 << 1)	/* Request to Send */
+#define MCR_DTR		(1 << 0)	/* Data Terminal Ready */
+
+#define MSR_DCD		(1 << 7)	/* Data Carrier Detect */
+#define MSR_RI		(1 << 6)	/* Ring Indicator */
+#define MSR_DSR		(1 << 5)	/* Data Set Ready */
+#define MSR_CTS		(1 << 4)	/* Clear To Send */
+#define MSR_DDCD	(1 << 3)	/* Delta Data Carrier Detect */
+#define MSR_TERI	(1 << 2)	/* Trailing Edge Ring Indicator */
+#define MSR_DDSR	(1 << 1)	/* Delta Data Set Ready */
+#define MSR_DCTS	(1 << 0)	/* Delta Clear To Send */
+
+/*
+ * IrSR (Infrared Selection Register)
+ */
+#define STISR_RXPL      (1 << 4)        /* Receive Data Polarity */
+#define STISR_TXPL      (1 << 3)        /* Transmit Data Polarity */
+#define STISR_XMODE     (1 << 2)        /* Transmit Pulse Width Select */
+#define STISR_RCVEIR    (1 << 1)        /* Receiver SIR Enable */
+#define STISR_XMITIR    (1 << 0)        /* Transmitter SIR Enable */
+
+
+/*
+ * I2C registers
+ */
+
+#define IBMR		__REG(0x40301680)  /* I2C Bus Monitor Register - IBMR */
+#define IDBR		__REG(0x40301688)  /* I2C Data Buffer Register - IDBR */
+#define ICR		__REG(0x40301690)  /* I2C Control Register - ICR */
+#define ISR		__REG(0x40301698)  /* I2C Status Register - ISR */
+#define ISAR		__REG(0x403016A0)  /* I2C Slave Address Register - ISAR */
+
+#define ICR_START	(1 << 0)	   /* start bit */
+#define ICR_STOP	(1 << 1)	   /* stop bit */
+#define ICR_ACKNAK	(1 << 2)	   /* send ACK(0) or NAK(1) */
+#define ICR_TB		(1 << 3)	   /* transfer byte bit */
+#define ICR_MA		(1 << 4)	   /* master abort */
+#define ICR_SCLE	(1 << 5)	   /* master clock enable */
+#define ICR_IUE		(1 << 6)	   /* unit enable */
+#define ICR_GCD		(1 << 7)	   /* general call disable */
+#define ICR_ITEIE	(1 << 8)	   /* enable tx interrupts */
+#define ICR_IRFIE	(1 << 9)	   /* enable rx interrupts */
+#define ICR_BEIE	(1 << 10)	   /* enable bus error ints */
+#define ICR_SSDIE	(1 << 11)	   /* slave STOP detected int enable */
+#define ICR_ALDIE	(1 << 12)	   /* enable arbitration interrupt */
+#define ICR_SADIE	(1 << 13)	   /* slave address detected int enable */
+#define ICR_UR		(1 << 14)	   /* unit reset */
+
+#define ISR_RWM		(1 << 0)	   /* read/write mode */
+#define ISR_ACKNAK	(1 << 1)	   /* ack/nak status */
+#define ISR_UB		(1 << 2)	   /* unit busy */
+#define ISR_IBB		(1 << 3)	   /* bus busy */	
+#define ISR_SSD		(1 << 4)	   /* slave stop detected */
+#define ISR_ALD		(1 << 5)	   /* arbitration loss detected */
+#define ISR_ITE		(1 << 6)	   /* tx buffer empty */
+#define ISR_IRF		(1 << 7)	   /* rx buffer full */
+#define ISR_GCAD	(1 << 8)	   /* general call address detected */
+#define ISR_SAD		(1 << 9)	   /* slave address detected */
+#define ISR_BED		(1 << 10)	   /* bus error no ACK/NAK */
+
+
+/*
+ * Serial Audio Controller
+ */
+
+/* FIXME: This clash with SA1111 defines */
+#ifndef CONFIG_SA1111
+#define SACR0		__REG(0x40400000)  /* Global Control Register */
+#define SACR1		__REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
+#define SASR0		__REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
+#define SAIMR		__REG(0x40400014)  /* Serial Audio Interrupt Mask Register */
+#define SAICR		__REG(0x40400018)  /* Serial Audio Interrupt Clear Register */
+#define SADIV		__REG(0x40400060)  /* Audio Clock Divider Register. */
+#define SADR		__REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
+#endif
+
+
+/*
+ * AC97 Controller registers
+ */
+
+#define POCR		__REG(0x40500000)  /* PCM Out Control Register */
+#define POCR_FEIE	(1 << 3)	/* FIFO Error Interrupt Enable */
+
+#define PICR		__REG(0x40500004)  /* PCM In Control Register */
+#define PICR_FEIE	(1 << 3)	/* FIFO Error Interrupt Enable */
+
+#define MCCR		__REG(0x40500008)  /* Mic In Control Register */
+#define MCCR_FEIE	(1 << 3)	/* FIFO Error Interrupt Enable */
+
+#define GCR		__REG(0x4050000C)  /* Global Control Register */
+#define GCR_CDONE_IE	(1 << 19)	/* Command Done Interrupt Enable */
+#define GCR_SDONE_IE	(1 << 18)	/* Status Done Interrupt Enable */
+#define GCR_SECRDY_IEN	(1 << 9)	/* Secondary Ready Interrupt Enable */
+#define GCR_PRIRDY_IEN	(1 << 8)	/* Primary Ready Interrupt Enable */
+#define GCR_SECRES_IEN	(1 << 5)	/* Secondary Resume Interrupt Enable */
+#define GCR_PRIRES_IEN	(1 << 4)	/* Primary Resume Interrupt Enable */
+#define GCR_ACLINK_OFF	(1 << 3)	/* AC-link Shut Off */
+#define GCR_WARM_RST	(1 << 2)	/* AC97 Warm Reset */
+#define GCR_COLD_RST	(1 << 1)	/* AC'97 Cold Reset (0 = active) */
+#define GCR_GIE		(1 << 0)	/* Codec GPI Interrupt Enable */
+
+#define POSR		__REG(0x40500010)  /* PCM Out Status Register */
+#define POSR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define PISR		__REG(0x40500014)  /* PCM In Status Register */
+#define PISR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define MCSR		__REG(0x40500018)  /* Mic In Status Register */
+#define MCSR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define GSR		__REG(0x4050001C)  /* Global Status Register */
+#define GSR_CDONE	(1 << 19)	/* Command Done */
+#define GSR_SDONE	(1 << 18)	/* Status Done */
+#define GSR_RDCS	(1 << 15)	/* Read Completion Status */
+#define GSR_BIT3SLT12	(1 << 14)	/* Bit 3 of slot 12 */
+#define GSR_BIT2SLT12	(1 << 13)	/* Bit 2 of slot 12 */
+#define GSR_BIT1SLT12	(1 << 12)	/* Bit 1 of slot 12 */
+#define GSR_SECRES	(1 << 11)	/* Secondary Resume Interrupt */
+#define GSR_PRIRES	(1 << 10)	/* Primary Resume Interrupt */
+#define GSR_SCR		(1 << 9)	/* Secondary Codec Ready */
+#define GSR_PCR		(1 << 8)	/*  Primary Codec Ready */
+#define GSR_MINT	(1 << 7)	/* Mic In Interrupt */
+#define GSR_POINT	(1 << 6)	/* PCM Out Interrupt */
+#define GSR_PIINT	(1 << 5)	/* PCM In Interrupt */
+#define GSR_MOINT	(1 << 2)	/* Modem Out Interrupt */
+#define GSR_MIINT	(1 << 1)	/* Modem In Interrupt */
+#define GSR_GSCI	(1 << 0)	/* Codec GPI Status Change Interrupt */
+
+#define CAR		__REG(0x40500020)  /* CODEC Access Register */
+#define CAR_CAIP	(1 << 0)	/* Codec Access In Progress */
+
+#define PCDR		__REG(0x40500040)  /* PCM FIFO Data Register */
+#define MCDR		__REG(0x40500060)  /* Mic-in FIFO Data Register */
+
+#define MOCR		__REG(0x40500100)  /* Modem Out Control Register */
+#define MOCR_FEIE	(1 << 3)	/* FIFO Error */
+
+#define MICR		__REG(0x40500108)  /* Modem In Control Register */
+#define MICR_FEIE	(1 << 3)	/* FIFO Error */
+
+#define MOSR		__REG(0x40500110)  /* Modem Out Status Register */
+#define MOSR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define MISR		__REG(0x40500118)  /* Modem In Status Register */
+#define MISR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define MODR		__REG(0x40500140)  /* Modem FIFO Data Register */
+
+#define PAC_REG_BASE	__REG(0x40500200)  /* Primary Audio Codec */
+#define SAC_REG_BASE	__REG(0x40500300)  /* Secondary Audio Codec */
+#define PMC_REG_BASE	__REG(0x40500400)  /* Primary Modem Codec */
+#define SMC_REG_BASE	__REG(0x40500500)  /* Secondary Modem Codec */
+
+
+/*
+ * USB Device Controller
+ */
+#define UDC_RES1	__REG(0x40600004)  /* UDC Undocumented - Reserved1 */
+#define UDC_RES2	__REG(0x40600008)  /* UDC Undocumented - Reserved2 */
+#define UDC_RES3	__REG(0x4060000C)  /* UDC Undocumented - Reserved3 */
+
+#define UDCCR		__REG(0x40600000)  /* UDC Control Register */
+#define UDCCR_UDE	(1 << 0)	/* UDC enable */
+#define UDCCR_UDA	(1 << 1)	/* UDC active */
+#define UDCCR_RSM	(1 << 2)	/* Device resume */
+#define UDCCR_RESIR	(1 << 3)	/* Resume interrupt request */
+#define UDCCR_SUSIR	(1 << 4)	/* Suspend interrupt request */
+#define UDCCR_SRM	(1 << 5)	/* Suspend/resume interrupt mask */
+#define UDCCR_RSTIR	(1 << 6)	/* Reset interrupt request */
+#define UDCCR_REM	(1 << 7)	/* Reset interrupt mask */
+
+#define UDCCS0		__REG(0x40600010)  /* UDC Endpoint 0 Control/Status Register */
+#define UDCCS0_OPR	(1 << 0)	/* OUT packet ready */
+#define UDCCS0_IPR	(1 << 1)	/* IN packet ready */
+#define UDCCS0_FTF	(1 << 2)	/* Flush Tx FIFO */
+#define UDCCS0_DRWF	(1 << 3)	/* Device remote wakeup feature */
+#define UDCCS0_SST	(1 << 4)	/* Sent stall */
+#define UDCCS0_FST	(1 << 5)	/* Force stall */
+#define UDCCS0_RNE	(1 << 6)	/* Receive FIFO no empty */
+#define UDCCS0_SA	(1 << 7)	/* Setup active */
+
+/* Bulk IN - Endpoint 1,6,11 */
+#define UDCCS1		__REG(0x40600014)  /* UDC Endpoint 1 (IN) Control/Status Register */
+#define UDCCS6		__REG(0x40600028)  /* UDC Endpoint 6 (IN) Control/Status Register */
+#define UDCCS11		__REG(0x4060003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
+
+#define UDCCS_BI_TFS	(1 << 0)	/* Transmit FIFO service */
+#define UDCCS_BI_TPC	(1 << 1)	/* Transmit packet complete */
+#define UDCCS_BI_FTF	(1 << 2)	/* Flush Tx FIFO */
+#define UDCCS_BI_TUR	(1 << 3)	/* Transmit FIFO underrun */
+#define UDCCS_BI_SST	(1 << 4)	/* Sent stall */
+#define UDCCS_BI_FST	(1 << 5)	/* Force stall */
+#define UDCCS_BI_TSP	(1 << 7)	/* Transmit short packet */
+
+/* Bulk OUT - Endpoint 2,7,12 */
+#define UDCCS2		__REG(0x40600018)  /* UDC Endpoint 2 (OUT) Control/Status Register */
+#define UDCCS7		__REG(0x4060002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
+#define UDCCS12		__REG(0x40600040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
+
+#define UDCCS_BO_RFS	(1 << 0)	/* Receive FIFO service */
+#define UDCCS_BO_RPC	(1 << 1)	/* Receive packet complete */
+#define UDCCS_BO_DME	(1 << 3)	/* DMA enable */
+#define UDCCS_BO_SST	(1 << 4)	/* Sent stall */
+#define UDCCS_BO_FST	(1 << 5)	/* Force stall */
+#define UDCCS_BO_RNE	(1 << 6)	/* Receive FIFO not empty */
+#define UDCCS_BO_RSP	(1 << 7)	/* Receive short packet */
+
+/* Isochronous IN - Endpoint 3,8,13 */
+#define UDCCS3		__REG(0x4060001C)  /* UDC Endpoint 3 (IN) Control/Status Register */
+#define UDCCS8		__REG(0x40600030)  /* UDC Endpoint 8 (IN) Control/Status Register */
+#define UDCCS13		__REG(0x40600044)  /* UDC Endpoint 13 (IN) Control/Status Register */
+
+#define UDCCS_II_TFS	(1 << 0)	/* Transmit FIFO service */
+#define UDCCS_II_TPC	(1 << 1)	/* Transmit packet complete */
+#define UDCCS_II_FTF	(1 << 2)	/* Flush Tx FIFO */
+#define UDCCS_II_TUR	(1 << 3)	/* Transmit FIFO underrun */
+#define UDCCS_II_TSP	(1 << 7)	/* Transmit short packet */
+
+/* Isochronous OUT - Endpoint 4,9,14 */
+#define UDCCS4		__REG(0x40600020)  /* UDC Endpoint 4 (OUT) Control/Status Register */
+#define UDCCS9		__REG(0x40600034)  /* UDC Endpoint 9 (OUT) Control/Status Register */
+#define UDCCS14		__REG(0x40600048)  /* UDC Endpoint 14 (OUT) Control/Status Register */
+
+#define UDCCS_IO_RFS	(1 << 0)	/* Receive FIFO service */
+#define UDCCS_IO_RPC	(1 << 1)	/* Receive packet complete */
+#define UDCCS_IO_ROF	(1 << 3)	/* Receive overflow */
+#define UDCCS_IO_DME	(1 << 3)	/* DMA enable */
+#define UDCCS_IO_RNE	(1 << 6)	/* Receive FIFO not empty */
+#define UDCCS_IO_RSP	(1 << 7)	/* Receive short packet */
+
+/* Interrupt IN - Endpoint 5,10,15 */
+#define UDCCS5		__REG(0x40600024)  /* UDC Endpoint 5 (Interrupt) Control/Status Register */
+#define UDCCS10		__REG(0x40600038)  /* UDC Endpoint 10 (Interrupt) Control/Status Register */
+#define UDCCS15		__REG(0x4060004C)  /* UDC Endpoint 15 (Interrupt) Control/Status Register */
+
+#define UDCCS_INT_TFS	(1 << 0)	/* Transmit FIFO service */
+#define UDCCS_INT_TPC	(1 << 1)	/* Transmit packet complete */
+#define UDCCS_INT_FTF	(1 << 2)	/* Flush Tx FIFO */
+#define UDCCS_INT_TUR	(1 << 3)	/* Transmit FIFO underrun */
+#define UDCCS_INT_SST	(1 << 4)	/* Sent stall */
+#define UDCCS_INT_FST	(1 << 5)	/* Force stall */
+#define UDCCS_INT_TSP	(1 << 7)	/* Transmit short packet */
+
+#define UFNRH		__REG(0x40600060)  /* UDC Frame Number Register High */
+#define UFNRL		__REG(0x40600064)  /* UDC Frame Number Register Low */
+#define UBCR2		__REG(0x40600068)  /* UDC Byte Count Reg 2 */
+#define UBCR4		__REG(0x4060006c)  /* UDC Byte Count Reg 4 */
+#define UBCR7		__REG(0x40600070)  /* UDC Byte Count Reg 7 */
+#define UBCR9		__REG(0x40600074)  /* UDC Byte Count Reg 9 */
+#define UBCR12		__REG(0x40600078)  /* UDC Byte Count Reg 12 */
+#define UBCR14		__REG(0x4060007c)  /* UDC Byte Count Reg 14 */
+#define UDDR0		__REG(0x40600080)  /* UDC Endpoint 0 Data Register */
+#define UDDR1		__REG(0x40600100)  /* UDC Endpoint 1 Data Register */
+#define UDDR2		__REG(0x40600180)  /* UDC Endpoint 2 Data Register */
+#define UDDR3		__REG(0x40600200)  /* UDC Endpoint 3 Data Register */
+#define UDDR4		__REG(0x40600400)  /* UDC Endpoint 4 Data Register */
+#define UDDR5		__REG(0x406000A0)  /* UDC Endpoint 5 Data Register */
+#define UDDR6		__REG(0x40600600)  /* UDC Endpoint 6 Data Register */
+#define UDDR7		__REG(0x40600680)  /* UDC Endpoint 7 Data Register */
+#define UDDR8		__REG(0x40600700)  /* UDC Endpoint 8 Data Register */
+#define UDDR9		__REG(0x40600900)  /* UDC Endpoint 9 Data Register */
+#define UDDR10		__REG(0x406000C0)  /* UDC Endpoint 10 Data Register */
+#define UDDR11		__REG(0x40600B00)  /* UDC Endpoint 11 Data Register */
+#define UDDR12		__REG(0x40600B80)  /* UDC Endpoint 12 Data Register */
+#define UDDR13		__REG(0x40600C00)  /* UDC Endpoint 13 Data Register */
+#define UDDR14		__REG(0x40600E00)  /* UDC Endpoint 14 Data Register */
+#define UDDR15		__REG(0x406000E0)  /* UDC Endpoint 15 Data Register */
+
+#define UICR0		__REG(0x40600050)  /* UDC Interrupt Control Register 0 */
+
+#define UICR0_IM0	(1 << 0)	/* Interrupt mask ep 0 */
+#define UICR0_IM1	(1 << 1)	/* Interrupt mask ep 1 */
+#define UICR0_IM2	(1 << 2)	/* Interrupt mask ep 2 */
+#define UICR0_IM3	(1 << 3)	/* Interrupt mask ep 3 */
+#define UICR0_IM4	(1 << 4)	/* Interrupt mask ep 4 */
+#define UICR0_IM5	(1 << 5)	/* Interrupt mask ep 5 */
+#define UICR0_IM6	(1 << 6)	/* Interrupt mask ep 6 */
+#define UICR0_IM7	(1 << 7)	/* Interrupt mask ep 7 */
+
+#define UICR1		__REG(0x40600054)  /* UDC Interrupt Control Register 1 */
+
+#define UICR1_IM8	(1 << 0)	/* Interrupt mask ep 8 */
+#define UICR1_IM9	(1 << 1)	/* Interrupt mask ep 9 */
+#define UICR1_IM10	(1 << 2)	/* Interrupt mask ep 10 */
+#define UICR1_IM11	(1 << 3)	/* Interrupt mask ep 11 */
+#define UICR1_IM12	(1 << 4)	/* Interrupt mask ep 12 */
+#define UICR1_IM13	(1 << 5)	/* Interrupt mask ep 13 */
+#define UICR1_IM14	(1 << 6)	/* Interrupt mask ep 14 */
+#define UICR1_IM15	(1 << 7)	/* Interrupt mask ep 15 */
+
+#define USIR0		__REG(0x40600058)  /* UDC Status Interrupt Register 0 */
+
+#define USIR0_IR0	(1 << 0)	/* Interrup request ep 0 */
+#define USIR0_IR1	(1 << 1)	/* Interrup request ep 1 */
+#define USIR0_IR2	(1 << 2)	/* Interrup request ep 2 */
+#define USIR0_IR3	(1 << 3)	/* Interrup request ep 3 */
+#define USIR0_IR4	(1 << 4)	/* Interrup request ep 4 */
+#define USIR0_IR5	(1 << 5)	/* Interrup request ep 5 */
+#define USIR0_IR6	(1 << 6)	/* Interrup request ep 6 */
+#define USIR0_IR7	(1 << 7)	/* Interrup request ep 7 */
+
+#define USIR1		__REG(0x4060005C)  /* UDC Status Interrupt Register 1 */
+
+#define USIR1_IR8	(1 << 0)	/* Interrup request ep 8 */
+#define USIR1_IR9	(1 << 1)	/* Interrup request ep 9 */
+#define USIR1_IR10	(1 << 2)	/* Interrup request ep 10 */
+#define USIR1_IR11	(1 << 3)	/* Interrup request ep 11 */
+#define USIR1_IR12	(1 << 4)	/* Interrup request ep 12 */
+#define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */
+#define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */
+#define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */
+
+
+/*
+ * Fast Infrared Communication Port
+ */
+
+#define ICCR0		__REG(0x40800000)  /* ICP Control Register 0 */
+#define ICCR1		__REG(0x40800004)  /* ICP Control Register 1 */
+#define ICCR2		__REG(0x40800008)  /* ICP Control Register 2 */
+#define ICDR		__REG(0x4080000c)  /* ICP Data Register */
+#define ICSR0		__REG(0x40800014)  /* ICP Status Register 0 */
+#define ICSR1		__REG(0x40800018)  /* ICP Status Register 1 */
+
+#define ICCR0_AME       (1 << 7)           /* Adress match enable */
+#define ICCR0_TIE       (1 << 6)           /* Transmit FIFO interrupt enable */ 
+#define ICCR0_RIE       (1 << 5)           /* Recieve FIFO interrupt enable */
+#define ICCR0_RXE       (1 << 4)           /* Receive enable */
+#define ICCR0_TXE       (1 << 3)           /* Transmit enable */
+#define ICCR0_TUS       (1 << 2)           /* Transmit FIFO underrun select */
+#define ICCR0_LBM       (1 << 1)           /* Loopback mode */
+#define ICCR0_ITR       (1 << 0)           /* IrDA transmission */
+
+#define ICSR0_FRE       (1 << 5)           /* Framing error */
+#define ICSR0_RFS       (1 << 4)           /* Receive FIFO service request */
+#define ICSR0_TFS       (1 << 3)           /* Transnit FIFO service request */
+#define ICSR0_RAB       (1 << 2)           /* Receiver abort */
+#define ICSR0_TUR       (1 << 1)           /* Trunsmit FIFO underun */
+#define ICSR0_EIF       (1 << 0)           /* End/Error in FIFO */
+
+#define ICSR1_ROR       (1 << 6)           /* Receiver FIFO underrun  */
+#define ICSR1_CRE       (1 << 5)           /* CRC error */
+#define ICSR1_EOF       (1 << 4)           /* End of frame */
+#define ICSR1_TNF       (1 << 3)           /* Transmit FIFO not full */
+#define ICSR1_RNE       (1 << 2)           /* Receive FIFO not empty */
+#define ICSR1_TBY       (1 << 1)           /* Tramsmiter busy flag */
+#define ICSR1_RSY       (1 << 0)           /* Recevier synchronized flag */
+
+
+/*
+ * Real Time Clock
+ */
+
+#define RCNR		__REG(0x40900000)  /* RTC Count Register */
+#define RTAR		__REG(0x40900004)  /* RTC Alarm Register */
+#define RTSR		__REG(0x40900008)  /* RTC Status Register */
+#define RTTR		__REG(0x4090000C)  /* RTC Timer Trim Register */
+
+#define RTSR_HZE	(1 << 3)	/* HZ interrupt enable */
+#define RTSR_ALE	(1 << 2)	/* RTC alarm interrupt enable */
+#define RTSR_HZ		(1 << 1)	/* HZ rising-edge detected */
+#define RTSR_AL		(1 << 0)	/* RTC alarm detected */
+
+
+/*
+ * OS Timer & Match Registers
+ */
+
+#define OSMR0		__REG(0x40A00000)  /* */
+#define OSMR1		__REG(0x40A00004)  /* */
+#define OSMR2		__REG(0x40A00008)  /* */
+#define OSMR3		__REG(0x40A0000C)  /* */
+#define OSCR		__REG(0x40A00010)  /* OS Timer Counter Register */
+#define OSSR		__REG(0x40A00014)  /* OS Timer Status Register */
+#define OWER		__REG(0x40A00018)  /* OS Timer Watchdog Enable Register */
+#define OIER		__REG(0x40A0001C)  /* OS Timer Interrupt Enable Register */
+
+#define OSSR_M3		(1 << 3)	/* Match status channel 3 */
+#define OSSR_M2		(1 << 2)	/* Match status channel 2 */
+#define OSSR_M1		(1 << 1)	/* Match status channel 1 */
+#define OSSR_M0		(1 << 0)	/* Match status channel 0 */
+
+#define OWER_WME	(1 << 0)	/* Watchdog Match Enable */
+
+#define OIER_E3		(1 << 3)	/* Interrupt enable channel 3 */
+#define OIER_E2		(1 << 2)	/* Interrupt enable channel 2 */
+#define OIER_E1		(1 << 1)	/* Interrupt enable channel 1 */
+#define OIER_E0		(1 << 0)	/* Interrupt enable channel 0 */
+
+
+/*
+ * Pulse Width Modulator
+ */
+
+#define PWM_CTRL0	__REG(0x40B00000)  /* PWM 0 Control Register */
+#define PWM_PWDUTY0	__REG(0x40B00004)  /* PWM 0 Duty Cycle Register */
+#define PWM_PERVAL0	__REG(0x40B00008)  /* PWM 0 Period Control Register */
+
+#define PWM_CTRL1	__REG(0x40C00000)  /* PWM 1Control Register */
+#define PWM_PWDUTY1	__REG(0x40C00004)  /* PWM 1 Duty Cycle Register */
+#define PWM_PERVAL1	__REG(0x40C00008)  /* PWM 1 Period Control Register */
+
+
+/*
+ * Interrupt Controller
+ */
+
+#define ICIP		__REG(0x40D00000)  /* Interrupt Controller IRQ Pending Register */
+#define ICMR		__REG(0x40D00004)  /* Interrupt Controller Mask Register */
+#define ICLR		__REG(0x40D00008)  /* Interrupt Controller Level Register */
+#define ICFP		__REG(0x40D0000C)  /* Interrupt Controller FIQ Pending Register */
+#define ICPR		__REG(0x40D00010)  /* Interrupt Controller Pending Register */
+#define ICCR		__REG(0x40D00014)  /* Interrupt Controller Control Register */
+
+
+/*
+ * General Purpose I/O
+ */
+
+#define GPLR0		__REG(0x40E00000)  /* GPIO Pin-Level Register GPIO<31:0> */
+#define GPLR1		__REG(0x40E00004)  /* GPIO Pin-Level Register GPIO<63:32> */
+#define GPLR2		__REG(0x40E00008)  /* GPIO Pin-Level Register GPIO<80:64> */
+
+#define GPDR0		__REG(0x40E0000C)  /* GPIO Pin Direction Register GPIO<31:0> */
+#define GPDR1		__REG(0x40E00010)  /* GPIO Pin Direction Register GPIO<63:32> */
+#define GPDR2		__REG(0x40E00014)  /* GPIO Pin Direction Register GPIO<80:64> */
+
+#define GPSR0		__REG(0x40E00018)  /* GPIO Pin Output Set Register GPIO<31:0> */
+#define GPSR1		__REG(0x40E0001C)  /* GPIO Pin Output Set Register GPIO<63:32> */
+#define GPSR2		__REG(0x40E00020)  /* GPIO Pin Output Set Register GPIO<80:64> */
+
+#define GPCR0		__REG(0x40E00024)  /* GPIO Pin Output Clear Register GPIO<31:0> */
+#define GPCR1		__REG(0x40E00028)  /* GPIO Pin Output Clear Register GPIO <63:32> */
+#define GPCR2		__REG(0x40E0002C)  /* GPIO Pin Output Clear Register GPIO <80:64> */
+
+#define GRER0		__REG(0x40E00030)  /* GPIO Rising-Edge Detect Register GPIO<31:0> */
+#define GRER1		__REG(0x40E00034)  /* GPIO Rising-Edge Detect Register GPIO<63:32> */
+#define GRER2		__REG(0x40E00038)  /* GPIO Rising-Edge Detect Register GPIO<80:64> */
+
+#define GFER0		__REG(0x40E0003C)  /* GPIO Falling-Edge Detect Register GPIO<31:0> */
+#define GFER1		__REG(0x40E00040)  /* GPIO Falling-Edge Detect Register GPIO<63:32> */
+#define GFER2		__REG(0x40E00044)  /* GPIO Falling-Edge Detect Register GPIO<80:64> */
+
+#define GEDR0		__REG(0x40E00048)  /* GPIO Edge Detect Status Register GPIO<31:0> */
+#define GEDR1		__REG(0x40E0004C)  /* GPIO Edge Detect Status Register GPIO<63:32> */
+#define GEDR2		__REG(0x40E00050)  /* GPIO Edge Detect Status Register GPIO<80:64> */
+
+#define GAFR0_L		__REG(0x40E00054)  /* GPIO Alternate Function Select Register GPIO<15:0> */
+#define GAFR0_U		__REG(0x40E00058)  /* GPIO Alternate Function Select Register GPIO<31:16> */
+#define GAFR1_L		__REG(0x40E0005C)  /* GPIO Alternate Function Select Register GPIO<47:32> */
+#define GAFR1_U		__REG(0x40E00060)  /* GPIO Alternate Function Select Register GPIO<63:48> */
+#define GAFR2_L		__REG(0x40E00064)  /* GPIO Alternate Function Select Register GPIO<79:64> */
+#define GAFR2_U		__REG(0x40E00068)  /* GPIO Alternate Function Select Register GPIO 80 */
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+#define GPLR(x)		__REG2(0x40E00000, ((x) & 0x60) >> 3)
+#define GPDR(x)		__REG2(0x40E0000C, ((x) & 0x60) >> 3)
+#define GPSR(x)		__REG2(0x40E00018, ((x) & 0x60) >> 3)
+#define GPCR(x)		__REG2(0x40E00024, ((x) & 0x60) >> 3)
+#define GRER(x)		__REG2(0x40E00030, ((x) & 0x60) >> 3)
+#define GFER(x)		__REG2(0x40E0003C, ((x) & 0x60) >> 3)
+#define GEDR(x)		__REG2(0x40E00048, ((x) & 0x60) >> 3)
+#define GAFR(x)		__REG2(0x40E00054, ((x) & 0x70) >> 2)
+
+/* GPIO alternate function assignments */
+
+#define GPIO1_RST		1	/* reset */
+#define GPIO6_MMCCLK		6	/* MMC Clock */
+#define GPIO8_48MHz		7	/* 48 MHz clock output */
+#define GPIO8_MMCCS0		8	/* MMC Chip Select 0 */
+#define GPIO9_MMCCS1		9	/* MMC Chip Select 1 */
+#define GPIO10_RTCCLK		10	/* real time clock (1 Hz) */
+#define GPIO11_3_6MHz		11	/* 3.6 MHz oscillator out */
+#define GPIO12_32KHz		12	/* 32 kHz out */
+#define GPIO13_MBGNT		13	/* memory controller grant */
+#define GPIO14_MBREQ		14	/* alternate bus master request */
+#define GPIO15_nCS_1		15	/* chip select 1 */
+#define GPIO16_PWM0		16	/* PWM0 output */
+#define GPIO17_PWM1		17	/* PWM1 output */
+#define GPIO18_RDY		18	/* Ext. Bus Ready */
+#define GPIO19_DREQ1		19	/* External DMA Request */
+#define GPIO20_DREQ0		20	/* External DMA Request */
+#define GPIO23_SCLK		23	/* SSP clock */
+#define GPIO24_SFRM		24	/* SSP Frame */
+#define GPIO25_STXD		25	/* SSP transmit */
+#define GPIO26_SRXD		26	/* SSP receive */
+#define GPIO27_SEXTCLK		27	/* SSP ext_clk */
+#define GPIO28_BITCLK		28	/* AC97/I2S bit_clk */
+#define GPIO29_SDATA_IN		29	/* AC97 Sdata_in0 / I2S Sdata_in */
+#define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
+#define GPIO31_SYNC		31	/* AC97/I2S sync */
+#define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
+#define GPIO33_nCS_5		33	/* chip select 5 */
+#define GPIO34_FFRXD		34	/* FFUART receive */
+#define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
+#define GPIO35_FFCTS		35	/* FFUART Clear to send */
+#define GPIO36_FFDCD		36	/* FFUART Data carrier detect */
+#define GPIO37_FFDSR		37	/* FFUART data set ready */
+#define GPIO38_FFRI		38	/* FFUART Ring Indicator */
+#define GPIO39_MMCCS1		39	/* MMC Chip Select 1 */
+#define GPIO39_FFTXD		39	/* FFUART transmit data */
+#define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
+#define GPIO41_FFRTS		41	/* FFUART request to send */
+#define GPIO42_BTRXD		42	/* BTUART receive data */
+#define GPIO43_BTTXD		43	/* BTUART transmit data */
+#define GPIO44_BTCTS		44	/* BTUART clear to send */
+#define GPIO45_BTRTS		45	/* BTUART request to send */
+#define GPIO46_ICPRXD		46	/* ICP receive data */
+#define GPIO46_STRXD		46	/* STD_UART receive data */
+#define GPIO47_ICPTXD		47	/* ICP transmit data */
+#define GPIO47_STTXD		47	/* STD_UART transmit data */
+#define GPIO48_nPOE		48	/* Output Enable for Card Space */
+#define GPIO49_nPWE		49	/* Write Enable for Card Space */
+#define GPIO50_nPIOR		50	/* I/O Read for Card Space */
+#define GPIO51_nPIOW		51	/* I/O Write for Card Space */
+#define GPIO52_nPCE_1		52	/* Card Enable for Card Space */
+#define GPIO53_nPCE_2		53	/* Card Enable for Card Space */
+#define GPIO53_MMCCLK		53	/* MMC Clock */
+#define GPIO54_MMCCLK		54	/* MMC Clock */
+#define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
+#define GPIO55_nPREG		55	/* Card Address bit 26 */
+#define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
+#define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
+#define GPIO58_LDD_0		58	/* LCD data pin 0 */
+#define GPIO59_LDD_1		59	/* LCD data pin 1 */
+#define GPIO60_LDD_2		60	/* LCD data pin 2 */
+#define GPIO61_LDD_3		61	/* LCD data pin 3 */
+#define GPIO62_LDD_4		62	/* LCD data pin 4 */
+#define GPIO63_LDD_5		63	/* LCD data pin 5 */
+#define GPIO64_LDD_6		64	/* LCD data pin 6 */
+#define GPIO65_LDD_7		65	/* LCD data pin 7 */
+#define GPIO66_LDD_8		66	/* LCD data pin 8 */
+#define GPIO66_MBREQ		66	/* alternate bus master req */
+#define GPIO67_LDD_9		67	/* LCD data pin 9 */
+#define GPIO67_MMCCS0		67	/* MMC Chip Select 0 */
+#define GPIO68_LDD_10		68	/* LCD data pin 10 */
+#define GPIO68_MMCCS1		68	/* MMC Chip Select 1 */
+#define GPIO69_LDD_11		69	/* LCD data pin 11 */
+#define GPIO69_MMCCLK		69	/* MMC_CLK */
+#define GPIO70_LDD_12		70	/* LCD data pin 12 */
+#define GPIO70_RTCCLK		70	/* Real Time clock (1 Hz) */
+#define GPIO71_LDD_13		71	/* LCD data pin 13 */
+#define GPIO71_3_6MHz		71	/* 3.6 MHz Oscillator clock */
+#define GPIO72_LDD_14		72	/* LCD data pin 14 */
+#define GPIO72_32kHz		72	/* 32 kHz clock */
+#define GPIO73_LDD_15		73	/* LCD data pin 15 */
+#define GPIO73_MBGNT		73	/* Memory controller grant */
+#define GPIO74_LCD_FCLK		74	/* LCD Frame clock */
+#define GPIO75_LCD_LCLK		75	/* LCD line clock */
+#define GPIO76_LCD_PCLK		76	/* LCD Pixel clock */
+#define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
+#define GPIO78_nCS_2		78	/* chip select 2 */
+#define GPIO79_nCS_3		79	/* chip select 3 */
+#define GPIO80_nCS_4		80	/* chip select 4 */
+
+/* GPIO alternate function mode & direction */
+
+#define GPIO_IN			0x000
+#define GPIO_OUT		0x080
+#define GPIO_ALT_FN_1_IN	0x100
+#define GPIO_ALT_FN_1_OUT	0x180
+#define GPIO_ALT_FN_2_IN	0x200
+#define GPIO_ALT_FN_2_OUT	0x280
+#define GPIO_ALT_FN_3_IN	0x300
+#define GPIO_ALT_FN_3_OUT	0x380
+#define GPIO_MD_MASK_NR		0x07f
+#define GPIO_MD_MASK_DIR	0x080
+#define GPIO_MD_MASK_FN		0x300
+
+#define GPIO1_RTS_MD		( 1 | GPIO_ALT_FN_1_IN)
+#define GPIO6_MMCCLK_MD		( 6 | GPIO_ALT_FN_1_OUT)
+#define GPIO8_48MHz_MD		( 8 | GPIO_ALT_FN_1_OUT)
+#define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
+#define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
+#define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
+#define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
+#define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
+#define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
+#define GPIO14_MBREQ_MD		(14 | GPIO_ALT_FN_1_IN)
+#define GPIO15_nCS_1_MD		(15 | GPIO_ALT_FN_2_OUT)
+#define GPIO16_PWM0_MD		(16 | GPIO_ALT_FN_2_OUT)
+#define GPIO17_PWM1_MD		(17 | GPIO_ALT_FN_2_OUT)
+#define GPIO18_RDY_MD		(18 | GPIO_ALT_FN_1_IN)
+#define GPIO19_DREQ1_MD		(19 | GPIO_ALT_FN_1_IN)
+#define GPIO20_DREQ0_MD		(20 | GPIO_ALT_FN_1_IN)
+#define GPIO23_SCLK_md		(23 | GPIO_ALT_FN_2_OUT)
+#define GPIO24_SFRM_MD		(24 | GPIO_ALT_FN_2_OUT)
+#define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
+#define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
+#define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
+#define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
+#define GPIO28_BITCLK_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
+#define GPIO29_SDATA_IN_AC97_MD	(29 | GPIO_ALT_FN_1_IN)
+#define GPIO29_SDATA_IN_I2S_MD	(29 | GPIO_ALT_FN_2_IN)
+#define GPIO30_SDATA_OUT_AC97_MD	(30 | GPIO_ALT_FN_2_OUT)
+#define GPIO30_SDATA_OUT_I2S_MD	(30 | GPIO_ALT_FN_1_OUT)
+#define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
+#define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
+#define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
+#define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
+#define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
+#define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
+#define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
+#define GPIO36_FFDCD_MD		(36 | GPIO_ALT_FN_1_IN)
+#define GPIO37_FFDSR_MD		(37 | GPIO_ALT_FN_1_IN)
+#define GPIO38_FFRI_MD		(38 | GPIO_ALT_FN_1_IN)
+#define GPIO39_MMCCS1_MD	(39 | GPIO_ALT_FN_1_OUT)
+#define GPIO39_FFTXD_MD		(39 | GPIO_ALT_FN_2_OUT)
+#define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
+#define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
+#define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
+#define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
+#define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
+#define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
+#define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
+#define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
+#define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
+#define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
+#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
+#define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
+#define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
+#define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
+#define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
+#define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
+#define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
+#define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
+#define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
+#define GPIO57_nIOIS16_MD	(57 | GPIO_ALT_FN_1_IN)
+#define GPIO58_LDD_0_MD		(58 | GPIO_ALT_FN_2_OUT)
+#define GPIO59_LDD_1_MD		(59 | GPIO_ALT_FN_2_OUT)
+#define GPIO60_LDD_2_MD		(60 | GPIO_ALT_FN_2_OUT)
+#define GPIO61_LDD_3_MD		(61 | GPIO_ALT_FN_2_OUT)
+#define GPIO62_LDD_4_MD		(62 | GPIO_ALT_FN_2_OUT)
+#define GPIO63_LDD_5_MD		(63 | GPIO_ALT_FN_2_OUT)
+#define GPIO64_LDD_6_MD		(64 | GPIO_ALT_FN_2_OUT)
+#define GPIO65_LDD_7_MD		(65 | GPIO_ALT_FN_2_OUT)
+#define GPIO66_LDD_8_MD		(66 | GPIO_ALT_FN_2_OUT)
+#define GPIO66_MBREQ_MD		(66 | GPIO_ALT_FN_1_IN)
+#define GPIO67_LDD_9_MD		(67 | GPIO_ALT_FN_2_OUT)
+#define GPIO67_MMCCS0_MD	(67 | GPIO_ALT_FN_1_OUT)
+#define GPIO68_LDD_10_MD	(68 | GPIO_ALT_FN_2_OUT)
+#define GPIO68_MMCCS1_MD	(68 | GPIO_ALT_FN_1_OUT)
+#define GPIO69_LDD_11_MD	(69 | GPIO_ALT_FN_2_OUT)
+#define GPIO69_MMCCLK_MD	(69 | GPIO_ALT_FN_1_OUT)
+#define GPIO70_LDD_12_MD	(70 | GPIO_ALT_FN_2_OUT)
+#define GPIO70_RTCCLK_MD	(70 | GPIO_ALT_FN_1_OUT)
+#define GPIO71_LDD_13_MD	(71 | GPIO_ALT_FN_2_OUT)
+#define GPIO71_3_6MHz_MD	(71 | GPIO_ALT_FN_1_OUT)
+#define GPIO72_LDD_14_MD	(72 | GPIO_ALT_FN_2_OUT)
+#define GPIO72_32kHz_MD		(72 | GPIO_ALT_FN_1_OUT)
+#define GPIO73_LDD_15_MD	(73 | GPIO_ALT_FN_2_OUT)
+#define GPIO73_MBGNT_MD		(73 | GPIO_ALT_FN_1_OUT)
+#define GPIO74_LCD_FCLK_MD	(74 | GPIO_ALT_FN_2_OUT)
+#define GPIO75_LCD_LCLK_MD	(75 | GPIO_ALT_FN_2_OUT)
+#define GPIO76_LCD_PCLK_MD	(76 | GPIO_ALT_FN_2_OUT)
+#define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
+#define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
+#define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
+#define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
+
+
+/*
+ * Power Manager
+ */
+
+#define PMCR		__REG(0x40F00000)  /* Power Manager Control Register */
+#define PSSR		__REG(0x40F00004)  /* Power Manager Sleep Status Register */
+#define PSPR		__REG(0x40F00008)  /* Power Manager Scratch Pad Register */
+#define PWER		__REG(0x40F0000C)  /* Power Manager Wake-up Enable Register */
+#define PRER		__REG(0x40F00010)  /* Power Manager GPIO Rising-Edge Detect Enable Register */
+#define PFER		__REG(0x40F00014)  /* Power Manager GPIO Falling-Edge Detect Enable Register */
+#define PEDR		__REG(0x40F00018)  /* Power Manager GPIO Edge Detect Status Register */
+#define PCFR		__REG(0x40F0001C)  /* Power Manager General Configuration Register */
+#define PGSR0		__REG(0x40F00020)  /* Power Manager GPIO Sleep State Register for GP[31-0] */
+#define PGSR1		__REG(0x40F00024)  /* Power Manager GPIO Sleep State Register for GP[63-32] */
+#define PGSR2		__REG(0x40F00028)  /* Power Manager GPIO Sleep State Register for GP[84-64] */
+#define RCSR		__REG(0x40F00030)  /* Reset Controller Status Register */
+
+#define PSSR_RDH	(1 << 5)	/* Read Disable Hold */
+#define PSSR_PH		(1 << 4)	/* Peripheral Control Hold */
+#define PSSR_VFS	(1 << 2)	/* VDD Fault Status */
+#define PSSR_BFS	(1 << 1)	/* Battery Fault Status */
+#define PSSR_SSS	(1 << 0)	/* Software Sleep Status */
+
+#define PCFR_DS		(1 << 3)	/* Deep Sleep Mode */
+#define PCFR_FS		(1 << 2)	/* Float Static Chip Selects */
+#define PCFR_FP		(1 << 1)	/* Float PCMCIA controls */
+#define PCFR_OPDE	(1 << 0)	/* 3.6864 MHz oscillator power-down enable */
+
+#define RCSR_GPR	(1 << 3)	/* GPIO Reset */
+#define RCSR_SMR	(1 << 2)	/* Sleep Mode */
+#define RCSR_WDR	(1 << 1)	/* Watchdog Reset */
+#define RCSR_HWR	(1 << 0)	/* Hardware Reset */
+
+
+/*
+ * SSP Serial Port Registers
+ */
+
+#define SSCR0		__REG(0x41000000)  /* SSP Control Register 0 */
+#define SSCR1		__REG(0x41000004)  /* SSP Control Register 1 */
+#define SSSR		__REG(0x41000008)  /* SSP Status Register */
+#define SSITR		__REG(0x4100000C)  /* SSP Interrupt Test Register */
+#define SSDR		__REG(0x41000010)  /* (Write / Read) SSP Data Write Register/SSP Data Read Register */
+
+
+/*
+ * MultiMediaCard (MMC) controller
+ */
+
+#define MMC_STRPCL	__REG(0x41100000)  /* Control to start and stop MMC clock */
+#define MMC_STAT	__REG(0x41100004)  /* MMC Status Register (read only) */
+#define MMC_CLKRT	__REG(0x41100008)  /* MMC clock rate */
+#define MMC_SPI		__REG(0x4110000c)  /* SPI mode control bits */
+#define MMC_CMDAT	__REG(0x41100010)  /* Command/response/data sequence control */
+#define MMC_RESTO	__REG(0x41100014)  /* Expected response time out */
+#define MMC_RDTO	__REG(0x41100018)  /* Expected data read time out */
+#define MMC_BLKLEN	__REG(0x4110001c)  /* Block length of data transaction */
+#define MMC_NOB		__REG(0x41100020)  /* Number of blocks, for block mode */
+#define MMC_PRTBUF	__REG(0x41100024)  /* Partial MMC_TXFIFO FIFO written */
+#define MMC_I_MASK	__REG(0x41100028)  /* Interrupt Mask */
+#define MMC_I_REG	__REG(0x4110002c)  /* Interrupt Register (read only) */
+#define MMC_CMD		__REG(0x41100030)  /* Index of current command */
+#define MMC_ARGH	__REG(0x41100034)  /* MSW part of the current command argument */
+#define MMC_ARGL	__REG(0x41100038)  /* LSW part of the current command argument */
+#define MMC_RES		__REG(0x4110003c)  /* Response FIFO (read only) */
+#define MMC_RXFIFO	__REG(0x41100040)  /* Receive FIFO (read only) */
+#define MMC_TXFIFO	__REG(0x41100044)  /* Transmit FIFO (write only) */
+
+
+/*
+ * Core Clock
+ */
+
+#define CCCR		__REG(0x41300000)  /* Core Clock Configuration Register */
+#define CKEN		__REG(0x41300004)  /* Clock Enable Register */
+#define OSCC		__REG(0x41300008)  /* Oscillator Configuration Register */
+
+#define CCCR_N_MASK	0x0380		/* Run Mode Frequency to Turbo Mode Frequency Multiplier */
+#define CCCR_M_MASK	0x0060		/* Memory Frequency to Run Mode Frequency Multiplier */
+#define CCCR_L_MASK	0x001f		/* Crystal Frequency to Memory Frequency Multiplier */
+
+#define CKEN16_LCD	(1 << 16)	/* LCD Unit Clock Enable */
+#define CKEN14_I2C	(1 << 14)	/* I2C Unit Clock Enable */
+#define CKEN13_FICP	(1 << 13)	/* FICP Unit Clock Enable */
+#define CKEN12_MMC	(1 << 12)	/* MMC Unit Clock Enable */
+#define CKEN11_USB	(1 << 11)	/* USB Unit Clock Enable */
+#define CKEN8_I2S	(1 << 8)	/* I2S Unit Clock Enable */
+#define CKEN7_BTUART	(1 << 7)	/* BTUART Unit Clock Enable */
+#define CKEN6_FFUART	(1 << 6)	/* FFUART Unit Clock Enable */
+#define CKEN5_STUART	(1 << 5)	/* STUART Unit Clock Enable */
+#define CKEN3_SSP	(1 << 3)	/* SSP Unit Clock Enable */
+#define CKEN2_AC97	(1 << 2)	/* AC97 Unit Clock Enable */
+#define CKEN1_PWM1	(1 << 1)	/* PWM1 Clock Enable */
+#define CKEN0_PWM0	(1 << 0)	/* PWM0 Clock Enable */
+
+#define OSCC_OON	(1 << 1)	/* 32.768kHz OON (write-once only bit) */
+#define OSCC_OOK	(1 << 0)	/* 32.768kHz OOK (read-only bit) */
+
+
+/*
+ * LCD
+ */
+
+#define LCCR0		__REG(0x44000000)  /* LCD Controller Control Register 0 */
+#define LCCR1		__REG(0x44000004)  /* LCD Controller Control Register 1 */
+#define LCCR2		__REG(0x44000008)  /* LCD Controller Control Register 2 */
+#define LCCR3		__REG(0x4400000C)  /* LCD Controller Control Register 3 */
+#define DFBR0		__REG(0x44000020)  /* DMA Channel 0 Frame Branch Register */
+#define DFBR1		__REG(0x44000024)  /* DMA Channel 1 Frame Branch Register */
+#define LCSR		__REG(0x44000038)  /* LCD Controller Status Register */
+#define LIIDR		__REG(0x4400003C)  /* LCD Controller Interrupt ID Register */
+#define TMEDRGBR	__REG(0x44000040)  /* TMED RGB Seed Register */
+#define TMEDCR		__REG(0x44000044)  /* TMED Control Register */
+
+#define FDADR0		__REG(0x44000200)  /* DMA Channel 0 Frame Descriptor Address Register */
+#define FSADR0		__REG(0x44000204)  /* DMA Channel 0 Frame Source Address Register */
+#define FIDR0		__REG(0x44000208)  /* DMA Channel 0 Frame ID Register */
+#define LDCMD0		__REG(0x4400020C)  /* DMA Channel 0 Command Register */
+#define FDADR1		__REG(0x44000210)  /* DMA Channel 1 Frame Descriptor Address Register */
+#define FSADR1		__REG(0x44000214)  /* DMA Channel 1 Frame Source Address Register */
+#define FIDR1		__REG(0x44000218)  /* DMA Channel 1 Frame ID Register */
+#define LDCMD1		__REG(0x4400021C)  /* DMA Channel 1 Command Register */
+
+#define LCCR0_ENB	(1 << 0)	/* LCD Controller enable */
+#define LCCR0_CMS	(1 << 1)	/* Color = 0, Monochrome = 1 */
+#define LCCR0_SDS	(1 << 2)	/* Single Panel = 0, Dual Panel = 1 */
+#define LCCR0_LDM	(1 << 3)	/* LCD Disable Done Mask */
+#define LCCR0_SFM	(1 << 4)	/* Start of frame mask */
+#define LCCR0_IUM	(1 << 5)	/* Input FIFO underrun mask */
+#define LCCR0_EFM	(1 << 6)	/* End of Frame mask */
+#define LCCR0_PAS	(1 << 7)	/* Passive = 0, Active = 1 */
+#define LCCR0_BLE	(1 << 8)	/* Little Endian = 0, Big Endian = 1 */
+#define LCCR0_DPD	(1 << 9)	/* Double Pixel mode, 4 pixel value = 0, 8 pixle values = 1 */
+#define LCCR0_DIS	(1 << 10)	/* LCD Disable */
+#define LCCR0_QDM	(1 << 11)	/* LCD Quick Disable mask */
+#define LCCR0_PDD	(0xff << 12)	/* Palette DMA request delay */
+#define LCCR0_PDD_S	12
+#define LCCR0_BM	(1 << 20) 	/* Branch mask */
+#define LCCR0_OUM	(1 << 21)	/* Output FIFO underrun mask */
+
+#define LCCR1_PPL       Fld (10, 0)      /* Pixels Per Line - 1 */
+#define LCCR1_DisWdth(Pixel)            /* Display Width [1..800 pix.]  */ \
+                        (((Pixel) - 1) << FShft (LCCR1_PPL))
+
+#define LCCR1_HSW       Fld (6, 10)     /* Horizontal Synchronization     */
+#define LCCR1_HorSnchWdth(Tpix)         /* Horizontal Synchronization     */ \
+                                        /* pulse Width [1..64 Tpix]       */ \
+                        (((Tpix) - 1) << FShft (LCCR1_HSW))
+
+#define LCCR1_ELW       Fld (8, 16)     /* End-of-Line pixel clock Wait    */
+                                        /* count - 1 [Tpix]                */
+#define LCCR1_EndLnDel(Tpix)            /*  End-of-Line Delay              */ \
+                                        /*  [1..256 Tpix]                  */ \
+                        (((Tpix) - 1) << FShft (LCCR1_ELW))
+
+#define LCCR1_BLW       Fld (8, 24)     /* Beginning-of-Line pixel clock   */
+                                        /* Wait count - 1 [Tpix]           */
+#define LCCR1_BegLnDel(Tpix)            /*  Beginning-of-Line Delay        */ \
+                                        /*  [1..256 Tpix]                  */ \
+                        (((Tpix) - 1) << FShft (LCCR1_BLW))
+
+
+#define LCCR2_LPP       Fld (10, 0)     /* Line Per Panel - 1              */
+#define LCCR2_DisHght(Line)             /*  Display Height [1..1024 lines] */ \
+                        (((Line) - 1) << FShft (LCCR2_LPP))
+
+#define LCCR2_VSW       Fld (6, 10)     /* Vertical Synchronization pulse  */
+                                        /* Width - 1 [Tln] (L_FCLK)        */
+#define LCCR2_VrtSnchWdth(Tln)          /*  Vertical Synchronization pulse */ \
+                                        /*  Width [1..64 Tln]              */ \
+                        (((Tln) - 1) << FShft (LCCR2_VSW))
+
+#define LCCR2_EFW       Fld (8, 16)     /* End-of-Frame line clock Wait    */
+                                        /* count [Tln]                     */
+#define LCCR2_EndFrmDel(Tln)            /*  End-of-Frame Delay             */ \
+                                        /*  [0..255 Tln]                   */ \
+                        ((Tln) << FShft (LCCR2_EFW))
+
+#define LCCR2_BFW       Fld (8, 24)     /* Beginning-of-Frame line clock   */
+                                        /* Wait count [Tln]                */
+#define LCCR2_BegFrmDel(Tln)            /*  Beginning-of-Frame Delay       */ \
+                                        /*  [0..255 Tln]                   */ \
+                        ((Tln) << FShft (LCCR2_BFW))
+
+#if 0
+#define LCCR3_PCD	(0xff)		/* Pixel clock divisor */
+#define LCCR3_ACB	(0xff << 8)	/* AC Bias pin frequency */
+#define LCCR3_ACB_S	8
+#endif
+
+#define LCCR3_API	(0xf << 16)	/* AC Bias pin trasitions per interrupt */
+#define LCCR3_API_S	16
+#define LCCR3_VSP	(1 << 20)	/* vertical sync polarity */
+#define LCCR3_HSP	(1 << 21)	/* horizontal sync polarity */
+#define LCCR3_PCP	(1 << 22)	/* pixel clock polarity */
+#define LCCR3_OEP	(1 << 23)	/* output enable polarity */
+#if 0
+#define LCCR3_BPP	(7 << 24)	/* bits per pixel */
+#define LCCR3_BPP_S	24
+#endif
+#define LCCR3_DPC	(1 << 27)	/* double pixel clock mode */
+
+
+#define LCCR3_PCD       Fld (8, 0)      /* Pixel Clock Divisor */
+#define LCCR3_PixClkDiv(Div)            /* Pixel Clock Divisor */ \
+                        (((Div) << FShft (LCCR3_PCD)))
+
+
+#define LCCR3_BPP       Fld (3, 24)     /* Bit Per Pixel */
+#define LCCR3_Bpp(Bpp)                  /* Bit Per Pixel */ \
+                        (((Bpp) << FShft (LCCR3_BPP)))
+
+#define LCCR3_ACB       Fld (8, 8)      /* AC Bias */
+#define LCCR3_Acb(Acb)                  /* BAC Bias */ \
+                        (((Acb) << FShft (LCCR3_ACB)))
+
+#define LCCR3_HorSnchH  (LCCR3_HSP*0)   /*  Horizontal Synchronization     */
+                                        /*  pulse active High              */
+#define LCCR3_HorSnchL  (LCCR3_HSP*1)   /*  Horizontal Synchronization     */
+
+#define LCCR3_VrtSnchH  (LCCR3_VSP*0)   /*  Vertical Synchronization pulse */
+                                        /*  active High                    */
+#define LCCR3_VrtSnchL  (LCCR3_VSP*1)   /*  Vertical Synchronization pulse */
+                                        /*  active Low                     */
+
+#define LCSR_LDD	(1 << 0)	/* LCD Disable Done */
+#define LCSR_SOF	(1 << 1)	/* Start of frame */
+#define LCSR_BER	(1 << 2)	/* Bus error */
+#define LCSR_ABC	(1 << 3)	/* AC Bias count */
+#define LCSR_IUL	(1 << 4)	/* input FIFO underrun Lower panel */
+#define LCSR_IUU	(1 << 5)	/* input FIFO underrun Upper panel */
+#define LCSR_OU		(1 << 6)	/* output FIFO underrun */
+#define LCSR_QD		(1 << 7)	/* quick disable */
+#define LCSR_EOF	(1 << 8)	/* end of frame */
+#define LCSR_BS		(1 << 9)	/* branch status */
+#define LCSR_SINT	(1 << 10)	/* subsequent interrupt */
+
+#define LDCMD_PAL	(1 << 26)	/* instructs DMA to load palette buffer */
+
+#define LCSR_LDD	(1 << 0)	/* LCD Disable Done */
+#define LCSR_SOF	(1 << 1)	/* Start of frame */
+#define LCSR_BER	(1 << 2)	/* Bus error */
+#define LCSR_ABC	(1 << 3)	/* AC Bias count */
+#define LCSR_IUL	(1 << 4)	/* input FIFO underrun Lower panel */
+#define LCSR_IUU	(1 << 5)	/* input FIFO underrun Upper panel */
+#define LCSR_OU		(1 << 6)	/* output FIFO underrun */
+#define LCSR_QD		(1 << 7)	/* quick disable */
+#define LCSR_EOF	(1 << 8)	/* end of frame */
+#define LCSR_BS		(1 << 9)	/* branch status */
+#define LCSR_SINT	(1 << 10)	/* subsequent interrupt */
+
+#define LDCMD_PAL	(1 << 26)	/* instructs DMA to load palette buffer */
+
+/*
+ * Memory controller
+ */
+
+#define MDCNFG		__REG(0x48000000)  /* SDRAM Configuration Register 0 */
+#define MDREFR		__REG(0x48000004)  /* SDRAM Refresh Control Register */
+#define MSC0		__REG(0x48000008)  /* Static Memory Control Register 0 */
+#define MSC1		__REG(0x4800000C)  /* Static Memory Control Register 1 */
+#define MSC2		__REG(0x48000010)  /* Static Memory Control Register 2 */
+#define MECR		__REG(0x48000014)  /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
+#define SXLCR		__REG(0x48000018)  /* LCR value to be written to SDRAM-Timing Synchronous Flash */
+#define SXCNFG		__REG(0x4800001C)  /* Synchronous Static Memory Control Register */
+#define SXMRS		__REG(0x48000024)  /* MRS value to be written to Synchronous Flash or SMROM */
+#define MCMEM0		__REG(0x48000028)  /* Card interface Common Memory Space Socket 0 Timing */
+#define MCMEM1		__REG(0x4800002C)  /* Card interface Common Memory Space Socket 1 Timing */
+#define MCATT0		__REG(0x48000030)  /* Card interface Attribute Space Socket 0 Timing Configuration */
+#define MCATT1		__REG(0x48000034)  /* Card interface Attribute Space Socket 1 Timing Configuration */
+#define MCIO0		__REG(0x48000038)  /* Card interface I/O Space Socket 0 Timing Configuration */
+#define MCIO1		__REG(0x4800003C)  /* Card interface I/O Space Socket 1 Timing Configuration */
+#define MDMRS		__REG(0x48000040)  /* MRS value to be written to SDRAM */
+#define BOOT_DEF	__REG(0x48000044)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
+
+#define MDREFR_K2FREE	(1 << 25)	/* SDRAM Free-Running Control */
+#define MDREFR_K1FREE	(1 << 24)	/* SDRAM Free-Running Control */
+#define MDREFR_K0FREE	(1 << 23)	/* SDRAM Free-Running Control */
+#define MDREFR_SLFRSH	(1 << 22)	/* SDRAM Self-Refresh Control/Status */
+#define MDREFR_APD	(1 << 20)	/* SDRAM/SSRAM Auto-Power-Down Enable */
+#define MDREFR_K2DB2	(1 << 19)	/* SDCLK2 Divide by 2 Control/Status */
+#define MDREFR_K2RUN	(1 << 18)	/* SDCLK2 Run Control/Status */
+#define MDREFR_K1DB2	(1 << 17)	/* SDCLK1 Divide by 2 Control/Status */
+#define MDREFR_K1RUN	(1 << 16)	/* SDCLK1 Run Control/Status */
+#define MDREFR_E1PIN	(1 << 15)	/* SDCKE1 Level Control/Status */
+#define MDREFR_K0DB2	(1 << 14)	/* SDCLK0 Divide by 2 Control/Status */
+#define MDREFR_K0RUN	(1 << 13)	/* SDCLK0 Run Control/Status */
+#define MDREFR_E0PIN	(1 << 12)	/* SDCKE0 Level Control/Status */
+
+#endif
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/serial.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,51 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/serial.h
+ * 
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software 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.
+ */
+
+
+#define BAUD_BASE	921600
+
+/* Standard COM flags */
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
+
+#define STD_SERIAL_PORT_DEFNS	\
+	{	\
+		type:			PORT_PXA,	\
+		xmit_fifo_size:		32,		\
+		baud_base:		BAUD_BASE,	\
+		iomem_base:		(void *)&FFUART,\
+		iomem_reg_shift:	2,		\
+		io_type:		SERIAL_IO_MEM32,\
+		irq:			IRQ_FFUART,	\
+		flags:			STD_COM_FLAGS,	\
+	}, {	\
+		type:			PORT_PXA,	\
+		xmit_fifo_size:		32,		\
+		baud_base:		BAUD_BASE,	\
+		iomem_base:		(void *)&BTUART,\
+		iomem_reg_shift:	2,		\
+		io_type:		SERIAL_IO_MEM32,\
+		irq:			IRQ_BTUART,	\
+		flags:			STD_COM_FLAGS,	\
+	}, {	\
+		type:			PORT_PXA,	\
+		xmit_fifo_size:		32,		\
+		baud_base:		BAUD_BASE,	\
+		iomem_base:		(void *)&STUART,\
+		iomem_reg_shift:	2,		\
+		io_type:		SERIAL_IO_MEM32,\
+		irq:			IRQ_STUART,	\
+		flags:			STD_COM_FLAGS,	\
+	}
+
+#define RS_TABLE_SIZE 8
+
+#define EXTRA_SERIAL_PORT_DEFNS
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/system.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-pxa/system.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software 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 "hardware.h"
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	if (mode == 's') {
+		/* Jump into ROM at address 0 */
+		cpu_reset(0);
+	} else {
+		/* Initialize the watchdog and let it fire */
+		OWER = OWER_WME;
+		OSSR = OSSR_M3;
+		OSMR3 = OSCR + 368640;	/* ... in 100 ms */
+	}
+}
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/time.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,86 @@
+/*
+ * linux/include/asm-arm/arch-pxa/time.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software 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.
+ */
+
+
+static inline unsigned long pxa_get_rtc_time(void)
+{
+	return RCNR;
+}
+
+static int pxa_set_rtc(void)
+{
+	unsigned long current_time = xtime.tv_sec;
+
+	if (RTSR & RTSR_ALE) {
+		/* make sure not to forward the clock over an alarm */
+		unsigned long alarm = RTAR;
+		if (current_time >= alarm && alarm >= RCNR)
+			return -ERESTARTSYS;
+	}
+	RCNR = current_time;
+	return 0;
+}
+
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long pxa_gettimeoffset (void)
+{
+	unsigned long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match = OSMR0 - OSCR;
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* Now convert them to usec */
+	usec = (unsigned long)(elapsed*tick)/LATCH;
+
+	return usec;
+}
+
+static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	long flags;
+	int next_match;
+
+	do_profile(regs);
+
+	/* Loop until we get ahead of the free running timer.
+	 * This ensures an exact clock tick count and time acuracy.
+	 * IRQs are disabled inside the loop to ensure coherence between
+	 * lost_ticks (updated in do_timer()) and the match reg value, so we
+	 * can use do_gettimeofday() from interrupt handlers.
+	 */
+	do {
+		do_leds();
+		do_set_rtc();
+		save_flags_cli( flags );
+		do_timer(regs);
+		OSSR = OSSR_M0;  /* Clear match on timer 0 */
+		next_match = (OSMR0 += LATCH);
+		restore_flags( flags );
+	} while( (signed long)(next_match - OSCR) <= 0 );
+}
+
+extern inline void setup_timer (void)
+{
+	gettimeoffset = pxa_gettimeoffset;
+	set_rtc = pxa_set_rtc;
+	xtime.tv_sec = pxa_get_rtc_time();
+	timer_irq.handler = pxa_timer_interrupt;
+	OSMR0 = 0;		/* set initial match at 0 */
+	OSSR = 0xf;		/* clear status on all timers */
+	setup_arm_irq(IRQ_OST0, &timer_irq);
+	OIER |= OIER_E0;	/* enable match on timer 0 to cause interrupts */
+	OSCR = 0;		/* initialize free-running timer, force first match */
+}
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/timex.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,17 @@
+/*
+ * linux/include/asm-arm/arch-pxa/timex.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software 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.
+ */
+
+/*
+ * PXA250/210 timer
+ */
+#define CLOCK_TICK_RATE		3686400
+#define CLOCK_TICK_FACTOR	80
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/trizeps2.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,206 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/trizeps2.h
+ *
+ * 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.
+ *
+ * Copyright (c) 2002 Luc De Cock, Teradyne DS, Ltd.
+ *
+ * 2002-10-10: Initial code started from idp.h
+ */
+
+
+/*
+ * Note: this file must be safe to include in assembly files
+ */
+
+/* comment out following if you have a board  with 32MB RAM */
+//#define PXA_TRIZEPS2_64MB	1
+#undef PXA_TRIZEPS2_64MB
+
+#define TRIZEPS2_FLASH_PHYS		(PXA_CS0_PHYS)
+#define TRIZEPS2_ALT_FLASH_PHYS		(PXA_CS1_PHYS)
+#define TRIZEPS2_MEDIAQ_PHYS		(PXA_CS3_PHYS)
+#define TRIZEPS2_IDE_PHYS		(PXA_CS5_PHYS + 0x03000000)
+#define TRIZEPS2_ETH_PHYS		(0x0C800000)
+#define TRIZEPS2_COREVOLT_PHYS		(PXA_CS5_PHYS + 0x03800000)
+#define TRIZEPS2_BCR_PHYS		(0x0E000000)
+#define TRIZEPS2_CPLD_PHYS		(0x0C000000)
+
+/*
+ * virtual memory map
+ */
+
+#define TRIZEPS2_IDE_BASE		(0xf0000000)
+#define TRIZEPS2_IDE_SIZE		(1*1024*1024)
+
+#define TRIZEPS2_ETH_BASE		(0xf1000000)
+#define TRIZEPS2_ETH_SIZE		(1*1024*1024)
+#define ETH_BASE		TRIZEPS2_ETH_BASE //smc9194 driver compatibility issue
+
+#define TRIZEPS2_COREVOLT_BASE	(TRIZEPS2_ETH_BASE + TRIZEPS2_ETH_SIZE)
+#define TRIZEPS2_COREVOLT_SIZE	(1*1024*1024)
+
+#define TRIZEPS2_BCR_BASE	(0xf0000000)
+#define TRIZEPS2_BCR_SIZE	(1*1024*1024)
+
+#define BCR_P2V(x)		((x) - TRIZEPS2_BCR_PHYS + TRIZEPS2_BCR_BASE)
+#define BCR_V2P(x)		((x) - TRIZEPS2_BCR_BASE + TRIZEPS2_BCR_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __BCR_REG(x)		(*((volatile unsigned short *)BCR_P2V(x)))
+#else
+#  define __BCR_REG(x)		BCR_P2V(x)
+#endif
+
+/* board level registers  */
+#define TRIZEPS2_CPLD_BASE	(0xf0100000)
+#define CPLD_P2V(x)             ((x) - TRIZEPS2_CPLD_PHYS + TRIZEPS2_CPLD_BASE)
+#define CPLD_V2P(x)             ((x) - TRIZEPS2_CPLD_BASE + TRIZEPS2_CPLD_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __CPLD_REG(x)         (*((volatile unsigned short *)CPLD_P2V(x)))
+#else
+#  define __CPLD_REG(x)         CPLD_P2V(x)
+#endif
+
+#define _TRIZEPS2_PCCARD_STATUS	(0x0c000000)
+#define TRIZEPS2_PCCARD_STATUS         __CPLD_REG(_TRIZEPS2_PCCARD_STATUS)
+
+/*
+ * CS memory timing via Static Memory Control Register (MSC0-2)
+ */
+
+#define MSC_CS(cs,val) ((val)<<((cs&1)<<4))
+
+#define MSC_RBUFF_SHIFT		15 
+#define MSC_RBUFF(x)		((x)<<MSC_RBUFF_SHIFT)
+#define MSC_RBUFF_SLOW		MSC_RBUFF(0)
+#define MSC_RBUFF_FAST		MSC_RBUFF(1)
+
+#define MSC_RRR_SHIFT		12
+#define MSC_RRR(x)		((x)<<MSC_RRR_SHIFT)
+
+#define MSC_RDN_SHIFT		8
+#define MSC_RDN(x)		((x)<<MSC_RDN_SHIFT)
+
+#define MSC_RDF_SHIFT		4
+#define MSC_RDF(x)		((x)<<MSC_RDF_SHIFT)
+
+#define MSC_RBW_SHIFT		3
+#define MSC_RBW(x)		((x)<<MSC_RBW_SHIFT)
+#define MSC_RBW_16		MSC_RBW(1)
+#define MSC_RBW_32		MSC_RBW(0)
+
+#define MSC_RT_SHIFT		0
+#define MSC_RT(x)		((x)<<MSC_RT_SHIFT)
+
+
+/*
+ * Bit masks for various registers
+ */
+// TRIZEPS2_BCR_PCCARD_PWR
+#define PCC_3V		(1 << 0)
+#define PCC_5V		(1 << 1)
+#define PCC_EN1		(1 << 2)
+#define PCC_EN0		(1 << 3)
+
+// TRIZEPS2_BCR_PCCARD_EN
+#define PCC_RESET	(1 << 6)
+#define PCC_ENABLE	(1 << 0)
+
+// TRIZEPS2_BSR_PCCARDx_STATUS
+#define _PCC_WRPROT	(1 << 7) // 7-4 read as low true
+#define _PCC_RESET	(1 << 6)
+#define _PCC_IRQ	(1 << 5)
+#define _PCC_INPACK	(1 << 4)
+#define PCC_BVD1	(1 << 0)
+#define PCC_BVD2	(1 << 1)
+#define PCC_VS1		(1 << 2)
+#define PCC_VS2		(1 << 3)
+
+// TRIZEPS2_BCR_CONTROL bits
+#define BCR_LCD_ON	(1 << 4)
+#define BCR_LCD_OFF	(0)
+#define BCR_LCD_MASK	(1 << 4)
+#define BCR_PCMCIA_RESET (1 << 7)
+#define BCR_PCMCIA_NORMAL (0)
+
+#define PCC_DETECT	(GPLR(24) & GPIO_bit(24))
+#define PCC_READY	(GPLR(1) & GPIO_bit(1))
+
+// Board Control Register
+#define _TRIZEPS2_BCR_CONTROL	(TRIZEPS2_BCR_PHYS)
+#define TRIZEPS2_BCR_CONTROL	__BCR_REG(_TRIZEPS2_BCR_CONTROL)
+
+// Board TTL-IO register
+#define TRIZEPS2_TTLIO_PHYS	(0x0d800000)
+#define TRIZEPS2_TTLIO_BASE	(0xf2000000)
+// various ioctl cmds
+#define TTLIO_RESET		0
+#define TTLIO_GET		1
+#define TTLIO_SET		2
+#define TTLIO_UNSET		3
+
+/*
+ * Macros for LCD Driver
+ */
+
+#ifdef CONFIG_FB_PXA
+
+#define FB_BACKLIGHT_ON()
+#define FB_BACKLIGHT_OFF()
+
+#define FB_PWR_ON()
+#define FB_PWR_OFF()
+
+#define FB_VLCD_ON()		WRITE_TRIZEPS2_BCR(BCR_LCD_ON,BCR_LCD_MASK);
+#define FB_VLCD_OFF()		WRITE_TRIZEPS2_BCR(BCR_LCD_OFF,BCR_LCD_MASK);
+
+#endif
+
+/* A listing of interrupts used by external hardware devices */
+
+#define GPIO_TOUCH_PANEL_IRQ		2
+#define TOUCH_PANEL_IRQ			IRQ_GPIO(GPIO_TOUCH_PANEL_IRQ)
+#define GPIO_ETHERNET_IRQ		19
+#define ETHERNET_IRQ			IRQ_GPIO(GPIO_ETHERNET_IRQ)
+#define GPIO_TTLIO_IRQ			23
+#define TTLIO_IRQ			IRQ_GPIO(GPIO_TTLIO_IRQ)
+
+#define TOUCH_PANEL_IRQ_EDGE		GPIO_FALLING_EDGE
+#define IDE_IRQ_EDGE			GPIO_RISING_EDGE
+#define ETHERNET_IRQ_EDGE		GPIO_RISING_EDGE
+
+#define PCMCIA_S_CD_VALID		IRQ_GPIO(24)
+#define PCMCIA_S_CD_VALID_EDGE		GPIO_BOTH_EDGES
+
+#define PCMCIA_S_RDYINT			IRQ_GPIO(1)
+#define PCMCIA_S_RDYINT_EDGE		GPIO_FALLING_EDGE
+
+/*
+ * macros for MTD driver
+ */
+
+#define FLASH_WRITE_PROTECT_DISABLE()	// ((TRIZEPS2_CPLD_FLASH_WE) &= ~(0x1))
+#define FLASH_WRITE_PROTECT_ENABLE()	// ((TRIZEPS2_CPLD_FLASH_WE) |= (0x1))
+
+/* shadow registers for write only registers */
+#ifndef __ASSEMBLY__
+extern unsigned short trizeps2_bcr_shadow;
+#endif
+
+/* 
+ * macros to write to write only register
+ *
+ * none of these macros are protected from 
+ * multiple drivers using them in interrupt context.
+ */
+
+#define WRITE_TRIZEPS2_BCR(value, mask) \
+{\
+	trizeps2_bcr_shadow = ((value & mask) | (trizeps2_bcr_shadow & ~mask));\
+	TRIZEPS2_BCR_CONTROL = trizeps2_bcr_shadow;\
+}
+
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/uncompress.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,42 @@
+/*
+ * linux/include/asm-arm/arch-pxa/uncompress.h
+ *  
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software 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.
+ */
+
+#define FFUART		((volatile unsigned long *)0x40100000)
+#define BTUART		((volatile unsigned long *)0x40200000)
+#define STUART		((volatile unsigned long *)0x40700000)
+
+#define UART		FFUART
+
+
+static __inline__ void putc(char c)
+{
+	while (!(UART[5] & 0x20));
+	UART[0] = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+	while (*s) {
+		putc(*s);
+		if (*s == '\n')
+			putc('\r');
+		s++;
+	}
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/asm-arm/arch-pxa/vmalloc.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-pxa/vmalloc.h
+ * 
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software 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.
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (0xe8000000)
--- linux-2.4.25/include/asm-arm/assembler.h~2.4.25-vrs2-pxa1.patch	2000-08-13 18:54:15.000000000 +0200
+++ linux-2.4.25/include/asm-arm/assembler.h	2004-03-31 17:15:12.000000000 +0200
@@ -13,3 +13,26 @@
 
 #include <asm/proc/ptrace.h>
 #include <asm/proc/assembler.h>
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull            lsr
+#define push            lsl
+#define byte(x)         (x*8)
+#else
+#define pull            lsl
+#define push            lsr
+#define byte(x)         ((3-x)*8)
+#endif
+
+/*
+ * Data preload for architectures that support it
+ */
+#if __LINUX_ARM_ARCH__ >= 5
+#define PLD(code...)	code
+#else
+#define PLD(code...)
+#endif
+
--- linux-2.4.25/include/asm-arm/bitops.h~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.25/include/asm-arm/bitops.h	2004-03-31 17:15:12.000000000 +0200
@@ -91,6 +91,8 @@
     return (((unsigned char *) addr)[nr >> 3] >> (nr & 7)) & 1;
 }	
 
+#if __LINUX_ARM_ARCH__ < 5
+
 /*
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
@@ -117,6 +119,23 @@
 
 #define ffs(x) generic_ffs(x)
 
+#else
+
+/*
+ * On ARMv5 and above those functions can be implemented around
+ * the clz instruction for much better code efficiency.
+ */
+
+extern __inline__ int generic_fls(int x);
+#define fls(x) \
+	( __builtin_constant_p(x) ? generic_fls(x) : \
+	  ({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
+#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
+#define __ffs(x) (ffs(x) - 1)
+#define ffz(x) __ffs( ~(x) )
+
+#endif
+
 /*
  * hweightN: returns the hamming weight (i.e. the number
  * of bits set) of a N-bit word
--- linux-2.4.25/include/asm-arm/io.h~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.25/include/asm-arm/io.h	2004-03-31 17:15:12.000000000 +0200
@@ -168,7 +168,7 @@
  * devices.  This is the "generic" version.  The PCI specific version
  * is in pci.h
  */
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, unsigned long flags);
 extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
 extern void consistent_sync(void *vaddr, size_t size, int rw);
 
--- linux-2.4.25/include/asm-arm/memory.h~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.25/include/asm-arm/memory.h	2004-03-31 17:15:12.000000000 +0200
@@ -123,6 +123,9 @@
      ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size)); \
 })
 
+/* We want large page mapping possible */
+#define VMALLOC_ALIGN		0x10000
+
 #endif
 
 /*
--- linux-2.4.25/include/asm-arm/proc-armv/pgtable.h~2.4.25-vrs2-pxa1.patch	2001-08-12 20:14:00.000000000 +0200
+++ linux-2.4.25/include/asm-arm/proc-armv/pgtable.h	2004-03-31 17:15:12.000000000 +0200
@@ -15,9 +15,6 @@
 #ifndef __ASM_PROC_PGTABLE_H
 #define __ASM_PROC_PGTABLE_H
 
-#include <asm/proc/domain.h>
-#include <asm/arch/vmalloc.h>
-
 /*
  * entries per page directory level: they are two-level, so
  * we don't really have any PMD directory.
@@ -26,27 +23,92 @@
 #define PTRS_PER_PMD		1
 #define PTRS_PER_PGD		4096
 
-/****************
-* PMD functions *
-****************/
-
-/* PMD types (actually level 1 descriptor) */
-#define PMD_TYPE_MASK		0x0003
-#define PMD_TYPE_FAULT		0x0000
-#define PMD_TYPE_TABLE		0x0001
-#define PMD_TYPE_SECT		0x0002
-#define PMD_UPDATABLE		0x0010
-#define PMD_SECT_CACHEABLE	0x0008
-#define PMD_SECT_BUFFERABLE	0x0004
-#define PMD_SECT_AP_WRITE	0x0400
-#define PMD_SECT_AP_READ	0x0800
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ *   - common
+ */
+#define PMD_TYPE_MASK		(3 << 0)
+#define PMD_TYPE_FAULT		(0 << 0)
+#define PMD_TYPE_TABLE		(1 << 0)
+#define PMD_TYPE_SECT		(2 << 0)
+#define PMD_UPDATABLE		(1 << 4)
 #define PMD_DOMAIN(x)		((x) << 5)
+#define PMD_PROTECTION		(1 << 9)	/* v5 */
+/*
+ *   - section
+ */
+#define PMD_SECT_BUFFERABLE	(1 << 2)
+#define PMD_SECT_CACHEABLE	(1 << 3)
+#define PMD_SECT_AP_WRITE	(1 << 10)
+#define PMD_SECT_AP_READ	(1 << 11)
+#define PMD_SECT_TEX(x)		((x) << 12)	/* v5 */
+/*
+ *   - coarse table
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ *   - common
+ */
+#define PTE_TYPE_MASK		(3 << 0)
+#define PTE_TYPE_FAULT		(0 << 0)
+#define PTE_TYPE_LARGE		(1 << 0)
+#define PTE_TYPE_SMALL		(2 << 0)
+#define PTE_TYPE_EXT		(3 << 0)	/* v5 */
+#define PTE_BUFFERABLE		(1 << 2)
+#define PTE_CACHEABLE		(1 << 3)
+
+/*
+ *   - extended small page/tiny page
+ */
+#define PTE_EXT_AP_UNO_SRO	(0 << 4)
+#define PTE_EXT_AP_UNO_SRW	(1 << 4)
+#define PTE_EXT_AP_URO_SRW	(2 << 4)
+#define PTE_EXT_AP_URW_SRW	(3 << 4)
+#define PTE_EXT_TEX(x)		((x) << 6)	/* v5 */
+
+/*
+ *   - small page
+ */
+#define PTE_SMALL_AP_UNO_SRO	(0x00 << 4)
+#define PTE_SMALL_AP_UNO_SRW	(0x55 << 4)
+#define PTE_SMALL_AP_URO_SRW	(0xaa << 4)
+#define PTE_SMALL_AP_URW_SRW	(0xff << 4)
+#define PTE_AP_READ		PTE_SMALL_AP_URO_SRW
+#define PTE_AP_WRITE		PTE_SMALL_AP_UNO_SRW
+
+/*
+ * "Linux" PTE definitions.
+ *
+ * We keep two sets of PTEs - the hardware and the linux version.
+ * This allows greater flexibility in the way we map the Linux bits
+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
+ * bits.
+ *
+ * The PTE table pointer refers to the hardware entries; the "Linux"
+ * entries are stored 1024 bytes below.
+ */
+#define L_PTE_PRESENT		(1 << 0)
+#define L_PTE_YOUNG		(1 << 1)
+#define L_PTE_BUFFERABLE	(1 << 2)	/* matches PTE */
+#define L_PTE_CACHEABLE		(1 << 3)	/* matches PTE */
+#define L_PTE_USER		(1 << 4)
+#define L_PTE_WRITE		(1 << 5)
+#define L_PTE_EXEC		(1 << 6)
+#define L_PTE_DIRTY		(1 << 7)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/proc/domain.h>
+#include <asm/arch/vmalloc.h>
 
 #define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
 #define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
 
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
-#define set_pmd(pmdp,pmd)	cpu_set_pmd(pmdp,pmd)
+#define set_pmd(pmdp,pmd)	cpu_set_pmd(pmdp, pmd)
 
 static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
 {
@@ -75,49 +137,8 @@
 	return __phys_to_virt(ptr);
 }
 
-/****************
-* PTE functions *
-****************/
-
-/* PTE types (actually level 2 descriptor) */
-#define PTE_TYPE_MASK		0x0003
-#define PTE_TYPE_FAULT		0x0000
-#define PTE_TYPE_LARGE		0x0001
-#define PTE_TYPE_SMALL		0x0002
-#define PTE_AP_READ		0x0aa0
-#define PTE_AP_WRITE		0x0550
-#define PTE_CACHEABLE		0x0008
-#define PTE_BUFFERABLE		0x0004
-
 #define set_pte(ptep, pte)	cpu_set_pte(ptep,pte)
 
-/* We now keep two sets of ptes - the physical and the linux version.
- * This gives us many advantages, and allows us greater flexibility.
- *
- * The Linux pte's contain:
- *  bit   meaning
- *   0    page present
- *   1    young
- *   2    bufferable	- matches physical pte
- *   3    cacheable	- matches physical pte
- *   4    user
- *   5    write
- *   6    execute
- *   7    dirty
- *  8-11  unused
- *  12-31 virtual page address
- *
- * These are stored at the pte pointer; the physical PTE is at -1024bytes
- */
-#define L_PTE_PRESENT		(1 << 0)
-#define L_PTE_YOUNG		(1 << 1)
-#define L_PTE_BUFFERABLE	(1 << 2)
-#define L_PTE_CACHEABLE		(1 << 3)
-#define L_PTE_USER		(1 << 4)
-#define L_PTE_WRITE		(1 << 5)
-#define L_PTE_EXEC		(1 << 6)
-#define L_PTE_DIRTY		(1 << 7)
-
 /*
  * The following macros handle the cache and bufferable bits...
  */
@@ -162,5 +183,8 @@
  * Mark the prot value as uncacheable and unbufferable.
  */
 #define pgprot_noncached(prot)	__pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
+#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~L_PTE_CACHEABLE)
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_PROC_PGTABLE_H */
--- linux-2.4.25/include/asm-arm/proc-armv/processor.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/include/asm-arm/proc-armv/processor.h	2004-03-31 17:15:12.000000000 +0200
@@ -23,6 +23,9 @@
 #define KERNEL_STACK_SIZE	PAGE_SIZE
 
 struct context_save_struct {
+#ifdef CONFIG_CPU_XSCALE
+	long long acc0;
+#endif
 	unsigned long cpsr;
 	unsigned long r4;
 	unsigned long r5;
@@ -35,7 +38,11 @@
 	unsigned long pc;
 };
 
+#ifdef CONFIG_CPU_XSCALE
+#define INIT_CSS (struct context_save_struct){ 0, SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#else
 #define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#endif
 
 #define EXTRA_THREAD_STRUCT						\
 	unsigned int	domain;
--- linux-2.4.25/include/asm-arm/proc-fns.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/include/asm-arm/proc-fns.h	2004-03-31 17:15:12.000000000 +0200
@@ -124,6 +124,14 @@
 #   define CPU_NAME sa1100
 #  endif
 # endif
+# ifdef CONFIG_CPU_XSCALE
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME xscale
+#  endif
+# endif
 #endif
 
 #ifndef MULTI_CPU
--- linux-2.4.25/include/asm-arm/procinfo.h~2.4.25-vrs2-pxa1.patch	2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.25/include/asm-arm/procinfo.h	2004-03-31 17:15:12.000000000 +0200
@@ -55,7 +55,8 @@
 #define HWCAP_FAST_MULT	16
 #define HWCAP_FPA	32
 #define HWCAP_VFP	64
-#define HWCAP_EDSP	128
+#define HWCAP_EDSP	128	/* El Segundo */
 #define HWCAP_JAVA	256
+#define HWCAP_XSCALE	512	/* XScale DSP co-processor */
 
 #endif
--- linux-2.4.25/include/asm-arm/uaccess.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/include/asm-arm/uaccess.h	2004-03-31 17:15:12.000000000 +0200
@@ -86,7 +86,7 @@
 			__get_user_x(__r1, __p, __e, 1, "lr");		\
 	       		break;						\
 		case 2:							\
-			__get_user_x(__r1, __p, __e, 2, "r2", "lr");	\
+			__get_user_x(__r1, __p, __e, 2, "ip", "lr");	\
 			break;						\
 		case 4:							\
 	       		__get_user_x(__r1, __p, __e, 4, "lr");		\
--- linux-2.4.25/include/linux/cramfs_fs_sb.h~2.4.25-vrs2-pxa1.patch	2001-07-20 01:14:53.000000000 +0200
+++ linux-2.4.25/include/linux/cramfs_fs_sb.h	2004-03-31 17:15:12.000000000 +0200
@@ -10,6 +10,10 @@
 			unsigned long blocks;
 			unsigned long files;
 			unsigned long flags;
+#ifdef CONFIG_CRAMFS_LINEAR
+			unsigned long linear_phys_addr;
+			char *        linear_virt_addr;
+#endif
 };
 
 #endif
--- linux-2.4.25/include/linux/i2c-id.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/include/linux/i2c-id.h	2004-03-31 17:15:12.000000000 +0200
@@ -100,6 +100,10 @@
 #define I2C_DRIVERID_SAA7191	57     /* video decoder                 */
 #define I2C_DRIVERID_INDYCAM	58     /* SGI IndyCam			*/
 
+#define I2C_DRIVERID_DS1307	46	/* real time clock: DS1307	*/
+#define I2C_DRIVERID_24LC64	47	/* EEprom 24LC64		*/
+#define I2C_DRIVERID_FM24CLB4	48	/* EEprom FM24CLB4		*/
+
 #define I2C_DRIVERID_EXP0	0xF0	/* experimental use id's	*/
 #define I2C_DRIVERID_EXP1	0xF1
 #define I2C_DRIVERID_EXP2	0xF2
@@ -172,6 +176,8 @@
 
 #define I2C_ALGO_OCP    0x120000	/* IBM or otherwise On-chip I2C algorithm */
 
+#define I2C_ALGO_PXA	0x400000	/* Intel PXA I2C algorithm  */
+
 #define I2C_ALGO_EXP	0x800000	/* experimental			*/
 
 #define I2C_ALGO_MASK	0xff0000	/* Mask for algorithms		*/
--- linux-2.4.25/include/linux/serial.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/include/linux/serial.h	2004-03-31 17:15:12.000000000 +0200
@@ -75,11 +75,13 @@
 #define PORT_16654	11
 #define PORT_16850	12
 #define PORT_RSA	13	/* RSA-DV II/S card */
-#define PORT_MAX	13
+#define PORT_PXA	14
+#define PORT_MAX	14
 
 #define SERIAL_IO_PORT	0
 #define SERIAL_IO_HUB6	1
 #define SERIAL_IO_MEM	2
+#define SERIAL_IO_MEM32	3
 
 struct serial_uart_config {
 	char	*name;
--- linux-2.4.25/include/linux/serial_reg.h~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/include/linux/serial_reg.h	2004-03-31 17:15:12.000000000 +0200
@@ -119,6 +119,14 @@
 #define UART_IERX_SLEEP  0x10	/* Enable sleep mode */
 
 /*
+ * The Intel PXA250/210 chip defines those bits
+ */
+#define UART_IER_DMAE	0x80	/* DMA Requests Enable */
+#define UART_IER_UUE	0x40	/* UART Unit Enable */
+#define UART_IER_NRZE	0x20	/* NRZ coding Enable */
+#define UART_IER_RTOIE	0x10	/* Receiver Time Out Interrupt Enable */
+
+/*
  * These are the definitions for the Modem Control Register
  */
 #define UART_MCR_AFE	0x20	/* Enable auto-RTS/CTS (TI16C750) */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/mmc/ioctl.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,25 @@
+/*
+ *  linux/include/linux/mmc/ioctl.h
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *	$Id: ioctl.h,v 0.2 2002/07/11 16:28:21 ted Exp ted $
+ *
+ *  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 __MMC_IOCTL_H__
+#define __MMC_IOCTL_H__
+
+#include <asm/ioctl.h>
+
+/* IOCTL commands provided by MMC subsystem */
+#define IOCMMCSTRNSMODE _IOW('I',0x0f01,int)
+#define IOCMMCGTRNSMODE _IOR('I',0x0f02,int)
+#define IOCMMCGCARDESC  _IOR('I',0x0f03,int) /* FIXME */
+#define IOCMMCGBLKSZMAX _IOR('I',0x0f04,ssize_t)
+#define IOCMMCGNOBMAX	_IOR('I',0x0f05,ssize_t)
+
+#endif /* __MMC_IOCTL_H__ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/mmc/mmc.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,143 @@
+/*
+ *  linux/include/linux/mmc/mmc.h 
+ *
+ *  Author: Vladimir Shebordaev 
+ *  Copyright:  MontaVista Software Inc.
+ *
+ *  $Id: mmc.h,v 0.2.1.2 2002/07/25 16:29:47 ted Exp ted $
+ *
+ *  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 __MMC_H__
+#define __MMC_H__
+
+#include <linux/types.h>
+#include <mmc/types.h>
+
+/*
+ * MMC card type
+ */
+enum _mmc_type {
+    MMC_CARD_TYPE_RO = 1,
+    MMC_CARD_TYPE_RW,
+    MMC_CARD_TYPE_IO
+};
+
+/*
+ * MMC card state
+ */
+enum _mmc_state {
+    MMC_CARD_STATE_IDLE = 1,
+    MMC_CARD_STATE_READY,
+    MMC_CARD_STATE_IDENT,
+    MMC_CARD_STATE_STNBY,
+    MMC_CARD_STATE_TRAN,
+    MMC_CARD_STATE_DATA,
+    MMC_CARD_STATE_RCV,
+    MMC_CARD_STATE_DIS,
+    MMC_CARD_STATE_UNPLUGGED=0xff
+};
+
+/*
+ * Data transfer mode
+ */
+enum _mmc_transfer_mode {
+    MMC_TRANSFER_MODE_STREAM = 1,
+    MMC_TRANSFER_MODE_BLOCK_SINGLE,
+    MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
+    MMC_TRANSFER_MODE_UNDEFINED = -1
+};
+
+struct _mmc_card_csd_rec { /* CSD register contents */
+/* FIXME: BYTE_ORDER */
+	u8	ecc:2,
+		file_format:2,
+		tmp_write_protect:1,
+		perm_write_protect:1,
+		copy:1,
+		file_format_grp:1;
+	u64	content_prot_app:1,
+		rsvd3:4,
+		write_bl_partial:1,
+		write_bl_len:4,
+		r2w_factor:3,
+		default_ecc:2,
+		wp_grp_enable:1,
+		wp_grp_size:5,
+		erase_grp_mult:5,
+		erase_grp_size:5,
+		c_size_mult:3,
+		vdd_w_curr_max:3,
+		vdd_w_curr_min:3,
+		vdd_r_curr_max:3,
+		vdd_r_curr_min:3,
+		c_size:12,
+		rsvd2:2,
+		dsr_imp:1,
+		read_blk_misalign:1,
+		write_blk_misalign:1,
+		read_bl_partial:1;
+
+	u16	read_bl_len:4,
+		ccc:12;
+	u8	tran_speed;
+	u8	nsac;
+	u8	taac;
+	u8	rsvd1:2,
+	  	spec_vers:4,
+		csd_structure:2;
+};
+
+struct _mmc_card_cid_rec { /* CID register contents */
+/* FIXME: BYTE_ORDER */
+	u8	mdt_year:4,
+		mdt_mon:4;
+	u32	psn;
+	u8	prv_minor:4,
+		prv_major:4;
+	u8	pnm[6];
+	u16	oid;
+	u8	mid;
+};
+
+/* 
+ * Public card description
+ */
+struct _mmc_card_info_rec {
+    mmc_type_t type;
+    mmc_transfer_mode_t transfer_mode; /* current data transfer mode */
+    __u16 rca;        /* card's RCA assigned during initialization */
+    struct _mmc_card_csd_rec csd;
+    struct _mmc_card_cid_rec cid;
+    __u32 tran_speed; /* kbits */
+    __u16 read_bl_len;
+    __u16 write_bl_len;
+    size_t capacity;    /* card's capacity in bytes */
+};
+
+/* 
+ * Micsellaneous defines
+ */
+#ifndef SEEK_SET
+#define SEEK_SET (0)
+#endif
+
+#ifndef SEEK_CUR
+#define SEEK_CUR (1)
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END (2)
+#endif
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#endif /* __MMC_H__ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/mmc/types.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,29 @@
+/*
+ *  linux/include/linux/mmc/types.h
+ *
+ *  Author:	Vladimir Shebordaev	
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *	$Id: types.h,v 0.2 2002/07/11 16:28:21 ted Exp ted $
+ *
+ *  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 __MMC_TYPES_H__
+#define __MMC_TYPES_H__
+
+/* MMC card */
+typedef enum _mmc_type mmc_type_t;
+typedef enum _mmc_state mmc_state_t;
+typedef enum _mmc_transfer_mode mmc_transfer_mode_t;
+
+typedef struct _mmc_card_csd_rec mmc_card_csd_rec_t;
+typedef struct _mmc_card_cid_rec mmc_card_cid_rec_t;
+
+typedef struct _mmc_card_info_rec mmc_card_info_rec_t;
+typedef struct _mmc_card_info_rec *mmc_card_info_t;
+
+typedef enum _mmc_error mmc_error_t;
+
+#endif /* __MMC_TYPES_H__ */
--- /dev/null	2003-09-23 19:59:22.000000000 +0200
+++ linux-2.4.25/include/video/lcdctrl.h	2004-03-31 17:15:12.000000000 +0200
@@ -0,0 +1,61 @@
+/*
+ *  lcdctrl.h
+ *
+ *  Generic LCD control for brightness, contrast, etc.
+ *  Device specific drivers implement a lcdctrl_device and
+ *  provides access to it via lcdctrl_device_get_ops().
+ *
+ *  Copyright (C) 2002 Intrinsyc Software 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.
+ *
+ *  History:
+ *    Mar 2002: Initial version [FB]
+ * 
+ */
+#ifndef __LCD_CONTROL_H
+#define __LCD_CONTROL_H
+
+#define _LCDCTRL_IOCTL_ON		1
+#define _LCDCTRL_IOCTL_OFF		2
+#define _LCDCTRL_IOCTL_INTENSITY	3
+#define _LCDCTRL_IOCTL_BRIGHTNESS	4
+#define _LCDCTRL_IOCTL_CONTRAST		5
+#define _LCDCTRL_IOCTL_GET_BRIGHTNESS	6
+#define _LCDCTRL_IOCTL_GET_CONTRAST	7
+#define _LCDCTRL_IOCTL_GET_INTENSITY	8
+
+#define _LCD_CONTROL_NAME "lcdctrl"
+
+#define LCD_NO_SYNC     0
+#define LCD_SYNC_NEEDED 1
+
+int lcdctrl_enable( void);
+int lcdctrl_disable( void);
+
+/* intensity, contrast, and brightness take values
+ * between 0..100.
+ */
+int lcdctrl_set_intensity( int intensity);
+int lcdctrl_set_contrast( int contrast, int sync);
+int lcdctrl_set_brightness( int brightness);
+
+int lcdctrl_get_intensity( void);
+int lcdctrl_get_contrast( void);
+int lcdctrl_get_brightness( void);
+
+struct lcdctrl_device
+{
+	int (*init)( int*, int*, int*);
+	int (*enable)(void);
+	int (*disable)(void);
+	int (*set_intensity)( int i);
+	int (*set_brightness)( int b);
+	int (*set_contrast)( int c, int sync);
+};
+
+int lcdctrl_init( void);
+
+#endif
--- linux-2.4.25/init/do_mounts.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/init/do_mounts.c	2004-03-31 17:15:12.000000000 +0200
@@ -394,6 +394,16 @@
 }
 #endif
 
+#ifdef CONFIG_ROOT_CRAMFS_LINEAR
+static int __init mount_linear_cramfs_root(void)
+{
+	void *data = root_mount_data;
+	if (sys_mount("/dev/root","/root","cramfs",root_mountflags,data) == 0)
+		return 1;
+	return 0;
+}
+#endif
+
 static int __init create_dev(char *name, kdev_t dev, char *devfs_name)
 {
 	void *handle;
@@ -759,6 +769,16 @@
 
 static void __init mount_root(void)
 {
+#ifdef CONFIG_ROOT_CRAMFS_LINEAR
+	if (ROOT_DEV == MKDEV(0, 0)) {
+		if (mount_linear_cramfs_root()) {
+			sys_chdir("/root");
+			ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
+			printk("VFS: Mounted root (linear cramfs filesystem).\n");
+			return;
+		}
+	}
+#endif
 #ifdef CONFIG_ROOT_NFS
        if (MAJOR(ROOT_DEV) == NFS_MAJOR
            && MINOR(ROOT_DEV) == NFS_MINOR) {
--- linux-2.4.25/mm/memory.c~2.4.25-vrs2-pxa1.patch	2004-03-31 17:15:09.000000000 +0200
+++ linux-2.4.25/mm/memory.c	2004-03-31 17:15:12.000000000 +0200
@@ -1018,6 +1018,41 @@
 	return 1;	/* Minor fault */
 
 bad_wp_page:
+	if (pte_present(pte) && pte_read(pte)) {
+		/*
+		 * Handle COW of XIP memory.
+		 * Note that the source memory actually isn't a ram page so
+		 * no struct page is associated to the source pte.
+		 */
+		char *dst;
+		int ret;
+
+		spin_unlock(&mm->page_table_lock);
+		new_page = alloc_page(GFP_HIGHUSER);
+		if (!new_page)
+			return -1;
+
+		/* copy XIP data to memory */
+		dst = kmap_atomic(new_page, KM_USER0);
+		ret = copy_from_user(dst, (void*)address, PAGE_SIZE);
+		kunmap_atomic(dst, KM_USER0);
+
+		/* make sure pte didn't change while we dropped the lock */
+		spin_lock(&mm->page_table_lock);
+		if (!ret && pte_same(*page_table, pte)) {
+			++mm->rss;
+			break_cow(vma, new_page, address, page_table);
+			lru_cache_add(new_page);
+			spin_unlock(&mm->page_table_lock);
+			return 1;	/* Minor fault */
+		}
+
+		/* pte changed: back off */
+		spin_unlock(&mm->page_table_lock);
+		page_cache_release(new_page);
+		return ret ? -1 : 1;
+	}
+
 	spin_unlock(&mm->page_table_lock);
 	printk("do_wp_page: bogus page at address %08lx\n", address);
 	return -1;